ptrace: fix delivery of final signals, improve dbg
This commit is contained in:
parent
4c04e01f61
commit
187b331e9e
51
apps/dbg.c
51
apps/dbg.c
@ -13,6 +13,7 @@
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/signal.h>
|
||||
@ -422,6 +423,32 @@ static void attempt_backtrace(pid_t pid, struct regs * regs) {
|
||||
}
|
||||
}
|
||||
|
||||
static int imatch(const char * a, const char * b) {
|
||||
do {
|
||||
if (!*a && !*b) return 1;
|
||||
if (tolower(*a) != tolower(*b)) return 0;
|
||||
a++;
|
||||
b++;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
static int signal_from_string(const char * str) {
|
||||
if (isdigit(*str)) {
|
||||
return strtoul(str,NULL,0);
|
||||
} else if (str[0] == 'S' && str[1] == 'I' && str[2] == 'G') {
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
if (signal_names[i] && imatch(signal_names[i], str)) return i;
|
||||
}
|
||||
return -1;
|
||||
} else {
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
if (signal_names[i] && imatch(signal_names[i]+3, str)) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void show_commandline(pid_t pid, int status, struct regs * regs) {
|
||||
|
||||
@ -492,6 +519,18 @@ static void show_commandline(pid_t pid, int status, struct regs * regs) {
|
||||
if (signum == SIGINT) signum = 0;
|
||||
ptrace(PTRACE_CONT, pid, NULL, (void*)(uintptr_t)signum);
|
||||
return;
|
||||
} else if (!strcmp(buf, "signal")) {
|
||||
if (!arg) {
|
||||
fprintf(stderr, "'signal' needs an argument\n");
|
||||
continue;
|
||||
}
|
||||
int signum = signal_from_string(arg);
|
||||
if (signum == -1) {
|
||||
fprintf(stderr, "'%s' is not a recognized signal\n", arg);
|
||||
continue;
|
||||
}
|
||||
ptrace(PTRACE_CONT, pid, NULL, (void*)(uintptr_t)signum);
|
||||
return;
|
||||
} else if (!strcmp(buf, "step") || !strcmp(buf,"s")) {
|
||||
int signum = WSTOPSIG(status);
|
||||
if (signum == SIGINT) signum = 0;
|
||||
@ -566,6 +605,16 @@ static void show_commandline(pid_t pid, int status, struct regs * regs) {
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
} else if (!strcmp(buf, "help")) {
|
||||
printf("commands:\n"
|
||||
" show (regs, libs)\n"
|
||||
" backtrace\n"
|
||||
" continue\n"
|
||||
" signal signum\n"
|
||||
" step\n"
|
||||
" poke addr byte\n"
|
||||
" print fmt addr\n");
|
||||
continue;
|
||||
} else {
|
||||
fprintf(stderr, "dbg: unrecognized command '%s'\n", buf);
|
||||
continue;
|
||||
@ -575,7 +624,7 @@ static void show_commandline(pid_t pid, int status, struct regs * regs) {
|
||||
_exitDebugger:
|
||||
if (binary_is_child) {
|
||||
fprintf(stderr, "Terminating child process '%d'.\n", pid);
|
||||
ptrace(PTRACE_CONT, pid, NULL, (void*)(uintptr_t)SIGKILL);
|
||||
ptrace(PTRACE_DETACH, pid, NULL, (void*)(uintptr_t)SIGKILL);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
@ -86,14 +86,38 @@ long ptrace_signal(int signal, int reason) {
|
||||
return signum;
|
||||
}
|
||||
|
||||
static void signal_and_continue(pid_t pid, process_t * tracee, int sig) {
|
||||
/* Unsuspend */
|
||||
__sync_and_and_fetch(&tracee->flags, ~(PROC_FLAG_SUSPENDED));
|
||||
|
||||
/* Does the process have a pending signal? */
|
||||
if ((tracee->status >> 8) & 0xFF && !(tracee->status >> 16)) {
|
||||
tracee->status = (sig << 8);
|
||||
make_process_ready(tracee);
|
||||
} else if (sig) {
|
||||
send_signal(pid, sig,1);
|
||||
} else {
|
||||
make_process_ready(tracee);
|
||||
}
|
||||
}
|
||||
|
||||
long ptrace_continue(pid_t pid, int sig) {
|
||||
process_t * tracee = process_from_pid(pid);
|
||||
if (!tracee || (tracee->tracer != this_core->current_process->id) || !(tracee->flags & PROC_FLAG_SUSPENDED)) return -ESRCH;
|
||||
|
||||
/* Unsuspend */
|
||||
__sync_and_and_fetch(&tracee->flags, ~(PROC_FLAG_SUSPENDED));
|
||||
tracee->status = (sig << 8);
|
||||
make_process_ready(tracee);
|
||||
signal_and_continue(pid,tracee,sig);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long ptrace_detach(pid_t pid, int sig) {
|
||||
process_t * tracee = process_from_pid(pid);
|
||||
if (!tracee || (tracee->tracer != this_core->current_process->id) || !(tracee->flags & PROC_FLAG_SUSPENDED)) return -ESRCH;
|
||||
|
||||
/* Mark us not the tracer. */
|
||||
tracee->tracer = 0;
|
||||
|
||||
signal_and_continue(pid,tracee,sig);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -200,6 +224,8 @@ long ptrace_handle(long request, pid_t pid, void * addr, void * data) {
|
||||
return ptrace_signals_only(pid);
|
||||
case PTRACE_SINGLESTEP:
|
||||
return ptrace_singlestep(pid,(uintptr_t)data);
|
||||
case PTRACE_DETACH:
|
||||
return ptrace_detach(pid,(uintptr_t)data);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user