]> granicus.if.org Git - strace/commitdiff
Implement RVAL_DECODED flag
authorDmitry V. Levin <ldv@altlinux.org>
Wed, 8 Jul 2015 14:10:56 +0000 (14:10 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Thu, 9 Jul 2015 01:08:01 +0000 (01:08 +0000)
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.

defs.h
ioctl.c
syscall.c

diff --git a/defs.h b/defs.h
index 6fcb5186a025fa9d9bcf94898235d19e711745fd..29b98efe2ea8c0d8ede98eaeea0784c222a81680 100644 (file)
--- 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 d10e45d294cc53cf491d75564566eceb86df9923..284828a5a468db2e042a19957e8adc28e190c5ee 100644 (file)
--- 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;
 }
index 0ab424c1a46179bd4e9248a98b1d81f113591aec..ea74e353f8a1c46dfb9d80736f4a2114a0b72d16 100644 (file)
--- 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("= ? <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;
 }