]> granicus.if.org Git - strace/commitdiff
ioctl: allow to stop decoding number
authorGabriel Laskar <gabriel@lse.epita.fr>
Fri, 4 Dec 2015 00:07:33 +0000 (01:07 +0100)
committerDmitry V. Levin <ldv@altlinux.org>
Fri, 4 Dec 2015 18:05:38 +0000 (18:05 +0000)
For some ioctls, like from drm, the identification of the correct ioctl
is done by custom code.  Specifying IOCTL_NUMBER_STOP_LOOKUP on
return of ioctl_decode_command_number() disables further calls to
ioctl_lookup().

* defs.h (IOCTL_NUMBER_UNKNOWN, IOCTL_NUMBER_HANDLED,
IOCTL_NUMBER_STOP_LOOKUP): Add macros representing ioctl number state
decoding.
* ioctl.c (SYS_FUNC(ioctl)): Skip ioctl_lookup() when
ioctl_decode_command_number() returns a value with
IOCTL_NUMBER_STOP_LOOKUP flag is set.

Suggested-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
Signed-off-by: Gabriel Laskar <gabriel@lse.epita.fr>
Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
defs.h
ioctl.c

diff --git a/defs.h b/defs.h
index 5086e1d3afd9da3c18a45bb6e981d3191dd42480..d0bef9416b7899cf77ba3b6eb1148ee1b992d554 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -450,6 +450,10 @@ extern const struct xlat whence_codes[];
 #define STACKTRACE_CAPTURE_ON_ENTER 01000 /* Capture stacktrace on "entering" stage */
 #define TRACE_INDIRECT_SUBCALL 02000   /* Syscall is an indirect socket/ipc subcall. */
 
+#define IOCTL_NUMBER_UNKNOWN 0
+#define IOCTL_NUMBER_HANDLED 1
+#define IOCTL_NUMBER_STOP_LOOKUP 010
+
 #define indirect_ipccall(tcp) (tcp->s_ent->sys_flags & TRACE_INDIRECT_SUBCALL)
 
 #if defined(ARM) || defined(AARCH64) \
diff --git a/ioctl.c b/ioctl.c
index adce9867fd87901eeee46c25a1d7e6132f70666c..f70dc44e4c8cefdf82a401fded01a299df753b27 100644 (file)
--- a/ioctl.c
+++ b/ioctl.c
@@ -278,15 +278,17 @@ SYS_FUNC(ioctl)
                printfd(tcp, tcp->u_arg[0]);
                tprints(", ");
                ret = ioctl_decode_command_number(tcp);
-               iop = ioctl_lookup(tcp->u_arg[1]);
-               if (iop) {
-                       if (ret)
-                               tprints(" or ");
-                       tprints(iop->symbol);
-                       while ((iop = ioctl_next_match(iop)))
-                               tprintf(" or %s", iop->symbol);
-               } else if (!ret) {
-                       ioctl_print_code(tcp->u_arg[1]);
+               if (!(ret & IOCTL_NUMBER_STOP_LOOKUP)) {
+                       iop = ioctl_lookup(tcp->u_arg[1]);
+                       if (iop) {
+                               if (ret)
+                                       tprints(" or ");
+                               tprints(iop->symbol);
+                               while ((iop = ioctl_next_match(iop)))
+                                       tprintf(" or %s", iop->symbol);
+                       } else if (!ret) {
+                               ioctl_print_code(tcp->u_arg[1]);
+                       }
                }
                ret = ioctl_decode(tcp);
        } else {