0001
0002
0003
0004
0005
0006
0007
0008 #include "trace/beauty/beauty.h"
0009 #include <linux/kernel.h>
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include <uapi/asm-generic/ioctls.h>
0020
0021 static size_t ioctl__scnprintf_tty_cmd(int nr, int dir, char *bf, size_t size)
0022 {
0023 static const char *ioctl_tty_cmd[] = {
0024 [_IOC_NR(TCGETS)] = "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
0025 "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL", "TIOCSCTTY",
0026 "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI", "TIOCGWINSZ", "TIOCSWINSZ",
0027 "TIOCMGET", "TIOCMBIS", "TIOCMBIC", "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR",
0028 "FIONREAD", "TIOCLINUX", "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT",
0029 "FIONBIO", "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP",
0030 [_IOC_NR(TIOCSBRK)] = "TIOCSBRK", "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2",
0031 "TCSETSW2", "TCSETSF2", "TIOCGRS48", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
0032 "TIOCGDEV", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG", "TIOCVHANGUP", "TIOCGPKT",
0033 "TIOCGPTLCK", [_IOC_NR(TIOCGEXCL)] = "TIOCGEXCL", "TIOCGPTPEER",
0034 "TIOCGISO7816", "TIOCSISO7816",
0035 [_IOC_NR(FIONCLEX)] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
0036 "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
0037 "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
0038 "TIOCMIWAIT", "TIOCGICOUNT", };
0039 static DEFINE_STRARRAY(ioctl_tty_cmd, "");
0040
0041 if (nr < strarray__ioctl_tty_cmd.nr_entries && strarray__ioctl_tty_cmd.entries[nr] != NULL)
0042 return scnprintf(bf, size, "%s", strarray__ioctl_tty_cmd.entries[nr]);
0043
0044 return scnprintf(bf, size, "(%#x, %#x, %#x)", 'T', nr, dir);
0045 }
0046
0047 static size_t ioctl__scnprintf_drm_cmd(int nr, int dir, char *bf, size_t size)
0048 {
0049 #include "trace/beauty/generated/ioctl/drm_ioctl_array.c"
0050 static DEFINE_STRARRAY(drm_ioctl_cmds, "");
0051
0052 if (nr < strarray__drm_ioctl_cmds.nr_entries && strarray__drm_ioctl_cmds.entries[nr] != NULL)
0053 return scnprintf(bf, size, "DRM_%s", strarray__drm_ioctl_cmds.entries[nr]);
0054
0055 return scnprintf(bf, size, "(%#x, %#x, %#x)", 'd', nr, dir);
0056 }
0057
0058 static size_t ioctl__scnprintf_sndrv_pcm_cmd(int nr, int dir, char *bf, size_t size)
0059 {
0060 #include "trace/beauty/generated/ioctl/sndrv_pcm_ioctl_array.c"
0061 static DEFINE_STRARRAY(sndrv_pcm_ioctl_cmds, "");
0062
0063 if (nr < strarray__sndrv_pcm_ioctl_cmds.nr_entries && strarray__sndrv_pcm_ioctl_cmds.entries[nr] != NULL)
0064 return scnprintf(bf, size, "SNDRV_PCM_%s", strarray__sndrv_pcm_ioctl_cmds.entries[nr]);
0065
0066 return scnprintf(bf, size, "(%#x, %#x, %#x)", 'A', nr, dir);
0067 }
0068
0069 static size_t ioctl__scnprintf_sndrv_ctl_cmd(int nr, int dir, char *bf, size_t size)
0070 {
0071 #include "trace/beauty/generated/ioctl/sndrv_ctl_ioctl_array.c"
0072 static DEFINE_STRARRAY(sndrv_ctl_ioctl_cmds, "");
0073
0074 if (nr < strarray__sndrv_ctl_ioctl_cmds.nr_entries && strarray__sndrv_ctl_ioctl_cmds.entries[nr] != NULL)
0075 return scnprintf(bf, size, "SNDRV_CTL_%s", strarray__sndrv_ctl_ioctl_cmds.entries[nr]);
0076
0077 return scnprintf(bf, size, "(%#x, %#x, %#x)", 'U', nr, dir);
0078 }
0079
0080 static size_t ioctl__scnprintf_kvm_cmd(int nr, int dir, char *bf, size_t size)
0081 {
0082 #include "trace/beauty/generated/ioctl/kvm_ioctl_array.c"
0083 static DEFINE_STRARRAY(kvm_ioctl_cmds, "");
0084
0085 if (nr < strarray__kvm_ioctl_cmds.nr_entries && strarray__kvm_ioctl_cmds.entries[nr] != NULL)
0086 return scnprintf(bf, size, "KVM_%s", strarray__kvm_ioctl_cmds.entries[nr]);
0087
0088 return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAE, nr, dir);
0089 }
0090
0091 static size_t ioctl__scnprintf_vhost_virtio_cmd(int nr, int dir, char *bf, size_t size)
0092 {
0093 #include "trace/beauty/generated/ioctl/vhost_virtio_ioctl_array.c"
0094 static DEFINE_STRARRAY(vhost_virtio_ioctl_cmds, "");
0095 static DEFINE_STRARRAY(vhost_virtio_ioctl_read_cmds, "");
0096 struct strarray *s = (dir & _IOC_READ) ? &strarray__vhost_virtio_ioctl_read_cmds : &strarray__vhost_virtio_ioctl_cmds;
0097
0098 if (nr < s->nr_entries && s->entries[nr] != NULL)
0099 return scnprintf(bf, size, "VHOST_%s", s->entries[nr]);
0100
0101 return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAF, nr, dir);
0102 }
0103
0104 static size_t ioctl__scnprintf_perf_cmd(int nr, int dir, char *bf, size_t size)
0105 {
0106 #include "trace/beauty/generated/ioctl/perf_ioctl_array.c"
0107 static DEFINE_STRARRAY(perf_ioctl_cmds, "");
0108
0109 if (nr < strarray__perf_ioctl_cmds.nr_entries && strarray__perf_ioctl_cmds.entries[nr] != NULL)
0110 return scnprintf(bf, size, "PERF_%s", strarray__perf_ioctl_cmds.entries[nr]);
0111
0112 return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAE, nr, dir);
0113 }
0114
0115 static size_t ioctl__scnprintf_usbdevfs_cmd(int nr, int dir, char *bf, size_t size)
0116 {
0117 #include "trace/beauty/generated/ioctl/usbdevfs_ioctl_array.c"
0118 static DEFINE_STRARRAY(usbdevfs_ioctl_cmds, "");
0119
0120 if (nr < strarray__usbdevfs_ioctl_cmds.nr_entries && strarray__usbdevfs_ioctl_cmds.entries[nr] != NULL)
0121 return scnprintf(bf, size, "USBDEVFS_%s", strarray__usbdevfs_ioctl_cmds.entries[nr]);
0122
0123 return scnprintf(bf, size, "(%c, %#x, %#x)", 'U', nr, dir);
0124 }
0125
0126 static size_t ioctl__scnprintf_cmd(unsigned long cmd, char *bf, size_t size, bool show_prefix)
0127 {
0128 const char *prefix = "_IOC_";
0129 int dir = _IOC_DIR(cmd),
0130 type = _IOC_TYPE(cmd),
0131 nr = _IOC_NR(cmd),
0132 sz = _IOC_SIZE(cmd);
0133 int printed = 0;
0134 static const struct ioctl_type {
0135 int type;
0136 size_t (*scnprintf)(int nr, int dir, char *bf, size_t size);
0137 } ioctl_types[] = {
0138 { .type = '$', .scnprintf = ioctl__scnprintf_perf_cmd, },
0139 ['A' - '$'] = { .type = 'A', .scnprintf = ioctl__scnprintf_sndrv_pcm_cmd, },
0140 ['T' - '$'] = { .type = 'T', .scnprintf = ioctl__scnprintf_tty_cmd, },
0141 ['U' - '$'] = { .type = 'U', .scnprintf = ioctl__scnprintf_sndrv_ctl_cmd, },
0142 ['d' - '$'] = { .type = 'd', .scnprintf = ioctl__scnprintf_drm_cmd, },
0143 [0xAE - '$'] = { .type = 0xAE, .scnprintf = ioctl__scnprintf_kvm_cmd, },
0144 [0xAF - '$'] = { .type = 0xAF, .scnprintf = ioctl__scnprintf_vhost_virtio_cmd, },
0145 };
0146 const int nr_types = ARRAY_SIZE(ioctl_types);
0147
0148 if (type >= ioctl_types[0].type && type <= ioctl_types[nr_types - 1].type) {
0149 const int index = type - ioctl_types[0].type;
0150
0151 if (ioctl_types[index].scnprintf != NULL)
0152 return ioctl_types[index].scnprintf(nr, dir, bf, size);
0153 }
0154
0155 printed += scnprintf(bf + printed, size - printed, "%c", '(');
0156
0157 if (dir == _IOC_NONE) {
0158 printed += scnprintf(bf + printed, size - printed, "%s%s", show_prefix ? prefix : "", "NONE");
0159 } else {
0160 if (dir & _IOC_READ)
0161 printed += scnprintf(bf + printed, size - printed, "%s%s", show_prefix ? prefix : "", "READ");
0162 if (dir & _IOC_WRITE) {
0163 printed += scnprintf(bf + printed, size - printed, "%s%s%s", dir & _IOC_READ ? "|" : "",
0164 show_prefix ? prefix : "", "WRITE");
0165 }
0166 }
0167
0168 return printed + scnprintf(bf + printed, size - printed, ", %#x, %#x, %#x)", type, nr, sz);
0169 }
0170
0171 #ifndef USB_DEVICE_MAJOR
0172 #define USB_DEVICE_MAJOR 189
0173 #endif
0174
0175 size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg)
0176 {
0177 unsigned long cmd = arg->val;
0178 int fd = syscall_arg__val(arg, 0);
0179 struct file *file = thread__files_entry(arg->thread, fd);
0180
0181 if (file != NULL) {
0182 if (file->dev_maj == USB_DEVICE_MAJOR)
0183 return ioctl__scnprintf_usbdevfs_cmd(_IOC_NR(cmd), _IOC_DIR(cmd), bf, size);
0184 }
0185
0186 return ioctl__scnprintf_cmd(cmd, bf, size, arg->show_string_prefix);
0187 }