parse-events.y 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. %pure-parser
  2. %parse-param {void *_data}
  3. %parse-param {void *scanner}
  4. %lex-param {void* scanner}
  5. %locations
  6. %{
  7. #define YYDEBUG 1
  8. #include <linux/compiler.h>
  9. #include <linux/list.h>
  10. #include <linux/types.h>
  11. #include "util.h"
  12. #include "parse-events.h"
  13. #include "parse-events-bison.h"
  14. #define ABORT_ON(val) \
  15. do { \
  16. if (val) \
  17. YYABORT; \
  18. } while (0)
  19. #define ALLOC_LIST(list) \
  20. do { \
  21. list = malloc(sizeof(*list)); \
  22. ABORT_ON(!list); \
  23. INIT_LIST_HEAD(list); \
  24. } while (0)
  25. static inc_group_count(struct list_head *list,
  26. struct parse_events_evlist *data)
  27. {
  28. /* Count groups only have more than 1 members */
  29. if (!list_is_last(list->next, list))
  30. data->nr_groups++;
  31. }
  32. %}
  33. %token PE_START_EVENTS PE_START_TERMS
  34. %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
  35. %token PE_EVENT_NAME
  36. %token PE_NAME
  37. %token PE_BPF_OBJECT PE_BPF_SOURCE
  38. %token PE_MODIFIER_EVENT PE_MODIFIER_BP
  39. %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
  40. %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
  41. %token PE_ERROR
  42. %token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
  43. %type <num> PE_VALUE
  44. %type <num> PE_VALUE_SYM_HW
  45. %type <num> PE_VALUE_SYM_SW
  46. %type <num> PE_RAW
  47. %type <num> PE_TERM
  48. %type <str> PE_NAME
  49. %type <str> PE_BPF_OBJECT
  50. %type <str> PE_BPF_SOURCE
  51. %type <str> PE_NAME_CACHE_TYPE
  52. %type <str> PE_NAME_CACHE_OP_RESULT
  53. %type <str> PE_MODIFIER_EVENT
  54. %type <str> PE_MODIFIER_BP
  55. %type <str> PE_EVENT_NAME
  56. %type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
  57. %type <num> value_sym
  58. %type <head> event_config
  59. %type <term> event_term
  60. %type <head> event_pmu
  61. %type <head> event_legacy_symbol
  62. %type <head> event_legacy_cache
  63. %type <head> event_legacy_mem
  64. %type <head> event_legacy_tracepoint
  65. %type <tracepoint_name> tracepoint_name
  66. %type <head> event_legacy_numeric
  67. %type <head> event_legacy_raw
  68. %type <head> event_bpf_file
  69. %type <head> event_def
  70. %type <head> event_mod
  71. %type <head> event_name
  72. %type <head> event
  73. %type <head> events
  74. %type <head> group_def
  75. %type <head> group
  76. %type <head> groups
  77. %union
  78. {
  79. char *str;
  80. u64 num;
  81. struct list_head *head;
  82. struct parse_events_term *term;
  83. struct tracepoint_name {
  84. char *sys;
  85. char *event;
  86. } tracepoint_name;
  87. }
  88. %%
  89. start:
  90. PE_START_EVENTS start_events
  91. |
  92. PE_START_TERMS start_terms
  93. start_events: groups
  94. {
  95. struct parse_events_evlist *data = _data;
  96. parse_events_update_lists($1, &data->list);
  97. }
  98. groups:
  99. groups ',' group
  100. {
  101. struct list_head *list = $1;
  102. struct list_head *group = $3;
  103. parse_events_update_lists(group, list);
  104. $$ = list;
  105. }
  106. |
  107. groups ',' event
  108. {
  109. struct list_head *list = $1;
  110. struct list_head *event = $3;
  111. parse_events_update_lists(event, list);
  112. $$ = list;
  113. }
  114. |
  115. group
  116. |
  117. event
  118. group:
  119. group_def ':' PE_MODIFIER_EVENT
  120. {
  121. struct list_head *list = $1;
  122. ABORT_ON(parse_events__modifier_group(list, $3));
  123. $$ = list;
  124. }
  125. |
  126. group_def
  127. group_def:
  128. PE_NAME '{' events '}'
  129. {
  130. struct list_head *list = $3;
  131. inc_group_count(list, _data);
  132. parse_events__set_leader($1, list);
  133. $$ = list;
  134. }
  135. |
  136. '{' events '}'
  137. {
  138. struct list_head *list = $2;
  139. inc_group_count(list, _data);
  140. parse_events__set_leader(NULL, list);
  141. $$ = list;
  142. }
  143. events:
  144. events ',' event
  145. {
  146. struct list_head *event = $3;
  147. struct list_head *list = $1;
  148. parse_events_update_lists(event, list);
  149. $$ = list;
  150. }
  151. |
  152. event
  153. event: event_mod
  154. event_mod:
  155. event_name PE_MODIFIER_EVENT
  156. {
  157. struct list_head *list = $1;
  158. /*
  159. * Apply modifier on all events added by single event definition
  160. * (there could be more events added for multiple tracepoint
  161. * definitions via '*?'.
  162. */
  163. ABORT_ON(parse_events__modifier_event(list, $2, false));
  164. $$ = list;
  165. }
  166. |
  167. event_name
  168. event_name:
  169. PE_EVENT_NAME event_def
  170. {
  171. ABORT_ON(parse_events_name($2, $1));
  172. free($1);
  173. $$ = $2;
  174. }
  175. |
  176. event_def
  177. event_def: event_pmu |
  178. event_legacy_symbol |
  179. event_legacy_cache sep_dc |
  180. event_legacy_mem |
  181. event_legacy_tracepoint sep_dc |
  182. event_legacy_numeric sep_dc |
  183. event_legacy_raw sep_dc |
  184. event_bpf_file
  185. event_pmu:
  186. PE_NAME '/' event_config '/'
  187. {
  188. struct parse_events_evlist *data = _data;
  189. struct list_head *list;
  190. ALLOC_LIST(list);
  191. ABORT_ON(parse_events_add_pmu(data, list, $1, $3));
  192. parse_events__free_terms($3);
  193. $$ = list;
  194. }
  195. |
  196. PE_NAME '/' '/'
  197. {
  198. struct parse_events_evlist *data = _data;
  199. struct list_head *list;
  200. ALLOC_LIST(list);
  201. ABORT_ON(parse_events_add_pmu(data, list, $1, NULL));
  202. $$ = list;
  203. }
  204. |
  205. PE_KERNEL_PMU_EVENT sep_dc
  206. {
  207. struct parse_events_evlist *data = _data;
  208. struct list_head *head;
  209. struct parse_events_term *term;
  210. struct list_head *list;
  211. ALLOC_LIST(head);
  212. ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
  213. $1, 1, &@1, NULL));
  214. list_add_tail(&term->list, head);
  215. ALLOC_LIST(list);
  216. ABORT_ON(parse_events_add_pmu(data, list, "cpu", head));
  217. parse_events__free_terms(head);
  218. $$ = list;
  219. }
  220. |
  221. PE_PMU_EVENT_PRE '-' PE_PMU_EVENT_SUF sep_dc
  222. {
  223. struct parse_events_evlist *data = _data;
  224. struct list_head *head;
  225. struct parse_events_term *term;
  226. struct list_head *list;
  227. char pmu_name[128];
  228. snprintf(&pmu_name, 128, "%s-%s", $1, $3);
  229. ALLOC_LIST(head);
  230. ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
  231. &pmu_name, 1, &@1, NULL));
  232. list_add_tail(&term->list, head);
  233. ALLOC_LIST(list);
  234. ABORT_ON(parse_events_add_pmu(data, list, "cpu", head));
  235. parse_events__free_terms(head);
  236. $$ = list;
  237. }
  238. value_sym:
  239. PE_VALUE_SYM_HW
  240. |
  241. PE_VALUE_SYM_SW
  242. event_legacy_symbol:
  243. value_sym '/' event_config '/'
  244. {
  245. struct parse_events_evlist *data = _data;
  246. struct list_head *list;
  247. int type = $1 >> 16;
  248. int config = $1 & 255;
  249. ALLOC_LIST(list);
  250. ABORT_ON(parse_events_add_numeric(data, list, type, config, $3));
  251. parse_events__free_terms($3);
  252. $$ = list;
  253. }
  254. |
  255. value_sym sep_slash_dc
  256. {
  257. struct parse_events_evlist *data = _data;
  258. struct list_head *list;
  259. int type = $1 >> 16;
  260. int config = $1 & 255;
  261. ALLOC_LIST(list);
  262. ABORT_ON(parse_events_add_numeric(data, list, type, config, NULL));
  263. $$ = list;
  264. }
  265. event_legacy_cache:
  266. PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
  267. {
  268. struct parse_events_evlist *data = _data;
  269. struct list_head *list;
  270. ALLOC_LIST(list);
  271. ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, $5));
  272. $$ = list;
  273. }
  274. |
  275. PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
  276. {
  277. struct parse_events_evlist *data = _data;
  278. struct list_head *list;
  279. ALLOC_LIST(list);
  280. ABORT_ON(parse_events_add_cache(list, &data->idx, $1, $3, NULL));
  281. $$ = list;
  282. }
  283. |
  284. PE_NAME_CACHE_TYPE
  285. {
  286. struct parse_events_evlist *data = _data;
  287. struct list_head *list;
  288. ALLOC_LIST(list);
  289. ABORT_ON(parse_events_add_cache(list, &data->idx, $1, NULL, NULL));
  290. $$ = list;
  291. }
  292. event_legacy_mem:
  293. PE_PREFIX_MEM PE_VALUE '/' PE_VALUE ':' PE_MODIFIER_BP sep_dc
  294. {
  295. struct parse_events_evlist *data = _data;
  296. struct list_head *list;
  297. ALLOC_LIST(list);
  298. ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
  299. (void *) $2, $6, $4));
  300. $$ = list;
  301. }
  302. |
  303. PE_PREFIX_MEM PE_VALUE '/' PE_VALUE sep_dc
  304. {
  305. struct parse_events_evlist *data = _data;
  306. struct list_head *list;
  307. ALLOC_LIST(list);
  308. ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
  309. (void *) $2, NULL, $4));
  310. $$ = list;
  311. }
  312. |
  313. PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
  314. {
  315. struct parse_events_evlist *data = _data;
  316. struct list_head *list;
  317. ALLOC_LIST(list);
  318. ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
  319. (void *) $2, $4, 0));
  320. $$ = list;
  321. }
  322. |
  323. PE_PREFIX_MEM PE_VALUE sep_dc
  324. {
  325. struct parse_events_evlist *data = _data;
  326. struct list_head *list;
  327. ALLOC_LIST(list);
  328. ABORT_ON(parse_events_add_breakpoint(list, &data->idx,
  329. (void *) $2, NULL, 0));
  330. $$ = list;
  331. }
  332. event_legacy_tracepoint:
  333. tracepoint_name
  334. {
  335. struct parse_events_evlist *data = _data;
  336. struct parse_events_error *error = data->error;
  337. struct list_head *list;
  338. ALLOC_LIST(list);
  339. if (error)
  340. error->idx = @1.first_column;
  341. if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event,
  342. error, NULL))
  343. return -1;
  344. $$ = list;
  345. }
  346. |
  347. tracepoint_name '/' event_config '/'
  348. {
  349. struct parse_events_evlist *data = _data;
  350. struct parse_events_error *error = data->error;
  351. struct list_head *list;
  352. ALLOC_LIST(list);
  353. if (error)
  354. error->idx = @1.first_column;
  355. if (parse_events_add_tracepoint(list, &data->idx, $1.sys, $1.event,
  356. error, $3))
  357. return -1;
  358. $$ = list;
  359. }
  360. tracepoint_name:
  361. PE_NAME '-' PE_NAME ':' PE_NAME
  362. {
  363. char sys_name[128];
  364. struct tracepoint_name tracepoint;
  365. snprintf(&sys_name, 128, "%s-%s", $1, $3);
  366. tracepoint.sys = &sys_name;
  367. tracepoint.event = $5;
  368. $$ = tracepoint;
  369. }
  370. |
  371. PE_NAME ':' PE_NAME
  372. {
  373. struct tracepoint_name tracepoint = {$1, $3};
  374. $$ = tracepoint;
  375. }
  376. event_legacy_numeric:
  377. PE_VALUE ':' PE_VALUE
  378. {
  379. struct parse_events_evlist *data = _data;
  380. struct list_head *list;
  381. ALLOC_LIST(list);
  382. ABORT_ON(parse_events_add_numeric(data, list, (u32)$1, $3, NULL));
  383. $$ = list;
  384. }
  385. event_legacy_raw:
  386. PE_RAW
  387. {
  388. struct parse_events_evlist *data = _data;
  389. struct list_head *list;
  390. ALLOC_LIST(list);
  391. ABORT_ON(parse_events_add_numeric(data, list, PERF_TYPE_RAW, $1, NULL));
  392. $$ = list;
  393. }
  394. event_bpf_file:
  395. PE_BPF_OBJECT
  396. {
  397. struct parse_events_evlist *data = _data;
  398. struct parse_events_error *error = data->error;
  399. struct list_head *list;
  400. ALLOC_LIST(list);
  401. ABORT_ON(parse_events_load_bpf(data, list, $1, false));
  402. $$ = list;
  403. }
  404. |
  405. PE_BPF_SOURCE
  406. {
  407. struct parse_events_evlist *data = _data;
  408. struct list_head *list;
  409. ALLOC_LIST(list);
  410. ABORT_ON(parse_events_load_bpf(data, list, $1, true));
  411. $$ = list;
  412. }
  413. start_terms: event_config
  414. {
  415. struct parse_events_terms *data = _data;
  416. data->terms = $1;
  417. }
  418. event_config:
  419. event_config ',' event_term
  420. {
  421. struct list_head *head = $1;
  422. struct parse_events_term *term = $3;
  423. ABORT_ON(!head);
  424. list_add_tail(&term->list, head);
  425. $$ = $1;
  426. }
  427. |
  428. event_term
  429. {
  430. struct list_head *head = malloc(sizeof(*head));
  431. struct parse_events_term *term = $1;
  432. ABORT_ON(!head);
  433. INIT_LIST_HEAD(head);
  434. list_add_tail(&term->list, head);
  435. $$ = head;
  436. }
  437. event_term:
  438. PE_NAME '=' PE_NAME
  439. {
  440. struct parse_events_term *term;
  441. ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_USER,
  442. $1, $3, &@1, &@3));
  443. $$ = term;
  444. }
  445. |
  446. PE_NAME '=' PE_VALUE
  447. {
  448. struct parse_events_term *term;
  449. ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
  450. $1, $3, &@1, &@3));
  451. $$ = term;
  452. }
  453. |
  454. PE_NAME '=' PE_VALUE_SYM_HW
  455. {
  456. struct parse_events_term *term;
  457. int config = $3 & 255;
  458. ABORT_ON(parse_events_term__sym_hw(&term, $1, config));
  459. $$ = term;
  460. }
  461. |
  462. PE_NAME
  463. {
  464. struct parse_events_term *term;
  465. ABORT_ON(parse_events_term__num(&term, PARSE_EVENTS__TERM_TYPE_USER,
  466. $1, 1, &@1, NULL));
  467. $$ = term;
  468. }
  469. |
  470. PE_VALUE_SYM_HW
  471. {
  472. struct parse_events_term *term;
  473. int config = $1 & 255;
  474. ABORT_ON(parse_events_term__sym_hw(&term, NULL, config));
  475. $$ = term;
  476. }
  477. |
  478. PE_TERM '=' PE_NAME
  479. {
  480. struct parse_events_term *term;
  481. ABORT_ON(parse_events_term__str(&term, (int)$1, NULL, $3, &@1, &@3));
  482. $$ = term;
  483. }
  484. |
  485. PE_TERM '=' PE_VALUE
  486. {
  487. struct parse_events_term *term;
  488. ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, $3, &@1, &@3));
  489. $$ = term;
  490. }
  491. |
  492. PE_TERM
  493. {
  494. struct parse_events_term *term;
  495. ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, &@1, NULL));
  496. $$ = term;
  497. }
  498. sep_dc: ':' |
  499. sep_slash_dc: '/' | ':' |
  500. %%
  501. void parse_events_error(YYLTYPE *loc, void *data,
  502. void *scanner __maybe_unused,
  503. char const *msg __maybe_unused)
  504. {
  505. parse_events_evlist_error(data, loc->last_column, "parser error");
  506. }