From 2f948b92316e30c5e19f413b863387dbb2de2451 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Sat, 26 Nov 2016 23:45:05 +0000 Subject: [PATCH] Set PTRACE_O_TRACEEXIT option and handle PTRACE_EVENT_EXIT events Do not assume that some syscalls do not generate syscall-exit-stops. When syscalls fail for any reason they may generate syscall-exit-stops. The solution is to wait for an actual exit reported by PTRACE_EVENT_EXIT and print the end of unfinished exiting syscall properly. * exit.c: Remove. * Makefile.am (strace_SOURCES): Remove exit.c. * linux/dummy.h (sys_exit): Alias to printargs_d. * strace.c (ptrace_setoptions): Add PTRACE_O_TRACEEXIT bit. (print_event_exit): New function. (trace): Use it in case of PTRACE_EVENT_EXIT. * syscall.c (trace_syscall_entering): Remove special handling of SEN_exit. --- Makefile.am | 1 - exit.c | 15 -------------- linux/dummy.h | 1 + strace.c | 55 +++++++++++++++++++++++++++++++++++++++++++++------ syscall.c | 2 +- 5 files changed, 51 insertions(+), 23 deletions(-) delete mode 100644 exit.c diff --git a/Makefile.am b/Makefile.am index 97276f12..80e80fcc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -104,7 +104,6 @@ strace_SOURCES = \ evdev.c \ eventfd.c \ execve.c \ - exit.c \ fadvise.c \ fallocate.c \ fanotify.c \ diff --git a/exit.c b/exit.c deleted file mode 100644 index b10f90c2..00000000 --- a/exit.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "defs.h" - -SYS_FUNC(exit) -{ - if (exiting(tcp)) { - error_msg("%s returned!", tcp->s_ent->sys_name); - return -1; - } - /* special case: we stop tracing this process, finish line now */ - tprintf("%ld) ", tcp->u_arg[0]); - tabto(); - tprints("= ?\n"); - line_ended(); - return 0; -} diff --git a/linux/dummy.h b/linux/dummy.h index 49dcf16a..4cb9ad46 100644 --- a/linux/dummy.h +++ b/linux/dummy.h @@ -123,6 +123,7 @@ #define sys_alarm printargs_u /* printargs_d does the right thing */ +#define sys_exit printargs_d #define sys_getpgid printargs_d #define sys_getsid printargs_d #define sys_nice printargs_d diff --git a/strace.c b/strace.c index 95e9d143..5e081ab4 100644 --- a/strace.c +++ b/strace.c @@ -80,7 +80,8 @@ const unsigned int syscall_trap_sig = SIGTRAP | 0x80; cflag_t cflag = CFLAG_NONE; unsigned int followfork = 0; -unsigned int ptrace_setoptions = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC; +unsigned int ptrace_setoptions = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC + | PTRACE_O_TRACEEXIT; unsigned int xflag = 0; bool debug_flag = 0; bool Tflag = 0; @@ -2158,6 +2159,43 @@ startup_tcb(struct tcb *tcp) } } +static void +print_event_exit(struct tcb *tcp) +{ + if (entering(tcp) || filtered(tcp) || hide_log(tcp) + || cflag == CFLAG_ONLY_STATS) { + return; + } + + if (followfork < 2 && printing_tcp && printing_tcp != tcp + && printing_tcp->curcol != 0) { + current_tcp = printing_tcp; + tprints(" \n"); + fflush(printing_tcp->outf); + printing_tcp->curcol = 0; + current_tcp = tcp; + } + + if ((followfork < 2 && printing_tcp != tcp) + || (tcp->flags & TCB_REPRINT)) { + tcp->flags &= ~TCB_REPRINT; + printleader(tcp); + tprintf("<... %s resumed>", tcp->s_ent->sys_name); + } + + if (!(tcp->sys_func_rval & RVAL_DECODED)) { + /* + * The decoder has probably decided to print something + * on exiting syscall which is not going to happen. + */ + tprints(" "); + } + tprints(") "); + tabto(); + tprints("= ?\n"); + line_ended(); +} + /* Returns true iff the main trace loop has to continue. */ static bool trace(void) @@ -2308,10 +2346,14 @@ trace(void) sig = WSTOPSIG(status); - if (event != 0) { - /* Ptrace event */ + switch (event) { + case 0: + break; + case PTRACE_EVENT_EXIT: + print_event_exit(tcp); + goto restart_tracee_with_sig_0; #if USE_SEIZE - if (event == PTRACE_EVENT_STOP) { + case PTRACE_EVENT_STOP: /* * PTRACE_INTERRUPT-stop or group-stop. * PTRACE_INTERRUPT-stop has sig == SIGTRAP here. @@ -2324,9 +2366,10 @@ trace(void) stopped = true; goto show_stopsig; } - } + /* fall through */ #endif - goto restart_tracee_with_sig_0; + default: + goto restart_tracee_with_sig_0; } /* diff --git a/syscall.c b/syscall.c index e5ab44a5..12962e2c 100644 --- a/syscall.c +++ b/syscall.c @@ -1148,7 +1148,7 @@ trace_syscall_entering(struct tcb *tcp) printleader(tcp); tprintf("%s(", tcp->s_ent->sys_name); - if ((tcp->qual_flg & QUAL_RAW) && SEN_exit != tcp->s_ent->sen) + if (tcp->qual_flg & QUAL_RAW) res = printargs(tcp); else res = tcp->s_ent->sys_func(tcp); -- 2.40.0