This change removes the trace_syscall function. Now, the code that uses syscall.c trace functions is expected to check whether it is a syscall entry or exit (with entering(tcp)/exiting(tcp)) itself, and then make an appropriate sequence of function calls.
* defs.h: Change comment on TCB_INSYSCALL, remove the prototype of trace_syscall, add prototypes for the new functions. * strace.c (trace_syscall): A static replacement for old trace_syscall. * syscall.c (trace_syscall): Remove. (trace_syscall_entering): Split into... (syscall_entering_decode, syscall_entering_trace, syscall_entering_finish): ...new functions. (trace_syscall_exiting): Split into... (syscall_exiting_decode, syscall_exiting_trace, syscall_exiting_finish): ...new functions. --- defs.h | 26 ++++++++------- strace.c | 24 ++++++++++++++ syscall.c | 110 ++++++++++++++++++++++++++++++++++---------------------------- 3 files changed, 100 insertions(+), 60 deletions(-) diff --git a/defs.h b/defs.h index 70ff07bc..f471055d 100644 --- a/defs.h +++ b/defs.h @@ -249,17 +249,13 @@ struct tcb { /* * Are we in system call entry or in syscall exit? * - * This bit is set after all syscall entry processing is done. - * Therefore, this bit will be set when next ptrace stop occurs, - * which should be syscall exit stop. Other stops which are possible - * directly after syscall entry (death, ptrace event stop) - * are simpler and handled without calling trace_syscall(), therefore - * the places where TCB_INSYSCALL can be set but we aren't in syscall stop - * are limited to trace(), this condition is never observed in trace_syscall() - * and below. - * The bit is cleared after all syscall exit processing is done. + * This bit is set in syscall_entering_finish() and cleared in + * syscall_exiting_finish(). + * Other stops which are possible directly after syscall entry (death, ptrace + * event stop) are handled without calling syscall_{entering,exiting}_*(). * - * Use entering(tcp) / exiting(tcp) to check this bit to make code more readable. + * Use entering(tcp) / exiting(tcp) to check this bit to make code more + * readable. */ #define TCB_INSYSCALL 0x04 #define TCB_ATTACHED 0x08 /* We attached to it already */ @@ -408,7 +404,15 @@ extern int read_int_from_file(const char *, int *); extern void set_sortby(const char *); extern void set_overhead(int); extern void print_pc(struct tcb *); -extern int trace_syscall(struct tcb *, unsigned int *); + +extern int syscall_entering_decode(struct tcb *); +extern int syscall_entering_trace(struct tcb *, unsigned int *); +extern void syscall_entering_finish(struct tcb *, int); + +extern int syscall_exiting_decode(struct tcb *, struct timeval *); +extern int syscall_exiting_trace(struct tcb *, struct timeval, int); +extern void syscall_exiting_finish(struct tcb *); + extern void count_syscall(struct tcb *, const struct timeval *); extern void call_summary(FILE *); diff --git a/strace.c b/strace.c index 6d5c29aa..1870bab8 100644 --- a/strace.c +++ b/strace.c @@ -2459,6 +2459,30 @@ next_event(int *pstatus, siginfo_t *si) } } +static int +trace_syscall(struct tcb *tcp, unsigned int *sig) +{ + if (entering(tcp)) { + int res = syscall_entering_decode(tcp); + switch (res) { + case 0: + return 0; + case 1: + res = syscall_entering_trace(tcp, sig); + } + syscall_entering_finish(tcp, res); + return res; + } else { + struct timeval tv = {}; + int res = syscall_exiting_decode(tcp, &tv); + if (res != 0) { + res = syscall_exiting_trace(tcp, tv, res); + } + syscall_exiting_finish(tcp); + return res; + } +} + /* Returns true iff the main trace loop has to continue. */ static bool dispatch_event(enum trace_event ret, int *pstatus, siginfo_t *si) diff --git a/syscall.c b/syscall.c index a34f640e..0250540c 100644 --- a/syscall.c +++ b/syscall.c @@ -651,25 +651,29 @@ tamper_with_syscall_exiting(struct tcb *tcp) return 0; } -static int -trace_syscall_entering(struct tcb *tcp, unsigned int *sig) +/* + * Returns: + * 0: "ignore this ptrace stop", bail out silently. + * 1: ok, decoded; call + * syscall_entering_finish(tcp, syscall_entering_trace(tcp, ...)). + * other: error; call syscall_entering_finish(tcp, res), where res is the value + * returned. + */ +int +syscall_entering_decode(struct tcb *tcp) { int res = get_scno(tcp); if (res == 0) return res; - int scno_good = res; - if (res == 1) - res = get_syscall_args(tcp); - - if (res != 1) { + if (res != 1 || (res = get_syscall_args(tcp)) != 1) { printleader(tcp); tprintf("%s(", scno_good == 1 ? tcp->s_ent->sys_name : "????"); /* * " <unavailable>" will be added later by the code which * detects ptrace errors. */ - goto ret; + return res; } #ifdef LINUX_MIPSO32 @@ -692,6 +696,12 @@ trace_syscall_entering(struct tcb *tcp, unsigned int *sig) } #endif + return 1; +} + +int +syscall_entering_trace(struct tcb *tcp, unsigned int *sig) +{ /* Restrain from fault injection while the trace executes strace code. */ if (hide_log(tcp)) { tcp->qual_flg &= ~QUAL_INJECT; @@ -710,24 +720,21 @@ trace_syscall_entering(struct tcb *tcp, unsigned int *sig) if (!(tcp->qual_flg & QUAL_TRACE) || (tracing_paths && !pathtrace_match(tcp)) ) { - tcp->flags |= TCB_INSYSCALL | TCB_FILTERED; - tcp->sys_func_rval = 0; + tcp->flags |= TCB_FILTERED; return 0; } tcp->flags &= ~TCB_FILTERED; if (hide_log(tcp)) { - res = 0; - goto ret; + return 0; } if (tcp->qual_flg & QUAL_INJECT) tamper_with_syscall_entering(tcp, sig); if (cflag == CFLAG_ONLY_STATS) { - res = 0; - goto ret; + return 0; } #ifdef USE_LIBUNWIND @@ -739,19 +746,20 @@ trace_syscall_entering(struct tcb *tcp, unsigned int *sig) printleader(tcp); tprintf("%s(", tcp->s_ent->sys_name); - if (tcp->qual_flg & QUAL_RAW) - res = printargs(tcp); - else - res = tcp->s_ent->sys_func(tcp); - + int res = (tcp->qual_flg & QUAL_RAW) + ? printargs(tcp) : tcp->s_ent->sys_func(tcp); fflush(tcp->outf); - ret: + return res; +} + +void +syscall_entering_finish(struct tcb *tcp, int res) +{ tcp->flags |= TCB_INSYSCALL; tcp->sys_func_rval = res; /* Measure the entrance time as late as possible to avoid errors. */ - if (Tflag || cflag) + if ((Tflag || cflag) && !filtered(tcp)) gettimeofday(&tcp->etime, NULL); - return res; } static bool @@ -760,14 +768,20 @@ syscall_tampered(struct tcb *tcp) return tcp->flags & TCB_TAMPERED; } -static int -trace_syscall_exiting(struct tcb *tcp) +/* Returns: + * 0: "bail out". + * 1: ok. + * -1: error in one of ptrace ops. + * + * If not 0, call syscall_exiting_trace(tcp, res), where res is the return + * value. Anyway, call syscall_exiting_finish(tcp) then. + */ +int +syscall_exiting_decode(struct tcb *tcp, struct timeval *ptv) { - struct timeval tv; - /* Measure the exit time as early as possible to avoid errors. */ if ((Tflag || cflag) && !(filtered(tcp) || hide_log(tcp))) - gettimeofday(&tv, NULL); + gettimeofday(ptv, NULL); #ifdef USE_LIBUNWIND if (stack_trace_enabled) { @@ -777,21 +791,25 @@ trace_syscall_exiting(struct tcb *tcp) #endif if (filtered(tcp) || hide_log(tcp)) - goto ret; + return 0; get_regs(tcp->pid); #if SUPPORTED_PERSONALITIES > 1 update_personality(tcp, tcp->currpers); #endif - int res = (get_regs_error ? -1 : get_syscall_result(tcp)); + return get_regs_error ? -1 : get_syscall_result(tcp); +} +int +syscall_exiting_trace(struct tcb *tcp, struct timeval tv, int res) +{ if (syserror(tcp) && syscall_tampered(tcp)) tamper_with_syscall_exiting(tcp); if (cflag) { count_syscall(tcp, &tv); if (cflag == CFLAG_ONLY_STATS) { - goto ret; + return 0; } } @@ -818,9 +836,6 @@ trace_syscall_exiting(struct tcb *tcp) tabto(); tprints("= ? <unavailable>\n"); line_ended(); - tcp->flags &= ~(TCB_INSYSCALL | TCB_TAMPERED); - tcp->sys_func_rval = 0; - free_tcb_priv_data(tcp); return res; } tcp->s_prev_ent = tcp->s_ent; @@ -838,7 +853,7 @@ trace_syscall_exiting(struct tcb *tcp) * is not shown at all. */ if (not_failing_only && tcp->u_error) - goto ret; /* ignore failed syscalls */ + return 0; /* ignore failed syscalls */ if (tcp->sys_func_rval & RVAL_DECODED) sys_res = tcp->sys_func_rval; else @@ -995,19 +1010,15 @@ trace_syscall_exiting(struct tcb *tcp) if (stack_trace_enabled) unwind_print_stacktrace(tcp); #endif - - ret: - tcp->flags &= ~(TCB_INSYSCALL | TCB_TAMPERED); - tcp->sys_func_rval = 0; - free_tcb_priv_data(tcp); return 0; } -int -trace_syscall(struct tcb *tcp, unsigned int *signo) +void +syscall_exiting_finish(struct tcb *tcp) { - return exiting(tcp) ? - trace_syscall_exiting(tcp) : trace_syscall_entering(tcp, signo); + tcp->flags &= ~(TCB_INSYSCALL | TCB_TAMPERED); + tcp->sys_func_rval = 0; + free_tcb_priv_data(tcp); } bool @@ -1230,10 +1241,11 @@ free_sysent_buf(void *ptr) /* * Returns: - * 0: "ignore this ptrace stop", bail out of trace_syscall_entering() silently. - * 1: ok, continue in trace_syscall_entering(). - * other: error, trace_syscall_entering() should print error indicator - * ("????" etc) and bail out. + * 0: "ignore this ptrace stop", syscall_entering_decode() should return a "bail + * out silently" code. + * 1: ok, continue in syscall_entering_decode(). + * other: error, syscall_entering_decode() should print error indicator + * ("????" etc) and return an appropriate code. */ int get_scno(struct tcb *tcp) @@ -1277,8 +1289,8 @@ static int get_syscall_result_regs(struct tcb *); #endif /* Returns: - * 1: ok, continue in trace_syscall_exiting(). - * -1: error, trace_syscall_exiting() should print error indicator + * 1: ok, continue in syscall_exiting_trace(). + * -1: error, syscall_exiting_trace() should print error indicator * ("????" etc) and bail out. */ static int -- 2.11.0 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel