Don't queue sysret events
- That's because on s390x, we use process call stack to actually figure out
whether it's a syscall/sysret event, and if it's sysret, then what syscall
it returns from. So we need to keep the stack in sync with reality.
diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c
index 5337cb0..b9536c3 100644
--- a/sysdeps/linux-gnu/trace.c
+++ b/sysdeps/linux-gnu/trace.c
@@ -168,6 +168,7 @@
int got_event : 1;
int delivered : 1;
int vforked : 1;
+ int sysret : 1;
} * pids;
struct pid_set {
@@ -380,7 +381,8 @@
if (!self->exiting) {
for (i = 0; i < self->pids.count; ++i)
if (self->pids.tasks[i].pid != 0
- && self->pids.tasks[i].delivered)
+ && (self->pids.tasks[i].delivered
+ || self->pids.tasks[i].sysret))
continue_process(self->pids.tasks[i].pid);
continue_process(self->task_enabling_breakpoint->pid);
destroy_event_handler(leader);
@@ -595,6 +597,17 @@
if (event_exit_p(event) && task_info != NULL)
task_info->pid = 0;
+ /* Always handle sysrets. Whether sysret occurred and what
+ * sys it rets from may need to be determined based on process
+ * stack, so we need to keep that in sync with reality. Note
+ * that we don't continue the process after the sysret is
+ * handled. See continue_after_syscall. */
+ if (event != NULL && event->type == EVENT_SYSRET) {
+ debug(1, "%d LT_EV_SYSRET", event->proc->pid);
+ event_to_queue = 0;
+ task_info->sysret = 1;
+ }
+
switch (state) {
case psh_stopping:
/* If everyone is stopped, singlestep. */
@@ -905,6 +918,17 @@
change_process_leader(proc, proc->parent->leader);
}
+void
+continue_after_syscall(Process * proc, int sysnum, int ret_p)
+{
+ /* Don't continue if we are mid-stopping. */
+ if (ret_p && (proc->event_handler != NULL
+ || (proc->leader != NULL
+ && proc->leader->event_handler != NULL)))
+ return;
+ continue_process(proc->pid);
+}
+
/* If ltrace gets SIGINT, the processes directly or indirectly run by
* ltrace get it too. We just have to wait long enough for the signal
* to be delivered and the process terminated, which we notice and