blob: 33803c0b94d6cb9ab1bb5adc750b3722ce847a7e [file] [log] [blame]
Steven Rostedtf7d82352012-04-06 00:47:53 +02001/*
2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
Jon Stanley7b9f6b42012-09-07 16:32:46 -040016 * License along with this program; if not, see <http://www.gnu.org/licenses>
Steven Rostedtf7d82352012-04-06 00:47:53 +020017 *
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 *
20 * The parts for function graph printing was taken and modified from the
21 * Linux Kernel that were written by
22 * - Copyright (C) 2009 Frederic Weisbecker,
23 * Frederic Weisbecker gave his permission to relicense the code to
24 * the Lesser General Public License.
25 */
Steven Rostedtf7d82352012-04-06 00:47:53 +020026#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <stdarg.h>
30#include <ctype.h>
31#include <errno.h>
Robert Richter0cf26012012-08-07 19:43:14 +020032#include <stdint.h>
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -030033#include <limits.h>
Steven Rostedtf7d82352012-04-06 00:47:53 +020034
35#include "event-parse.h"
Steven Rostedt668fe012012-04-06 00:47:55 +020036#include "event-utils.h"
Steven Rostedtf7d82352012-04-06 00:47:53 +020037
38static const char *input_buf;
39static unsigned long long input_buf_ptr;
40static unsigned long long input_buf_siz;
41
Tom Zanussi5205aec2012-04-06 00:47:58 +020042static int is_flag_field;
43static int is_symbolic_field;
44
Steven Rostedtf7d82352012-04-06 00:47:53 +020045static int show_warning = 1;
46
47#define do_warning(fmt, ...) \
48 do { \
49 if (show_warning) \
50 warning(fmt, ##__VA_ARGS__); \
51 } while (0)
52
Namhyung Kim3388cc32014-03-19 10:22:53 +090053#define do_warning_event(event, fmt, ...) \
54 do { \
55 if (!show_warning) \
56 continue; \
57 \
58 if (event) \
59 warning("[%s:%s] " fmt, event->system, \
60 event->name, ##__VA_ARGS__); \
61 else \
62 warning(fmt, ##__VA_ARGS__); \
63 } while (0)
64
Steven Rostedtf7d82352012-04-06 00:47:53 +020065static void init_input_buf(const char *buf, unsigned long long size)
66{
67 input_buf = buf;
68 input_buf_siz = size;
69 input_buf_ptr = 0;
70}
71
72const char *pevent_get_input_buf(void)
73{
74 return input_buf;
75}
76
77unsigned long long pevent_get_input_buf_ptr(void)
78{
79 return input_buf_ptr;
80}
81
82struct event_handler {
83 struct event_handler *next;
84 int id;
85 const char *sys_name;
86 const char *event_name;
87 pevent_event_handler_func func;
88 void *context;
89};
90
91struct pevent_func_params {
92 struct pevent_func_params *next;
93 enum pevent_func_arg_type type;
94};
95
96struct pevent_function_handler {
97 struct pevent_function_handler *next;
98 enum pevent_func_arg_type ret_type;
99 char *name;
100 pevent_func_handler func;
101 struct pevent_func_params *params;
102 int nr_args;
103};
104
105static unsigned long long
106process_defined_func(struct trace_seq *s, void *data, int size,
107 struct event_format *event, struct print_arg *arg);
108
109static void free_func_handle(struct pevent_function_handler *func);
110
111/**
112 * pevent_buffer_init - init buffer for parsing
113 * @buf: buffer to parse
114 * @size: the size of the buffer
115 *
116 * For use with pevent_read_token(), this initializes the internal
117 * buffer that pevent_read_token() will parse.
118 */
119void pevent_buffer_init(const char *buf, unsigned long long size)
120{
121 init_input_buf(buf, size);
122}
123
124void breakpoint(void)
125{
126 static int x;
127 x++;
128}
129
130struct print_arg *alloc_arg(void)
131{
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -0300132 return calloc(1, sizeof(struct print_arg));
Steven Rostedtf7d82352012-04-06 00:47:53 +0200133}
134
135struct cmdline {
136 char *comm;
137 int pid;
138};
139
140static int cmdline_cmp(const void *a, const void *b)
141{
142 const struct cmdline *ca = a;
143 const struct cmdline *cb = b;
144
145 if (ca->pid < cb->pid)
146 return -1;
147 if (ca->pid > cb->pid)
148 return 1;
149
150 return 0;
151}
152
153struct cmdline_list {
154 struct cmdline_list *next;
155 char *comm;
156 int pid;
157};
158
159static int cmdline_init(struct pevent *pevent)
160{
161 struct cmdline_list *cmdlist = pevent->cmdlist;
162 struct cmdline_list *item;
163 struct cmdline *cmdlines;
164 int i;
165
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300166 cmdlines = malloc(sizeof(*cmdlines) * pevent->cmdline_count);
167 if (!cmdlines)
168 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200169
170 i = 0;
171 while (cmdlist) {
172 cmdlines[i].pid = cmdlist->pid;
173 cmdlines[i].comm = cmdlist->comm;
174 i++;
175 item = cmdlist;
176 cmdlist = cmdlist->next;
177 free(item);
178 }
179
180 qsort(cmdlines, pevent->cmdline_count, sizeof(*cmdlines), cmdline_cmp);
181
182 pevent->cmdlines = cmdlines;
183 pevent->cmdlist = NULL;
184
185 return 0;
186}
187
Arnaldo Carvalho de Melo27f94d52012-11-09 17:40:47 -0300188static const char *find_cmdline(struct pevent *pevent, int pid)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200189{
190 const struct cmdline *comm;
191 struct cmdline key;
192
193 if (!pid)
194 return "<idle>";
195
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300196 if (!pevent->cmdlines && cmdline_init(pevent))
197 return "<not enough memory for cmdlines!>";
Steven Rostedtf7d82352012-04-06 00:47:53 +0200198
199 key.pid = pid;
200
201 comm = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
202 sizeof(*pevent->cmdlines), cmdline_cmp);
203
204 if (comm)
205 return comm->comm;
206 return "<...>";
207}
208
209/**
210 * pevent_pid_is_registered - return if a pid has a cmdline registered
211 * @pevent: handle for the pevent
212 * @pid: The pid to check if it has a cmdline registered with.
213 *
214 * Returns 1 if the pid has a cmdline mapped to it
215 * 0 otherwise.
216 */
217int pevent_pid_is_registered(struct pevent *pevent, int pid)
218{
219 const struct cmdline *comm;
220 struct cmdline key;
221
222 if (!pid)
223 return 1;
224
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300225 if (!pevent->cmdlines && cmdline_init(pevent))
226 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200227
228 key.pid = pid;
229
230 comm = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
231 sizeof(*pevent->cmdlines), cmdline_cmp);
232
233 if (comm)
234 return 1;
235 return 0;
236}
237
238/*
239 * If the command lines have been converted to an array, then
240 * we must add this pid. This is much slower than when cmdlines
241 * are added before the array is initialized.
242 */
243static int add_new_comm(struct pevent *pevent, const char *comm, int pid)
244{
245 struct cmdline *cmdlines = pevent->cmdlines;
246 const struct cmdline *cmdline;
247 struct cmdline key;
248
249 if (!pid)
250 return 0;
251
252 /* avoid duplicates */
253 key.pid = pid;
254
255 cmdline = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
256 sizeof(*pevent->cmdlines), cmdline_cmp);
257 if (cmdline) {
258 errno = EEXIST;
259 return -1;
260 }
261
262 cmdlines = realloc(cmdlines, sizeof(*cmdlines) * (pevent->cmdline_count + 1));
263 if (!cmdlines) {
264 errno = ENOMEM;
265 return -1;
266 }
267
Steven Rostedtf7d82352012-04-06 00:47:53 +0200268 cmdlines[pevent->cmdline_count].comm = strdup(comm);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300269 if (!cmdlines[pevent->cmdline_count].comm) {
270 free(cmdlines);
271 errno = ENOMEM;
272 return -1;
273 }
274
275 cmdlines[pevent->cmdline_count].pid = pid;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200276
277 if (cmdlines[pevent->cmdline_count].comm)
278 pevent->cmdline_count++;
279
280 qsort(cmdlines, pevent->cmdline_count, sizeof(*cmdlines), cmdline_cmp);
281 pevent->cmdlines = cmdlines;
282
283 return 0;
284}
285
286/**
287 * pevent_register_comm - register a pid / comm mapping
288 * @pevent: handle for the pevent
289 * @comm: the command line to register
290 * @pid: the pid to map the command line to
291 *
292 * This adds a mapping to search for command line names with
293 * a given pid. The comm is duplicated.
294 */
295int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
296{
297 struct cmdline_list *item;
298
299 if (pevent->cmdlines)
300 return add_new_comm(pevent, comm, pid);
301
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300302 item = malloc(sizeof(*item));
303 if (!item)
304 return -1;
305
Steven Rostedtf7d82352012-04-06 00:47:53 +0200306 item->comm = strdup(comm);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300307 if (!item->comm) {
308 free(item);
309 return -1;
310 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200311 item->pid = pid;
312 item->next = pevent->cmdlist;
313
314 pevent->cmdlist = item;
315 pevent->cmdline_count++;
316
317 return 0;
318}
319
Yoshihiro YUNOMAE1b372ca2013-11-01 17:53:53 -0400320void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock)
321{
322 pevent->trace_clock = trace_clock;
323}
324
Steven Rostedtf7d82352012-04-06 00:47:53 +0200325struct func_map {
326 unsigned long long addr;
327 char *func;
328 char *mod;
329};
330
331struct func_list {
332 struct func_list *next;
333 unsigned long long addr;
334 char *func;
335 char *mod;
336};
337
338static int func_cmp(const void *a, const void *b)
339{
340 const struct func_map *fa = a;
341 const struct func_map *fb = b;
342
343 if (fa->addr < fb->addr)
344 return -1;
345 if (fa->addr > fb->addr)
346 return 1;
347
348 return 0;
349}
350
351/*
352 * We are searching for a record in between, not an exact
353 * match.
354 */
355static int func_bcmp(const void *a, const void *b)
356{
357 const struct func_map *fa = a;
358 const struct func_map *fb = b;
359
360 if ((fa->addr == fb->addr) ||
361
362 (fa->addr > fb->addr &&
363 fa->addr < (fb+1)->addr))
364 return 0;
365
366 if (fa->addr < fb->addr)
367 return -1;
368
369 return 1;
370}
371
372static int func_map_init(struct pevent *pevent)
373{
374 struct func_list *funclist;
375 struct func_list *item;
376 struct func_map *func_map;
377 int i;
378
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300379 func_map = malloc(sizeof(*func_map) * (pevent->func_count + 1));
380 if (!func_map)
381 return -1;
382
Steven Rostedtf7d82352012-04-06 00:47:53 +0200383 funclist = pevent->funclist;
384
385 i = 0;
386 while (funclist) {
387 func_map[i].func = funclist->func;
388 func_map[i].addr = funclist->addr;
389 func_map[i].mod = funclist->mod;
390 i++;
391 item = funclist;
392 funclist = funclist->next;
393 free(item);
394 }
395
396 qsort(func_map, pevent->func_count, sizeof(*func_map), func_cmp);
397
398 /*
399 * Add a special record at the end.
400 */
401 func_map[pevent->func_count].func = NULL;
402 func_map[pevent->func_count].addr = 0;
403 func_map[pevent->func_count].mod = NULL;
404
405 pevent->func_map = func_map;
406 pevent->funclist = NULL;
407
408 return 0;
409}
410
411static struct func_map *
412find_func(struct pevent *pevent, unsigned long long addr)
413{
414 struct func_map *func;
415 struct func_map key;
416
417 if (!pevent->func_map)
418 func_map_init(pevent);
419
420 key.addr = addr;
421
422 func = bsearch(&key, pevent->func_map, pevent->func_count,
423 sizeof(*pevent->func_map), func_bcmp);
424
425 return func;
426}
427
428/**
429 * pevent_find_function - find a function by a given address
430 * @pevent: handle for the pevent
431 * @addr: the address to find the function with
432 *
433 * Returns a pointer to the function stored that has the given
434 * address. Note, the address does not have to be exact, it
435 * will select the function that would contain the address.
436 */
437const char *pevent_find_function(struct pevent *pevent, unsigned long long addr)
438{
439 struct func_map *map;
440
441 map = find_func(pevent, addr);
442 if (!map)
443 return NULL;
444
445 return map->func;
446}
447
448/**
449 * pevent_find_function_address - find a function address by a given address
450 * @pevent: handle for the pevent
451 * @addr: the address to find the function with
452 *
453 * Returns the address the function starts at. This can be used in
454 * conjunction with pevent_find_function to print both the function
455 * name and the function offset.
456 */
457unsigned long long
458pevent_find_function_address(struct pevent *pevent, unsigned long long addr)
459{
460 struct func_map *map;
461
462 map = find_func(pevent, addr);
463 if (!map)
464 return 0;
465
466 return map->addr;
467}
468
469/**
470 * pevent_register_function - register a function with a given address
471 * @pevent: handle for the pevent
472 * @function: the function name to register
473 * @addr: the address the function starts at
474 * @mod: the kernel module the function may be in (NULL for none)
475 *
476 * This registers a function name with an address and module.
477 * The @func passed in is duplicated.
478 */
479int pevent_register_function(struct pevent *pevent, char *func,
480 unsigned long long addr, char *mod)
481{
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300482 struct func_list *item = malloc(sizeof(*item));
Steven Rostedtf7d82352012-04-06 00:47:53 +0200483
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300484 if (!item)
485 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200486
487 item->next = pevent->funclist;
488 item->func = strdup(func);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300489 if (!item->func)
490 goto out_free;
491
492 if (mod) {
Steven Rostedtf7d82352012-04-06 00:47:53 +0200493 item->mod = strdup(mod);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300494 if (!item->mod)
495 goto out_free_func;
496 } else
Steven Rostedtf7d82352012-04-06 00:47:53 +0200497 item->mod = NULL;
498 item->addr = addr;
499
Namhyung Kimca638582012-04-09 11:54:31 +0900500 pevent->funclist = item;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200501 pevent->func_count++;
502
503 return 0;
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300504
505out_free_func:
506 free(item->func);
507 item->func = NULL;
508out_free:
509 free(item);
510 errno = ENOMEM;
511 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200512}
513
514/**
515 * pevent_print_funcs - print out the stored functions
516 * @pevent: handle for the pevent
517 *
518 * This prints out the stored functions.
519 */
520void pevent_print_funcs(struct pevent *pevent)
521{
522 int i;
523
524 if (!pevent->func_map)
525 func_map_init(pevent);
526
527 for (i = 0; i < (int)pevent->func_count; i++) {
528 printf("%016llx %s",
529 pevent->func_map[i].addr,
530 pevent->func_map[i].func);
531 if (pevent->func_map[i].mod)
532 printf(" [%s]\n", pevent->func_map[i].mod);
533 else
534 printf("\n");
535 }
536}
537
538struct printk_map {
539 unsigned long long addr;
540 char *printk;
541};
542
543struct printk_list {
544 struct printk_list *next;
545 unsigned long long addr;
546 char *printk;
547};
548
549static int printk_cmp(const void *a, const void *b)
550{
Namhyung Kim0fc45ef2012-04-09 11:54:29 +0900551 const struct printk_map *pa = a;
552 const struct printk_map *pb = b;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200553
Namhyung Kim0fc45ef2012-04-09 11:54:29 +0900554 if (pa->addr < pb->addr)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200555 return -1;
Namhyung Kim0fc45ef2012-04-09 11:54:29 +0900556 if (pa->addr > pb->addr)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200557 return 1;
558
559 return 0;
560}
561
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300562static int printk_map_init(struct pevent *pevent)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200563{
564 struct printk_list *printklist;
565 struct printk_list *item;
566 struct printk_map *printk_map;
567 int i;
568
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300569 printk_map = malloc(sizeof(*printk_map) * (pevent->printk_count + 1));
570 if (!printk_map)
571 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200572
573 printklist = pevent->printklist;
574
575 i = 0;
576 while (printklist) {
577 printk_map[i].printk = printklist->printk;
578 printk_map[i].addr = printklist->addr;
579 i++;
580 item = printklist;
581 printklist = printklist->next;
582 free(item);
583 }
584
585 qsort(printk_map, pevent->printk_count, sizeof(*printk_map), printk_cmp);
586
587 pevent->printk_map = printk_map;
588 pevent->printklist = NULL;
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300589
590 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200591}
592
593static struct printk_map *
594find_printk(struct pevent *pevent, unsigned long long addr)
595{
596 struct printk_map *printk;
597 struct printk_map key;
598
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300599 if (!pevent->printk_map && printk_map_init(pevent))
600 return NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200601
602 key.addr = addr;
603
604 printk = bsearch(&key, pevent->printk_map, pevent->printk_count,
605 sizeof(*pevent->printk_map), printk_cmp);
606
607 return printk;
608}
609
610/**
611 * pevent_register_print_string - register a string by its address
612 * @pevent: handle for the pevent
613 * @fmt: the string format to register
614 * @addr: the address the string was located at
615 *
616 * This registers a string by the address it was stored in the kernel.
617 * The @fmt passed in is duplicated.
618 */
Steven Rostedt (Red Hat)18900af2013-11-01 17:53:54 -0400619int pevent_register_print_string(struct pevent *pevent, const char *fmt,
Steven Rostedtf7d82352012-04-06 00:47:53 +0200620 unsigned long long addr)
621{
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300622 struct printk_list *item = malloc(sizeof(*item));
Steven Rostedt (Red Hat)18900af2013-11-01 17:53:54 -0400623 char *p;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200624
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300625 if (!item)
626 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200627
628 item->next = pevent->printklist;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200629 item->addr = addr;
630
Steven Rostedt (Red Hat)18900af2013-11-01 17:53:54 -0400631 /* Strip off quotes and '\n' from the end */
632 if (fmt[0] == '"')
633 fmt++;
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300634 item->printk = strdup(fmt);
Namhyung Kimca638582012-04-09 11:54:31 +0900635 if (!item->printk)
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300636 goto out_free;
Namhyung Kimca638582012-04-09 11:54:31 +0900637
Steven Rostedt (Red Hat)18900af2013-11-01 17:53:54 -0400638 p = item->printk + strlen(item->printk) - 1;
639 if (*p == '"')
640 *p = 0;
641
642 p -= 2;
643 if (strcmp(p, "\\n") == 0)
644 *p = 0;
645
Namhyung Kimca638582012-04-09 11:54:31 +0900646 pevent->printklist = item;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200647 pevent->printk_count++;
648
649 return 0;
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300650
651out_free:
652 free(item);
653 errno = ENOMEM;
654 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200655}
656
657/**
658 * pevent_print_printk - print out the stored strings
659 * @pevent: handle for the pevent
660 *
661 * This prints the string formats that were stored.
662 */
663void pevent_print_printk(struct pevent *pevent)
664{
665 int i;
666
667 if (!pevent->printk_map)
668 printk_map_init(pevent);
669
670 for (i = 0; i < (int)pevent->printk_count; i++) {
671 printf("%016llx %s\n",
672 pevent->printk_map[i].addr,
673 pevent->printk_map[i].printk);
674 }
675}
676
677static struct event_format *alloc_event(void)
678{
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -0300679 return calloc(1, sizeof(struct event_format));
Steven Rostedtf7d82352012-04-06 00:47:53 +0200680}
681
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300682static int add_event(struct pevent *pevent, struct event_format *event)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200683{
684 int i;
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300685 struct event_format **events = realloc(pevent->events, sizeof(event) *
686 (pevent->nr_events + 1));
687 if (!events)
688 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200689
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300690 pevent->events = events;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200691
692 for (i = 0; i < pevent->nr_events; i++) {
693 if (pevent->events[i]->id > event->id)
694 break;
695 }
696 if (i < pevent->nr_events)
697 memmove(&pevent->events[i + 1],
698 &pevent->events[i],
699 sizeof(event) * (pevent->nr_events - i));
700
701 pevent->events[i] = event;
702 pevent->nr_events++;
703
704 event->pevent = pevent;
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300705
706 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200707}
708
709static int event_item_type(enum event_type type)
710{
711 switch (type) {
712 case EVENT_ITEM ... EVENT_SQUOTE:
713 return 1;
714 case EVENT_ERROR ... EVENT_DELIM:
715 default:
716 return 0;
717 }
718}
719
720static void free_flag_sym(struct print_flag_sym *fsym)
721{
722 struct print_flag_sym *next;
723
724 while (fsym) {
725 next = fsym->next;
726 free(fsym->value);
727 free(fsym->str);
728 free(fsym);
729 fsym = next;
730 }
731}
732
733static void free_arg(struct print_arg *arg)
734{
735 struct print_arg *farg;
736
737 if (!arg)
738 return;
739
740 switch (arg->type) {
741 case PRINT_ATOM:
742 free(arg->atom.atom);
743 break;
744 case PRINT_FIELD:
745 free(arg->field.name);
746 break;
747 case PRINT_FLAGS:
748 free_arg(arg->flags.field);
749 free(arg->flags.delim);
750 free_flag_sym(arg->flags.flags);
751 break;
752 case PRINT_SYMBOL:
753 free_arg(arg->symbol.field);
754 free_flag_sym(arg->symbol.symbols);
755 break;
Namhyung Kime080e6f2012-06-27 09:41:41 +0900756 case PRINT_HEX:
757 free_arg(arg->hex.field);
758 free_arg(arg->hex.size);
759 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200760 case PRINT_TYPE:
761 free(arg->typecast.type);
762 free_arg(arg->typecast.item);
763 break;
764 case PRINT_STRING:
765 case PRINT_BSTRING:
766 free(arg->string.string);
767 break;
768 case PRINT_DYNAMIC_ARRAY:
769 free(arg->dynarray.index);
770 break;
771 case PRINT_OP:
772 free(arg->op.op);
773 free_arg(arg->op.left);
774 free_arg(arg->op.right);
775 break;
776 case PRINT_FUNC:
777 while (arg->func.args) {
778 farg = arg->func.args;
779 arg->func.args = farg->next;
780 free_arg(farg);
781 }
782 break;
783
784 case PRINT_NULL:
785 default:
786 break;
787 }
788
789 free(arg);
790}
791
792static enum event_type get_type(int ch)
793{
794 if (ch == '\n')
795 return EVENT_NEWLINE;
796 if (isspace(ch))
797 return EVENT_SPACE;
798 if (isalnum(ch) || ch == '_')
799 return EVENT_ITEM;
800 if (ch == '\'')
801 return EVENT_SQUOTE;
802 if (ch == '"')
803 return EVENT_DQUOTE;
804 if (!isprint(ch))
805 return EVENT_NONE;
806 if (ch == '(' || ch == ')' || ch == ',')
807 return EVENT_DELIM;
808
809 return EVENT_OP;
810}
811
812static int __read_char(void)
813{
814 if (input_buf_ptr >= input_buf_siz)
815 return -1;
816
817 return input_buf[input_buf_ptr++];
818}
819
820static int __peek_char(void)
821{
822 if (input_buf_ptr >= input_buf_siz)
823 return -1;
824
825 return input_buf[input_buf_ptr];
826}
827
828/**
829 * pevent_peek_char - peek at the next character that will be read
830 *
831 * Returns the next character read, or -1 if end of buffer.
832 */
833int pevent_peek_char(void)
834{
835 return __peek_char();
836}
837
Namhyung Kimdeba3fb2012-04-09 11:54:30 +0900838static int extend_token(char **tok, char *buf, int size)
839{
840 char *newtok = realloc(*tok, size);
841
842 if (!newtok) {
843 free(*tok);
844 *tok = NULL;
845 return -1;
846 }
847
848 if (!*tok)
849 strcpy(newtok, buf);
850 else
851 strcat(newtok, buf);
852 *tok = newtok;
853
854 return 0;
855}
856
Steven Rostedtf7d82352012-04-06 00:47:53 +0200857static enum event_type force_token(const char *str, char **tok);
858
859static enum event_type __read_token(char **tok)
860{
861 char buf[BUFSIZ];
862 int ch, last_ch, quote_ch, next_ch;
863 int i = 0;
864 int tok_size = 0;
865 enum event_type type;
866
867 *tok = NULL;
868
869
870 ch = __read_char();
871 if (ch < 0)
872 return EVENT_NONE;
873
874 type = get_type(ch);
875 if (type == EVENT_NONE)
876 return type;
877
878 buf[i++] = ch;
879
880 switch (type) {
881 case EVENT_NEWLINE:
882 case EVENT_DELIM:
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -0300883 if (asprintf(tok, "%c", ch) < 0)
884 return EVENT_ERROR;
885
Steven Rostedtf7d82352012-04-06 00:47:53 +0200886 return type;
887
888 case EVENT_OP:
889 switch (ch) {
890 case '-':
891 next_ch = __peek_char();
892 if (next_ch == '>') {
893 buf[i++] = __read_char();
894 break;
895 }
896 /* fall through */
897 case '+':
898 case '|':
899 case '&':
900 case '>':
901 case '<':
902 last_ch = ch;
903 ch = __peek_char();
904 if (ch != last_ch)
905 goto test_equal;
906 buf[i++] = __read_char();
907 switch (last_ch) {
908 case '>':
909 case '<':
910 goto test_equal;
911 default:
912 break;
913 }
914 break;
915 case '!':
916 case '=':
917 goto test_equal;
918 default: /* what should we do instead? */
919 break;
920 }
921 buf[i] = 0;
922 *tok = strdup(buf);
923 return type;
924
925 test_equal:
926 ch = __peek_char();
927 if (ch == '=')
928 buf[i++] = __read_char();
929 goto out;
930
931 case EVENT_DQUOTE:
932 case EVENT_SQUOTE:
933 /* don't keep quotes */
934 i--;
935 quote_ch = ch;
936 last_ch = 0;
937 concat:
938 do {
939 if (i == (BUFSIZ - 1)) {
940 buf[i] = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200941 tok_size += BUFSIZ;
Namhyung Kimdeba3fb2012-04-09 11:54:30 +0900942
943 if (extend_token(tok, buf, tok_size) < 0)
944 return EVENT_NONE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200945 i = 0;
946 }
947 last_ch = ch;
948 ch = __read_char();
949 buf[i++] = ch;
950 /* the '\' '\' will cancel itself */
951 if (ch == '\\' && last_ch == '\\')
952 last_ch = 0;
953 } while (ch != quote_ch || last_ch == '\\');
954 /* remove the last quote */
955 i--;
956
957 /*
958 * For strings (double quotes) check the next token.
959 * If it is another string, concatinate the two.
960 */
961 if (type == EVENT_DQUOTE) {
962 unsigned long long save_input_buf_ptr = input_buf_ptr;
963
964 do {
965 ch = __read_char();
966 } while (isspace(ch));
967 if (ch == '"')
968 goto concat;
969 input_buf_ptr = save_input_buf_ptr;
970 }
971
972 goto out;
973
974 case EVENT_ERROR ... EVENT_SPACE:
975 case EVENT_ITEM:
976 default:
977 break;
978 }
979
980 while (get_type(__peek_char()) == type) {
981 if (i == (BUFSIZ - 1)) {
982 buf[i] = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200983 tok_size += BUFSIZ;
Namhyung Kimdeba3fb2012-04-09 11:54:30 +0900984
985 if (extend_token(tok, buf, tok_size) < 0)
986 return EVENT_NONE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200987 i = 0;
988 }
989 ch = __read_char();
990 buf[i++] = ch;
991 }
992
993 out:
994 buf[i] = 0;
Namhyung Kimdeba3fb2012-04-09 11:54:30 +0900995 if (extend_token(tok, buf, tok_size + i + 1) < 0)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200996 return EVENT_NONE;
997
998 if (type == EVENT_ITEM) {
999 /*
1000 * Older versions of the kernel has a bug that
1001 * creates invalid symbols and will break the mac80211
1002 * parsing. This is a work around to that bug.
1003 *
1004 * See Linux kernel commit:
1005 * 811cb50baf63461ce0bdb234927046131fc7fa8b
1006 */
1007 if (strcmp(*tok, "LOCAL_PR_FMT") == 0) {
1008 free(*tok);
1009 *tok = NULL;
1010 return force_token("\"\%s\" ", tok);
1011 } else if (strcmp(*tok, "STA_PR_FMT") == 0) {
1012 free(*tok);
1013 *tok = NULL;
1014 return force_token("\" sta:%pM\" ", tok);
1015 } else if (strcmp(*tok, "VIF_PR_FMT") == 0) {
1016 free(*tok);
1017 *tok = NULL;
1018 return force_token("\" vif:%p(%d)\" ", tok);
1019 }
1020 }
1021
1022 return type;
1023}
1024
1025static enum event_type force_token(const char *str, char **tok)
1026{
1027 const char *save_input_buf;
1028 unsigned long long save_input_buf_ptr;
1029 unsigned long long save_input_buf_siz;
1030 enum event_type type;
1031
1032 /* save off the current input pointers */
1033 save_input_buf = input_buf;
1034 save_input_buf_ptr = input_buf_ptr;
1035 save_input_buf_siz = input_buf_siz;
1036
1037 init_input_buf(str, strlen(str));
1038
1039 type = __read_token(tok);
1040
1041 /* reset back to original token */
1042 input_buf = save_input_buf;
1043 input_buf_ptr = save_input_buf_ptr;
1044 input_buf_siz = save_input_buf_siz;
1045
1046 return type;
1047}
1048
1049static void free_token(char *tok)
1050{
1051 if (tok)
1052 free(tok);
1053}
1054
1055static enum event_type read_token(char **tok)
1056{
1057 enum event_type type;
1058
1059 for (;;) {
1060 type = __read_token(tok);
1061 if (type != EVENT_SPACE)
1062 return type;
1063
1064 free_token(*tok);
1065 }
1066
1067 /* not reached */
1068 *tok = NULL;
1069 return EVENT_NONE;
1070}
1071
1072/**
1073 * pevent_read_token - access to utilites to use the pevent parser
1074 * @tok: The token to return
1075 *
1076 * This will parse tokens from the string given by
1077 * pevent_init_data().
1078 *
1079 * Returns the token type.
1080 */
1081enum event_type pevent_read_token(char **tok)
1082{
1083 return read_token(tok);
1084}
1085
1086/**
1087 * pevent_free_token - free a token returned by pevent_read_token
1088 * @token: the token to free
1089 */
1090void pevent_free_token(char *token)
1091{
1092 free_token(token);
1093}
1094
1095/* no newline */
1096static enum event_type read_token_item(char **tok)
1097{
1098 enum event_type type;
1099
1100 for (;;) {
1101 type = __read_token(tok);
1102 if (type != EVENT_SPACE && type != EVENT_NEWLINE)
1103 return type;
1104 free_token(*tok);
1105 *tok = NULL;
1106 }
1107
1108 /* not reached */
1109 *tok = NULL;
1110 return EVENT_NONE;
1111}
1112
1113static int test_type(enum event_type type, enum event_type expect)
1114{
1115 if (type != expect) {
1116 do_warning("Error: expected type %d but read %d",
1117 expect, type);
1118 return -1;
1119 }
1120 return 0;
1121}
1122
1123static int test_type_token(enum event_type type, const char *token,
1124 enum event_type expect, const char *expect_tok)
1125{
1126 if (type != expect) {
1127 do_warning("Error: expected type %d but read %d",
1128 expect, type);
1129 return -1;
1130 }
1131
1132 if (strcmp(token, expect_tok) != 0) {
1133 do_warning("Error: expected '%s' but read '%s'",
1134 expect_tok, token);
1135 return -1;
1136 }
1137 return 0;
1138}
1139
1140static int __read_expect_type(enum event_type expect, char **tok, int newline_ok)
1141{
1142 enum event_type type;
1143
1144 if (newline_ok)
1145 type = read_token(tok);
1146 else
1147 type = read_token_item(tok);
1148 return test_type(type, expect);
1149}
1150
1151static int read_expect_type(enum event_type expect, char **tok)
1152{
1153 return __read_expect_type(expect, tok, 1);
1154}
1155
1156static int __read_expected(enum event_type expect, const char *str,
1157 int newline_ok)
1158{
1159 enum event_type type;
1160 char *token;
1161 int ret;
1162
1163 if (newline_ok)
1164 type = read_token(&token);
1165 else
1166 type = read_token_item(&token);
1167
1168 ret = test_type_token(type, token, expect, str);
1169
1170 free_token(token);
1171
1172 return ret;
1173}
1174
1175static int read_expected(enum event_type expect, const char *str)
1176{
1177 return __read_expected(expect, str, 1);
1178}
1179
1180static int read_expected_item(enum event_type expect, const char *str)
1181{
1182 return __read_expected(expect, str, 0);
1183}
1184
1185static char *event_read_name(void)
1186{
1187 char *token;
1188
1189 if (read_expected(EVENT_ITEM, "name") < 0)
1190 return NULL;
1191
1192 if (read_expected(EVENT_OP, ":") < 0)
1193 return NULL;
1194
1195 if (read_expect_type(EVENT_ITEM, &token) < 0)
1196 goto fail;
1197
1198 return token;
1199
1200 fail:
1201 free_token(token);
1202 return NULL;
1203}
1204
1205static int event_read_id(void)
1206{
1207 char *token;
1208 int id;
1209
1210 if (read_expected_item(EVENT_ITEM, "ID") < 0)
1211 return -1;
1212
1213 if (read_expected(EVENT_OP, ":") < 0)
1214 return -1;
1215
1216 if (read_expect_type(EVENT_ITEM, &token) < 0)
1217 goto fail;
1218
1219 id = strtoul(token, NULL, 0);
1220 free_token(token);
1221 return id;
1222
1223 fail:
1224 free_token(token);
1225 return -1;
1226}
1227
1228static int field_is_string(struct format_field *field)
1229{
1230 if ((field->flags & FIELD_IS_ARRAY) &&
1231 (strstr(field->type, "char") || strstr(field->type, "u8") ||
1232 strstr(field->type, "s8")))
1233 return 1;
1234
1235 return 0;
1236}
1237
1238static int field_is_dynamic(struct format_field *field)
1239{
1240 if (strncmp(field->type, "__data_loc", 10) == 0)
1241 return 1;
1242
1243 return 0;
1244}
1245
1246static int field_is_long(struct format_field *field)
1247{
1248 /* includes long long */
1249 if (strstr(field->type, "long"))
1250 return 1;
1251
1252 return 0;
1253}
1254
Jiri Olsae23c1a52013-01-24 21:46:43 +01001255static unsigned int type_size(const char *name)
1256{
1257 /* This covers all FIELD_IS_STRING types. */
1258 static struct {
1259 const char *type;
1260 unsigned int size;
1261 } table[] = {
1262 { "u8", 1 },
1263 { "u16", 2 },
1264 { "u32", 4 },
1265 { "u64", 8 },
1266 { "s8", 1 },
1267 { "s16", 2 },
1268 { "s32", 4 },
1269 { "s64", 8 },
1270 { "char", 1 },
1271 { },
1272 };
1273 int i;
1274
1275 for (i = 0; table[i].type; i++) {
1276 if (!strcmp(table[i].type, name))
1277 return table[i].size;
1278 }
1279
1280 return 0;
1281}
1282
Steven Rostedtf7d82352012-04-06 00:47:53 +02001283static int event_read_fields(struct event_format *event, struct format_field **fields)
1284{
1285 struct format_field *field = NULL;
1286 enum event_type type;
1287 char *token;
1288 char *last_token;
1289 int count = 0;
1290
1291 do {
Jiri Olsae23c1a52013-01-24 21:46:43 +01001292 unsigned int size_dynamic = 0;
1293
Steven Rostedtf7d82352012-04-06 00:47:53 +02001294 type = read_token(&token);
1295 if (type == EVENT_NEWLINE) {
1296 free_token(token);
1297 return count;
1298 }
1299
1300 count++;
1301
1302 if (test_type_token(type, token, EVENT_ITEM, "field"))
1303 goto fail;
1304 free_token(token);
1305
1306 type = read_token(&token);
1307 /*
1308 * The ftrace fields may still use the "special" name.
1309 * Just ignore it.
1310 */
1311 if (event->flags & EVENT_FL_ISFTRACE &&
1312 type == EVENT_ITEM && strcmp(token, "special") == 0) {
1313 free_token(token);
1314 type = read_token(&token);
1315 }
1316
1317 if (test_type_token(type, token, EVENT_OP, ":") < 0)
1318 goto fail;
1319
1320 free_token(token);
1321 if (read_expect_type(EVENT_ITEM, &token) < 0)
1322 goto fail;
1323
1324 last_token = token;
1325
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -03001326 field = calloc(1, sizeof(*field));
1327 if (!field)
1328 goto fail;
1329
Steven Rostedtf7d82352012-04-06 00:47:53 +02001330 field->event = event;
1331
1332 /* read the rest of the type */
1333 for (;;) {
1334 type = read_token(&token);
1335 if (type == EVENT_ITEM ||
1336 (type == EVENT_OP && strcmp(token, "*") == 0) ||
1337 /*
1338 * Some of the ftrace fields are broken and have
1339 * an illegal "." in them.
1340 */
1341 (event->flags & EVENT_FL_ISFTRACE &&
1342 type == EVENT_OP && strcmp(token, ".") == 0)) {
1343
1344 if (strcmp(token, "*") == 0)
1345 field->flags |= FIELD_IS_POINTER;
1346
1347 if (field->type) {
Namhyung Kimd2864472012-04-09 11:54:33 +09001348 char *new_type;
1349 new_type = realloc(field->type,
1350 strlen(field->type) +
1351 strlen(last_token) + 2);
1352 if (!new_type) {
1353 free(last_token);
1354 goto fail;
1355 }
1356 field->type = new_type;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001357 strcat(field->type, " ");
1358 strcat(field->type, last_token);
1359 free(last_token);
1360 } else
1361 field->type = last_token;
1362 last_token = token;
1363 continue;
1364 }
1365
1366 break;
1367 }
1368
1369 if (!field->type) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09001370 do_warning_event(event, "%s: no type found", __func__);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001371 goto fail;
1372 }
1373 field->name = last_token;
1374
1375 if (test_type(type, EVENT_OP))
1376 goto fail;
1377
1378 if (strcmp(token, "[") == 0) {
1379 enum event_type last_type = type;
1380 char *brackets = token;
Namhyung Kimd2864472012-04-09 11:54:33 +09001381 char *new_brackets;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001382 int len;
1383
1384 field->flags |= FIELD_IS_ARRAY;
1385
1386 type = read_token(&token);
1387
1388 if (type == EVENT_ITEM)
1389 field->arraylen = strtoul(token, NULL, 0);
1390 else
1391 field->arraylen = 0;
1392
1393 while (strcmp(token, "]") != 0) {
1394 if (last_type == EVENT_ITEM &&
1395 type == EVENT_ITEM)
1396 len = 2;
1397 else
1398 len = 1;
1399 last_type = type;
1400
Namhyung Kimd2864472012-04-09 11:54:33 +09001401 new_brackets = realloc(brackets,
1402 strlen(brackets) +
1403 strlen(token) + len);
1404 if (!new_brackets) {
1405 free(brackets);
1406 goto fail;
1407 }
1408 brackets = new_brackets;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001409 if (len == 2)
1410 strcat(brackets, " ");
1411 strcat(brackets, token);
1412 /* We only care about the last token */
1413 field->arraylen = strtoul(token, NULL, 0);
1414 free_token(token);
1415 type = read_token(&token);
1416 if (type == EVENT_NONE) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09001417 do_warning_event(event, "failed to find token");
Steven Rostedtf7d82352012-04-06 00:47:53 +02001418 goto fail;
1419 }
1420 }
1421
1422 free_token(token);
1423
Namhyung Kimd2864472012-04-09 11:54:33 +09001424 new_brackets = realloc(brackets, strlen(brackets) + 2);
1425 if (!new_brackets) {
1426 free(brackets);
1427 goto fail;
1428 }
1429 brackets = new_brackets;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001430 strcat(brackets, "]");
1431
1432 /* add brackets to type */
1433
1434 type = read_token(&token);
1435 /*
1436 * If the next token is not an OP, then it is of
1437 * the format: type [] item;
1438 */
1439 if (type == EVENT_ITEM) {
Namhyung Kimd2864472012-04-09 11:54:33 +09001440 char *new_type;
1441 new_type = realloc(field->type,
1442 strlen(field->type) +
1443 strlen(field->name) +
1444 strlen(brackets) + 2);
1445 if (!new_type) {
1446 free(brackets);
1447 goto fail;
1448 }
1449 field->type = new_type;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001450 strcat(field->type, " ");
1451 strcat(field->type, field->name);
Jiri Olsae23c1a52013-01-24 21:46:43 +01001452 size_dynamic = type_size(field->name);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001453 free_token(field->name);
1454 strcat(field->type, brackets);
1455 field->name = token;
1456 type = read_token(&token);
1457 } else {
Namhyung Kimd2864472012-04-09 11:54:33 +09001458 char *new_type;
1459 new_type = realloc(field->type,
1460 strlen(field->type) +
1461 strlen(brackets) + 1);
1462 if (!new_type) {
1463 free(brackets);
1464 goto fail;
1465 }
1466 field->type = new_type;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001467 strcat(field->type, brackets);
1468 }
1469 free(brackets);
1470 }
1471
1472 if (field_is_string(field))
1473 field->flags |= FIELD_IS_STRING;
1474 if (field_is_dynamic(field))
1475 field->flags |= FIELD_IS_DYNAMIC;
1476 if (field_is_long(field))
1477 field->flags |= FIELD_IS_LONG;
1478
1479 if (test_type_token(type, token, EVENT_OP, ";"))
1480 goto fail;
1481 free_token(token);
1482
1483 if (read_expected(EVENT_ITEM, "offset") < 0)
1484 goto fail_expect;
1485
1486 if (read_expected(EVENT_OP, ":") < 0)
1487 goto fail_expect;
1488
1489 if (read_expect_type(EVENT_ITEM, &token))
1490 goto fail;
1491 field->offset = strtoul(token, NULL, 0);
1492 free_token(token);
1493
1494 if (read_expected(EVENT_OP, ";") < 0)
1495 goto fail_expect;
1496
1497 if (read_expected(EVENT_ITEM, "size") < 0)
1498 goto fail_expect;
1499
1500 if (read_expected(EVENT_OP, ":") < 0)
1501 goto fail_expect;
1502
1503 if (read_expect_type(EVENT_ITEM, &token))
1504 goto fail;
1505 field->size = strtoul(token, NULL, 0);
1506 free_token(token);
1507
1508 if (read_expected(EVENT_OP, ";") < 0)
1509 goto fail_expect;
1510
1511 type = read_token(&token);
1512 if (type != EVENT_NEWLINE) {
1513 /* newer versions of the kernel have a "signed" type */
1514 if (test_type_token(type, token, EVENT_ITEM, "signed"))
1515 goto fail;
1516
1517 free_token(token);
1518
1519 if (read_expected(EVENT_OP, ":") < 0)
1520 goto fail_expect;
1521
1522 if (read_expect_type(EVENT_ITEM, &token))
1523 goto fail;
1524
Tom Zanussi10ee9fa2013-01-18 13:51:25 -06001525 if (strtoul(token, NULL, 0))
1526 field->flags |= FIELD_IS_SIGNED;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001527
1528 free_token(token);
1529 if (read_expected(EVENT_OP, ";") < 0)
1530 goto fail_expect;
1531
1532 if (read_expect_type(EVENT_NEWLINE, &token))
1533 goto fail;
1534 }
1535
1536 free_token(token);
1537
1538 if (field->flags & FIELD_IS_ARRAY) {
1539 if (field->arraylen)
1540 field->elementsize = field->size / field->arraylen;
Jiri Olsae23c1a52013-01-24 21:46:43 +01001541 else if (field->flags & FIELD_IS_DYNAMIC)
1542 field->elementsize = size_dynamic;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001543 else if (field->flags & FIELD_IS_STRING)
1544 field->elementsize = 1;
Jiri Olsae23c1a52013-01-24 21:46:43 +01001545 else if (field->flags & FIELD_IS_LONG)
1546 field->elementsize = event->pevent ?
1547 event->pevent->long_size :
1548 sizeof(long);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001549 } else
1550 field->elementsize = field->size;
1551
1552 *fields = field;
1553 fields = &field->next;
1554
1555 } while (1);
1556
1557 return 0;
1558
1559fail:
1560 free_token(token);
1561fail_expect:
Namhyung Kim57d34dc2012-05-23 11:36:47 +09001562 if (field) {
1563 free(field->type);
1564 free(field->name);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001565 free(field);
Namhyung Kim57d34dc2012-05-23 11:36:47 +09001566 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001567 return -1;
1568}
1569
1570static int event_read_format(struct event_format *event)
1571{
1572 char *token;
1573 int ret;
1574
1575 if (read_expected_item(EVENT_ITEM, "format") < 0)
1576 return -1;
1577
1578 if (read_expected(EVENT_OP, ":") < 0)
1579 return -1;
1580
1581 if (read_expect_type(EVENT_NEWLINE, &token))
1582 goto fail;
1583 free_token(token);
1584
1585 ret = event_read_fields(event, &event->format.common_fields);
1586 if (ret < 0)
1587 return ret;
1588 event->format.nr_common = ret;
1589
1590 ret = event_read_fields(event, &event->format.fields);
1591 if (ret < 0)
1592 return ret;
1593 event->format.nr_fields = ret;
1594
1595 return 0;
1596
1597 fail:
1598 free_token(token);
1599 return -1;
1600}
1601
1602static enum event_type
1603process_arg_token(struct event_format *event, struct print_arg *arg,
1604 char **tok, enum event_type type);
1605
1606static enum event_type
1607process_arg(struct event_format *event, struct print_arg *arg, char **tok)
1608{
1609 enum event_type type;
1610 char *token;
1611
1612 type = read_token(&token);
1613 *tok = token;
1614
1615 return process_arg_token(event, arg, tok, type);
1616}
1617
1618static enum event_type
1619process_op(struct event_format *event, struct print_arg *arg, char **tok);
1620
Steven Rostedteff2c922013-11-18 14:23:14 -05001621/*
1622 * For __print_symbolic() and __print_flags, we need to completely
1623 * evaluate the first argument, which defines what to print next.
1624 */
1625static enum event_type
1626process_field_arg(struct event_format *event, struct print_arg *arg, char **tok)
1627{
1628 enum event_type type;
1629
1630 type = process_arg(event, arg, tok);
1631
1632 while (type == EVENT_OP) {
1633 type = process_op(event, arg, tok);
1634 }
1635
1636 return type;
1637}
1638
Steven Rostedtf7d82352012-04-06 00:47:53 +02001639static enum event_type
1640process_cond(struct event_format *event, struct print_arg *top, char **tok)
1641{
1642 struct print_arg *arg, *left, *right;
1643 enum event_type type;
1644 char *token = NULL;
1645
1646 arg = alloc_arg();
1647 left = alloc_arg();
1648 right = alloc_arg();
1649
Namhyung Kimb1ac7542012-09-20 11:09:19 +09001650 if (!arg || !left || !right) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09001651 do_warning_event(event, "%s: not enough memory!", __func__);
Namhyung Kimb1ac7542012-09-20 11:09:19 +09001652 /* arg will be freed at out_free */
1653 free_arg(left);
1654 free_arg(right);
1655 goto out_free;
1656 }
1657
Steven Rostedtf7d82352012-04-06 00:47:53 +02001658 arg->type = PRINT_OP;
1659 arg->op.left = left;
1660 arg->op.right = right;
1661
1662 *tok = NULL;
1663 type = process_arg(event, left, &token);
1664
1665 again:
1666 /* Handle other operations in the arguments */
1667 if (type == EVENT_OP && strcmp(token, ":") != 0) {
1668 type = process_op(event, left, &token);
1669 goto again;
1670 }
1671
1672 if (test_type_token(type, token, EVENT_OP, ":"))
1673 goto out_free;
1674
1675 arg->op.op = token;
1676
1677 type = process_arg(event, right, &token);
1678
1679 top->op.right = arg;
1680
1681 *tok = token;
1682 return type;
1683
1684out_free:
1685 /* Top may point to itself */
1686 top->op.right = NULL;
1687 free_token(token);
1688 free_arg(arg);
1689 return EVENT_ERROR;
1690}
1691
1692static enum event_type
1693process_array(struct event_format *event, struct print_arg *top, char **tok)
1694{
1695 struct print_arg *arg;
1696 enum event_type type;
1697 char *token = NULL;
1698
1699 arg = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09001700 if (!arg) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09001701 do_warning_event(event, "%s: not enough memory!", __func__);
Namhyung Kimb1ac7542012-09-20 11:09:19 +09001702 /* '*tok' is set to top->op.op. No need to free. */
1703 *tok = NULL;
1704 return EVENT_ERROR;
1705 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001706
1707 *tok = NULL;
1708 type = process_arg(event, arg, &token);
1709 if (test_type_token(type, token, EVENT_OP, "]"))
1710 goto out_free;
1711
1712 top->op.right = arg;
1713
1714 free_token(token);
1715 type = read_token_item(&token);
1716 *tok = token;
1717
1718 return type;
1719
1720out_free:
Namhyung Kim1bce6e02012-09-19 15:58:41 +09001721 free_token(token);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001722 free_arg(arg);
1723 return EVENT_ERROR;
1724}
1725
1726static int get_op_prio(char *op)
1727{
1728 if (!op[1]) {
1729 switch (op[0]) {
1730 case '~':
1731 case '!':
1732 return 4;
1733 case '*':
1734 case '/':
1735 case '%':
1736 return 6;
1737 case '+':
1738 case '-':
1739 return 7;
1740 /* '>>' and '<<' are 8 */
1741 case '<':
1742 case '>':
1743 return 9;
1744 /* '==' and '!=' are 10 */
1745 case '&':
1746 return 11;
1747 case '^':
1748 return 12;
1749 case '|':
1750 return 13;
1751 case '?':
1752 return 16;
1753 default:
Vaibhav Nagarnaik14ffde02012-04-06 00:48:01 +02001754 do_warning("unknown op '%c'", op[0]);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001755 return -1;
1756 }
1757 } else {
1758 if (strcmp(op, "++") == 0 ||
1759 strcmp(op, "--") == 0) {
1760 return 3;
1761 } else if (strcmp(op, ">>") == 0 ||
1762 strcmp(op, "<<") == 0) {
1763 return 8;
1764 } else if (strcmp(op, ">=") == 0 ||
1765 strcmp(op, "<=") == 0) {
1766 return 9;
1767 } else if (strcmp(op, "==") == 0 ||
1768 strcmp(op, "!=") == 0) {
1769 return 10;
1770 } else if (strcmp(op, "&&") == 0) {
1771 return 14;
1772 } else if (strcmp(op, "||") == 0) {
1773 return 15;
1774 } else {
Vaibhav Nagarnaik14ffde02012-04-06 00:48:01 +02001775 do_warning("unknown op '%s'", op);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001776 return -1;
1777 }
1778 }
1779}
1780
Vaibhav Nagarnaik14ffde02012-04-06 00:48:01 +02001781static int set_op_prio(struct print_arg *arg)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001782{
1783
1784 /* single ops are the greatest */
Vaibhav Nagarnaik14ffde02012-04-06 00:48:01 +02001785 if (!arg->op.left || arg->op.left->type == PRINT_NULL)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001786 arg->op.prio = 0;
Vaibhav Nagarnaik14ffde02012-04-06 00:48:01 +02001787 else
1788 arg->op.prio = get_op_prio(arg->op.op);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001789
Vaibhav Nagarnaik14ffde02012-04-06 00:48:01 +02001790 return arg->op.prio;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001791}
1792
1793/* Note, *tok does not get freed, but will most likely be saved */
1794static enum event_type
1795process_op(struct event_format *event, struct print_arg *arg, char **tok)
1796{
1797 struct print_arg *left, *right = NULL;
1798 enum event_type type;
1799 char *token;
1800
1801 /* the op is passed in via tok */
1802 token = *tok;
1803
1804 if (arg->type == PRINT_OP && !arg->op.left) {
1805 /* handle single op */
1806 if (token[1]) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09001807 do_warning_event(event, "bad op token %s", token);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001808 goto out_free;
1809 }
1810 switch (token[0]) {
1811 case '~':
1812 case '!':
1813 case '+':
1814 case '-':
1815 break;
1816 default:
Namhyung Kim3388cc32014-03-19 10:22:53 +09001817 do_warning_event(event, "bad op token %s", token);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001818 goto out_free;
1819
1820 }
1821
1822 /* make an empty left */
1823 left = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09001824 if (!left)
1825 goto out_warn_free;
1826
Steven Rostedtf7d82352012-04-06 00:47:53 +02001827 left->type = PRINT_NULL;
1828 arg->op.left = left;
1829
1830 right = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09001831 if (!right)
1832 goto out_warn_free;
1833
Steven Rostedtf7d82352012-04-06 00:47:53 +02001834 arg->op.right = right;
1835
1836 /* do not free the token, it belongs to an op */
1837 *tok = NULL;
1838 type = process_arg(event, right, tok);
1839
1840 } else if (strcmp(token, "?") == 0) {
1841
1842 left = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09001843 if (!left)
1844 goto out_warn_free;
1845
Steven Rostedtf7d82352012-04-06 00:47:53 +02001846 /* copy the top arg to the left */
1847 *left = *arg;
1848
1849 arg->type = PRINT_OP;
1850 arg->op.op = token;
1851 arg->op.left = left;
1852 arg->op.prio = 0;
1853
Namhyung Kim41e51a22012-09-19 15:58:42 +09001854 /* it will set arg->op.right */
Steven Rostedtf7d82352012-04-06 00:47:53 +02001855 type = process_cond(event, arg, tok);
1856
1857 } else if (strcmp(token, ">>") == 0 ||
1858 strcmp(token, "<<") == 0 ||
1859 strcmp(token, "&") == 0 ||
1860 strcmp(token, "|") == 0 ||
1861 strcmp(token, "&&") == 0 ||
1862 strcmp(token, "||") == 0 ||
1863 strcmp(token, "-") == 0 ||
1864 strcmp(token, "+") == 0 ||
1865 strcmp(token, "*") == 0 ||
1866 strcmp(token, "^") == 0 ||
1867 strcmp(token, "/") == 0 ||
1868 strcmp(token, "<") == 0 ||
1869 strcmp(token, ">") == 0 ||
Namhyung Kimff582682013-01-15 17:02:19 +09001870 strcmp(token, "<=") == 0 ||
1871 strcmp(token, ">=") == 0 ||
Steven Rostedtf7d82352012-04-06 00:47:53 +02001872 strcmp(token, "==") == 0 ||
1873 strcmp(token, "!=") == 0) {
1874
1875 left = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09001876 if (!left)
1877 goto out_warn_free;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001878
1879 /* copy the top arg to the left */
1880 *left = *arg;
1881
1882 arg->type = PRINT_OP;
1883 arg->op.op = token;
1884 arg->op.left = left;
Namhyung Kim41e51a22012-09-19 15:58:42 +09001885 arg->op.right = NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001886
Vaibhav Nagarnaik14ffde02012-04-06 00:48:01 +02001887 if (set_op_prio(arg) == -1) {
1888 event->flags |= EVENT_FL_FAILED;
Namhyung Kimd1de1082012-05-23 11:36:49 +09001889 /* arg->op.op (= token) will be freed at out_free */
1890 arg->op.op = NULL;
Vaibhav Nagarnaik14ffde02012-04-06 00:48:01 +02001891 goto out_free;
1892 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001893
1894 type = read_token_item(&token);
1895 *tok = token;
1896
1897 /* could just be a type pointer */
1898 if ((strcmp(arg->op.op, "*") == 0) &&
1899 type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
Namhyung Kimd2864472012-04-09 11:54:33 +09001900 char *new_atom;
1901
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03001902 if (left->type != PRINT_ATOM) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09001903 do_warning_event(event, "bad pointer type");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03001904 goto out_free;
1905 }
Namhyung Kimd2864472012-04-09 11:54:33 +09001906 new_atom = realloc(left->atom.atom,
Steven Rostedtf7d82352012-04-06 00:47:53 +02001907 strlen(left->atom.atom) + 3);
Namhyung Kimd2864472012-04-09 11:54:33 +09001908 if (!new_atom)
Namhyung Kimb1ac7542012-09-20 11:09:19 +09001909 goto out_warn_free;
Namhyung Kimd2864472012-04-09 11:54:33 +09001910
1911 left->atom.atom = new_atom;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001912 strcat(left->atom.atom, " *");
1913 free(arg->op.op);
1914 *arg = *left;
1915 free(left);
1916
1917 return type;
1918 }
1919
1920 right = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09001921 if (!right)
1922 goto out_warn_free;
1923
Steven Rostedtf7d82352012-04-06 00:47:53 +02001924 type = process_arg_token(event, right, tok, type);
1925 arg->op.right = right;
1926
1927 } else if (strcmp(token, "[") == 0) {
1928
1929 left = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09001930 if (!left)
1931 goto out_warn_free;
1932
Steven Rostedtf7d82352012-04-06 00:47:53 +02001933 *left = *arg;
1934
1935 arg->type = PRINT_OP;
1936 arg->op.op = token;
1937 arg->op.left = left;
1938
1939 arg->op.prio = 0;
1940
Namhyung Kim41e51a22012-09-19 15:58:42 +09001941 /* it will set arg->op.right */
Steven Rostedtf7d82352012-04-06 00:47:53 +02001942 type = process_array(event, arg, tok);
1943
1944 } else {
Namhyung Kim3388cc32014-03-19 10:22:53 +09001945 do_warning_event(event, "unknown op '%s'", token);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001946 event->flags |= EVENT_FL_FAILED;
1947 /* the arg is now the left side */
1948 goto out_free;
1949 }
1950
1951 if (type == EVENT_OP && strcmp(*tok, ":") != 0) {
1952 int prio;
1953
1954 /* higher prios need to be closer to the root */
1955 prio = get_op_prio(*tok);
1956
1957 if (prio > arg->op.prio)
1958 return process_op(event, arg, tok);
1959
1960 return process_op(event, right, tok);
1961 }
1962
1963 return type;
1964
Namhyung Kimb1ac7542012-09-20 11:09:19 +09001965out_warn_free:
Namhyung Kim3388cc32014-03-19 10:22:53 +09001966 do_warning_event(event, "%s: not enough memory!", __func__);
Namhyung Kimb1ac7542012-09-20 11:09:19 +09001967out_free:
Steven Rostedtf7d82352012-04-06 00:47:53 +02001968 free_token(token);
1969 *tok = NULL;
1970 return EVENT_ERROR;
1971}
1972
1973static enum event_type
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001974process_entry(struct event_format *event __maybe_unused, struct print_arg *arg,
Steven Rostedtf7d82352012-04-06 00:47:53 +02001975 char **tok)
1976{
1977 enum event_type type;
1978 char *field;
1979 char *token;
1980
1981 if (read_expected(EVENT_OP, "->") < 0)
1982 goto out_err;
1983
1984 if (read_expect_type(EVENT_ITEM, &token) < 0)
1985 goto out_free;
1986 field = token;
1987
1988 arg->type = PRINT_FIELD;
1989 arg->field.name = field;
1990
Tom Zanussi5205aec2012-04-06 00:47:58 +02001991 if (is_flag_field) {
1992 arg->field.field = pevent_find_any_field(event, arg->field.name);
1993 arg->field.field->flags |= FIELD_IS_FLAG;
1994 is_flag_field = 0;
1995 } else if (is_symbolic_field) {
1996 arg->field.field = pevent_find_any_field(event, arg->field.name);
1997 arg->field.field->flags |= FIELD_IS_SYMBOLIC;
1998 is_symbolic_field = 0;
1999 }
2000
Steven Rostedtf7d82352012-04-06 00:47:53 +02002001 type = read_token(&token);
2002 *tok = token;
2003
2004 return type;
2005
2006 out_free:
2007 free_token(token);
2008 out_err:
2009 *tok = NULL;
2010 return EVENT_ERROR;
2011}
2012
2013static char *arg_eval (struct print_arg *arg);
2014
2015static unsigned long long
2016eval_type_str(unsigned long long val, const char *type, int pointer)
2017{
2018 int sign = 0;
2019 char *ref;
2020 int len;
2021
2022 len = strlen(type);
2023
2024 if (pointer) {
2025
2026 if (type[len-1] != '*') {
2027 do_warning("pointer expected with non pointer type");
2028 return val;
2029 }
2030
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03002031 ref = malloc(len);
2032 if (!ref) {
2033 do_warning("%s: not enough memory!", __func__);
2034 return val;
2035 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02002036 memcpy(ref, type, len);
2037
2038 /* chop off the " *" */
2039 ref[len - 2] = 0;
2040
2041 val = eval_type_str(val, ref, 0);
2042 free(ref);
2043 return val;
2044 }
2045
2046 /* check if this is a pointer */
2047 if (type[len - 1] == '*')
2048 return val;
2049
2050 /* Try to figure out the arg size*/
2051 if (strncmp(type, "struct", 6) == 0)
2052 /* all bets off */
2053 return val;
2054
2055 if (strcmp(type, "u8") == 0)
2056 return val & 0xff;
2057
2058 if (strcmp(type, "u16") == 0)
2059 return val & 0xffff;
2060
2061 if (strcmp(type, "u32") == 0)
2062 return val & 0xffffffff;
2063
2064 if (strcmp(type, "u64") == 0 ||
2065 strcmp(type, "s64"))
2066 return val;
2067
2068 if (strcmp(type, "s8") == 0)
2069 return (unsigned long long)(char)val & 0xff;
2070
2071 if (strcmp(type, "s16") == 0)
2072 return (unsigned long long)(short)val & 0xffff;
2073
2074 if (strcmp(type, "s32") == 0)
2075 return (unsigned long long)(int)val & 0xffffffff;
2076
2077 if (strncmp(type, "unsigned ", 9) == 0) {
2078 sign = 0;
2079 type += 9;
2080 }
2081
2082 if (strcmp(type, "char") == 0) {
2083 if (sign)
2084 return (unsigned long long)(char)val & 0xff;
2085 else
2086 return val & 0xff;
2087 }
2088
2089 if (strcmp(type, "short") == 0) {
2090 if (sign)
2091 return (unsigned long long)(short)val & 0xffff;
2092 else
2093 return val & 0xffff;
2094 }
2095
2096 if (strcmp(type, "int") == 0) {
2097 if (sign)
2098 return (unsigned long long)(int)val & 0xffffffff;
2099 else
2100 return val & 0xffffffff;
2101 }
2102
2103 return val;
2104}
2105
2106/*
2107 * Try to figure out the type.
2108 */
2109static unsigned long long
2110eval_type(unsigned long long val, struct print_arg *arg, int pointer)
2111{
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03002112 if (arg->type != PRINT_TYPE) {
2113 do_warning("expected type argument");
2114 return 0;
2115 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02002116
2117 return eval_type_str(val, arg->typecast.type, pointer);
2118}
2119
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002120static int arg_num_eval(struct print_arg *arg, long long *val)
Steven Rostedtf7d82352012-04-06 00:47:53 +02002121{
2122 long long left, right;
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002123 int ret = 1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002124
2125 switch (arg->type) {
2126 case PRINT_ATOM:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002127 *val = strtoll(arg->atom.atom, NULL, 0);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002128 break;
2129 case PRINT_TYPE:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002130 ret = arg_num_eval(arg->typecast.item, val);
2131 if (!ret)
2132 break;
2133 *val = eval_type(*val, arg, 0);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002134 break;
2135 case PRINT_OP:
2136 switch (arg->op.op[0]) {
2137 case '|':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002138 ret = arg_num_eval(arg->op.left, &left);
2139 if (!ret)
2140 break;
2141 ret = arg_num_eval(arg->op.right, &right);
2142 if (!ret)
2143 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002144 if (arg->op.op[1])
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002145 *val = left || right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002146 else
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002147 *val = left | right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002148 break;
2149 case '&':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002150 ret = arg_num_eval(arg->op.left, &left);
2151 if (!ret)
2152 break;
2153 ret = arg_num_eval(arg->op.right, &right);
2154 if (!ret)
2155 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002156 if (arg->op.op[1])
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002157 *val = left && right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002158 else
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002159 *val = left & right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002160 break;
2161 case '<':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002162 ret = arg_num_eval(arg->op.left, &left);
2163 if (!ret)
2164 break;
2165 ret = arg_num_eval(arg->op.right, &right);
2166 if (!ret)
2167 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002168 switch (arg->op.op[1]) {
2169 case 0:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002170 *val = left < right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002171 break;
2172 case '<':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002173 *val = left << right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002174 break;
2175 case '=':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002176 *val = left <= right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002177 break;
2178 default:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002179 do_warning("unknown op '%s'", arg->op.op);
2180 ret = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002181 }
2182 break;
2183 case '>':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002184 ret = arg_num_eval(arg->op.left, &left);
2185 if (!ret)
2186 break;
2187 ret = arg_num_eval(arg->op.right, &right);
2188 if (!ret)
2189 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002190 switch (arg->op.op[1]) {
2191 case 0:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002192 *val = left > right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002193 break;
2194 case '>':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002195 *val = left >> right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002196 break;
2197 case '=':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002198 *val = left >= right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002199 break;
2200 default:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002201 do_warning("unknown op '%s'", arg->op.op);
2202 ret = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002203 }
2204 break;
2205 case '=':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002206 ret = arg_num_eval(arg->op.left, &left);
2207 if (!ret)
2208 break;
2209 ret = arg_num_eval(arg->op.right, &right);
2210 if (!ret)
2211 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002212
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002213 if (arg->op.op[1] != '=') {
2214 do_warning("unknown op '%s'", arg->op.op);
2215 ret = 0;
2216 } else
2217 *val = left == right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002218 break;
2219 case '!':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002220 ret = arg_num_eval(arg->op.left, &left);
2221 if (!ret)
2222 break;
2223 ret = arg_num_eval(arg->op.right, &right);
2224 if (!ret)
2225 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002226
2227 switch (arg->op.op[1]) {
2228 case '=':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002229 *val = left != right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002230 break;
2231 default:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002232 do_warning("unknown op '%s'", arg->op.op);
2233 ret = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002234 }
2235 break;
2236 case '-':
2237 /* check for negative */
2238 if (arg->op.left->type == PRINT_NULL)
2239 left = 0;
2240 else
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002241 ret = arg_num_eval(arg->op.left, &left);
2242 if (!ret)
2243 break;
2244 ret = arg_num_eval(arg->op.right, &right);
2245 if (!ret)
2246 break;
2247 *val = left - right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002248 break;
Vaibhav Nagarnaikb4828592012-04-06 00:48:03 +02002249 case '+':
2250 if (arg->op.left->type == PRINT_NULL)
2251 left = 0;
2252 else
2253 ret = arg_num_eval(arg->op.left, &left);
2254 if (!ret)
2255 break;
2256 ret = arg_num_eval(arg->op.right, &right);
2257 if (!ret)
2258 break;
2259 *val = left + right;
2260 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002261 default:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002262 do_warning("unknown op '%s'", arg->op.op);
2263 ret = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002264 }
2265 break;
2266
2267 case PRINT_NULL:
2268 case PRINT_FIELD ... PRINT_SYMBOL:
2269 case PRINT_STRING:
2270 case PRINT_BSTRING:
2271 default:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002272 do_warning("invalid eval type %d", arg->type);
2273 ret = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002274
2275 }
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002276 return ret;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002277}
2278
2279static char *arg_eval (struct print_arg *arg)
2280{
2281 long long val;
2282 static char buf[20];
2283
2284 switch (arg->type) {
2285 case PRINT_ATOM:
2286 return arg->atom.atom;
2287 case PRINT_TYPE:
2288 return arg_eval(arg->typecast.item);
2289 case PRINT_OP:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002290 if (!arg_num_eval(arg, &val))
2291 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002292 sprintf(buf, "%lld", val);
2293 return buf;
2294
2295 case PRINT_NULL:
2296 case PRINT_FIELD ... PRINT_SYMBOL:
2297 case PRINT_STRING:
2298 case PRINT_BSTRING:
2299 default:
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03002300 do_warning("invalid eval type %d", arg->type);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002301 break;
2302 }
2303
2304 return NULL;
2305}
2306
2307static enum event_type
2308process_fields(struct event_format *event, struct print_flag_sym **list, char **tok)
2309{
2310 enum event_type type;
2311 struct print_arg *arg = NULL;
2312 struct print_flag_sym *field;
2313 char *token = *tok;
2314 char *value;
2315
2316 do {
2317 free_token(token);
2318 type = read_token_item(&token);
2319 if (test_type_token(type, token, EVENT_OP, "{"))
2320 break;
2321
2322 arg = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002323 if (!arg)
2324 goto out_free;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002325
2326 free_token(token);
2327 type = process_arg(event, arg, &token);
Stefan Hajnoczi00b9da72012-05-23 11:36:42 +09002328
2329 if (type == EVENT_OP)
2330 type = process_op(event, arg, &token);
2331
2332 if (type == EVENT_ERROR)
2333 goto out_free;
2334
Steven Rostedtf7d82352012-04-06 00:47:53 +02002335 if (test_type_token(type, token, EVENT_DELIM, ","))
2336 goto out_free;
2337
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -03002338 field = calloc(1, sizeof(*field));
2339 if (!field)
2340 goto out_free;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002341
2342 value = arg_eval(arg);
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002343 if (value == NULL)
Namhyung Kimf8c49d22012-09-19 15:58:43 +09002344 goto out_free_field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002345 field->value = strdup(value);
Namhyung Kimca638582012-04-09 11:54:31 +09002346 if (field->value == NULL)
Namhyung Kimf8c49d22012-09-19 15:58:43 +09002347 goto out_free_field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002348
2349 free_arg(arg);
2350 arg = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002351 if (!arg)
2352 goto out_free;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002353
2354 free_token(token);
2355 type = process_arg(event, arg, &token);
2356 if (test_type_token(type, token, EVENT_OP, "}"))
Namhyung Kimf8c49d22012-09-19 15:58:43 +09002357 goto out_free_field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002358
2359 value = arg_eval(arg);
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002360 if (value == NULL)
Namhyung Kimf8c49d22012-09-19 15:58:43 +09002361 goto out_free_field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002362 field->str = strdup(value);
Namhyung Kimca638582012-04-09 11:54:31 +09002363 if (field->str == NULL)
Namhyung Kimf8c49d22012-09-19 15:58:43 +09002364 goto out_free_field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002365 free_arg(arg);
2366 arg = NULL;
2367
2368 *list = field;
2369 list = &field->next;
2370
2371 free_token(token);
2372 type = read_token_item(&token);
2373 } while (type == EVENT_DELIM && strcmp(token, ",") == 0);
2374
2375 *tok = token;
2376 return type;
2377
Namhyung Kimf8c49d22012-09-19 15:58:43 +09002378out_free_field:
2379 free_flag_sym(field);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002380out_free:
2381 free_arg(arg);
2382 free_token(token);
2383 *tok = NULL;
2384
2385 return EVENT_ERROR;
2386}
2387
2388static enum event_type
2389process_flags(struct event_format *event, struct print_arg *arg, char **tok)
2390{
2391 struct print_arg *field;
2392 enum event_type type;
2393 char *token;
2394
2395 memset(arg, 0, sizeof(*arg));
2396 arg->type = PRINT_FLAGS;
2397
2398 field = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002399 if (!field) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09002400 do_warning_event(event, "%s: not enough memory!", __func__);
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002401 goto out_free;
2402 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02002403
Steven Rostedteff2c922013-11-18 14:23:14 -05002404 type = process_field_arg(event, field, &token);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002405
2406 /* Handle operations in the first argument */
2407 while (type == EVENT_OP)
2408 type = process_op(event, field, &token);
2409
2410 if (test_type_token(type, token, EVENT_DELIM, ","))
Namhyung Kim70d93042012-09-19 15:58:44 +09002411 goto out_free_field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002412 free_token(token);
2413
2414 arg->flags.field = field;
2415
2416 type = read_token_item(&token);
2417 if (event_item_type(type)) {
2418 arg->flags.delim = token;
2419 type = read_token_item(&token);
2420 }
2421
2422 if (test_type_token(type, token, EVENT_DELIM, ","))
2423 goto out_free;
2424
2425 type = process_fields(event, &arg->flags.flags, &token);
2426 if (test_type_token(type, token, EVENT_DELIM, ")"))
2427 goto out_free;
2428
2429 free_token(token);
2430 type = read_token_item(tok);
2431 return type;
2432
Namhyung Kim70d93042012-09-19 15:58:44 +09002433out_free_field:
2434 free_arg(field);
2435out_free:
Steven Rostedtf7d82352012-04-06 00:47:53 +02002436 free_token(token);
2437 *tok = NULL;
2438 return EVENT_ERROR;
2439}
2440
2441static enum event_type
2442process_symbols(struct event_format *event, struct print_arg *arg, char **tok)
2443{
2444 struct print_arg *field;
2445 enum event_type type;
2446 char *token;
2447
2448 memset(arg, 0, sizeof(*arg));
2449 arg->type = PRINT_SYMBOL;
2450
2451 field = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002452 if (!field) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09002453 do_warning_event(event, "%s: not enough memory!", __func__);
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002454 goto out_free;
2455 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02002456
Steven Rostedteff2c922013-11-18 14:23:14 -05002457 type = process_field_arg(event, field, &token);
2458
Steven Rostedtf7d82352012-04-06 00:47:53 +02002459 if (test_type_token(type, token, EVENT_DELIM, ","))
Namhyung Kim70d93042012-09-19 15:58:44 +09002460 goto out_free_field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002461
2462 arg->symbol.field = field;
2463
2464 type = process_fields(event, &arg->symbol.symbols, &token);
2465 if (test_type_token(type, token, EVENT_DELIM, ")"))
2466 goto out_free;
2467
2468 free_token(token);
2469 type = read_token_item(tok);
2470 return type;
2471
Namhyung Kim70d93042012-09-19 15:58:44 +09002472out_free_field:
2473 free_arg(field);
2474out_free:
Steven Rostedtf7d82352012-04-06 00:47:53 +02002475 free_token(token);
2476 *tok = NULL;
2477 return EVENT_ERROR;
2478}
2479
2480static enum event_type
Namhyung Kime080e6f2012-06-27 09:41:41 +09002481process_hex(struct event_format *event, struct print_arg *arg, char **tok)
2482{
2483 struct print_arg *field;
2484 enum event_type type;
2485 char *token;
2486
2487 memset(arg, 0, sizeof(*arg));
2488 arg->type = PRINT_HEX;
2489
2490 field = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002491 if (!field) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09002492 do_warning_event(event, "%s: not enough memory!", __func__);
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002493 goto out_free;
2494 }
2495
Namhyung Kime080e6f2012-06-27 09:41:41 +09002496 type = process_arg(event, field, &token);
2497
2498 if (test_type_token(type, token, EVENT_DELIM, ","))
2499 goto out_free;
2500
2501 arg->hex.field = field;
2502
2503 free_token(token);
2504
2505 field = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002506 if (!field) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09002507 do_warning_event(event, "%s: not enough memory!", __func__);
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002508 *tok = NULL;
2509 return EVENT_ERROR;
2510 }
2511
Namhyung Kime080e6f2012-06-27 09:41:41 +09002512 type = process_arg(event, field, &token);
2513
2514 if (test_type_token(type, token, EVENT_DELIM, ")"))
2515 goto out_free;
2516
2517 arg->hex.size = field;
2518
2519 free_token(token);
2520 type = read_token_item(tok);
2521 return type;
2522
2523 out_free:
2524 free_arg(field);
2525 free_token(token);
2526 *tok = NULL;
2527 return EVENT_ERROR;
2528}
2529
2530static enum event_type
Steven Rostedtf7d82352012-04-06 00:47:53 +02002531process_dynamic_array(struct event_format *event, struct print_arg *arg, char **tok)
2532{
2533 struct format_field *field;
2534 enum event_type type;
2535 char *token;
2536
2537 memset(arg, 0, sizeof(*arg));
2538 arg->type = PRINT_DYNAMIC_ARRAY;
2539
2540 /*
2541 * The item within the parenthesis is another field that holds
2542 * the index into where the array starts.
2543 */
2544 type = read_token(&token);
2545 *tok = token;
2546 if (type != EVENT_ITEM)
2547 goto out_free;
2548
2549 /* Find the field */
2550
2551 field = pevent_find_field(event, token);
2552 if (!field)
2553 goto out_free;
2554
2555 arg->dynarray.field = field;
2556 arg->dynarray.index = 0;
2557
2558 if (read_expected(EVENT_DELIM, ")") < 0)
2559 goto out_free;
2560
2561 free_token(token);
2562 type = read_token_item(&token);
2563 *tok = token;
2564 if (type != EVENT_OP || strcmp(token, "[") != 0)
2565 return type;
2566
2567 free_token(token);
2568 arg = alloc_arg();
Sasha Levinfba7a782012-12-21 15:00:58 -05002569 if (!arg) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09002570 do_warning_event(event, "%s: not enough memory!", __func__);
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002571 *tok = NULL;
2572 return EVENT_ERROR;
2573 }
2574
Steven Rostedtf7d82352012-04-06 00:47:53 +02002575 type = process_arg(event, arg, &token);
2576 if (type == EVENT_ERROR)
Namhyung Kimb3511d02012-05-23 11:36:50 +09002577 goto out_free_arg;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002578
2579 if (!test_type_token(type, token, EVENT_OP, "]"))
Namhyung Kimb3511d02012-05-23 11:36:50 +09002580 goto out_free_arg;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002581
2582 free_token(token);
2583 type = read_token_item(tok);
2584 return type;
2585
Namhyung Kimb3511d02012-05-23 11:36:50 +09002586 out_free_arg:
2587 free_arg(arg);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002588 out_free:
Steven Rostedtf7d82352012-04-06 00:47:53 +02002589 free_token(token);
2590 *tok = NULL;
2591 return EVENT_ERROR;
2592}
2593
2594static enum event_type
2595process_paren(struct event_format *event, struct print_arg *arg, char **tok)
2596{
2597 struct print_arg *item_arg;
2598 enum event_type type;
2599 char *token;
2600
2601 type = process_arg(event, arg, &token);
2602
2603 if (type == EVENT_ERROR)
2604 goto out_free;
2605
2606 if (type == EVENT_OP)
2607 type = process_op(event, arg, &token);
2608
2609 if (type == EVENT_ERROR)
2610 goto out_free;
2611
2612 if (test_type_token(type, token, EVENT_DELIM, ")"))
2613 goto out_free;
2614
2615 free_token(token);
2616 type = read_token_item(&token);
2617
2618 /*
2619 * If the next token is an item or another open paren, then
2620 * this was a typecast.
2621 */
2622 if (event_item_type(type) ||
2623 (type == EVENT_DELIM && strcmp(token, "(") == 0)) {
2624
2625 /* make this a typecast and contine */
2626
2627 /* prevous must be an atom */
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03002628 if (arg->type != PRINT_ATOM) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09002629 do_warning_event(event, "previous needed to be PRINT_ATOM");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03002630 goto out_free;
2631 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02002632
2633 item_arg = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002634 if (!item_arg) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09002635 do_warning_event(event, "%s: not enough memory!",
2636 __func__);
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002637 goto out_free;
2638 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02002639
2640 arg->type = PRINT_TYPE;
2641 arg->typecast.type = arg->atom.atom;
2642 arg->typecast.item = item_arg;
2643 type = process_arg_token(event, item_arg, &token, type);
2644
2645 }
2646
2647 *tok = token;
2648 return type;
2649
2650 out_free:
2651 free_token(token);
2652 *tok = NULL;
2653 return EVENT_ERROR;
2654}
2655
2656
2657static enum event_type
Irina Tirdea1d037ca2012-09-11 01:15:03 +03002658process_str(struct event_format *event __maybe_unused, struct print_arg *arg,
2659 char **tok)
Steven Rostedtf7d82352012-04-06 00:47:53 +02002660{
2661 enum event_type type;
2662 char *token;
2663
2664 if (read_expect_type(EVENT_ITEM, &token) < 0)
2665 goto out_free;
2666
2667 arg->type = PRINT_STRING;
2668 arg->string.string = token;
2669 arg->string.offset = -1;
2670
2671 if (read_expected(EVENT_DELIM, ")") < 0)
2672 goto out_err;
2673
2674 type = read_token(&token);
2675 *tok = token;
2676
2677 return type;
2678
2679 out_free:
2680 free_token(token);
2681 out_err:
2682 *tok = NULL;
2683 return EVENT_ERROR;
2684}
2685
2686static struct pevent_function_handler *
2687find_func_handler(struct pevent *pevent, char *func_name)
2688{
2689 struct pevent_function_handler *func;
2690
Steven Rostedt101782e2012-10-01 20:13:51 -04002691 if (!pevent)
2692 return NULL;
2693
Steven Rostedtf7d82352012-04-06 00:47:53 +02002694 for (func = pevent->func_handlers; func; func = func->next) {
2695 if (strcmp(func->name, func_name) == 0)
2696 break;
2697 }
2698
2699 return func;
2700}
2701
2702static void remove_func_handler(struct pevent *pevent, char *func_name)
2703{
2704 struct pevent_function_handler *func;
2705 struct pevent_function_handler **next;
2706
2707 next = &pevent->func_handlers;
2708 while ((func = *next)) {
2709 if (strcmp(func->name, func_name) == 0) {
2710 *next = func->next;
2711 free_func_handle(func);
2712 break;
2713 }
2714 next = &func->next;
2715 }
2716}
2717
2718static enum event_type
2719process_func_handler(struct event_format *event, struct pevent_function_handler *func,
2720 struct print_arg *arg, char **tok)
2721{
2722 struct print_arg **next_arg;
2723 struct print_arg *farg;
2724 enum event_type type;
2725 char *token;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002726 int i;
2727
2728 arg->type = PRINT_FUNC;
2729 arg->func.func = func;
2730
2731 *tok = NULL;
2732
2733 next_arg = &(arg->func.args);
2734 for (i = 0; i < func->nr_args; i++) {
2735 farg = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002736 if (!farg) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09002737 do_warning_event(event, "%s: not enough memory!",
2738 __func__);
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002739 return EVENT_ERROR;
2740 }
2741
Steven Rostedtf7d82352012-04-06 00:47:53 +02002742 type = process_arg(event, farg, &token);
Steven Rostedt3a3ffa22013-11-18 21:38:20 -05002743 if (i < (func->nr_args - 1)) {
2744 if (type != EVENT_DELIM || strcmp(token, ",") != 0) {
2745 warning("Error: function '%s()' expects %d arguments but event %s only uses %d",
2746 func->name, func->nr_args,
2747 event->name, i + 1);
2748 goto err;
2749 }
2750 } else {
2751 if (type != EVENT_DELIM || strcmp(token, ")") != 0) {
2752 warning("Error: function '%s()' only expects %d arguments but event %s has more",
2753 func->name, func->nr_args, event->name);
2754 goto err;
2755 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02002756 }
2757
2758 *next_arg = farg;
2759 next_arg = &(farg->next);
2760 free_token(token);
2761 }
2762
2763 type = read_token(&token);
2764 *tok = token;
2765
2766 return type;
Steven Rostedt3a3ffa22013-11-18 21:38:20 -05002767
2768err:
2769 free_arg(farg);
2770 free_token(token);
2771 return EVENT_ERROR;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002772}
2773
2774static enum event_type
2775process_function(struct event_format *event, struct print_arg *arg,
2776 char *token, char **tok)
2777{
2778 struct pevent_function_handler *func;
2779
2780 if (strcmp(token, "__print_flags") == 0) {
2781 free_token(token);
Tom Zanussi5205aec2012-04-06 00:47:58 +02002782 is_flag_field = 1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002783 return process_flags(event, arg, tok);
2784 }
2785 if (strcmp(token, "__print_symbolic") == 0) {
2786 free_token(token);
Tom Zanussi5205aec2012-04-06 00:47:58 +02002787 is_symbolic_field = 1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002788 return process_symbols(event, arg, tok);
2789 }
Namhyung Kime080e6f2012-06-27 09:41:41 +09002790 if (strcmp(token, "__print_hex") == 0) {
2791 free_token(token);
2792 return process_hex(event, arg, tok);
2793 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02002794 if (strcmp(token, "__get_str") == 0) {
2795 free_token(token);
2796 return process_str(event, arg, tok);
2797 }
2798 if (strcmp(token, "__get_dynamic_array") == 0) {
2799 free_token(token);
2800 return process_dynamic_array(event, arg, tok);
2801 }
2802
2803 func = find_func_handler(event->pevent, token);
2804 if (func) {
2805 free_token(token);
2806 return process_func_handler(event, func, arg, tok);
2807 }
2808
Namhyung Kim3388cc32014-03-19 10:22:53 +09002809 do_warning_event(event, "function %s not defined", token);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002810 free_token(token);
2811 return EVENT_ERROR;
2812}
2813
2814static enum event_type
2815process_arg_token(struct event_format *event, struct print_arg *arg,
2816 char **tok, enum event_type type)
2817{
2818 char *token;
2819 char *atom;
2820
2821 token = *tok;
2822
2823 switch (type) {
2824 case EVENT_ITEM:
2825 if (strcmp(token, "REC") == 0) {
2826 free_token(token);
2827 type = process_entry(event, arg, &token);
2828 break;
2829 }
2830 atom = token;
2831 /* test the next token */
2832 type = read_token_item(&token);
2833
2834 /*
2835 * If the next token is a parenthesis, then this
2836 * is a function.
2837 */
2838 if (type == EVENT_DELIM && strcmp(token, "(") == 0) {
2839 free_token(token);
2840 token = NULL;
2841 /* this will free atom. */
2842 type = process_function(event, arg, atom, &token);
2843 break;
2844 }
2845 /* atoms can be more than one token long */
2846 while (type == EVENT_ITEM) {
Namhyung Kimd2864472012-04-09 11:54:33 +09002847 char *new_atom;
2848 new_atom = realloc(atom,
2849 strlen(atom) + strlen(token) + 2);
2850 if (!new_atom) {
2851 free(atom);
2852 *tok = NULL;
2853 free_token(token);
2854 return EVENT_ERROR;
2855 }
2856 atom = new_atom;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002857 strcat(atom, " ");
2858 strcat(atom, token);
2859 free_token(token);
2860 type = read_token_item(&token);
2861 }
2862
2863 arg->type = PRINT_ATOM;
2864 arg->atom.atom = atom;
2865 break;
2866
2867 case EVENT_DQUOTE:
2868 case EVENT_SQUOTE:
2869 arg->type = PRINT_ATOM;
2870 arg->atom.atom = token;
2871 type = read_token_item(&token);
2872 break;
2873 case EVENT_DELIM:
2874 if (strcmp(token, "(") == 0) {
2875 free_token(token);
2876 type = process_paren(event, arg, &token);
2877 break;
2878 }
2879 case EVENT_OP:
2880 /* handle single ops */
2881 arg->type = PRINT_OP;
2882 arg->op.op = token;
2883 arg->op.left = NULL;
2884 type = process_op(event, arg, &token);
2885
2886 /* On error, the op is freed */
2887 if (type == EVENT_ERROR)
2888 arg->op.op = NULL;
2889
2890 /* return error type if errored */
2891 break;
2892
2893 case EVENT_ERROR ... EVENT_NEWLINE:
2894 default:
Namhyung Kim3388cc32014-03-19 10:22:53 +09002895 do_warning_event(event, "unexpected type %d", type);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03002896 return EVENT_ERROR;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002897 }
2898 *tok = token;
2899
2900 return type;
2901}
2902
2903static int event_read_print_args(struct event_format *event, struct print_arg **list)
2904{
2905 enum event_type type = EVENT_ERROR;
2906 struct print_arg *arg;
2907 char *token;
2908 int args = 0;
2909
2910 do {
2911 if (type == EVENT_NEWLINE) {
2912 type = read_token_item(&token);
2913 continue;
2914 }
2915
2916 arg = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002917 if (!arg) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09002918 do_warning_event(event, "%s: not enough memory!",
2919 __func__);
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002920 return -1;
2921 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02002922
2923 type = process_arg(event, arg, &token);
2924
2925 if (type == EVENT_ERROR) {
2926 free_token(token);
2927 free_arg(arg);
2928 return -1;
2929 }
2930
2931 *list = arg;
2932 args++;
2933
2934 if (type == EVENT_OP) {
2935 type = process_op(event, arg, &token);
2936 free_token(token);
2937 if (type == EVENT_ERROR) {
2938 *list = NULL;
2939 free_arg(arg);
2940 return -1;
2941 }
2942 list = &arg->next;
2943 continue;
2944 }
2945
2946 if (type == EVENT_DELIM && strcmp(token, ",") == 0) {
2947 free_token(token);
2948 *list = arg;
2949 list = &arg->next;
2950 continue;
2951 }
2952 break;
2953 } while (type != EVENT_NONE);
2954
2955 if (type != EVENT_NONE && type != EVENT_ERROR)
2956 free_token(token);
2957
2958 return args;
2959}
2960
2961static int event_read_print(struct event_format *event)
2962{
2963 enum event_type type;
2964 char *token;
2965 int ret;
2966
2967 if (read_expected_item(EVENT_ITEM, "print") < 0)
2968 return -1;
2969
2970 if (read_expected(EVENT_ITEM, "fmt") < 0)
2971 return -1;
2972
2973 if (read_expected(EVENT_OP, ":") < 0)
2974 return -1;
2975
2976 if (read_expect_type(EVENT_DQUOTE, &token) < 0)
2977 goto fail;
2978
2979 concat:
2980 event->print_fmt.format = token;
2981 event->print_fmt.args = NULL;
2982
2983 /* ok to have no arg */
2984 type = read_token_item(&token);
2985
2986 if (type == EVENT_NONE)
2987 return 0;
2988
2989 /* Handle concatenation of print lines */
2990 if (type == EVENT_DQUOTE) {
2991 char *cat;
2992
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03002993 if (asprintf(&cat, "%s%s", event->print_fmt.format, token) < 0)
2994 goto fail;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002995 free_token(token);
2996 free_token(event->print_fmt.format);
2997 event->print_fmt.format = NULL;
2998 token = cat;
2999 goto concat;
3000 }
3001
3002 if (test_type_token(type, token, EVENT_DELIM, ","))
3003 goto fail;
3004
3005 free_token(token);
3006
3007 ret = event_read_print_args(event, &event->print_fmt.args);
3008 if (ret < 0)
3009 return -1;
3010
3011 return ret;
3012
3013 fail:
3014 free_token(token);
3015 return -1;
3016}
3017
3018/**
3019 * pevent_find_common_field - return a common field by event
3020 * @event: handle for the event
3021 * @name: the name of the common field to return
3022 *
3023 * Returns a common field from the event by the given @name.
3024 * This only searchs the common fields and not all field.
3025 */
3026struct format_field *
3027pevent_find_common_field(struct event_format *event, const char *name)
3028{
3029 struct format_field *format;
3030
3031 for (format = event->format.common_fields;
3032 format; format = format->next) {
3033 if (strcmp(format->name, name) == 0)
3034 break;
3035 }
3036
3037 return format;
3038}
3039
3040/**
3041 * pevent_find_field - find a non-common field
3042 * @event: handle for the event
3043 * @name: the name of the non-common field
3044 *
3045 * Returns a non-common field by the given @name.
3046 * This does not search common fields.
3047 */
3048struct format_field *
3049pevent_find_field(struct event_format *event, const char *name)
3050{
3051 struct format_field *format;
3052
3053 for (format = event->format.fields;
3054 format; format = format->next) {
3055 if (strcmp(format->name, name) == 0)
3056 break;
3057 }
3058
3059 return format;
3060}
3061
3062/**
3063 * pevent_find_any_field - find any field by name
3064 * @event: handle for the event
3065 * @name: the name of the field
3066 *
3067 * Returns a field by the given @name.
3068 * This searchs the common field names first, then
3069 * the non-common ones if a common one was not found.
3070 */
3071struct format_field *
3072pevent_find_any_field(struct event_format *event, const char *name)
3073{
3074 struct format_field *format;
3075
3076 format = pevent_find_common_field(event, name);
3077 if (format)
3078 return format;
3079 return pevent_find_field(event, name);
3080}
3081
3082/**
3083 * pevent_read_number - read a number from data
3084 * @pevent: handle for the pevent
3085 * @ptr: the raw data
3086 * @size: the size of the data that holds the number
3087 *
3088 * Returns the number (converted to host) from the
3089 * raw data.
3090 */
3091unsigned long long pevent_read_number(struct pevent *pevent,
3092 const void *ptr, int size)
3093{
3094 switch (size) {
3095 case 1:
3096 return *(unsigned char *)ptr;
3097 case 2:
3098 return data2host2(pevent, ptr);
3099 case 4:
3100 return data2host4(pevent, ptr);
3101 case 8:
3102 return data2host8(pevent, ptr);
3103 default:
3104 /* BUG! */
3105 return 0;
3106 }
3107}
3108
3109/**
3110 * pevent_read_number_field - read a number from data
3111 * @field: a handle to the field
3112 * @data: the raw data to read
3113 * @value: the value to place the number in
3114 *
3115 * Reads raw data according to a field offset and size,
3116 * and translates it into @value.
3117 *
3118 * Returns 0 on success, -1 otherwise.
3119 */
3120int pevent_read_number_field(struct format_field *field, const void *data,
3121 unsigned long long *value)
3122{
3123 if (!field)
3124 return -1;
3125 switch (field->size) {
3126 case 1:
3127 case 2:
3128 case 4:
3129 case 8:
3130 *value = pevent_read_number(field->event->pevent,
3131 data + field->offset, field->size);
3132 return 0;
3133 default:
3134 return -1;
3135 }
3136}
3137
3138static int get_common_info(struct pevent *pevent,
3139 const char *type, int *offset, int *size)
3140{
3141 struct event_format *event;
3142 struct format_field *field;
3143
3144 /*
3145 * All events should have the same common elements.
3146 * Pick any event to find where the type is;
3147 */
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003148 if (!pevent->events) {
3149 do_warning("no event_list!");
3150 return -1;
3151 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003152
3153 event = pevent->events[0];
3154 field = pevent_find_common_field(event, type);
3155 if (!field)
Steven Rostedt0866a972012-05-22 14:52:40 +09003156 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003157
3158 *offset = field->offset;
3159 *size = field->size;
3160
3161 return 0;
3162}
3163
3164static int __parse_common(struct pevent *pevent, void *data,
3165 int *size, int *offset, const char *name)
3166{
3167 int ret;
3168
3169 if (!*size) {
3170 ret = get_common_info(pevent, name, offset, size);
3171 if (ret < 0)
3172 return ret;
3173 }
3174 return pevent_read_number(pevent, data + *offset, *size);
3175}
3176
3177static int trace_parse_common_type(struct pevent *pevent, void *data)
3178{
3179 return __parse_common(pevent, data,
3180 &pevent->type_size, &pevent->type_offset,
3181 "common_type");
3182}
3183
3184static int parse_common_pid(struct pevent *pevent, void *data)
3185{
3186 return __parse_common(pevent, data,
3187 &pevent->pid_size, &pevent->pid_offset,
3188 "common_pid");
3189}
3190
3191static int parse_common_pc(struct pevent *pevent, void *data)
3192{
3193 return __parse_common(pevent, data,
3194 &pevent->pc_size, &pevent->pc_offset,
3195 "common_preempt_count");
3196}
3197
3198static int parse_common_flags(struct pevent *pevent, void *data)
3199{
3200 return __parse_common(pevent, data,
3201 &pevent->flags_size, &pevent->flags_offset,
3202 "common_flags");
3203}
3204
3205static int parse_common_lock_depth(struct pevent *pevent, void *data)
3206{
Steven Rostedt0866a972012-05-22 14:52:40 +09003207 return __parse_common(pevent, data,
3208 &pevent->ld_size, &pevent->ld_offset,
3209 "common_lock_depth");
3210}
Steven Rostedtf7d82352012-04-06 00:47:53 +02003211
Steven Rostedt0866a972012-05-22 14:52:40 +09003212static int parse_common_migrate_disable(struct pevent *pevent, void *data)
3213{
3214 return __parse_common(pevent, data,
3215 &pevent->ld_size, &pevent->ld_offset,
3216 "common_migrate_disable");
Steven Rostedtf7d82352012-04-06 00:47:53 +02003217}
3218
3219static int events_id_cmp(const void *a, const void *b);
3220
3221/**
3222 * pevent_find_event - find an event by given id
3223 * @pevent: a handle to the pevent
3224 * @id: the id of the event
3225 *
3226 * Returns an event that has a given @id.
3227 */
3228struct event_format *pevent_find_event(struct pevent *pevent, int id)
3229{
3230 struct event_format **eventptr;
3231 struct event_format key;
3232 struct event_format *pkey = &key;
3233
3234 /* Check cache first */
3235 if (pevent->last_event && pevent->last_event->id == id)
3236 return pevent->last_event;
3237
3238 key.id = id;
3239
3240 eventptr = bsearch(&pkey, pevent->events, pevent->nr_events,
3241 sizeof(*pevent->events), events_id_cmp);
3242
3243 if (eventptr) {
3244 pevent->last_event = *eventptr;
3245 return *eventptr;
3246 }
3247
3248 return NULL;
3249}
3250
3251/**
3252 * pevent_find_event_by_name - find an event by given name
3253 * @pevent: a handle to the pevent
3254 * @sys: the system name to search for
3255 * @name: the name of the event to search for
3256 *
3257 * This returns an event with a given @name and under the system
3258 * @sys. If @sys is NULL the first event with @name is returned.
3259 */
3260struct event_format *
3261pevent_find_event_by_name(struct pevent *pevent,
3262 const char *sys, const char *name)
3263{
3264 struct event_format *event;
3265 int i;
3266
3267 if (pevent->last_event &&
3268 strcmp(pevent->last_event->name, name) == 0 &&
3269 (!sys || strcmp(pevent->last_event->system, sys) == 0))
3270 return pevent->last_event;
3271
3272 for (i = 0; i < pevent->nr_events; i++) {
3273 event = pevent->events[i];
3274 if (strcmp(event->name, name) == 0) {
3275 if (!sys)
3276 break;
3277 if (strcmp(event->system, sys) == 0)
3278 break;
3279 }
3280 }
3281 if (i == pevent->nr_events)
3282 event = NULL;
3283
3284 pevent->last_event = event;
3285 return event;
3286}
3287
3288static unsigned long long
3289eval_num_arg(void *data, int size, struct event_format *event, struct print_arg *arg)
3290{
3291 struct pevent *pevent = event->pevent;
3292 unsigned long long val = 0;
3293 unsigned long long left, right;
3294 struct print_arg *typearg = NULL;
3295 struct print_arg *larg;
3296 unsigned long offset;
3297 unsigned int field_size;
3298
3299 switch (arg->type) {
3300 case PRINT_NULL:
3301 /* ?? */
3302 return 0;
3303 case PRINT_ATOM:
3304 return strtoull(arg->atom.atom, NULL, 0);
3305 case PRINT_FIELD:
3306 if (!arg->field.field) {
3307 arg->field.field = pevent_find_any_field(event, arg->field.name);
3308 if (!arg->field.field)
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003309 goto out_warning_field;
3310
Steven Rostedtf7d82352012-04-06 00:47:53 +02003311 }
3312 /* must be a number */
3313 val = pevent_read_number(pevent, data + arg->field.field->offset,
3314 arg->field.field->size);
3315 break;
3316 case PRINT_FLAGS:
3317 case PRINT_SYMBOL:
Namhyung Kime080e6f2012-06-27 09:41:41 +09003318 case PRINT_HEX:
Steven Rostedtf7d82352012-04-06 00:47:53 +02003319 break;
3320 case PRINT_TYPE:
3321 val = eval_num_arg(data, size, event, arg->typecast.item);
3322 return eval_type(val, arg, 0);
3323 case PRINT_STRING:
3324 case PRINT_BSTRING:
3325 return 0;
3326 case PRINT_FUNC: {
3327 struct trace_seq s;
3328 trace_seq_init(&s);
3329 val = process_defined_func(&s, data, size, event, arg);
3330 trace_seq_destroy(&s);
3331 return val;
3332 }
3333 case PRINT_OP:
3334 if (strcmp(arg->op.op, "[") == 0) {
3335 /*
3336 * Arrays are special, since we don't want
3337 * to read the arg as is.
3338 */
3339 right = eval_num_arg(data, size, event, arg->op.right);
3340
3341 /* handle typecasts */
3342 larg = arg->op.left;
3343 while (larg->type == PRINT_TYPE) {
3344 if (!typearg)
3345 typearg = larg;
3346 larg = larg->typecast.item;
3347 }
3348
3349 /* Default to long size */
3350 field_size = pevent->long_size;
3351
3352 switch (larg->type) {
3353 case PRINT_DYNAMIC_ARRAY:
3354 offset = pevent_read_number(pevent,
3355 data + larg->dynarray.field->offset,
3356 larg->dynarray.field->size);
3357 if (larg->dynarray.field->elementsize)
3358 field_size = larg->dynarray.field->elementsize;
3359 /*
3360 * The actual length of the dynamic array is stored
3361 * in the top half of the field, and the offset
3362 * is in the bottom half of the 32 bit field.
3363 */
3364 offset &= 0xffff;
3365 offset += right;
3366 break;
3367 case PRINT_FIELD:
3368 if (!larg->field.field) {
3369 larg->field.field =
3370 pevent_find_any_field(event, larg->field.name);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003371 if (!larg->field.field) {
3372 arg = larg;
3373 goto out_warning_field;
3374 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003375 }
3376 field_size = larg->field.field->elementsize;
3377 offset = larg->field.field->offset +
3378 right * larg->field.field->elementsize;
3379 break;
3380 default:
3381 goto default_op; /* oops, all bets off */
3382 }
3383 val = pevent_read_number(pevent,
3384 data + offset, field_size);
3385 if (typearg)
3386 val = eval_type(val, typearg, 1);
3387 break;
3388 } else if (strcmp(arg->op.op, "?") == 0) {
3389 left = eval_num_arg(data, size, event, arg->op.left);
3390 arg = arg->op.right;
3391 if (left)
3392 val = eval_num_arg(data, size, event, arg->op.left);
3393 else
3394 val = eval_num_arg(data, size, event, arg->op.right);
3395 break;
3396 }
3397 default_op:
3398 left = eval_num_arg(data, size, event, arg->op.left);
3399 right = eval_num_arg(data, size, event, arg->op.right);
3400 switch (arg->op.op[0]) {
3401 case '!':
3402 switch (arg->op.op[1]) {
3403 case 0:
3404 val = !right;
3405 break;
3406 case '=':
3407 val = left != right;
3408 break;
3409 default:
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003410 goto out_warning_op;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003411 }
3412 break;
3413 case '~':
3414 val = ~right;
3415 break;
3416 case '|':
3417 if (arg->op.op[1])
3418 val = left || right;
3419 else
3420 val = left | right;
3421 break;
3422 case '&':
3423 if (arg->op.op[1])
3424 val = left && right;
3425 else
3426 val = left & right;
3427 break;
3428 case '<':
3429 switch (arg->op.op[1]) {
3430 case 0:
3431 val = left < right;
3432 break;
3433 case '<':
3434 val = left << right;
3435 break;
3436 case '=':
3437 val = left <= right;
3438 break;
3439 default:
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003440 goto out_warning_op;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003441 }
3442 break;
3443 case '>':
3444 switch (arg->op.op[1]) {
3445 case 0:
3446 val = left > right;
3447 break;
3448 case '>':
3449 val = left >> right;
3450 break;
3451 case '=':
3452 val = left >= right;
3453 break;
3454 default:
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003455 goto out_warning_op;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003456 }
3457 break;
3458 case '=':
3459 if (arg->op.op[1] != '=')
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003460 goto out_warning_op;
3461
Steven Rostedtf7d82352012-04-06 00:47:53 +02003462 val = left == right;
3463 break;
3464 case '-':
3465 val = left - right;
3466 break;
3467 case '+':
3468 val = left + right;
3469 break;
Steven Rostedt2e7a5fc2012-04-06 00:48:04 +02003470 case '/':
3471 val = left / right;
3472 break;
3473 case '*':
3474 val = left * right;
3475 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003476 default:
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003477 goto out_warning_op;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003478 }
3479 break;
Steven Rostedt0497a9e2013-11-11 16:08:10 -05003480 case PRINT_DYNAMIC_ARRAY:
3481 /* Without [], we pass the address to the dynamic data */
3482 offset = pevent_read_number(pevent,
3483 data + arg->dynarray.field->offset,
3484 arg->dynarray.field->size);
3485 /*
3486 * The actual length of the dynamic array is stored
3487 * in the top half of the field, and the offset
3488 * is in the bottom half of the 32 bit field.
3489 */
3490 offset &= 0xffff;
Arnaldo Carvalho de Melo6b5fa0b2013-11-19 16:14:51 -03003491 val = (unsigned long long)((unsigned long)data + offset);
Steven Rostedt0497a9e2013-11-11 16:08:10 -05003492 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003493 default: /* not sure what to do there */
3494 return 0;
3495 }
3496 return val;
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003497
3498out_warning_op:
Namhyung Kim3388cc32014-03-19 10:22:53 +09003499 do_warning_event(event, "%s: unknown op '%s'", __func__, arg->op.op);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003500 return 0;
3501
3502out_warning_field:
Namhyung Kim3388cc32014-03-19 10:22:53 +09003503 do_warning_event(event, "%s: field %s not found",
3504 __func__, arg->field.name);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003505 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003506}
3507
3508struct flag {
3509 const char *name;
3510 unsigned long long value;
3511};
3512
3513static const struct flag flags[] = {
3514 { "HI_SOFTIRQ", 0 },
3515 { "TIMER_SOFTIRQ", 1 },
3516 { "NET_TX_SOFTIRQ", 2 },
3517 { "NET_RX_SOFTIRQ", 3 },
3518 { "BLOCK_SOFTIRQ", 4 },
3519 { "BLOCK_IOPOLL_SOFTIRQ", 5 },
3520 { "TASKLET_SOFTIRQ", 6 },
3521 { "SCHED_SOFTIRQ", 7 },
3522 { "HRTIMER_SOFTIRQ", 8 },
3523 { "RCU_SOFTIRQ", 9 },
3524
3525 { "HRTIMER_NORESTART", 0 },
3526 { "HRTIMER_RESTART", 1 },
3527};
3528
3529static unsigned long long eval_flag(const char *flag)
3530{
3531 int i;
3532
3533 /*
3534 * Some flags in the format files do not get converted.
3535 * If the flag is not numeric, see if it is something that
3536 * we already know about.
3537 */
3538 if (isdigit(flag[0]))
3539 return strtoull(flag, NULL, 0);
3540
3541 for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++)
3542 if (strcmp(flags[i].name, flag) == 0)
3543 return flags[i].value;
3544
3545 return 0;
3546}
3547
3548static void print_str_to_seq(struct trace_seq *s, const char *format,
3549 int len_arg, const char *str)
3550{
3551 if (len_arg >= 0)
3552 trace_seq_printf(s, format, len_arg, str);
3553 else
3554 trace_seq_printf(s, format, str);
3555}
3556
3557static void print_str_arg(struct trace_seq *s, void *data, int size,
3558 struct event_format *event, const char *format,
3559 int len_arg, struct print_arg *arg)
3560{
3561 struct pevent *pevent = event->pevent;
3562 struct print_flag_sym *flag;
Namhyung Kimb7008072012-06-27 09:41:40 +09003563 struct format_field *field;
Steven Rostedt (Red Hat)0970b5f2013-11-01 17:53:55 -04003564 struct printk_map *printk;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003565 unsigned long long val, fval;
3566 unsigned long addr;
3567 char *str;
Namhyung Kime080e6f2012-06-27 09:41:41 +09003568 unsigned char *hex;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003569 int print;
Namhyung Kime080e6f2012-06-27 09:41:41 +09003570 int i, len;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003571
3572 switch (arg->type) {
3573 case PRINT_NULL:
3574 /* ?? */
3575 return;
3576 case PRINT_ATOM:
3577 print_str_to_seq(s, format, len_arg, arg->atom.atom);
3578 return;
3579 case PRINT_FIELD:
Namhyung Kimb7008072012-06-27 09:41:40 +09003580 field = arg->field.field;
3581 if (!field) {
3582 field = pevent_find_any_field(event, arg->field.name);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003583 if (!field) {
3584 str = arg->field.name;
3585 goto out_warning_field;
3586 }
Namhyung Kimb7008072012-06-27 09:41:40 +09003587 arg->field.field = field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003588 }
3589 /* Zero sized fields, mean the rest of the data */
Namhyung Kimb7008072012-06-27 09:41:40 +09003590 len = field->size ? : size - field->offset;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003591
3592 /*
3593 * Some events pass in pointers. If this is not an array
3594 * and the size is the same as long_size, assume that it
3595 * is a pointer.
3596 */
Namhyung Kimb7008072012-06-27 09:41:40 +09003597 if (!(field->flags & FIELD_IS_ARRAY) &&
3598 field->size == pevent->long_size) {
3599 addr = *(unsigned long *)(data + field->offset);
Steven Rostedt (Red Hat)0970b5f2013-11-01 17:53:55 -04003600 /* Check if it matches a print format */
3601 printk = find_printk(pevent, addr);
3602 if (printk)
3603 trace_seq_puts(s, printk->printk);
3604 else
3605 trace_seq_printf(s, "%lx", addr);
Steven Rostedtf7d82352012-04-06 00:47:53 +02003606 break;
3607 }
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003608 str = malloc(len + 1);
3609 if (!str) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09003610 do_warning_event(event, "%s: not enough memory!",
3611 __func__);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003612 return;
3613 }
Namhyung Kimb7008072012-06-27 09:41:40 +09003614 memcpy(str, data + field->offset, len);
Steven Rostedtf7d82352012-04-06 00:47:53 +02003615 str[len] = 0;
3616 print_str_to_seq(s, format, len_arg, str);
3617 free(str);
3618 break;
3619 case PRINT_FLAGS:
3620 val = eval_num_arg(data, size, event, arg->flags.field);
3621 print = 0;
3622 for (flag = arg->flags.flags; flag; flag = flag->next) {
3623 fval = eval_flag(flag->value);
3624 if (!val && !fval) {
3625 print_str_to_seq(s, format, len_arg, flag->str);
3626 break;
3627 }
3628 if (fval && (val & fval) == fval) {
3629 if (print && arg->flags.delim)
3630 trace_seq_puts(s, arg->flags.delim);
3631 print_str_to_seq(s, format, len_arg, flag->str);
3632 print = 1;
3633 val &= ~fval;
3634 }
3635 }
3636 break;
3637 case PRINT_SYMBOL:
3638 val = eval_num_arg(data, size, event, arg->symbol.field);
3639 for (flag = arg->symbol.symbols; flag; flag = flag->next) {
3640 fval = eval_flag(flag->value);
3641 if (val == fval) {
3642 print_str_to_seq(s, format, len_arg, flag->str);
3643 break;
3644 }
3645 }
3646 break;
Namhyung Kime080e6f2012-06-27 09:41:41 +09003647 case PRINT_HEX:
Howard Cochranb30f75e2013-11-01 17:53:56 -04003648 if (arg->hex.field->type == PRINT_DYNAMIC_ARRAY) {
3649 unsigned long offset;
3650 offset = pevent_read_number(pevent,
3651 data + arg->hex.field->dynarray.field->offset,
3652 arg->hex.field->dynarray.field->size);
3653 hex = data + (offset & 0xffff);
3654 } else {
3655 field = arg->hex.field->field.field;
3656 if (!field) {
3657 str = arg->hex.field->field.name;
3658 field = pevent_find_any_field(event, str);
3659 if (!field)
3660 goto out_warning_field;
3661 arg->hex.field->field.field = field;
3662 }
3663 hex = data + field->offset;
Namhyung Kime080e6f2012-06-27 09:41:41 +09003664 }
Namhyung Kime080e6f2012-06-27 09:41:41 +09003665 len = eval_num_arg(data, size, event, arg->hex.size);
3666 for (i = 0; i < len; i++) {
3667 if (i)
3668 trace_seq_putc(s, ' ');
3669 trace_seq_printf(s, "%02x", hex[i]);
3670 }
3671 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003672
3673 case PRINT_TYPE:
3674 break;
3675 case PRINT_STRING: {
3676 int str_offset;
3677
3678 if (arg->string.offset == -1) {
3679 struct format_field *f;
3680
3681 f = pevent_find_any_field(event, arg->string.string);
3682 arg->string.offset = f->offset;
3683 }
3684 str_offset = data2host4(pevent, data + arg->string.offset);
3685 str_offset &= 0xffff;
3686 print_str_to_seq(s, format, len_arg, ((char *)data) + str_offset);
3687 break;
3688 }
3689 case PRINT_BSTRING:
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003690 print_str_to_seq(s, format, len_arg, arg->string.string);
Steven Rostedtf7d82352012-04-06 00:47:53 +02003691 break;
3692 case PRINT_OP:
3693 /*
3694 * The only op for string should be ? :
3695 */
3696 if (arg->op.op[0] != '?')
3697 return;
3698 val = eval_num_arg(data, size, event, arg->op.left);
3699 if (val)
3700 print_str_arg(s, data, size, event,
3701 format, len_arg, arg->op.right->op.left);
3702 else
3703 print_str_arg(s, data, size, event,
3704 format, len_arg, arg->op.right->op.right);
3705 break;
3706 case PRINT_FUNC:
3707 process_defined_func(s, data, size, event, arg);
3708 break;
3709 default:
3710 /* well... */
3711 break;
3712 }
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003713
3714 return;
3715
3716out_warning_field:
Namhyung Kim3388cc32014-03-19 10:22:53 +09003717 do_warning_event(event, "%s: field %s not found",
3718 __func__, arg->field.name);
Steven Rostedtf7d82352012-04-06 00:47:53 +02003719}
3720
3721static unsigned long long
3722process_defined_func(struct trace_seq *s, void *data, int size,
3723 struct event_format *event, struct print_arg *arg)
3724{
3725 struct pevent_function_handler *func_handle = arg->func.func;
3726 struct pevent_func_params *param;
3727 unsigned long long *args;
3728 unsigned long long ret;
3729 struct print_arg *farg;
3730 struct trace_seq str;
3731 struct save_str {
3732 struct save_str *next;
3733 char *str;
3734 } *strings = NULL, *string;
3735 int i;
3736
3737 if (!func_handle->nr_args) {
3738 ret = (*func_handle->func)(s, NULL);
3739 goto out;
3740 }
3741
3742 farg = arg->func.args;
3743 param = func_handle->params;
3744
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003745 ret = ULLONG_MAX;
3746 args = malloc(sizeof(*args) * func_handle->nr_args);
3747 if (!args)
3748 goto out;
3749
Steven Rostedtf7d82352012-04-06 00:47:53 +02003750 for (i = 0; i < func_handle->nr_args; i++) {
3751 switch (param->type) {
3752 case PEVENT_FUNC_ARG_INT:
3753 case PEVENT_FUNC_ARG_LONG:
3754 case PEVENT_FUNC_ARG_PTR:
3755 args[i] = eval_num_arg(data, size, event, farg);
3756 break;
3757 case PEVENT_FUNC_ARG_STRING:
3758 trace_seq_init(&str);
3759 print_str_arg(&str, data, size, event, "%s", -1, farg);
3760 trace_seq_terminate(&str);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003761 string = malloc(sizeof(*string));
3762 if (!string) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09003763 do_warning_event(event, "%s(%d): malloc str",
3764 __func__, __LINE__);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003765 goto out_free;
3766 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003767 string->next = strings;
3768 string->str = strdup(str.buffer);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003769 if (!string->str) {
3770 free(string);
Namhyung Kim3388cc32014-03-19 10:22:53 +09003771 do_warning_event(event, "%s(%d): malloc str",
3772 __func__, __LINE__);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003773 goto out_free;
3774 }
Robert Richter0cf26012012-08-07 19:43:14 +02003775 args[i] = (uintptr_t)string->str;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003776 strings = string;
3777 trace_seq_destroy(&str);
3778 break;
3779 default:
3780 /*
3781 * Something went totally wrong, this is not
3782 * an input error, something in this code broke.
3783 */
Namhyung Kim3388cc32014-03-19 10:22:53 +09003784 do_warning_event(event, "Unexpected end of arguments\n");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003785 goto out_free;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003786 }
3787 farg = farg->next;
Namhyung Kim21c69e72012-05-23 11:36:51 +09003788 param = param->next;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003789 }
3790
3791 ret = (*func_handle->func)(s, args);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003792out_free:
Steven Rostedtf7d82352012-04-06 00:47:53 +02003793 free(args);
3794 while (strings) {
3795 string = strings;
3796 strings = string->next;
3797 free(string->str);
3798 free(string);
3799 }
3800
3801 out:
3802 /* TBD : handle return type here */
3803 return ret;
3804}
3805
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003806static void free_args(struct print_arg *args)
3807{
3808 struct print_arg *next;
3809
3810 while (args) {
3811 next = args->next;
3812
3813 free_arg(args);
3814 args = next;
3815 }
3816}
3817
Steven Rostedtf7d82352012-04-06 00:47:53 +02003818static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event_format *event)
3819{
3820 struct pevent *pevent = event->pevent;
3821 struct format_field *field, *ip_field;
3822 struct print_arg *args, *arg, **next;
3823 unsigned long long ip, val;
3824 char *ptr;
3825 void *bptr;
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003826 int vsize;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003827
3828 field = pevent->bprint_buf_field;
3829 ip_field = pevent->bprint_ip_field;
3830
3831 if (!field) {
3832 field = pevent_find_field(event, "buf");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003833 if (!field) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09003834 do_warning_event(event, "can't find buffer field for binary printk");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003835 return NULL;
3836 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003837 ip_field = pevent_find_field(event, "ip");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003838 if (!ip_field) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09003839 do_warning_event(event, "can't find ip field for binary printk");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003840 return NULL;
3841 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003842 pevent->bprint_buf_field = field;
3843 pevent->bprint_ip_field = ip_field;
3844 }
3845
3846 ip = pevent_read_number(pevent, data + ip_field->offset, ip_field->size);
3847
3848 /*
3849 * The first arg is the IP pointer.
3850 */
3851 args = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09003852 if (!args) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09003853 do_warning_event(event, "%s(%d): not enough memory!",
3854 __func__, __LINE__);
Namhyung Kimb1ac7542012-09-20 11:09:19 +09003855 return NULL;
3856 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003857 arg = args;
3858 arg->next = NULL;
3859 next = &arg->next;
3860
3861 arg->type = PRINT_ATOM;
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003862
3863 if (asprintf(&arg->atom.atom, "%lld", ip) < 0)
3864 goto out_free;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003865
Steven Rostedt (Red Hat)0883d9d2013-11-01 17:53:57 -04003866 /* skip the first "%pf: " */
3867 for (ptr = fmt + 5, bptr = data + field->offset;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003868 bptr < data + size && *ptr; ptr++) {
3869 int ls = 0;
3870
3871 if (*ptr == '%') {
3872 process_again:
3873 ptr++;
3874 switch (*ptr) {
3875 case '%':
3876 break;
3877 case 'l':
3878 ls++;
3879 goto process_again;
3880 case 'L':
3881 ls = 2;
3882 goto process_again;
3883 case '0' ... '9':
3884 goto process_again;
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003885 case '.':
3886 goto process_again;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003887 case 'p':
3888 ls = 1;
3889 /* fall through */
3890 case 'd':
3891 case 'u':
3892 case 'x':
3893 case 'i':
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003894 switch (ls) {
3895 case 0:
3896 vsize = 4;
3897 break;
3898 case 1:
3899 vsize = pevent->long_size;
3900 break;
3901 case 2:
3902 vsize = 8;
Peter Huewec9bbabe2012-04-24 23:19:40 +02003903 break;
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003904 default:
3905 vsize = ls; /* ? */
3906 break;
3907 }
3908 /* fall through */
3909 case '*':
3910 if (*ptr == '*')
3911 vsize = 4;
3912
Steven Rostedtf7d82352012-04-06 00:47:53 +02003913 /* the pointers are always 4 bytes aligned */
3914 bptr = (void *)(((unsigned long)bptr + 3) &
3915 ~3);
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003916 val = pevent_read_number(pevent, bptr, vsize);
3917 bptr += vsize;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003918 arg = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09003919 if (!arg) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09003920 do_warning_event(event, "%s(%d): not enough memory!",
Namhyung Kimb1ac7542012-09-20 11:09:19 +09003921 __func__, __LINE__);
3922 goto out_free;
3923 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003924 arg->next = NULL;
3925 arg->type = PRINT_ATOM;
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003926 if (asprintf(&arg->atom.atom, "%lld", val) < 0) {
3927 free(arg);
3928 goto out_free;
3929 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003930 *next = arg;
3931 next = &arg->next;
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003932 /*
3933 * The '*' case means that an arg is used as the length.
3934 * We need to continue to figure out for what.
3935 */
3936 if (*ptr == '*')
3937 goto process_again;
3938
Steven Rostedtf7d82352012-04-06 00:47:53 +02003939 break;
3940 case 's':
3941 arg = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09003942 if (!arg) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09003943 do_warning_event(event, "%s(%d): not enough memory!",
Namhyung Kimb1ac7542012-09-20 11:09:19 +09003944 __func__, __LINE__);
3945 goto out_free;
3946 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003947 arg->next = NULL;
3948 arg->type = PRINT_BSTRING;
3949 arg->string.string = strdup(bptr);
Namhyung Kimca638582012-04-09 11:54:31 +09003950 if (!arg->string.string)
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003951 goto out_free;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003952 bptr += strlen(bptr) + 1;
3953 *next = arg;
3954 next = &arg->next;
3955 default:
3956 break;
3957 }
3958 }
3959 }
3960
3961 return args;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003962
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003963out_free:
3964 free_args(args);
3965 return NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003966}
3967
3968static char *
Irina Tirdea1d037ca2012-09-11 01:15:03 +03003969get_bprint_format(void *data, int size __maybe_unused,
3970 struct event_format *event)
Steven Rostedtf7d82352012-04-06 00:47:53 +02003971{
3972 struct pevent *pevent = event->pevent;
3973 unsigned long long addr;
3974 struct format_field *field;
3975 struct printk_map *printk;
3976 char *format;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003977
3978 field = pevent->bprint_fmt_field;
3979
3980 if (!field) {
3981 field = pevent_find_field(event, "fmt");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003982 if (!field) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09003983 do_warning_event(event, "can't find format field for binary printk");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003984 return NULL;
3985 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003986 pevent->bprint_fmt_field = field;
3987 }
3988
3989 addr = pevent_read_number(pevent, data + field->offset, field->size);
3990
3991 printk = find_printk(pevent, addr);
3992 if (!printk) {
Steven Rostedt (Red Hat)0883d9d2013-11-01 17:53:57 -04003993 if (asprintf(&format, "%%pf: (NO FORMAT FOUND at %llx)\n", addr) < 0)
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003994 return NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003995 return format;
3996 }
3997
Steven Rostedt (Red Hat)0883d9d2013-11-01 17:53:57 -04003998 if (asprintf(&format, "%s: %s", "%pf", printk->printk) < 0)
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003999 return NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004000
4001 return format;
4002}
4003
4004static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,
4005 struct event_format *event, struct print_arg *arg)
4006{
4007 unsigned char *buf;
Arnaldo Carvalho de Melo27f94d52012-11-09 17:40:47 -03004008 const char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x";
Steven Rostedtf7d82352012-04-06 00:47:53 +02004009
4010 if (arg->type == PRINT_FUNC) {
4011 process_defined_func(s, data, size, event, arg);
4012 return;
4013 }
4014
4015 if (arg->type != PRINT_FIELD) {
4016 trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d",
4017 arg->type);
4018 return;
4019 }
4020
4021 if (mac == 'm')
4022 fmt = "%.2x%.2x%.2x%.2x%.2x%.2x";
4023 if (!arg->field.field) {
4024 arg->field.field =
4025 pevent_find_any_field(event, arg->field.name);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03004026 if (!arg->field.field) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09004027 do_warning_event(event, "%s: field %s not found",
4028 __func__, arg->field.name);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03004029 return;
4030 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004031 }
4032 if (arg->field.field->size != 6) {
4033 trace_seq_printf(s, "INVALIDMAC");
4034 return;
4035 }
4036 buf = data + arg->field.field->offset;
4037 trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
4038}
4039
Namhyung Kim600da3c2012-06-22 17:10:15 +09004040static int is_printable_array(char *p, unsigned int len)
4041{
4042 unsigned int i;
4043
4044 for (i = 0; i < len && p[i]; i++)
Steven Rostedt (Red Hat)5efb9fb2013-11-01 17:53:58 -04004045 if (!isprint(p[i]) && !isspace(p[i]))
Namhyung Kim600da3c2012-06-22 17:10:15 +09004046 return 0;
4047 return 1;
4048}
4049
Arnaldo Carvalho de Meloca383a42012-11-09 15:18:57 -03004050static void print_event_fields(struct trace_seq *s, void *data,
4051 int size __maybe_unused,
Steven Rostedtf7d82352012-04-06 00:47:53 +02004052 struct event_format *event)
4053{
4054 struct format_field *field;
4055 unsigned long long val;
4056 unsigned int offset, len, i;
4057
4058 field = event->format.fields;
4059 while (field) {
4060 trace_seq_printf(s, " %s=", field->name);
4061 if (field->flags & FIELD_IS_ARRAY) {
4062 offset = field->offset;
4063 len = field->size;
4064 if (field->flags & FIELD_IS_DYNAMIC) {
4065 val = pevent_read_number(event->pevent, data + offset, len);
4066 offset = val;
4067 len = offset >> 16;
4068 offset &= 0xffff;
4069 }
Namhyung Kim600da3c2012-06-22 17:10:15 +09004070 if (field->flags & FIELD_IS_STRING &&
4071 is_printable_array(data + offset, len)) {
Steven Rostedtf7d82352012-04-06 00:47:53 +02004072 trace_seq_printf(s, "%s", (char *)data + offset);
4073 } else {
4074 trace_seq_puts(s, "ARRAY[");
4075 for (i = 0; i < len; i++) {
4076 if (i)
4077 trace_seq_puts(s, ", ");
4078 trace_seq_printf(s, "%02x",
4079 *((unsigned char *)data + offset + i));
4080 }
4081 trace_seq_putc(s, ']');
Namhyung Kim600da3c2012-06-22 17:10:15 +09004082 field->flags &= ~FIELD_IS_STRING;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004083 }
4084 } else {
4085 val = pevent_read_number(event->pevent, data + field->offset,
4086 field->size);
4087 if (field->flags & FIELD_IS_POINTER) {
4088 trace_seq_printf(s, "0x%llx", val);
4089 } else if (field->flags & FIELD_IS_SIGNED) {
4090 switch (field->size) {
4091 case 4:
4092 /*
4093 * If field is long then print it in hex.
4094 * A long usually stores pointers.
4095 */
4096 if (field->flags & FIELD_IS_LONG)
4097 trace_seq_printf(s, "0x%x", (int)val);
4098 else
4099 trace_seq_printf(s, "%d", (int)val);
4100 break;
4101 case 2:
4102 trace_seq_printf(s, "%2d", (short)val);
4103 break;
4104 case 1:
4105 trace_seq_printf(s, "%1d", (char)val);
4106 break;
4107 default:
4108 trace_seq_printf(s, "%lld", val);
4109 }
4110 } else {
4111 if (field->flags & FIELD_IS_LONG)
4112 trace_seq_printf(s, "0x%llx", val);
4113 else
4114 trace_seq_printf(s, "%llu", val);
4115 }
4116 }
4117 field = field->next;
4118 }
4119}
4120
4121static void pretty_print(struct trace_seq *s, void *data, int size, struct event_format *event)
4122{
4123 struct pevent *pevent = event->pevent;
4124 struct print_fmt *print_fmt = &event->print_fmt;
4125 struct print_arg *arg = print_fmt->args;
4126 struct print_arg *args = NULL;
4127 const char *ptr = print_fmt->format;
4128 unsigned long long val;
4129 struct func_map *func;
4130 const char *saveptr;
Steven Rostedt12e55562013-11-19 18:29:37 -05004131 struct trace_seq p;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004132 char *bprint_fmt = NULL;
4133 char format[32];
4134 int show_func;
4135 int len_as_arg;
4136 int len_arg;
4137 int len;
4138 int ls;
4139
4140 if (event->flags & EVENT_FL_FAILED) {
4141 trace_seq_printf(s, "[FAILED TO PARSE]");
4142 print_event_fields(s, data, size, event);
4143 return;
4144 }
4145
4146 if (event->flags & EVENT_FL_ISBPRINT) {
4147 bprint_fmt = get_bprint_format(data, size, event);
4148 args = make_bprint_args(bprint_fmt, data, size, event);
4149 arg = args;
4150 ptr = bprint_fmt;
4151 }
4152
4153 for (; *ptr; ptr++) {
4154 ls = 0;
4155 if (*ptr == '\\') {
4156 ptr++;
4157 switch (*ptr) {
4158 case 'n':
4159 trace_seq_putc(s, '\n');
4160 break;
4161 case 't':
4162 trace_seq_putc(s, '\t');
4163 break;
4164 case 'r':
4165 trace_seq_putc(s, '\r');
4166 break;
4167 case '\\':
4168 trace_seq_putc(s, '\\');
4169 break;
4170 default:
4171 trace_seq_putc(s, *ptr);
4172 break;
4173 }
4174
4175 } else if (*ptr == '%') {
4176 saveptr = ptr;
4177 show_func = 0;
4178 len_as_arg = 0;
4179 cont_process:
4180 ptr++;
4181 switch (*ptr) {
4182 case '%':
4183 trace_seq_putc(s, '%');
4184 break;
4185 case '#':
4186 /* FIXME: need to handle properly */
4187 goto cont_process;
4188 case 'h':
4189 ls--;
4190 goto cont_process;
4191 case 'l':
4192 ls++;
4193 goto cont_process;
4194 case 'L':
4195 ls = 2;
4196 goto cont_process;
4197 case '*':
4198 /* The argument is the length. */
Namhyung Kim245c5a12012-09-07 11:49:45 +09004199 if (!arg) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09004200 do_warning_event(event, "no argument match");
Namhyung Kim245c5a12012-09-07 11:49:45 +09004201 event->flags |= EVENT_FL_FAILED;
4202 goto out_failed;
4203 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004204 len_arg = eval_num_arg(data, size, event, arg);
4205 len_as_arg = 1;
4206 arg = arg->next;
4207 goto cont_process;
4208 case '.':
4209 case 'z':
4210 case 'Z':
4211 case '0' ... '9':
4212 goto cont_process;
4213 case 'p':
4214 if (pevent->long_size == 4)
4215 ls = 1;
4216 else
4217 ls = 2;
4218
4219 if (*(ptr+1) == 'F' ||
4220 *(ptr+1) == 'f') {
4221 ptr++;
4222 show_func = *ptr;
4223 } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') {
4224 print_mac_arg(s, *(ptr+1), data, size, event, arg);
4225 ptr++;
Steven Rostedtaaf05c72012-01-09 15:58:09 -05004226 arg = arg->next;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004227 break;
4228 }
4229
4230 /* fall through */
4231 case 'd':
4232 case 'i':
4233 case 'x':
4234 case 'X':
4235 case 'u':
Namhyung Kim245c5a12012-09-07 11:49:45 +09004236 if (!arg) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09004237 do_warning_event(event, "no argument match");
Namhyung Kim245c5a12012-09-07 11:49:45 +09004238 event->flags |= EVENT_FL_FAILED;
4239 goto out_failed;
4240 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004241
4242 len = ((unsigned long)ptr + 1) -
4243 (unsigned long)saveptr;
4244
4245 /* should never happen */
Namhyung Kim245c5a12012-09-07 11:49:45 +09004246 if (len > 31) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09004247 do_warning_event(event, "bad format!");
Namhyung Kim245c5a12012-09-07 11:49:45 +09004248 event->flags |= EVENT_FL_FAILED;
4249 len = 31;
4250 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004251
4252 memcpy(format, saveptr, len);
4253 format[len] = 0;
4254
4255 val = eval_num_arg(data, size, event, arg);
4256 arg = arg->next;
4257
4258 if (show_func) {
4259 func = find_func(pevent, val);
4260 if (func) {
4261 trace_seq_puts(s, func->func);
4262 if (show_func == 'F')
4263 trace_seq_printf(s,
4264 "+0x%llx",
4265 val - func->addr);
4266 break;
4267 }
4268 }
Wolfgang Mauererc5b35b72012-03-22 11:18:21 +01004269 if (pevent->long_size == 8 && ls &&
4270 sizeof(long) != 8) {
Steven Rostedtf7d82352012-04-06 00:47:53 +02004271 char *p;
4272
4273 ls = 2;
4274 /* make %l into %ll */
4275 p = strchr(format, 'l');
4276 if (p)
Wolfgang Mauererc5b35b72012-03-22 11:18:21 +01004277 memmove(p+1, p, strlen(p)+1);
Steven Rostedtf7d82352012-04-06 00:47:53 +02004278 else if (strcmp(format, "%p") == 0)
4279 strcpy(format, "0x%llx");
4280 }
4281 switch (ls) {
4282 case -2:
4283 if (len_as_arg)
4284 trace_seq_printf(s, format, len_arg, (char)val);
4285 else
4286 trace_seq_printf(s, format, (char)val);
4287 break;
4288 case -1:
4289 if (len_as_arg)
4290 trace_seq_printf(s, format, len_arg, (short)val);
4291 else
4292 trace_seq_printf(s, format, (short)val);
4293 break;
4294 case 0:
4295 if (len_as_arg)
4296 trace_seq_printf(s, format, len_arg, (int)val);
4297 else
4298 trace_seq_printf(s, format, (int)val);
4299 break;
4300 case 1:
4301 if (len_as_arg)
4302 trace_seq_printf(s, format, len_arg, (long)val);
4303 else
4304 trace_seq_printf(s, format, (long)val);
4305 break;
4306 case 2:
4307 if (len_as_arg)
4308 trace_seq_printf(s, format, len_arg,
4309 (long long)val);
4310 else
4311 trace_seq_printf(s, format, (long long)val);
4312 break;
4313 default:
Namhyung Kim3388cc32014-03-19 10:22:53 +09004314 do_warning_event(event, "bad count (%d)", ls);
Namhyung Kim245c5a12012-09-07 11:49:45 +09004315 event->flags |= EVENT_FL_FAILED;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004316 }
4317 break;
4318 case 's':
Namhyung Kim245c5a12012-09-07 11:49:45 +09004319 if (!arg) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09004320 do_warning_event(event, "no matching argument");
Namhyung Kim245c5a12012-09-07 11:49:45 +09004321 event->flags |= EVENT_FL_FAILED;
4322 goto out_failed;
4323 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004324
4325 len = ((unsigned long)ptr + 1) -
4326 (unsigned long)saveptr;
4327
4328 /* should never happen */
Namhyung Kim245c5a12012-09-07 11:49:45 +09004329 if (len > 31) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09004330 do_warning_event(event, "bad format!");
Namhyung Kim245c5a12012-09-07 11:49:45 +09004331 event->flags |= EVENT_FL_FAILED;
4332 len = 31;
4333 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004334
4335 memcpy(format, saveptr, len);
4336 format[len] = 0;
4337 if (!len_as_arg)
4338 len_arg = -1;
Steven Rostedt12e55562013-11-19 18:29:37 -05004339 /* Use helper trace_seq */
4340 trace_seq_init(&p);
4341 print_str_arg(&p, data, size, event,
Steven Rostedtf7d82352012-04-06 00:47:53 +02004342 format, len_arg, arg);
Steven Rostedt12e55562013-11-19 18:29:37 -05004343 trace_seq_terminate(&p);
4344 trace_seq_puts(s, p.buffer);
Steven Rostedtf7d82352012-04-06 00:47:53 +02004345 arg = arg->next;
4346 break;
4347 default:
4348 trace_seq_printf(s, ">%c<", *ptr);
4349
4350 }
4351 } else
4352 trace_seq_putc(s, *ptr);
4353 }
4354
Namhyung Kim245c5a12012-09-07 11:49:45 +09004355 if (event->flags & EVENT_FL_FAILED) {
4356out_failed:
4357 trace_seq_printf(s, "[FAILED TO PARSE]");
4358 }
4359
Steven Rostedtf7d82352012-04-06 00:47:53 +02004360 if (args) {
4361 free_args(args);
4362 free(bprint_fmt);
4363 }
4364}
4365
4366/**
4367 * pevent_data_lat_fmt - parse the data for the latency format
4368 * @pevent: a handle to the pevent
4369 * @s: the trace_seq to write to
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09004370 * @record: the record to read from
Steven Rostedtf7d82352012-04-06 00:47:53 +02004371 *
4372 * This parses out the Latency format (interrupts disabled,
4373 * need rescheduling, in hard/soft interrupt, preempt count
4374 * and lock depth) and places it into the trace_seq.
4375 */
4376void pevent_data_lat_fmt(struct pevent *pevent,
Steven Rostedt1c698182012-04-06 00:48:06 +02004377 struct trace_seq *s, struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02004378{
4379 static int check_lock_depth = 1;
Steven Rostedt0866a972012-05-22 14:52:40 +09004380 static int check_migrate_disable = 1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004381 static int lock_depth_exists;
Steven Rostedt0866a972012-05-22 14:52:40 +09004382 static int migrate_disable_exists;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004383 unsigned int lat_flags;
4384 unsigned int pc;
4385 int lock_depth;
Steven Rostedt0866a972012-05-22 14:52:40 +09004386 int migrate_disable;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004387 int hardirq;
4388 int softirq;
4389 void *data = record->data;
4390
4391 lat_flags = parse_common_flags(pevent, data);
4392 pc = parse_common_pc(pevent, data);
4393 /* lock_depth may not always exist */
Steven Rostedtf7d82352012-04-06 00:47:53 +02004394 if (lock_depth_exists)
4395 lock_depth = parse_common_lock_depth(pevent, data);
Steven Rostedt0866a972012-05-22 14:52:40 +09004396 else if (check_lock_depth) {
4397 lock_depth = parse_common_lock_depth(pevent, data);
4398 if (lock_depth < 0)
4399 check_lock_depth = 0;
4400 else
4401 lock_depth_exists = 1;
4402 }
4403
4404 /* migrate_disable may not always exist */
4405 if (migrate_disable_exists)
4406 migrate_disable = parse_common_migrate_disable(pevent, data);
4407 else if (check_migrate_disable) {
4408 migrate_disable = parse_common_migrate_disable(pevent, data);
4409 if (migrate_disable < 0)
4410 check_migrate_disable = 0;
4411 else
4412 migrate_disable_exists = 1;
4413 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004414
4415 hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
4416 softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
4417
4418 trace_seq_printf(s, "%c%c%c",
4419 (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
4420 (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
4421 'X' : '.',
4422 (lat_flags & TRACE_FLAG_NEED_RESCHED) ?
4423 'N' : '.',
4424 (hardirq && softirq) ? 'H' :
4425 hardirq ? 'h' : softirq ? 's' : '.');
4426
4427 if (pc)
4428 trace_seq_printf(s, "%x", pc);
4429 else
4430 trace_seq_putc(s, '.');
4431
Steven Rostedt0866a972012-05-22 14:52:40 +09004432 if (migrate_disable_exists) {
4433 if (migrate_disable < 0)
4434 trace_seq_putc(s, '.');
4435 else
4436 trace_seq_printf(s, "%d", migrate_disable);
4437 }
4438
Steven Rostedtf7d82352012-04-06 00:47:53 +02004439 if (lock_depth_exists) {
4440 if (lock_depth < 0)
4441 trace_seq_putc(s, '.');
4442 else
4443 trace_seq_printf(s, "%d", lock_depth);
4444 }
4445
4446 trace_seq_terminate(s);
4447}
4448
4449/**
4450 * pevent_data_type - parse out the given event type
4451 * @pevent: a handle to the pevent
4452 * @rec: the record to read from
4453 *
4454 * This returns the event id from the @rec.
4455 */
Steven Rostedt1c698182012-04-06 00:48:06 +02004456int pevent_data_type(struct pevent *pevent, struct pevent_record *rec)
Steven Rostedtf7d82352012-04-06 00:47:53 +02004457{
4458 return trace_parse_common_type(pevent, rec->data);
4459}
4460
4461/**
4462 * pevent_data_event_from_type - find the event by a given type
4463 * @pevent: a handle to the pevent
4464 * @type: the type of the event.
4465 *
4466 * This returns the event form a given @type;
4467 */
4468struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type)
4469{
4470 return pevent_find_event(pevent, type);
4471}
4472
4473/**
4474 * pevent_data_pid - parse the PID from raw data
4475 * @pevent: a handle to the pevent
4476 * @rec: the record to parse
4477 *
4478 * This returns the PID from a raw data.
4479 */
Steven Rostedt1c698182012-04-06 00:48:06 +02004480int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec)
Steven Rostedtf7d82352012-04-06 00:47:53 +02004481{
4482 return parse_common_pid(pevent, rec->data);
4483}
4484
4485/**
4486 * pevent_data_comm_from_pid - return the command line from PID
4487 * @pevent: a handle to the pevent
4488 * @pid: the PID of the task to search for
4489 *
4490 * This returns a pointer to the command line that has the given
4491 * @pid.
4492 */
4493const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid)
4494{
4495 const char *comm;
4496
4497 comm = find_cmdline(pevent, pid);
4498 return comm;
4499}
4500
4501/**
4502 * pevent_data_comm_from_pid - parse the data into the print format
4503 * @s: the trace_seq to write to
4504 * @event: the handle to the event
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09004505 * @record: the record to read from
Steven Rostedtf7d82352012-04-06 00:47:53 +02004506 *
4507 * This parses the raw @data using the given @event information and
4508 * writes the print format into the trace_seq.
4509 */
4510void pevent_event_info(struct trace_seq *s, struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02004511 struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02004512{
4513 int print_pretty = 1;
4514
Steven Rostedtc6c2b962013-11-01 17:53:59 -04004515 if (event->pevent->print_raw || (event->flags & EVENT_FL_PRINTRAW))
Steven Rostedtf7d82352012-04-06 00:47:53 +02004516 print_event_fields(s, record->data, record->size, event);
4517 else {
4518
Steven Rostedtc6c2b962013-11-01 17:53:59 -04004519 if (event->handler && !(event->flags & EVENT_FL_NOHANDLE))
Steven Rostedtf7d82352012-04-06 00:47:53 +02004520 print_pretty = event->handler(s, record, event,
4521 event->context);
4522
4523 if (print_pretty)
4524 pretty_print(s, record->data, record->size, event);
4525 }
4526
4527 trace_seq_terminate(s);
4528}
4529
Yoshihiro YUNOMAE1b372ca2013-11-01 17:53:53 -04004530static bool is_timestamp_in_us(char *trace_clock, bool use_trace_clock)
4531{
4532 if (!use_trace_clock)
4533 return true;
4534
4535 if (!strcmp(trace_clock, "local") || !strcmp(trace_clock, "global")
4536 || !strcmp(trace_clock, "uptime") || !strcmp(trace_clock, "perf"))
4537 return true;
4538
4539 /* trace_clock is setting in tsc or counter mode */
4540 return false;
4541}
4542
Steven Rostedtf7d82352012-04-06 00:47:53 +02004543void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
Yoshihiro YUNOMAE1b372ca2013-11-01 17:53:53 -04004544 struct pevent_record *record, bool use_trace_clock)
Steven Rostedtf7d82352012-04-06 00:47:53 +02004545{
Arnaldo Carvalho de Melo27f94d52012-11-09 17:40:47 -03004546 static const char *spaces = " "; /* 20 spaces */
Steven Rostedtf7d82352012-04-06 00:47:53 +02004547 struct event_format *event;
4548 unsigned long secs;
4549 unsigned long usecs;
Steven Rostedt4dc10242012-04-06 00:47:57 +02004550 unsigned long nsecs;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004551 const char *comm;
4552 void *data = record->data;
4553 int type;
4554 int pid;
4555 int len;
Steven Rostedt4dc10242012-04-06 00:47:57 +02004556 int p;
Yoshihiro YUNOMAE1b372ca2013-11-01 17:53:53 -04004557 bool use_usec_format;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004558
Yoshihiro YUNOMAE1b372ca2013-11-01 17:53:53 -04004559 use_usec_format = is_timestamp_in_us(pevent->trace_clock,
4560 use_trace_clock);
4561 if (use_usec_format) {
4562 secs = record->ts / NSECS_PER_SEC;
4563 nsecs = record->ts - secs * NSECS_PER_SEC;
4564 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004565
4566 if (record->size < 0) {
4567 do_warning("ug! negative record size %d", record->size);
4568 return;
4569 }
4570
4571 type = trace_parse_common_type(pevent, data);
4572
4573 event = pevent_find_event(pevent, type);
4574 if (!event) {
4575 do_warning("ug! no event found for type %d", type);
4576 return;
4577 }
4578
4579 pid = parse_common_pid(pevent, data);
4580 comm = find_cmdline(pevent, pid);
4581
4582 if (pevent->latency_format) {
4583 trace_seq_printf(s, "%8.8s-%-5d %3d",
4584 comm, pid, record->cpu);
4585 pevent_data_lat_fmt(pevent, s, record);
4586 } else
4587 trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu);
4588
Yoshihiro YUNOMAE1b372ca2013-11-01 17:53:53 -04004589 if (use_usec_format) {
4590 if (pevent->flags & PEVENT_NSEC_OUTPUT) {
4591 usecs = nsecs;
4592 p = 9;
4593 } else {
4594 usecs = (nsecs + 500) / NSECS_PER_USEC;
4595 p = 6;
4596 }
Steven Rostedt4dc10242012-04-06 00:47:57 +02004597
Yoshihiro YUNOMAE1b372ca2013-11-01 17:53:53 -04004598 trace_seq_printf(s, " %5lu.%0*lu: %s: ",
4599 secs, p, usecs, event->name);
4600 } else
4601 trace_seq_printf(s, " %12llu: %s: ",
4602 record->ts, event->name);
Steven Rostedtf7d82352012-04-06 00:47:53 +02004603
4604 /* Space out the event names evenly. */
4605 len = strlen(event->name);
4606 if (len < 20)
4607 trace_seq_printf(s, "%.*s", 20 - len, spaces);
4608
4609 pevent_event_info(s, event, record);
4610}
4611
4612static int events_id_cmp(const void *a, const void *b)
4613{
4614 struct event_format * const * ea = a;
4615 struct event_format * const * eb = b;
4616
4617 if ((*ea)->id < (*eb)->id)
4618 return -1;
4619
4620 if ((*ea)->id > (*eb)->id)
4621 return 1;
4622
4623 return 0;
4624}
4625
4626static int events_name_cmp(const void *a, const void *b)
4627{
4628 struct event_format * const * ea = a;
4629 struct event_format * const * eb = b;
4630 int res;
4631
4632 res = strcmp((*ea)->name, (*eb)->name);
4633 if (res)
4634 return res;
4635
4636 res = strcmp((*ea)->system, (*eb)->system);
4637 if (res)
4638 return res;
4639
4640 return events_id_cmp(a, b);
4641}
4642
4643static int events_system_cmp(const void *a, const void *b)
4644{
4645 struct event_format * const * ea = a;
4646 struct event_format * const * eb = b;
4647 int res;
4648
4649 res = strcmp((*ea)->system, (*eb)->system);
4650 if (res)
4651 return res;
4652
4653 res = strcmp((*ea)->name, (*eb)->name);
4654 if (res)
4655 return res;
4656
4657 return events_id_cmp(a, b);
4658}
4659
4660struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type sort_type)
4661{
4662 struct event_format **events;
4663 int (*sort)(const void *a, const void *b);
4664
4665 events = pevent->sort_events;
4666
4667 if (events && pevent->last_type == sort_type)
4668 return events;
4669
4670 if (!events) {
4671 events = malloc(sizeof(*events) * (pevent->nr_events + 1));
4672 if (!events)
4673 return NULL;
4674
4675 memcpy(events, pevent->events, sizeof(*events) * pevent->nr_events);
4676 events[pevent->nr_events] = NULL;
4677
4678 pevent->sort_events = events;
4679
4680 /* the internal events are sorted by id */
4681 if (sort_type == EVENT_SORT_ID) {
4682 pevent->last_type = sort_type;
4683 return events;
4684 }
4685 }
4686
4687 switch (sort_type) {
4688 case EVENT_SORT_ID:
4689 sort = events_id_cmp;
4690 break;
4691 case EVENT_SORT_NAME:
4692 sort = events_name_cmp;
4693 break;
4694 case EVENT_SORT_SYSTEM:
4695 sort = events_system_cmp;
4696 break;
4697 default:
4698 return events;
4699 }
4700
4701 qsort(events, pevent->nr_events, sizeof(*events), sort);
4702 pevent->last_type = sort_type;
4703
4704 return events;
4705}
4706
4707static struct format_field **
4708get_event_fields(const char *type, const char *name,
4709 int count, struct format_field *list)
4710{
4711 struct format_field **fields;
4712 struct format_field *field;
4713 int i = 0;
4714
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03004715 fields = malloc(sizeof(*fields) * (count + 1));
4716 if (!fields)
4717 return NULL;
4718
Steven Rostedtf7d82352012-04-06 00:47:53 +02004719 for (field = list; field; field = field->next) {
4720 fields[i++] = field;
4721 if (i == count + 1) {
4722 do_warning("event %s has more %s fields than specified",
4723 name, type);
4724 i--;
4725 break;
4726 }
4727 }
4728
4729 if (i != count)
4730 do_warning("event %s has less %s fields than specified",
4731 name, type);
4732
4733 fields[i] = NULL;
4734
4735 return fields;
4736}
4737
4738/**
4739 * pevent_event_common_fields - return a list of common fields for an event
4740 * @event: the event to return the common fields of.
4741 *
4742 * Returns an allocated array of fields. The last item in the array is NULL.
4743 * The array must be freed with free().
4744 */
4745struct format_field **pevent_event_common_fields(struct event_format *event)
4746{
4747 return get_event_fields("common", event->name,
4748 event->format.nr_common,
4749 event->format.common_fields);
4750}
4751
4752/**
4753 * pevent_event_fields - return a list of event specific fields for an event
4754 * @event: the event to return the fields of.
4755 *
4756 * Returns an allocated array of fields. The last item in the array is NULL.
4757 * The array must be freed with free().
4758 */
4759struct format_field **pevent_event_fields(struct event_format *event)
4760{
4761 return get_event_fields("event", event->name,
4762 event->format.nr_fields,
4763 event->format.fields);
4764}
4765
4766static void print_fields(struct trace_seq *s, struct print_flag_sym *field)
4767{
4768 trace_seq_printf(s, "{ %s, %s }", field->value, field->str);
4769 if (field->next) {
4770 trace_seq_puts(s, ", ");
4771 print_fields(s, field->next);
4772 }
4773}
4774
4775/* for debugging */
4776static void print_args(struct print_arg *args)
4777{
4778 int print_paren = 1;
4779 struct trace_seq s;
4780
4781 switch (args->type) {
4782 case PRINT_NULL:
4783 printf("null");
4784 break;
4785 case PRINT_ATOM:
4786 printf("%s", args->atom.atom);
4787 break;
4788 case PRINT_FIELD:
4789 printf("REC->%s", args->field.name);
4790 break;
4791 case PRINT_FLAGS:
4792 printf("__print_flags(");
4793 print_args(args->flags.field);
4794 printf(", %s, ", args->flags.delim);
4795 trace_seq_init(&s);
4796 print_fields(&s, args->flags.flags);
4797 trace_seq_do_printf(&s);
4798 trace_seq_destroy(&s);
4799 printf(")");
4800 break;
4801 case PRINT_SYMBOL:
4802 printf("__print_symbolic(");
4803 print_args(args->symbol.field);
4804 printf(", ");
4805 trace_seq_init(&s);
4806 print_fields(&s, args->symbol.symbols);
4807 trace_seq_do_printf(&s);
4808 trace_seq_destroy(&s);
4809 printf(")");
4810 break;
Namhyung Kime080e6f2012-06-27 09:41:41 +09004811 case PRINT_HEX:
4812 printf("__print_hex(");
4813 print_args(args->hex.field);
4814 printf(", ");
4815 print_args(args->hex.size);
4816 printf(")");
4817 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004818 case PRINT_STRING:
4819 case PRINT_BSTRING:
4820 printf("__get_str(%s)", args->string.string);
4821 break;
4822 case PRINT_TYPE:
4823 printf("(%s)", args->typecast.type);
4824 print_args(args->typecast.item);
4825 break;
4826 case PRINT_OP:
4827 if (strcmp(args->op.op, ":") == 0)
4828 print_paren = 0;
4829 if (print_paren)
4830 printf("(");
4831 print_args(args->op.left);
4832 printf(" %s ", args->op.op);
4833 print_args(args->op.right);
4834 if (print_paren)
4835 printf(")");
4836 break;
4837 default:
4838 /* we should warn... */
4839 return;
4840 }
4841 if (args->next) {
4842 printf("\n");
4843 print_args(args->next);
4844 }
4845}
4846
4847static void parse_header_field(const char *field,
4848 int *offset, int *size, int mandatory)
4849{
4850 unsigned long long save_input_buf_ptr;
4851 unsigned long long save_input_buf_siz;
4852 char *token;
4853 int type;
4854
4855 save_input_buf_ptr = input_buf_ptr;
4856 save_input_buf_siz = input_buf_siz;
4857
4858 if (read_expected(EVENT_ITEM, "field") < 0)
4859 return;
4860 if (read_expected(EVENT_OP, ":") < 0)
4861 return;
4862
4863 /* type */
4864 if (read_expect_type(EVENT_ITEM, &token) < 0)
4865 goto fail;
4866 free_token(token);
4867
4868 /*
4869 * If this is not a mandatory field, then test it first.
4870 */
4871 if (mandatory) {
4872 if (read_expected(EVENT_ITEM, field) < 0)
4873 return;
4874 } else {
4875 if (read_expect_type(EVENT_ITEM, &token) < 0)
4876 goto fail;
4877 if (strcmp(token, field) != 0)
4878 goto discard;
4879 free_token(token);
4880 }
4881
4882 if (read_expected(EVENT_OP, ";") < 0)
4883 return;
4884 if (read_expected(EVENT_ITEM, "offset") < 0)
4885 return;
4886 if (read_expected(EVENT_OP, ":") < 0)
4887 return;
4888 if (read_expect_type(EVENT_ITEM, &token) < 0)
4889 goto fail;
4890 *offset = atoi(token);
4891 free_token(token);
4892 if (read_expected(EVENT_OP, ";") < 0)
4893 return;
4894 if (read_expected(EVENT_ITEM, "size") < 0)
4895 return;
4896 if (read_expected(EVENT_OP, ":") < 0)
4897 return;
4898 if (read_expect_type(EVENT_ITEM, &token) < 0)
4899 goto fail;
4900 *size = atoi(token);
4901 free_token(token);
4902 if (read_expected(EVENT_OP, ";") < 0)
4903 return;
4904 type = read_token(&token);
4905 if (type != EVENT_NEWLINE) {
4906 /* newer versions of the kernel have a "signed" type */
4907 if (type != EVENT_ITEM)
4908 goto fail;
4909
4910 if (strcmp(token, "signed") != 0)
4911 goto fail;
4912
4913 free_token(token);
4914
4915 if (read_expected(EVENT_OP, ":") < 0)
4916 return;
4917
4918 if (read_expect_type(EVENT_ITEM, &token))
4919 goto fail;
4920
4921 free_token(token);
4922 if (read_expected(EVENT_OP, ";") < 0)
4923 return;
4924
4925 if (read_expect_type(EVENT_NEWLINE, &token))
4926 goto fail;
4927 }
4928 fail:
4929 free_token(token);
4930 return;
4931
4932 discard:
4933 input_buf_ptr = save_input_buf_ptr;
4934 input_buf_siz = save_input_buf_siz;
4935 *offset = 0;
4936 *size = 0;
4937 free_token(token);
4938}
4939
4940/**
4941 * pevent_parse_header_page - parse the data stored in the header page
4942 * @pevent: the handle to the pevent
4943 * @buf: the buffer storing the header page format string
4944 * @size: the size of @buf
4945 * @long_size: the long size to use if there is no header
4946 *
4947 * This parses the header page format for information on the
4948 * ring buffer used. The @buf should be copied from
4949 *
4950 * /sys/kernel/debug/tracing/events/header_page
4951 */
4952int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size,
4953 int long_size)
4954{
4955 int ignore;
4956
4957 if (!size) {
4958 /*
4959 * Old kernels did not have header page info.
4960 * Sorry but we just use what we find here in user space.
4961 */
4962 pevent->header_page_ts_size = sizeof(long long);
4963 pevent->header_page_size_size = long_size;
4964 pevent->header_page_data_offset = sizeof(long long) + long_size;
4965 pevent->old_format = 1;
4966 return -1;
4967 }
4968 init_input_buf(buf, size);
4969
4970 parse_header_field("timestamp", &pevent->header_page_ts_offset,
4971 &pevent->header_page_ts_size, 1);
4972 parse_header_field("commit", &pevent->header_page_size_offset,
4973 &pevent->header_page_size_size, 1);
4974 parse_header_field("overwrite", &pevent->header_page_overwrite,
4975 &ignore, 0);
4976 parse_header_field("data", &pevent->header_page_data_offset,
4977 &pevent->header_page_data_size, 1);
4978
4979 return 0;
4980}
4981
4982static int event_matches(struct event_format *event,
4983 int id, const char *sys_name,
4984 const char *event_name)
4985{
4986 if (id >= 0 && id != event->id)
4987 return 0;
4988
4989 if (event_name && (strcmp(event_name, event->name) != 0))
4990 return 0;
4991
4992 if (sys_name && (strcmp(sys_name, event->system) != 0))
4993 return 0;
4994
4995 return 1;
4996}
4997
4998static void free_handler(struct event_handler *handle)
4999{
5000 free((void *)handle->sys_name);
5001 free((void *)handle->event_name);
5002 free(handle);
5003}
5004
5005static int find_event_handle(struct pevent *pevent, struct event_format *event)
5006{
5007 struct event_handler *handle, **next;
5008
5009 for (next = &pevent->handlers; *next;
5010 next = &(*next)->next) {
5011 handle = *next;
5012 if (event_matches(event, handle->id,
5013 handle->sys_name,
5014 handle->event_name))
5015 break;
5016 }
5017
5018 if (!(*next))
5019 return 0;
5020
5021 pr_stat("overriding event (%d) %s:%s with new print handler",
5022 event->id, event->system, event->name);
5023
5024 event->handler = handle->func;
5025 event->context = handle->context;
5026
5027 *next = handle->next;
5028 free_handler(handle);
5029
5030 return 1;
5031}
5032
5033/**
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005034 * __pevent_parse_format - parse the event format
Steven Rostedtf7d82352012-04-06 00:47:53 +02005035 * @buf: the buffer storing the event format string
5036 * @size: the size of @buf
5037 * @sys: the system the event belongs to
5038 *
5039 * This parses the event format and creates an event structure
5040 * to quickly parse raw data for a given event.
5041 *
5042 * These files currently come from:
5043 *
5044 * /sys/kernel/debug/tracing/events/.../.../format
5045 */
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005046enum pevent_errno __pevent_parse_format(struct event_format **eventp,
5047 struct pevent *pevent, const char *buf,
5048 unsigned long size, const char *sys)
Steven Rostedtf7d82352012-04-06 00:47:53 +02005049{
5050 struct event_format *event;
5051 int ret;
5052
5053 init_input_buf(buf, size);
5054
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005055 *eventp = event = alloc_event();
Steven Rostedtf7d82352012-04-06 00:47:53 +02005056 if (!event)
Namhyung Kimbffddff2012-08-22 16:00:29 +09005057 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005058
5059 event->name = event_read_name();
5060 if (!event->name) {
5061 /* Bad event? */
Namhyung Kimbffddff2012-08-22 16:00:29 +09005062 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
5063 goto event_alloc_failed;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005064 }
5065
5066 if (strcmp(sys, "ftrace") == 0) {
Steven Rostedtf7d82352012-04-06 00:47:53 +02005067 event->flags |= EVENT_FL_ISFTRACE;
5068
5069 if (strcmp(event->name, "bprint") == 0)
5070 event->flags |= EVENT_FL_ISBPRINT;
5071 }
5072
5073 event->id = event_read_id();
Namhyung Kimbffddff2012-08-22 16:00:29 +09005074 if (event->id < 0) {
5075 ret = PEVENT_ERRNO__READ_ID_FAILED;
5076 /*
5077 * This isn't an allocation error actually.
5078 * But as the ID is critical, just bail out.
5079 */
5080 goto event_alloc_failed;
5081 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005082
5083 event->system = strdup(sys);
Namhyung Kimbffddff2012-08-22 16:00:29 +09005084 if (!event->system) {
5085 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
5086 goto event_alloc_failed;
5087 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005088
Steven Rostedt101782e2012-10-01 20:13:51 -04005089 /* Add pevent to event so that it can be referenced */
5090 event->pevent = pevent;
5091
Steven Rostedtf7d82352012-04-06 00:47:53 +02005092 ret = event_read_format(event);
5093 if (ret < 0) {
Namhyung Kimbffddff2012-08-22 16:00:29 +09005094 ret = PEVENT_ERRNO__READ_FORMAT_FAILED;
5095 goto event_parse_failed;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005096 }
5097
5098 /*
5099 * If the event has an override, don't print warnings if the event
5100 * print format fails to parse.
5101 */
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005102 if (pevent && find_event_handle(pevent, event))
Steven Rostedtf7d82352012-04-06 00:47:53 +02005103 show_warning = 0;
5104
5105 ret = event_read_print(event);
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005106 show_warning = 1;
5107
Steven Rostedtf7d82352012-04-06 00:47:53 +02005108 if (ret < 0) {
Namhyung Kimbffddff2012-08-22 16:00:29 +09005109 ret = PEVENT_ERRNO__READ_PRINT_FAILED;
5110 goto event_parse_failed;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005111 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005112
5113 if (!ret && (event->flags & EVENT_FL_ISFTRACE)) {
5114 struct format_field *field;
5115 struct print_arg *arg, **list;
5116
5117 /* old ftrace had no args */
Steven Rostedtf7d82352012-04-06 00:47:53 +02005118 list = &event->print_fmt.args;
5119 for (field = event->format.fields; field; field = field->next) {
5120 arg = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09005121 if (!arg) {
5122 event->flags |= EVENT_FL_FAILED;
5123 return PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED;
5124 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005125 arg->type = PRINT_FIELD;
5126 arg->field.name = strdup(field->name);
Namhyung Kimca638582012-04-09 11:54:31 +09005127 if (!arg->field.name) {
Namhyung Kim4b5632b2012-04-23 13:58:34 +09005128 event->flags |= EVENT_FL_FAILED;
Namhyung Kimfd34f0b2012-08-22 16:00:28 +09005129 free_arg(arg);
Namhyung Kimbffddff2012-08-22 16:00:29 +09005130 return PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED;
Namhyung Kimca638582012-04-09 11:54:31 +09005131 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005132 arg->field.field = field;
Namhyung Kimfd34f0b2012-08-22 16:00:28 +09005133 *list = arg;
5134 list = &arg->next;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005135 }
5136 return 0;
5137 }
5138
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005139 return 0;
5140
5141 event_parse_failed:
5142 event->flags |= EVENT_FL_FAILED;
5143 return ret;
5144
5145 event_alloc_failed:
5146 free(event->system);
5147 free(event->name);
5148 free(event);
5149 *eventp = NULL;
5150 return ret;
5151}
5152
Jiri Olsa71ad9582013-12-03 14:09:19 +01005153static enum pevent_errno
5154__pevent_parse_event(struct pevent *pevent,
5155 struct event_format **eventp,
5156 const char *buf, unsigned long size,
5157 const char *sys)
5158{
5159 int ret = __pevent_parse_format(eventp, pevent, buf, size, sys);
5160 struct event_format *event = *eventp;
5161
5162 if (event == NULL)
5163 return ret;
5164
5165 if (pevent && add_event(pevent, event)) {
5166 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
5167 goto event_add_failed;
5168 }
5169
5170#define PRINT_ARGS 0
5171 if (PRINT_ARGS && event->print_fmt.args)
5172 print_args(event->print_fmt.args);
5173
5174 return 0;
5175
5176event_add_failed:
5177 pevent_free_format(event);
5178 return ret;
5179}
5180
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005181/**
5182 * pevent_parse_format - parse the event format
Jiri Olsa71ad9582013-12-03 14:09:19 +01005183 * @pevent: the handle to the pevent
5184 * @eventp: returned format
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005185 * @buf: the buffer storing the event format string
5186 * @size: the size of @buf
5187 * @sys: the system the event belongs to
5188 *
5189 * This parses the event format and creates an event structure
5190 * to quickly parse raw data for a given event.
5191 *
5192 * These files currently come from:
5193 *
5194 * /sys/kernel/debug/tracing/events/.../.../format
5195 */
Jiri Olsa71ad9582013-12-03 14:09:19 +01005196enum pevent_errno pevent_parse_format(struct pevent *pevent,
5197 struct event_format **eventp,
5198 const char *buf,
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005199 unsigned long size, const char *sys)
5200{
Jiri Olsa71ad9582013-12-03 14:09:19 +01005201 return __pevent_parse_event(pevent, eventp, buf, size, sys);
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005202}
5203
5204/**
5205 * pevent_parse_event - parse the event format
5206 * @pevent: the handle to the pevent
5207 * @buf: the buffer storing the event format string
5208 * @size: the size of @buf
5209 * @sys: the system the event belongs to
5210 *
5211 * This parses the event format and creates an event structure
5212 * to quickly parse raw data for a given event.
5213 *
5214 * These files currently come from:
5215 *
5216 * /sys/kernel/debug/tracing/events/.../.../format
5217 */
5218enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
5219 unsigned long size, const char *sys)
5220{
5221 struct event_format *event = NULL;
Jiri Olsa71ad9582013-12-03 14:09:19 +01005222 return __pevent_parse_event(pevent, &event, buf, size, sys);
Steven Rostedtf7d82352012-04-06 00:47:53 +02005223}
5224
Namhyung Kim2f197b92012-08-22 16:00:30 +09005225#undef _PE
5226#define _PE(code, str) str
5227static const char * const pevent_error_str[] = {
5228 PEVENT_ERRORS
5229};
5230#undef _PE
5231
Arnaldo Carvalho de Meloca383a42012-11-09 15:18:57 -03005232int pevent_strerror(struct pevent *pevent __maybe_unused,
5233 enum pevent_errno errnum, char *buf, size_t buflen)
Namhyung Kim2f197b92012-08-22 16:00:30 +09005234{
5235 int idx;
5236 const char *msg;
5237
5238 if (errnum >= 0) {
Namhyung Kime1aa7c32012-08-22 16:00:31 +09005239 msg = strerror_r(errnum, buf, buflen);
5240 if (msg != buf) {
5241 size_t len = strlen(msg);
Irina Tirdea9612ef62012-09-08 03:43:22 +03005242 memcpy(buf, msg, min(buflen - 1, len));
5243 *(buf + min(buflen - 1, len)) = '\0';
Namhyung Kime1aa7c32012-08-22 16:00:31 +09005244 }
Namhyung Kim2f197b92012-08-22 16:00:30 +09005245 return 0;
5246 }
5247
5248 if (errnum <= __PEVENT_ERRNO__START ||
5249 errnum >= __PEVENT_ERRNO__END)
5250 return -1;
5251
Namhyung Kimf63fe792012-08-23 16:37:00 +09005252 idx = errnum - __PEVENT_ERRNO__START - 1;
Namhyung Kim2f197b92012-08-22 16:00:30 +09005253 msg = pevent_error_str[idx];
Namhyung Kimbf19b822013-12-12 16:36:17 +09005254 snprintf(buf, buflen, "%s", msg);
Namhyung Kim2f197b92012-08-22 16:00:30 +09005255
5256 return 0;
5257}
5258
Steven Rostedtf7d82352012-04-06 00:47:53 +02005259int get_field_val(struct trace_seq *s, struct format_field *field,
Steven Rostedt1c698182012-04-06 00:48:06 +02005260 const char *name, struct pevent_record *record,
Steven Rostedtf7d82352012-04-06 00:47:53 +02005261 unsigned long long *val, int err)
5262{
5263 if (!field) {
5264 if (err)
5265 trace_seq_printf(s, "<CANT FIND FIELD %s>", name);
5266 return -1;
5267 }
5268
5269 if (pevent_read_number_field(field, record->data, val)) {
5270 if (err)
5271 trace_seq_printf(s, " %s=INVALID", name);
5272 return -1;
5273 }
5274
5275 return 0;
5276}
5277
5278/**
5279 * pevent_get_field_raw - return the raw pointer into the data field
5280 * @s: The seq to print to on error
5281 * @event: the event that the field is for
5282 * @name: The name of the field
5283 * @record: The record with the field name.
5284 * @len: place to store the field length.
5285 * @err: print default error if failed.
5286 *
5287 * Returns a pointer into record->data of the field and places
5288 * the length of the field in @len.
5289 *
5290 * On failure, it returns NULL.
5291 */
5292void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02005293 const char *name, struct pevent_record *record,
Steven Rostedtf7d82352012-04-06 00:47:53 +02005294 int *len, int err)
5295{
5296 struct format_field *field;
5297 void *data = record->data;
5298 unsigned offset;
5299 int dummy;
5300
5301 if (!event)
5302 return NULL;
5303
5304 field = pevent_find_field(event, name);
5305
5306 if (!field) {
5307 if (err)
5308 trace_seq_printf(s, "<CANT FIND FIELD %s>", name);
5309 return NULL;
5310 }
5311
5312 /* Allow @len to be NULL */
5313 if (!len)
5314 len = &dummy;
5315
5316 offset = field->offset;
5317 if (field->flags & FIELD_IS_DYNAMIC) {
5318 offset = pevent_read_number(event->pevent,
5319 data + offset, field->size);
5320 *len = offset >> 16;
5321 offset &= 0xffff;
5322 } else
5323 *len = field->size;
5324
5325 return data + offset;
5326}
5327
5328/**
5329 * pevent_get_field_val - find a field and return its value
5330 * @s: The seq to print to on error
5331 * @event: the event that the field is for
5332 * @name: The name of the field
5333 * @record: The record with the field name.
5334 * @val: place to store the value of the field.
5335 * @err: print default error if failed.
5336 *
5337 * Returns 0 on success -1 on field not found.
5338 */
5339int pevent_get_field_val(struct trace_seq *s, struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02005340 const char *name, struct pevent_record *record,
Steven Rostedtf7d82352012-04-06 00:47:53 +02005341 unsigned long long *val, int err)
5342{
5343 struct format_field *field;
5344
5345 if (!event)
5346 return -1;
5347
5348 field = pevent_find_field(event, name);
5349
5350 return get_field_val(s, field, name, record, val, err);
5351}
5352
5353/**
5354 * pevent_get_common_field_val - find a common field and return its value
5355 * @s: The seq to print to on error
5356 * @event: the event that the field is for
5357 * @name: The name of the field
5358 * @record: The record with the field name.
5359 * @val: place to store the value of the field.
5360 * @err: print default error if failed.
5361 *
5362 * Returns 0 on success -1 on field not found.
5363 */
5364int pevent_get_common_field_val(struct trace_seq *s, struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02005365 const char *name, struct pevent_record *record,
Steven Rostedtf7d82352012-04-06 00:47:53 +02005366 unsigned long long *val, int err)
5367{
5368 struct format_field *field;
5369
5370 if (!event)
5371 return -1;
5372
5373 field = pevent_find_common_field(event, name);
5374
5375 return get_field_val(s, field, name, record, val, err);
5376}
5377
5378/**
5379 * pevent_get_any_field_val - find a any field and return its value
5380 * @s: The seq to print to on error
5381 * @event: the event that the field is for
5382 * @name: The name of the field
5383 * @record: The record with the field name.
5384 * @val: place to store the value of the field.
5385 * @err: print default error if failed.
5386 *
5387 * Returns 0 on success -1 on field not found.
5388 */
5389int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02005390 const char *name, struct pevent_record *record,
Steven Rostedtf7d82352012-04-06 00:47:53 +02005391 unsigned long long *val, int err)
5392{
5393 struct format_field *field;
5394
5395 if (!event)
5396 return -1;
5397
5398 field = pevent_find_any_field(event, name);
5399
5400 return get_field_val(s, field, name, record, val, err);
5401}
5402
5403/**
5404 * pevent_print_num_field - print a field and a format
5405 * @s: The seq to print to
5406 * @fmt: The printf format to print the field with.
5407 * @event: the event that the field is for
5408 * @name: The name of the field
5409 * @record: The record with the field name.
5410 * @err: print default error if failed.
5411 *
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09005412 * Returns: 0 on success, -1 field not found, or 1 if buffer is full.
Steven Rostedtf7d82352012-04-06 00:47:53 +02005413 */
5414int pevent_print_num_field(struct trace_seq *s, const char *fmt,
5415 struct event_format *event, const char *name,
Steven Rostedt1c698182012-04-06 00:48:06 +02005416 struct pevent_record *record, int err)
Steven Rostedtf7d82352012-04-06 00:47:53 +02005417{
5418 struct format_field *field = pevent_find_field(event, name);
5419 unsigned long long val;
5420
5421 if (!field)
5422 goto failed;
5423
5424 if (pevent_read_number_field(field, record->data, &val))
5425 goto failed;
5426
5427 return trace_seq_printf(s, fmt, val);
5428
5429 failed:
5430 if (err)
5431 trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
5432 return -1;
5433}
5434
Steven Rostedt6d862b82013-11-01 17:54:00 -04005435/**
5436 * pevent_print_func_field - print a field and a format for function pointers
5437 * @s: The seq to print to
5438 * @fmt: The printf format to print the field with.
5439 * @event: the event that the field is for
5440 * @name: The name of the field
5441 * @record: The record with the field name.
5442 * @err: print default error if failed.
5443 *
5444 * Returns: 0 on success, -1 field not found, or 1 if buffer is full.
5445 */
5446int pevent_print_func_field(struct trace_seq *s, const char *fmt,
5447 struct event_format *event, const char *name,
5448 struct pevent_record *record, int err)
5449{
5450 struct format_field *field = pevent_find_field(event, name);
5451 struct pevent *pevent = event->pevent;
5452 unsigned long long val;
5453 struct func_map *func;
5454 char tmp[128];
5455
5456 if (!field)
5457 goto failed;
5458
5459 if (pevent_read_number_field(field, record->data, &val))
5460 goto failed;
5461
5462 func = find_func(pevent, val);
5463
5464 if (func)
5465 snprintf(tmp, 128, "%s/0x%llx", func->func, func->addr - val);
5466 else
5467 sprintf(tmp, "0x%08llx", val);
5468
5469 return trace_seq_printf(s, fmt, tmp);
5470
5471 failed:
5472 if (err)
5473 trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
5474 return -1;
5475}
5476
Steven Rostedtf7d82352012-04-06 00:47:53 +02005477static void free_func_handle(struct pevent_function_handler *func)
5478{
5479 struct pevent_func_params *params;
5480
5481 free(func->name);
5482
5483 while (func->params) {
5484 params = func->params;
5485 func->params = params->next;
5486 free(params);
5487 }
5488
5489 free(func);
5490}
5491
5492/**
5493 * pevent_register_print_function - register a helper function
5494 * @pevent: the handle to the pevent
5495 * @func: the function to process the helper function
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09005496 * @ret_type: the return type of the helper function
Steven Rostedtf7d82352012-04-06 00:47:53 +02005497 * @name: the name of the helper function
5498 * @parameters: A list of enum pevent_func_arg_type
5499 *
5500 * Some events may have helper functions in the print format arguments.
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09005501 * This allows a plugin to dynamically create a way to process one
Steven Rostedtf7d82352012-04-06 00:47:53 +02005502 * of these functions.
5503 *
5504 * The @parameters is a variable list of pevent_func_arg_type enums that
5505 * must end with PEVENT_FUNC_ARG_VOID.
5506 */
5507int pevent_register_print_function(struct pevent *pevent,
5508 pevent_func_handler func,
5509 enum pevent_func_arg_type ret_type,
5510 char *name, ...)
5511{
5512 struct pevent_function_handler *func_handle;
5513 struct pevent_func_params **next_param;
5514 struct pevent_func_params *param;
5515 enum pevent_func_arg_type type;
5516 va_list ap;
Namhyung Kim67ed9392012-09-07 11:49:47 +09005517 int ret;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005518
5519 func_handle = find_func_handler(pevent, name);
5520 if (func_handle) {
5521 /*
5522 * This is most like caused by the users own
5523 * plugins updating the function. This overrides the
5524 * system defaults.
5525 */
5526 pr_stat("override of function helper '%s'", name);
5527 remove_func_handler(pevent, name);
5528 }
5529
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -03005530 func_handle = calloc(1, sizeof(*func_handle));
Namhyung Kim67ed9392012-09-07 11:49:47 +09005531 if (!func_handle) {
5532 do_warning("Failed to allocate function handler");
5533 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
5534 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005535
5536 func_handle->ret_type = ret_type;
5537 func_handle->name = strdup(name);
5538 func_handle->func = func;
Namhyung Kim67ed9392012-09-07 11:49:47 +09005539 if (!func_handle->name) {
5540 do_warning("Failed to allocate function name");
5541 free(func_handle);
5542 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
5543 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005544
5545 next_param = &(func_handle->params);
5546 va_start(ap, name);
5547 for (;;) {
5548 type = va_arg(ap, enum pevent_func_arg_type);
5549 if (type == PEVENT_FUNC_ARG_VOID)
5550 break;
5551
Arnaldo Carvalho de Meloe46466b2012-11-09 15:42:26 -03005552 if (type >= PEVENT_FUNC_ARG_MAX_TYPES) {
Namhyung Kim67ed9392012-09-07 11:49:47 +09005553 do_warning("Invalid argument type %d", type);
5554 ret = PEVENT_ERRNO__INVALID_ARG_TYPE;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005555 goto out_free;
5556 }
5557
Namhyung Kim67ed9392012-09-07 11:49:47 +09005558 param = malloc(sizeof(*param));
5559 if (!param) {
5560 do_warning("Failed to allocate function param");
5561 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
5562 goto out_free;
5563 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005564 param->type = type;
5565 param->next = NULL;
5566
5567 *next_param = param;
5568 next_param = &(param->next);
5569
5570 func_handle->nr_args++;
5571 }
5572 va_end(ap);
5573
5574 func_handle->next = pevent->func_handlers;
5575 pevent->func_handlers = func_handle;
5576
5577 return 0;
5578 out_free:
5579 va_end(ap);
5580 free_func_handle(func_handle);
Namhyung Kim67ed9392012-09-07 11:49:47 +09005581 return ret;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005582}
5583
Namhyung Kim20c7e5a2014-01-16 11:31:08 +09005584/**
5585 * pevent_unregister_print_function - unregister a helper function
5586 * @pevent: the handle to the pevent
5587 * @func: the function to process the helper function
5588 * @name: the name of the helper function
5589 *
5590 * This function removes existing print handler for function @name.
5591 *
5592 * Returns 0 if the handler was removed successully, -1 otherwise.
5593 */
5594int pevent_unregister_print_function(struct pevent *pevent,
5595 pevent_func_handler func, char *name)
5596{
5597 struct pevent_function_handler *func_handle;
5598
5599 func_handle = find_func_handler(pevent, name);
5600 if (func_handle && func_handle->func == func) {
5601 remove_func_handler(pevent, name);
5602 return 0;
5603 }
5604 return -1;
5605}
5606
Namhyung Kimad137012014-01-16 11:31:07 +09005607static struct event_format *pevent_search_event(struct pevent *pevent, int id,
5608 const char *sys_name,
5609 const char *event_name)
5610{
5611 struct event_format *event;
5612
5613 if (id >= 0) {
5614 /* search by id */
5615 event = pevent_find_event(pevent, id);
5616 if (!event)
5617 return NULL;
5618 if (event_name && (strcmp(event_name, event->name) != 0))
5619 return NULL;
5620 if (sys_name && (strcmp(sys_name, event->system) != 0))
5621 return NULL;
5622 } else {
5623 event = pevent_find_event_by_name(pevent, sys_name, event_name);
5624 if (!event)
5625 return NULL;
5626 }
5627 return event;
5628}
5629
Steven Rostedtf7d82352012-04-06 00:47:53 +02005630/**
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09005631 * pevent_register_event_handler - register a way to parse an event
Steven Rostedtf7d82352012-04-06 00:47:53 +02005632 * @pevent: the handle to the pevent
5633 * @id: the id of the event to register
5634 * @sys_name: the system name the event belongs to
5635 * @event_name: the name of the event
5636 * @func: the function to call to parse the event information
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09005637 * @context: the data to be passed to @func
Steven Rostedtf7d82352012-04-06 00:47:53 +02005638 *
5639 * This function allows a developer to override the parsing of
5640 * a given event. If for some reason the default print format
5641 * is not sufficient, this function will register a function
5642 * for an event to be used to parse the data instead.
5643 *
5644 * If @id is >= 0, then it is used to find the event.
5645 * else @sys_name and @event_name are used.
5646 */
Namhyung Kim79d5adf2013-06-04 14:20:18 +09005647int pevent_register_event_handler(struct pevent *pevent, int id,
5648 const char *sys_name, const char *event_name,
5649 pevent_event_handler_func func, void *context)
Steven Rostedtf7d82352012-04-06 00:47:53 +02005650{
5651 struct event_format *event;
5652 struct event_handler *handle;
5653
Namhyung Kimad137012014-01-16 11:31:07 +09005654 event = pevent_search_event(pevent, id, sys_name, event_name);
5655 if (event == NULL)
5656 goto not_found;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005657
5658 pr_stat("overriding event (%d) %s:%s with new print handler",
5659 event->id, event->system, event->name);
5660
5661 event->handler = func;
5662 event->context = context;
5663 return 0;
5664
5665 not_found:
5666 /* Save for later use. */
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -03005667 handle = calloc(1, sizeof(*handle));
Namhyung Kim0ca8da02012-09-07 11:49:46 +09005668 if (!handle) {
5669 do_warning("Failed to allocate event handler");
5670 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
5671 }
5672
Steven Rostedtf7d82352012-04-06 00:47:53 +02005673 handle->id = id;
5674 if (event_name)
5675 handle->event_name = strdup(event_name);
5676 if (sys_name)
5677 handle->sys_name = strdup(sys_name);
5678
Namhyung Kimca638582012-04-09 11:54:31 +09005679 if ((event_name && !handle->event_name) ||
5680 (sys_name && !handle->sys_name)) {
Namhyung Kim0ca8da02012-09-07 11:49:46 +09005681 do_warning("Failed to allocate event/sys name");
5682 free((void *)handle->event_name);
5683 free((void *)handle->sys_name);
5684 free(handle);
5685 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
Namhyung Kimca638582012-04-09 11:54:31 +09005686 }
5687
Steven Rostedtf7d82352012-04-06 00:47:53 +02005688 handle->func = func;
5689 handle->next = pevent->handlers;
5690 pevent->handlers = handle;
5691 handle->context = context;
5692
5693 return -1;
5694}
5695
Namhyung Kimad137012014-01-16 11:31:07 +09005696static int handle_matches(struct event_handler *handler, int id,
5697 const char *sys_name, const char *event_name,
5698 pevent_event_handler_func func, void *context)
5699{
5700 if (id >= 0 && id != handler->id)
5701 return 0;
5702
5703 if (event_name && (strcmp(event_name, handler->event_name) != 0))
5704 return 0;
5705
5706 if (sys_name && (strcmp(sys_name, handler->sys_name) != 0))
5707 return 0;
5708
5709 if (func != handler->func || context != handler->context)
5710 return 0;
5711
5712 return 1;
5713}
5714
5715/**
5716 * pevent_unregister_event_handler - unregister an existing event handler
5717 * @pevent: the handle to the pevent
5718 * @id: the id of the event to unregister
5719 * @sys_name: the system name the handler belongs to
5720 * @event_name: the name of the event handler
5721 * @func: the function to call to parse the event information
5722 * @context: the data to be passed to @func
5723 *
5724 * This function removes existing event handler (parser).
5725 *
5726 * If @id is >= 0, then it is used to find the event.
5727 * else @sys_name and @event_name are used.
5728 *
5729 * Returns 0 if handler was removed successfully, -1 if event was not found.
5730 */
5731int pevent_unregister_event_handler(struct pevent *pevent, int id,
5732 const char *sys_name, const char *event_name,
5733 pevent_event_handler_func func, void *context)
5734{
5735 struct event_format *event;
5736 struct event_handler *handle;
5737 struct event_handler **next;
5738
5739 event = pevent_search_event(pevent, id, sys_name, event_name);
5740 if (event == NULL)
5741 goto not_found;
5742
5743 if (event->handler == func && event->context == context) {
5744 pr_stat("removing override handler for event (%d) %s:%s. Going back to default handler.",
5745 event->id, event->system, event->name);
5746
5747 event->handler = NULL;
5748 event->context = NULL;
5749 return 0;
5750 }
5751
5752not_found:
5753 for (next = &pevent->handlers; *next; next = &(*next)->next) {
5754 handle = *next;
5755 if (handle_matches(handle, id, sys_name, event_name,
5756 func, context))
5757 break;
5758 }
5759
5760 if (!(*next))
5761 return -1;
5762
5763 *next = handle->next;
5764 free_handler(handle);
5765
5766 return 0;
5767}
5768
Steven Rostedtf7d82352012-04-06 00:47:53 +02005769/**
5770 * pevent_alloc - create a pevent handle
5771 */
5772struct pevent *pevent_alloc(void)
5773{
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -03005774 struct pevent *pevent = calloc(1, sizeof(*pevent));
Steven Rostedtf7d82352012-04-06 00:47:53 +02005775
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -03005776 if (pevent)
5777 pevent->ref_count = 1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005778
5779 return pevent;
5780}
5781
5782void pevent_ref(struct pevent *pevent)
5783{
5784 pevent->ref_count++;
5785}
5786
5787static void free_format_fields(struct format_field *field)
5788{
5789 struct format_field *next;
5790
5791 while (field) {
5792 next = field->next;
5793 free(field->type);
5794 free(field->name);
5795 free(field);
5796 field = next;
5797 }
5798}
5799
5800static void free_formats(struct format *format)
5801{
5802 free_format_fields(format->common_fields);
5803 free_format_fields(format->fields);
5804}
5805
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005806void pevent_free_format(struct event_format *event)
Steven Rostedtf7d82352012-04-06 00:47:53 +02005807{
5808 free(event->name);
5809 free(event->system);
5810
5811 free_formats(&event->format);
5812
5813 free(event->print_fmt.format);
5814 free_args(event->print_fmt.args);
5815
5816 free(event);
5817}
5818
5819/**
5820 * pevent_free - free a pevent handle
5821 * @pevent: the pevent handle to free
5822 */
5823void pevent_free(struct pevent *pevent)
5824{
Steven Rostedta2525a02012-04-06 00:48:02 +02005825 struct cmdline_list *cmdlist, *cmdnext;
5826 struct func_list *funclist, *funcnext;
5827 struct printk_list *printklist, *printknext;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005828 struct pevent_function_handler *func_handler;
5829 struct event_handler *handle;
5830 int i;
5831
Steven Rostedta2525a02012-04-06 00:48:02 +02005832 if (!pevent)
5833 return;
5834
5835 cmdlist = pevent->cmdlist;
5836 funclist = pevent->funclist;
5837 printklist = pevent->printklist;
5838
Steven Rostedtf7d82352012-04-06 00:47:53 +02005839 pevent->ref_count--;
5840 if (pevent->ref_count)
5841 return;
5842
5843 if (pevent->cmdlines) {
5844 for (i = 0; i < pevent->cmdline_count; i++)
5845 free(pevent->cmdlines[i].comm);
5846 free(pevent->cmdlines);
5847 }
5848
5849 while (cmdlist) {
5850 cmdnext = cmdlist->next;
5851 free(cmdlist->comm);
5852 free(cmdlist);
5853 cmdlist = cmdnext;
5854 }
5855
5856 if (pevent->func_map) {
Arnaldo Carvalho de Melo8a38cce2012-11-09 15:32:00 -03005857 for (i = 0; i < (int)pevent->func_count; i++) {
Steven Rostedtf7d82352012-04-06 00:47:53 +02005858 free(pevent->func_map[i].func);
5859 free(pevent->func_map[i].mod);
5860 }
5861 free(pevent->func_map);
5862 }
5863
5864 while (funclist) {
5865 funcnext = funclist->next;
5866 free(funclist->func);
5867 free(funclist->mod);
5868 free(funclist);
5869 funclist = funcnext;
5870 }
5871
5872 while (pevent->func_handlers) {
5873 func_handler = pevent->func_handlers;
5874 pevent->func_handlers = func_handler->next;
5875 free_func_handle(func_handler);
5876 }
5877
5878 if (pevent->printk_map) {
Arnaldo Carvalho de Melo8a38cce2012-11-09 15:32:00 -03005879 for (i = 0; i < (int)pevent->printk_count; i++)
Steven Rostedtf7d82352012-04-06 00:47:53 +02005880 free(pevent->printk_map[i].printk);
5881 free(pevent->printk_map);
5882 }
5883
5884 while (printklist) {
5885 printknext = printklist->next;
5886 free(printklist->printk);
5887 free(printklist);
5888 printklist = printknext;
5889 }
5890
5891 for (i = 0; i < pevent->nr_events; i++)
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005892 pevent_free_format(pevent->events[i]);
Steven Rostedtf7d82352012-04-06 00:47:53 +02005893
5894 while (pevent->handlers) {
5895 handle = pevent->handlers;
5896 pevent->handlers = handle->next;
5897 free_handler(handle);
5898 }
5899
5900 free(pevent->events);
5901 free(pevent->sort_events);
5902
5903 free(pevent);
5904}
5905
5906void pevent_unref(struct pevent *pevent)
5907{
5908 pevent_free(pevent);
5909}