]> granicus.if.org Git - strace/commitdiff
ioctl: add decoding for parametrized command names
authorGabriel Laskar <gabriel@lse.epita.fr>
Wed, 21 Jan 2015 22:35:27 +0000 (23:35 +0100)
committerDmitry V. Levin <ldv@altlinux.org>
Wed, 21 Jan 2015 23:10:38 +0000 (23:10 +0000)
Some ioctl commands from evdev, hiddev, mixer, uinput, spi, and joystick
are parametrized by a size or a number that are variable.  This change
implements printing of these parametrized ioctl command names.

* configure.ac (AC_CHECK_HEADERS): Add linux/input.h.
* defs.h (ioctl_decode_number): New prototype.
* io.c (sys_ioctl): Use ioctl_decode_number.
* ioctl.c (ioctl_decode_number): New function.
* xlat/evdev_abs.in: New file.
* xlat/evdev_ev.in: New file.

Signed-off-by: Gabriel Laskar <gabriel@lse.epita.fr>
configure.ac
defs.h
io.c
ioctl.c
xlat/evdev_abs.in [new file with mode: 0644]
xlat/evdev_ev.in [new file with mode: 0644]

index c2e64f1012bf636e97fb8e8ca3c1d41933724996..2359d49dc92f43e25f9053b8db804896b477081c 100644 (file)
@@ -223,6 +223,7 @@ AC_CHECK_HEADERS(m4_normalize([
        inttypes.h
        ioctls.h
        linux/falloc.h
+       linux/input.h
        linux/perf_event.h
        linux/ptrace.h
        linux/utsname.h
diff --git a/defs.h b/defs.h
index 33cdef0330a8acbcf9c11611085d6e689134e507..8d654a593079f3b0269c107f99dee3fbf09e8f1a 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -735,6 +735,7 @@ extern const struct_ioctlent *ioctl_lookup(const unsigned int);
 extern const struct_ioctlent *ioctl_next_match(const struct_ioctlent *);
 extern void ioctl_print_code(const unsigned int);
 extern int ioctl_decode(struct tcb *, const unsigned int, long);
+extern int ioctl_decode_command_number(const unsigned int);
 extern int block_ioctl(struct tcb *, const unsigned int, long);
 extern int loop_ioctl(struct tcb *, const unsigned int, long);
 extern int mtd_ioctl(struct tcb *, const unsigned int, long);
diff --git a/io.c b/io.c
index 2a36c000d001b5075d73ed9eadeea3ceb088dea2..6b24159ade0360f83d15397945053f85bbccb2a5 100644 (file)
--- a/io.c
+++ b/io.c
@@ -398,13 +398,16 @@ sys_ioctl(struct tcb *tcp)
        if (entering(tcp)) {
                printfd(tcp, tcp->u_arg[0]);
                tprints(", ");
-               iop = ioctl_lookup(tcp->u_arg[1]);
-               if (iop) {
-                       tprints(iop->symbol);
-                       while ((iop = ioctl_next_match(iop)))
-                               tprintf(" or %s", iop->symbol);
-               } else
-                       ioctl_print_code(tcp->u_arg[1]);
+               if (!ioctl_decode_command_number(tcp->u_arg[1])) {
+                       iop = ioctl_lookup(tcp->u_arg[1]);
+                       if (iop) {
+                               tprints(iop->symbol);
+                               while ((iop = ioctl_next_match(iop)))
+                                       tprintf(" or %s", iop->symbol);
+                       } else {
+                               ioctl_print_code(tcp->u_arg[1]);
+                       }
+               }
                ioctl_decode(tcp, tcp->u_arg[1], tcp->u_arg[2]);
        }
        else {
diff --git a/ioctl.c b/ioctl.c
index f9d570e8357172075d9e5556bf99a064a6fa7689..65786647ff119de17d34b52a5defce77486509dd 100644 (file)
--- a/ioctl.c
+++ b/ioctl.c
 #include <asm/ioctl.h>
 #include "xlat/ioctl_dirs.h"
 
+#ifdef HAVE_LINUX_INPUT_H
+# include <linux/input.h>
+#endif
+
+#include "xlat/evdev_abs.h"
+#include "xlat/evdev_ev.h"
+
 static int
 compare(const void *a, const void *b)
 {
@@ -77,6 +84,144 @@ ioctl_print_code(const unsigned int code)
                _IOC_TYPE(code), _IOC_NR(code), _IOC_SIZE(code));
 }
 
+static int
+evdev_decode_number(unsigned int arg)
+{
+       unsigned int nr = _IOC_NR(arg);
+
+       if (_IOC_DIR(arg) == _IOC_WRITE) {
+               if (nr >= 0xc0 && nr <= 0xc0 + 0x3f) {
+                       tprints("EVIOCSABS(");
+                       printxval(evdev_abs, nr - 0xc0, "EV_???");
+                       tprints(")");
+                       return 1;
+               }
+       }
+
+       if (_IOC_DIR(arg) != _IOC_READ)
+               return 0;
+
+       if (nr >= 0x20 && nr <= 0x20 + 0x1f) {
+               tprints("EVIOCGBIT(");
+               printxval(evdev_ev, nr - 0x20, "EV_???");
+               tprintf(", %u)", _IOC_SIZE(arg));
+               return 1;
+       } else if (nr >= 0x40 && nr <= 0x40 + 0x3f) {
+               tprints("EVIOCGABS(");
+               printxval(evdev_abs, nr - 0x40, "ABS_???");
+               tprints(")");
+               return 1;
+       }
+
+       switch (_IOC_NR(nr)) {
+               case 0x06:
+                       tprintf("EVIOCGNAME(%u)", _IOC_SIZE(arg));
+                       return 1;
+               case 0x07:
+                       tprintf("EVIOCGPHYS(%u)", _IOC_SIZE(arg));
+                       return 1;
+               case 0x08:
+                       tprintf("EVIOCGUNIQ(%u)", _IOC_SIZE(arg));
+                       return 1;
+               case 0x09:
+                       tprintf("EVIOCGPROP(%u)", _IOC_SIZE(arg));
+                       return 1;
+               case 0x0a:
+                       tprintf("EVIOCGMTSLOTS(%u)", _IOC_SIZE(arg));
+                       return 1;
+               case 0x18:
+                       tprintf("EVIOCGKEY(%u)", _IOC_SIZE(arg));
+                       return 1;
+               case 0x19:
+                       tprintf("EVIOCGLED(%u)", _IOC_SIZE(arg));
+                       return 1;
+               case 0x1a:
+                       tprintf("EVIOCGSND(%u)", _IOC_SIZE(arg));
+                       return 1;
+               case 0x1b:
+                       tprintf("EVIOCGSW(%u)", _IOC_SIZE(arg));
+                       return 1;
+               default:
+                       return 0;
+       }
+}
+
+static int
+hiddev_decode_number(unsigned int arg)
+{
+       if (_IOC_DIR(arg) == _IOC_READ) {
+               switch (_IOC_NR(arg)) {
+                       case 0x04:
+                               tprintf("HIDIOCGRAWNAME(%u)", _IOC_SIZE(arg));
+                               return 1;
+                       case 0x05:
+                               tprintf("HIDIOCGRAWPHYS(%u)", _IOC_SIZE(arg));
+                               return 1;
+                       case 0x06:
+                               tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(arg));
+                               return 1;
+                       case 0x12:
+                               tprintf("HIDIOCGPHYS(%u)", _IOC_SIZE(arg));
+                               return 1;
+                       default:
+                               return 0;
+               }
+       } else if (_IOC_DIR(arg) == (_IOC_READ | _IOC_WRITE)) {
+               switch (_IOC_NR(arg)) {
+                       case 0x06:
+                               tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(arg));
+                               return 1;
+                       case 0x07:
+                               tprintf("HIDIOCGFEATURE(%u)", _IOC_SIZE(arg));
+                               return 1;
+                       default:
+                               return 0;
+               }
+       }
+
+       return 0;
+}
+
+int
+ioctl_decode_command_number(unsigned int arg)
+{
+       switch (_IOC_TYPE(arg)) {
+               case 'E':
+                       return evdev_decode_number(arg);
+               case 'H':
+                       return hiddev_decode_number(arg);
+               case 'M':
+                       if (_IOC_DIR(arg) == _IOC_WRITE) {
+                               tprintf("MIXER_WRITE(%u)", _IOC_NR(arg));
+                               return 1;
+                       } else if (_IOC_DIR(arg) == _IOC_READ) {
+                               tprintf("MIXER_READ(%u)", _IOC_NR(arg));
+                               return 1;
+                       }
+                       return 0;
+               case 'U':
+                       if (_IOC_DIR(arg) == _IOC_READ && _IOC_NR(arg) == 0x2c) {
+                               tprintf("UI_GET_SYSNAME(%u)", _IOC_SIZE(arg));
+                               return 1;
+                       }
+                       return 0;
+               case 'j':
+                       if (_IOC_DIR(arg) == _IOC_READ && _IOC_NR(arg) == 0x13) {
+                               tprintf("JSIOCGNAME(%u)", _IOC_SIZE(arg));
+                               return 1;
+                       }
+                       return 0;
+               case 'k':
+                       if (_IOC_DIR(arg) == _IOC_WRITE && _IOC_NR(arg) == 0) {
+                               tprintf("SPI_IOC_MESSAGE(%u)", _IOC_SIZE(arg));
+                               return 1;
+                       }
+                       return 0;
+               default:
+                       return 0;
+       }
+}
+
 int
 ioctl_decode(struct tcb *tcp, unsigned int code, long arg)
 {
diff --git a/xlat/evdev_abs.in b/xlat/evdev_abs.in
new file mode 100644 (file)
index 0000000..ec8c2f4
--- /dev/null
@@ -0,0 +1,41 @@
+ABS_X
+ABS_Y
+ABS_Z
+ABS_RX
+ABS_RY
+ABS_RZ
+ABS_THROTTLE
+ABS_RUDDER
+ABS_WHEEL
+ABS_GAS
+ABS_BRAKE
+ABS_HAT0X
+ABS_HAT0Y
+ABS_HAT1X
+ABS_HAT1Y
+ABS_HAT2X
+ABS_HAT2Y
+ABS_HAT3X
+ABS_HAT3Y
+ABS_PRESSURE
+ABS_DISTANCE
+ABS_TILT_X
+ABS_TILT_Y
+ABS_TOOL_WIDTH
+ABS_VOLUME
+ABS_MISC
+ABS_MT_SLOT
+ABS_MT_TOUCH_MAJOR
+ABS_MT_TOUCH_MINOR
+ABS_MT_WIDTH_MAJOR
+ABS_MT_WIDTH_MINOR
+ABS_MT_ORIENTATION
+ABS_MT_POSITION_X
+ABS_MT_POSITION_Y
+ABS_MT_TOOL_TYPE
+ABS_MT_BLOB_ID
+ABS_MT_TRACKING_ID
+ABS_MT_PRESSURE
+ABS_MT_DISTANCE
+ABS_MT_TOOL_X
+ABS_MT_TOOL_Y
diff --git a/xlat/evdev_ev.in b/xlat/evdev_ev.in
new file mode 100644 (file)
index 0000000..0974b59
--- /dev/null
@@ -0,0 +1,12 @@
+EV_SYN
+EV_KEY
+EV_REL
+EV_ABS
+EV_MSC
+EV_SW
+EV_LED
+EV_SND
+EV_REP
+EV_FF
+EV_PWR
+EV_FF_STATUS