dyn_test.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * User Events Dyn Events Test Program
  4. *
  5. * Copyright (c) 2021 Beau Belgrave <beaub@linux.microsoft.com>
  6. */
  7. #include <errno.h>
  8. #include <linux/user_events.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <fcntl.h>
  12. #include <sys/ioctl.h>
  13. #include <sys/stat.h>
  14. #include <unistd.h>
  15. #include "../kselftest_harness.h"
  16. #include "user_events_selftests.h"
  17. const char *dyn_file = "/sys/kernel/tracing/dynamic_events";
  18. const char *abi_file = "/sys/kernel/tracing/user_events_data";
  19. const char *enable_file = "/sys/kernel/tracing/events/user_events/__test_event/enable";
  20. static int event_delete(void)
  21. {
  22. int fd = open(abi_file, O_RDWR);
  23. int ret;
  24. if (fd < 0)
  25. return -1;
  26. ret = ioctl(fd, DIAG_IOCSDEL, "__test_event");
  27. close(fd);
  28. return ret;
  29. }
  30. static bool wait_for_delete(void)
  31. {
  32. int i;
  33. for (i = 0; i < 1000; ++i) {
  34. int fd = open(enable_file, O_RDONLY);
  35. if (fd == -1)
  36. return true;
  37. close(fd);
  38. usleep(1000);
  39. }
  40. return false;
  41. }
  42. static int reg_event(int fd, int *check, int bit, const char *value)
  43. {
  44. struct user_reg reg = {0};
  45. reg.size = sizeof(reg);
  46. reg.name_args = (__u64)value;
  47. reg.enable_bit = bit;
  48. reg.enable_addr = (__u64)check;
  49. reg.enable_size = sizeof(*check);
  50. if (ioctl(fd, DIAG_IOCSREG, &reg) == -1)
  51. return -1;
  52. return 0;
  53. }
  54. static int unreg_event(int fd, int *check, int bit)
  55. {
  56. struct user_unreg unreg = {0};
  57. unreg.size = sizeof(unreg);
  58. unreg.disable_bit = bit;
  59. unreg.disable_addr = (__u64)check;
  60. return ioctl(fd, DIAG_IOCSUNREG, &unreg);
  61. }
  62. static int parse_dyn(const char *value)
  63. {
  64. int fd = open(dyn_file, O_RDWR | O_APPEND);
  65. int len = strlen(value);
  66. int ret;
  67. if (fd == -1)
  68. return -1;
  69. ret = write(fd, value, len);
  70. if (ret == len)
  71. ret = 0;
  72. else
  73. ret = -1;
  74. close(fd);
  75. if (ret == 0)
  76. event_delete();
  77. return ret;
  78. }
  79. static int parse_abi(int *check, const char *value)
  80. {
  81. int fd = open(abi_file, O_RDWR);
  82. int ret;
  83. if (fd == -1)
  84. return -1;
  85. /* Until we have persist flags via dynamic events, use the base name */
  86. if (value[0] != 'u' || value[1] != ':') {
  87. close(fd);
  88. return -1;
  89. }
  90. ret = reg_event(fd, check, 31, value + 2);
  91. if (ret != -1) {
  92. if (unreg_event(fd, check, 31) == -1)
  93. printf("WARN: Couldn't unreg event\n");
  94. }
  95. close(fd);
  96. return ret;
  97. }
  98. static int parse(int *check, const char *value)
  99. {
  100. int abi_ret = parse_abi(check, value);
  101. int dyn_ret = parse_dyn(value);
  102. /* Ensure both ABI and DYN parse the same way */
  103. if (dyn_ret != abi_ret)
  104. return -1;
  105. return dyn_ret;
  106. }
  107. static int check_match(int *check, const char *first, const char *second, bool *match)
  108. {
  109. int fd = open(abi_file, O_RDWR);
  110. int ret = -1;
  111. if (fd == -1)
  112. return -1;
  113. if (reg_event(fd, check, 31, first) == -1)
  114. goto cleanup;
  115. if (reg_event(fd, check, 30, second) == -1) {
  116. if (errno == EADDRINUSE) {
  117. /* Name is in use, with different fields */
  118. *match = false;
  119. ret = 0;
  120. }
  121. goto cleanup;
  122. }
  123. *match = true;
  124. ret = 0;
  125. cleanup:
  126. unreg_event(fd, check, 31);
  127. unreg_event(fd, check, 30);
  128. close(fd);
  129. wait_for_delete();
  130. return ret;
  131. }
  132. #define TEST_MATCH(x, y) \
  133. do { \
  134. bool match; \
  135. ASSERT_NE(-1, check_match(&self->check, x, y, &match)); \
  136. ASSERT_EQ(true, match); \
  137. } while (0)
  138. #define TEST_NMATCH(x, y) \
  139. do { \
  140. bool match; \
  141. ASSERT_NE(-1, check_match(&self->check, x, y, &match)); \
  142. ASSERT_EQ(false, match); \
  143. } while (0)
  144. #define TEST_PARSE(x) ASSERT_NE(-1, parse(&self->check, x))
  145. #define TEST_NPARSE(x) ASSERT_EQ(-1, parse(&self->check, x))
  146. FIXTURE(user) {
  147. int check;
  148. bool umount;
  149. };
  150. FIXTURE_SETUP(user) {
  151. USER_EVENT_FIXTURE_SETUP(return, self->umount);
  152. }
  153. FIXTURE_TEARDOWN(user) {
  154. USER_EVENT_FIXTURE_TEARDOWN(self->umount);
  155. wait_for_delete();
  156. }
  157. TEST_F(user, basic_types) {
  158. /* All should work */
  159. TEST_PARSE("u:__test_event u64 a");
  160. TEST_PARSE("u:__test_event u32 a");
  161. TEST_PARSE("u:__test_event u16 a");
  162. TEST_PARSE("u:__test_event u8 a");
  163. TEST_PARSE("u:__test_event char a");
  164. TEST_PARSE("u:__test_event unsigned char a");
  165. TEST_PARSE("u:__test_event int a");
  166. TEST_PARSE("u:__test_event unsigned int a");
  167. TEST_PARSE("u:__test_event short a");
  168. TEST_PARSE("u:__test_event unsigned short a");
  169. TEST_PARSE("u:__test_event char[20] a");
  170. TEST_PARSE("u:__test_event unsigned char[20] a");
  171. TEST_PARSE("u:__test_event char[0x14] a");
  172. TEST_PARSE("u:__test_event unsigned char[0x14] a");
  173. /* Bad size format should fail */
  174. TEST_NPARSE("u:__test_event char[aa] a");
  175. /* Large size should fail */
  176. TEST_NPARSE("u:__test_event char[9999] a");
  177. /* Long size string should fail */
  178. TEST_NPARSE("u:__test_event char[0x0000000000001] a");
  179. }
  180. TEST_F(user, loc_types) {
  181. /* All should work */
  182. TEST_PARSE("u:__test_event __data_loc char[] a");
  183. TEST_PARSE("u:__test_event __data_loc unsigned char[] a");
  184. TEST_PARSE("u:__test_event __rel_loc char[] a");
  185. TEST_PARSE("u:__test_event __rel_loc unsigned char[] a");
  186. }
  187. TEST_F(user, size_types) {
  188. /* Should work */
  189. TEST_PARSE("u:__test_event struct custom a 20");
  190. /* Size not specified on struct should fail */
  191. TEST_NPARSE("u:__test_event struct custom a");
  192. /* Size specified on non-struct should fail */
  193. TEST_NPARSE("u:__test_event char a 20");
  194. }
  195. TEST_F(user, matching) {
  196. /* Single name matches */
  197. TEST_MATCH("__test_event u32 a",
  198. "__test_event u32 a");
  199. /* Multiple names match */
  200. TEST_MATCH("__test_event u32 a; u32 b",
  201. "__test_event u32 a; u32 b");
  202. /* Multiple names match with dangling ; */
  203. TEST_MATCH("__test_event u32 a; u32 b",
  204. "__test_event u32 a; u32 b;");
  205. /* Single name doesn't match */
  206. TEST_NMATCH("__test_event u32 a",
  207. "__test_event u32 b");
  208. /* Multiple names don't match */
  209. TEST_NMATCH("__test_event u32 a; u32 b",
  210. "__test_event u32 b; u32 a");
  211. /* Types don't match */
  212. TEST_NMATCH("__test_event u64 a; u64 b",
  213. "__test_event u32 a; u32 b");
  214. /* Struct name and size matches */
  215. TEST_MATCH("__test_event struct my_struct a 20",
  216. "__test_event struct my_struct a 20");
  217. /* Struct name don't match */
  218. TEST_NMATCH("__test_event struct my_struct a 20",
  219. "__test_event struct my_struct b 20");
  220. /* Struct size don't match */
  221. TEST_NMATCH("__test_event struct my_struct a 20",
  222. "__test_event struct my_struct a 21");
  223. }
  224. int main(int argc, char **argv)
  225. {
  226. return test_harness_run(argc, argv);
  227. }