diff options
author | Petr Machata <pmachata@redhat.com> | 2012-04-15 04:35:48 +0200 |
---|---|---|
committer | Petr Machata <pmachata@redhat.com> | 2012-04-19 01:51:32 +0200 |
commit | 1e2a4dd274ebb612e0cfa5c83ef081e5846aa949 (patch) | |
tree | ed70790e6a5398d82efcd85872c2caac9824ad90 /sysdeps/linux-gnu/trace.c | |
parent | abfe118271cd45581f33f71b0cf0fddc3a2e1b05 (diff) | |
download | ltrace-1e2a4dd274ebb612e0cfa5c83ef081e5846aa949.tar.gz |
Expose on_all_stopped hooks for linux stopping handler
Diffstat (limited to 'sysdeps/linux-gnu/trace.c')
-rw-r--r-- | sysdeps/linux-gnu/trace.c | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c index 18e9bfb..8438aa8 100644 --- a/sysdeps/linux-gnu/trace.c +++ b/sysdeps/linux-gnu/trace.c @@ -631,21 +631,30 @@ singlestep_error(struct process_stopping_handler *self, Event **eventp) { struct Process *teb = self->task_enabling_breakpoint; Breakpoint *sbp = self->breakpoint_being_enabled; - fprintf(stderr, "%d couldn't singlestep over %s (%p)\n", + fprintf(stderr, "%d couldn't continue when handling %s (%p) at %p\n", teb->pid, sbp->libsym != NULL ? sbp->libsym->name : NULL, - sbp->addr); + sbp->addr, get_instruction_pointer(teb)); delete_breakpoint(teb->leader, sbp->addr); post_singlestep(self, eventp); } +static int +pt_continue(struct process_stopping_handler *self) +{ + struct Process *teb = self->task_enabling_breakpoint; + debug(1, "PTRACE_CONT"); + return ptrace(PTRACE_CONT, teb->pid, 0, 0) != 0 ? -1 : 0; +} + static void -disable_and_singlestep(struct process_stopping_handler *self) +disable_and(struct process_stopping_handler *self, + int (*do_this)(struct process_stopping_handler *self)) { struct Process *teb = self->task_enabling_breakpoint; - debug(DEBUG_PROCESS, "all stopped, now SINGLESTEP %d", teb->pid); + debug(DEBUG_PROCESS, "all stopped, now singlestep/cont %d", teb->pid); if (self->breakpoint_being_enabled->enabled) disable_breakpoint(teb, self->breakpoint_being_enabled); - if (singlestep(self) < 0) { + if ((do_this)(self) < 0) { singlestep_error(self, &event); //goto psh_sinking; /* XXX FIME */ abort(); @@ -653,6 +662,18 @@ disable_and_singlestep(struct process_stopping_handler *self) self->state = psh_singlestep; } +void +linux_ptrace_disable_and_singlestep(struct process_stopping_handler *self) +{ + disable_and(self, &singlestep); +} + +void +linux_ptrace_disable_and_continue(struct process_stopping_handler *self) +{ + disable_and(self, &pt_continue); +} + /* This event handler is installed when we are in the process of * stopping the whole thread group to do the pointer re-enablement for * one of the threads. We pump all events to the queue for later @@ -732,9 +753,8 @@ process_stopping_on_event(struct event_handler *super, Event *event) } } - /* Essentially we don't care what event caused - * the thread to stop. We can do the - * re-enablement now. */ + /* Re-enable the breakpoint that we are + * stepping over. */ struct breakpoint *sbp = self->breakpoint_being_enabled; if (sbp->enabled) enable_breakpoint(teb, sbp); @@ -804,7 +824,7 @@ process_install_stopping_handler(struct Process *proc, struct breakpoint *sbp, return -1; if (as == NULL) - as = &disable_and_singlestep; + as = &linux_ptrace_disable_and_singlestep; if (ks == NULL) ks = &no; if (uw == NULL) |