From: Dmitry V. Levin Date: Wed, 8 Jul 2015 14:10:56 +0000 (+0000) Subject: Implement RVAL_DECODED flag X-Git-Tag: v4.11~482 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=204c2bc9cb50daf4d3c8b5067a57c071ef55dfc4;p=strace Implement RVAL_DECODED flag Implement a method for "on entering" parsers to return "done with decoding" information to their callers. If a syscall parser called from trace_syscall_entering returns a value with RVAL_DECODED bit set, record this value in tcp->sys_func_rval and use it in trace_syscall_exiting instead of calling the parser on exiting syscall. If an ioctl parser returned RVAL_DECODED, this would tell SYS_FUNC(ioctl) that the decoding is finished but fallback printing of the ioctl command argument is needed, while e.g. RVAL_DONE+1 would mean that the decoding is finished and no fallback decoding is needed. * defs.h (struct tcb): Add sys_func_rval. (RVAL_DECODED): New macro. * syscall.c (trace_syscall_entering): Initialize tcp->sys_func_rval along with setting TCB_INSYSCALL flag. (trace_syscall_exiting): Use tcp->sys_func_rval instead of calling tcp->s_ent->sys_func when the former has RVAL_DECODED flag set. Reset tcp->sys_func_rval along with clearing TCB_INSYSCALL flag. * ioctl.c (sys_ioctl): Set RVAL_DECODED flag on exiting. Print ioctl argument iff RVAL_DECODED is set and fallback decoding is requested. --- diff --git a/defs.h b/defs.h index 6fcb5186..29b98efe 100644 --- a/defs.h +++ b/defs.h @@ -274,6 +274,7 @@ struct tcb { #if SUPPORTED_PERSONALITIES > 1 unsigned int currpers; /* Personality at the time of scno update */ #endif + int sys_func_rval; /* Syscall entry parser's return value */ int curcol; /* Output column for this process */ FILE *outf; /* Output file for this process */ const char *auxstr; /* Auxiliary info from syscall (see RVAL_STR) */ @@ -368,6 +369,8 @@ extern const struct xlat whence_codes[]; #define RVAL_STR 020 /* Print `auxstr' field after return val */ #define RVAL_NONE 040 /* Print nothing */ +#define RVAL_DECODED 0100 /* syscall decoding finished */ + #define TRACE_FILE 001 /* Trace file-related syscalls. */ #define TRACE_IPC 002 /* Trace IPC-related syscalls. */ #define TRACE_NETWORK 004 /* Trace network-related syscalls. */ diff --git a/ioctl.c b/ioctl.c index d10e45d2..284828a5 100644 --- a/ioctl.c +++ b/ioctl.c @@ -272,6 +272,7 @@ ioctl_decode(struct tcb *tcp) SYS_FUNC(ioctl) { const struct_ioctlent *iop; + int ret; if (entering(tcp)) { printfd(tcp, tcp->u_arg[0]); @@ -286,14 +287,22 @@ SYS_FUNC(ioctl) ioctl_print_code(tcp->u_arg[1]); } } - ioctl_decode(tcp); + ret = ioctl_decode(tcp); + } else { + ret = ioctl_decode(tcp) | RVAL_DECODED; } - else { - int ret = ioctl_decode(tcp); - if (!ret) - tprintf(", %#lx", tcp->u_arg[2]); + + if (ret & RVAL_DECODED) { + ret &= ~RVAL_DECODED; + if (ret) + --ret; else - return ret - 1; + tprintf(", %#lx", tcp->u_arg[2]); + ret |= RVAL_DECODED; + } else { + if (ret) + --ret; } - return 0; + + return ret; } diff --git a/syscall.c b/syscall.c index 0ab424c1..ea74e353 100644 --- a/syscall.c +++ b/syscall.c @@ -814,6 +814,7 @@ trace_syscall_entering(struct tcb *tcp) || (tracing_paths && !pathtrace_match(tcp)) ) { tcp->flags |= TCB_INSYSCALL | TCB_FILTERED; + tcp->sys_func_rval = 0; return 0; } @@ -844,6 +845,7 @@ trace_syscall_entering(struct tcb *tcp) fflush(tcp->outf); ret: tcp->flags |= TCB_INSYSCALL; + tcp->sys_func_rval = res; /* Measure the entrance time as late as possible to avoid errors. */ if (Tflag || cflag) gettimeofday(&tcp->etime, NULL); @@ -910,6 +912,7 @@ trace_syscall_exiting(struct tcb *tcp) tprints("= ? \n"); line_ended(); tcp->flags &= ~TCB_INSYSCALL; + tcp->sys_func_rval = 0; return res; } tcp->s_prev_ent = tcp->s_ent; @@ -928,7 +931,10 @@ trace_syscall_exiting(struct tcb *tcp) */ if (not_failing_only && tcp->u_error) goto ret; /* ignore failed syscalls */ - sys_res = tcp->s_ent->sys_func(tcp); + if (tcp->sys_func_rval & RVAL_DECODED) + sys_res = tcp->sys_func_rval; + else + sys_res = tcp->s_ent->sys_func(tcp); } tprints(") "); @@ -1081,6 +1087,7 @@ trace_syscall_exiting(struct tcb *tcp) ret: tcp->flags &= ~TCB_INSYSCALL; + tcp->sys_func_rval = 0; return 0; }