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.
This commit is contained in:
Дмитрий Левин 2015-07-08 14:10:56 +00:00
parent 746db06d91
commit 204c2bc9cb
3 changed files with 27 additions and 8 deletions

3
defs.h
View File

@ -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. */

23
ioctl.c
View File

@ -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;
}

View File

@ -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("= ? <unavailable>\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;
}