ioctl.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * trace/beauty/ioctl.c
  3. *
  4. * Copyright (C) 2017, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
  5. *
  6. * Released under the GPL v2. (and only v2, not any later version)
  7. */
  8. #include "trace/beauty/beauty.h"
  9. #include <linux/kernel.h>
  10. /*
  11. * FIXME: to support all arches we have to improve this, for
  12. * now, to build on older systems without things like TIOCGEXCL,
  13. * get it directly from our copy.
  14. *
  15. * Right now only x86 is being supported for beautifying ioctl args
  16. * in 'perf trace', see tools/perf/trace/beauty/Build and builtin-trace.c
  17. */
  18. #include <uapi/asm-generic/ioctls.h>
  19. static size_t ioctl__scnprintf_tty_cmd(int nr, int dir, char *bf, size_t size)
  20. {
  21. static const char *ioctl_tty_cmd[] = {
  22. [_IOC_NR(TCGETS)] = "TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
  23. "TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL", "TIOCSCTTY",
  24. "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI", "TIOCGWINSZ", "TIOCSWINSZ",
  25. "TIOCMGET", "TIOCMBIS", "TIOCMBIC", "TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR",
  26. "FIONREAD", "TIOCLINUX", "TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT",
  27. "FIONBIO", "TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP",
  28. [_IOC_NR(TIOCSBRK)] = "TIOCSBRK", "TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2",
  29. "TCSETSW2", "TCSETSF2", "TIOCGRS48", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
  30. "TIOCGDEV", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG", "TIOCVHANGUP", "TIOCGPKT",
  31. "TIOCGPTLCK", [_IOC_NR(TIOCGEXCL)] = "TIOCGEXCL", "TIOCGPTPEER",
  32. [_IOC_NR(FIONCLEX)] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
  33. "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
  34. "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
  35. "TIOCMIWAIT", "TIOCGICOUNT", };
  36. static DEFINE_STRARRAY(ioctl_tty_cmd);
  37. if (nr < strarray__ioctl_tty_cmd.nr_entries && strarray__ioctl_tty_cmd.entries[nr] != NULL)
  38. return scnprintf(bf, size, "%s", strarray__ioctl_tty_cmd.entries[nr]);
  39. return scnprintf(bf, size, "(%#x, %#x, %#x)", 'T', nr, dir);
  40. }
  41. static size_t ioctl__scnprintf_drm_cmd(int nr, int dir, char *bf, size_t size)
  42. {
  43. #include "trace/beauty/generated/ioctl/drm_ioctl_array.c"
  44. static DEFINE_STRARRAY(drm_ioctl_cmds);
  45. if (nr < strarray__drm_ioctl_cmds.nr_entries && strarray__drm_ioctl_cmds.entries[nr] != NULL)
  46. return scnprintf(bf, size, "DRM_%s", strarray__drm_ioctl_cmds.entries[nr]);
  47. return scnprintf(bf, size, "(%#x, %#x, %#x)", 'd', nr, dir);
  48. }
  49. static size_t ioctl__scnprintf_sndrv_pcm_cmd(int nr, int dir, char *bf, size_t size)
  50. {
  51. #include "trace/beauty/generated/ioctl/sndrv_pcm_ioctl_array.c"
  52. static DEFINE_STRARRAY(sndrv_pcm_ioctl_cmds);
  53. if (nr < strarray__sndrv_pcm_ioctl_cmds.nr_entries && strarray__sndrv_pcm_ioctl_cmds.entries[nr] != NULL)
  54. return scnprintf(bf, size, "SNDRV_PCM_%s", strarray__sndrv_pcm_ioctl_cmds.entries[nr]);
  55. return scnprintf(bf, size, "(%#x, %#x, %#x)", 'A', nr, dir);
  56. }
  57. static size_t ioctl__scnprintf_sndrv_ctl_cmd(int nr, int dir, char *bf, size_t size)
  58. {
  59. #include "trace/beauty/generated/ioctl/sndrv_ctl_ioctl_array.c"
  60. static DEFINE_STRARRAY(sndrv_ctl_ioctl_cmds);
  61. if (nr < strarray__sndrv_ctl_ioctl_cmds.nr_entries && strarray__sndrv_ctl_ioctl_cmds.entries[nr] != NULL)
  62. return scnprintf(bf, size, "SNDRV_CTL_%s", strarray__sndrv_ctl_ioctl_cmds.entries[nr]);
  63. return scnprintf(bf, size, "(%#x, %#x, %#x)", 'U', nr, dir);
  64. }
  65. static size_t ioctl__scnprintf_kvm_cmd(int nr, int dir, char *bf, size_t size)
  66. {
  67. #include "trace/beauty/generated/ioctl/kvm_ioctl_array.c"
  68. static DEFINE_STRARRAY(kvm_ioctl_cmds);
  69. if (nr < strarray__kvm_ioctl_cmds.nr_entries && strarray__kvm_ioctl_cmds.entries[nr] != NULL)
  70. return scnprintf(bf, size, "KVM_%s", strarray__kvm_ioctl_cmds.entries[nr]);
  71. return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAE, nr, dir);
  72. }
  73. static size_t ioctl__scnprintf_vhost_virtio_cmd(int nr, int dir, char *bf, size_t size)
  74. {
  75. #include "trace/beauty/generated/ioctl/vhost_virtio_ioctl_array.c"
  76. static DEFINE_STRARRAY(vhost_virtio_ioctl_cmds);
  77. static DEFINE_STRARRAY(vhost_virtio_ioctl_read_cmds);
  78. struct strarray *s = (dir & _IOC_READ) ? &strarray__vhost_virtio_ioctl_read_cmds : &strarray__vhost_virtio_ioctl_cmds;
  79. if (nr < s->nr_entries && s->entries[nr] != NULL)
  80. return scnprintf(bf, size, "VHOST_%s", s->entries[nr]);
  81. return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAF, nr, dir);
  82. }
  83. static size_t ioctl__scnprintf_perf_cmd(int nr, int dir, char *bf, size_t size)
  84. {
  85. #include "trace/beauty/generated/ioctl/perf_ioctl_array.c"
  86. static DEFINE_STRARRAY(perf_ioctl_cmds);
  87. if (nr < strarray__perf_ioctl_cmds.nr_entries && strarray__perf_ioctl_cmds.entries[nr] != NULL)
  88. return scnprintf(bf, size, "PERF_%s", strarray__perf_ioctl_cmds.entries[nr]);
  89. return scnprintf(bf, size, "(%#x, %#x, %#x)", 0xAE, nr, dir);
  90. }
  91. static size_t ioctl__scnprintf_cmd(unsigned long cmd, char *bf, size_t size)
  92. {
  93. int dir = _IOC_DIR(cmd),
  94. type = _IOC_TYPE(cmd),
  95. nr = _IOC_NR(cmd),
  96. sz = _IOC_SIZE(cmd);
  97. int printed = 0;
  98. static const struct ioctl_type {
  99. int type;
  100. size_t (*scnprintf)(int nr, int dir, char *bf, size_t size);
  101. } ioctl_types[] = { /* Must be ordered by type */
  102. { .type = '$', .scnprintf = ioctl__scnprintf_perf_cmd, },
  103. ['A' - '$'] = { .type = 'A', .scnprintf = ioctl__scnprintf_sndrv_pcm_cmd, },
  104. ['T' - '$'] = { .type = 'T', .scnprintf = ioctl__scnprintf_tty_cmd, },
  105. ['U' - '$'] = { .type = 'U', .scnprintf = ioctl__scnprintf_sndrv_ctl_cmd, },
  106. ['d' - '$'] = { .type = 'd', .scnprintf = ioctl__scnprintf_drm_cmd, },
  107. [0xAE - '$'] = { .type = 0xAE, .scnprintf = ioctl__scnprintf_kvm_cmd, },
  108. [0xAF - '$'] = { .type = 0xAF, .scnprintf = ioctl__scnprintf_vhost_virtio_cmd, },
  109. };
  110. const int nr_types = ARRAY_SIZE(ioctl_types);
  111. if (type >= ioctl_types[0].type && type <= ioctl_types[nr_types - 1].type) {
  112. const int index = type - ioctl_types[0].type;
  113. if (ioctl_types[index].scnprintf != NULL)
  114. return ioctl_types[index].scnprintf(nr, dir, bf, size);
  115. }
  116. printed += scnprintf(bf + printed, size - printed, "%c", '(');
  117. if (dir == _IOC_NONE) {
  118. printed += scnprintf(bf + printed, size - printed, "%s", "NONE");
  119. } else {
  120. if (dir & _IOC_READ)
  121. printed += scnprintf(bf + printed, size - printed, "%s", "READ");
  122. if (dir & _IOC_WRITE)
  123. printed += scnprintf(bf + printed, size - printed, "%s%s", dir & _IOC_READ ? "|" : "", "WRITE");
  124. }
  125. return printed + scnprintf(bf + printed, size - printed, ", %#x, %#x, %#x)", type, nr, sz);
  126. }
  127. size_t syscall_arg__scnprintf_ioctl_cmd(char *bf, size_t size, struct syscall_arg *arg)
  128. {
  129. unsigned long cmd = arg->val;
  130. return ioctl__scnprintf_cmd(cmd, bf, size);
  131. }