ioctl: add decoding for parametrized command names

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>
This commit is contained in:
Gabriel Laskar 2015-01-21 23:35:27 +01:00 committed by Dmitry V. Levin
parent 63630746ef
commit 6f9a01c721
6 changed files with 210 additions and 7 deletions

View 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

1
defs.h
View File

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

17
io.c
View File

@ -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 {

145
ioctl.c
View File

@ -32,6 +32,13 @@
#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)
{

41
xlat/evdev_abs.in Normal file
View File

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

12
xlat/evdev_ev.in Normal file
View File

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