aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/linux-gnu/trace.c
diff options
context:
space:
mode:
authorPetr Machata <pmachata@redhat.com>2012-04-15 04:35:48 +0200
committerPetr Machata <pmachata@redhat.com>2012-04-19 01:51:32 +0200
commit1e2a4dd274ebb612e0cfa5c83ef081e5846aa949 (patch)
treeed70790e6a5398d82efcd85872c2caac9824ad90 /sysdeps/linux-gnu/trace.c
parentabfe118271cd45581f33f71b0cf0fddc3a2e1b05 (diff)
downloadltrace-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.c38
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)