|
|
|
#include "common.h"
|
|
|
|
|
|
|
|
#include "dwarf.c"
|
|
|
|
#include "eh_frame.c"
|
|
|
|
#include "util.c"
|
|
|
|
#include "command.c"
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
if (argc != 2) {
|
|
|
|
printf("Usage: %s executable\n", argv[0]);
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct mi_process process = process_create(argv[1]);
|
|
|
|
printf("pid of child = %d\n", process.pid);
|
|
|
|
|
|
|
|
size_t max_command_length = 1023;
|
|
|
|
int command_length = 0;
|
|
|
|
char *command = malloc(max_command_length + 1);
|
|
|
|
char *last_command = malloc(max_command_length + 1);
|
|
|
|
|
|
|
|
parse_debug_info(process.elf, &process.debug);
|
|
|
|
parse_eh_frame(process);
|
|
|
|
|
|
|
|
process.base_address = 0x555555554000UL; // get_executable_base_address(file, proc.pid);
|
|
|
|
process.main_address = get_address_of_subroutine(process, "main");
|
|
|
|
|
|
|
|
printf("Base address: %#lx\n", process.base_address);
|
|
|
|
printf("Main address: %#lx\n", process.main_address);
|
|
|
|
|
|
|
|
printf("> ");
|
|
|
|
fflush(stdout);
|
|
|
|
|
|
|
|
parse_debug_line(process.elf, &process.debug);
|
|
|
|
|
|
|
|
while ((command_length = getline(&command, &max_command_length, stdin))) {
|
|
|
|
if (command_length == 1) {
|
|
|
|
memset(command, 0, max_command_length);
|
|
|
|
memcpy(command, last_command, command_length);
|
|
|
|
}
|
|
|
|
|
|
|
|
int wait = 0;
|
|
|
|
|
|
|
|
if (0 == strncmp(command, "exit\n", command_length) || 0 == strncmp(command, "q\n", command_length)) {
|
|
|
|
break;
|
|
|
|
} else if (0 == strncmp(command, "regs\n", command_length)) {
|
|
|
|
command_regs(process);
|
|
|
|
} else if (0 == strncmp(command, "step\n", command_length)) {
|
|
|
|
command_step(process);
|
|
|
|
} else if (0 == strncmp(command, "start\n", command_length)) {
|
|
|
|
command_start(process);
|
|
|
|
} else if (0 == strncmp(command, "print ", 6)) {
|
|
|
|
command_print(process, command + 6, command_length - 7);
|
|
|
|
} else if (0 == strncmp(command, "next\n", command_length)) {
|
|
|
|
command_next(process);
|
|
|
|
} else if (0 == strncmp(command, "line\n", command_length)) {
|
|
|
|
command_list(process);
|
|
|
|
} else if (0 == strncmp(command, "bt\n", command_length)) {
|
|
|
|
command_backtrace(process);
|
|
|
|
} else if (0 == strncmp(command, "cont\n", command_length)) {
|
|
|
|
command_cont(process);
|
|
|
|
wait = 1;
|
|
|
|
} else if (0 == strncmp(command, "kill\n", command_length)) {
|
|
|
|
command_kill(process);
|
|
|
|
wait = 1;
|
|
|
|
} else {
|
|
|
|
printf("Unknown command: %.*s", command_length, command);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wait) {
|
|
|
|
int wstatus;
|
|
|
|
int cpid = waitpid(process.pid, &wstatus, 0);
|
|
|
|
|
|
|
|
if (cpid != 0) {
|
|
|
|
if (WIFEXITED(wstatus)) {
|
|
|
|
int status = WEXITSTATUS(wstatus);
|
|
|
|
printf("Child terminated normally with status %d\n", status);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (WIFSIGNALED(wstatus)) {
|
|
|
|
int signal = WTERMSIG(wstatus);
|
|
|
|
printf("Child terminated by signal %d (%s)\n", signal, strsignal(signal));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (WIFSTOPPED(wstatus)) {
|
|
|
|
int signal = WSTOPSIG(wstatus);
|
|
|
|
printf("Child stopped by signal %d (%s)\n", signal, strsignal(signal));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (WIFCONTINUED(wstatus)) {
|
|
|
|
printf("Child continued by SIGCONT\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(last_command, 0, max_command_length);
|
|
|
|
memcpy(last_command, command, command_length);
|
|
|
|
|
|
|
|
printf("> ");
|
|
|
|
}
|
|
|
|
|
|
|
|
return(0);
|
|
|
|
}
|