blob: baec7d887da4fafeeacbda82697ecff6200c95da [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) {
Namhyung Kim9e9e5df2014-03-19 10:22:54 +09002745 do_warning_event(event,
2746 "Error: function '%s()' expects %d arguments but event %s only uses %d",
Steven Rostedt3a3ffa22013-11-18 21:38:20 -05002747 func->name, func->nr_args,
2748 event->name, i + 1);
2749 goto err;
2750 }
2751 } else {
2752 if (type != EVENT_DELIM || strcmp(token, ")") != 0) {
Namhyung Kim9e9e5df2014-03-19 10:22:54 +09002753 do_warning_event(event,
2754 "Error: function '%s()' only expects %d arguments but event %s has more",
Steven Rostedt3a3ffa22013-11-18 21:38:20 -05002755 func->name, func->nr_args, event->name);
2756 goto err;
2757 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02002758 }
2759
2760 *next_arg = farg;
2761 next_arg = &(farg->next);
2762 free_token(token);
2763 }
2764
2765 type = read_token(&token);
2766 *tok = token;
2767
2768 return type;
Steven Rostedt3a3ffa22013-11-18 21:38:20 -05002769
2770err:
2771 free_arg(farg);
2772 free_token(token);
2773 return EVENT_ERROR;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002774}
2775
2776static enum event_type
2777process_function(struct event_format *event, struct print_arg *arg,
2778 char *token, char **tok)
2779{
2780 struct pevent_function_handler *func;
2781
2782 if (strcmp(token, "__print_flags") == 0) {
2783 free_token(token);
Tom Zanussi5205aec2012-04-06 00:47:58 +02002784 is_flag_field = 1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002785 return process_flags(event, arg, tok);
2786 }
2787 if (strcmp(token, "__print_symbolic") == 0) {
2788 free_token(token);
Tom Zanussi5205aec2012-04-06 00:47:58 +02002789 is_symbolic_field = 1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002790 return process_symbols(event, arg, tok);
2791 }
Namhyung Kime080e6f2012-06-27 09:41:41 +09002792 if (strcmp(token, "__print_hex") == 0) {
2793 free_token(token);
2794 return process_hex(event, arg, tok);
2795 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02002796 if (strcmp(token, "__get_str") == 0) {
2797 free_token(token);
2798 return process_str(event, arg, tok);
2799 }
2800 if (strcmp(token, "__get_dynamic_array") == 0) {
2801 free_token(token);
2802 return process_dynamic_array(event, arg, tok);
2803 }
2804
2805 func = find_func_handler(event->pevent, token);
2806 if (func) {
2807 free_token(token);
2808 return process_func_handler(event, func, arg, tok);
2809 }
2810
Namhyung Kim3388cc32014-03-19 10:22:53 +09002811 do_warning_event(event, "function %s not defined", token);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002812 free_token(token);
2813 return EVENT_ERROR;
2814}
2815
2816static enum event_type
2817process_arg_token(struct event_format *event, struct print_arg *arg,
2818 char **tok, enum event_type type)
2819{
2820 char *token;
2821 char *atom;
2822
2823 token = *tok;
2824
2825 switch (type) {
2826 case EVENT_ITEM:
2827 if (strcmp(token, "REC") == 0) {
2828 free_token(token);
2829 type = process_entry(event, arg, &token);
2830 break;
2831 }
2832 atom = token;
2833 /* test the next token */
2834 type = read_token_item(&token);
2835
2836 /*
2837 * If the next token is a parenthesis, then this
2838 * is a function.
2839 */
2840 if (type == EVENT_DELIM && strcmp(token, "(") == 0) {
2841 free_token(token);
2842 token = NULL;
2843 /* this will free atom. */
2844 type = process_function(event, arg, atom, &token);
2845 break;
2846 }
2847 /* atoms can be more than one token long */
2848 while (type == EVENT_ITEM) {
Namhyung Kimd2864472012-04-09 11:54:33 +09002849 char *new_atom;
2850 new_atom = realloc(atom,
2851 strlen(atom) + strlen(token) + 2);
2852 if (!new_atom) {
2853 free(atom);
2854 *tok = NULL;
2855 free_token(token);
2856 return EVENT_ERROR;
2857 }
2858 atom = new_atom;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002859 strcat(atom, " ");
2860 strcat(atom, token);
2861 free_token(token);
2862 type = read_token_item(&token);
2863 }
2864
2865 arg->type = PRINT_ATOM;
2866 arg->atom.atom = atom;
2867 break;
2868
2869 case EVENT_DQUOTE:
2870 case EVENT_SQUOTE:
2871 arg->type = PRINT_ATOM;
2872 arg->atom.atom = token;
2873 type = read_token_item(&token);
2874 break;
2875 case EVENT_DELIM:
2876 if (strcmp(token, "(") == 0) {
2877 free_token(token);
2878 type = process_paren(event, arg, &token);
2879 break;
2880 }
2881 case EVENT_OP:
2882 /* handle single ops */
2883 arg->type = PRINT_OP;
2884 arg->op.op = token;
2885 arg->op.left = NULL;
2886 type = process_op(event, arg, &token);
2887
2888 /* On error, the op is freed */
2889 if (type == EVENT_ERROR)
2890 arg->op.op = NULL;
2891
2892 /* return error type if errored */
2893 break;
2894
2895 case EVENT_ERROR ... EVENT_NEWLINE:
2896 default:
Namhyung Kim3388cc32014-03-19 10:22:53 +09002897 do_warning_event(event, "unexpected type %d", type);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03002898 return EVENT_ERROR;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002899 }
2900 *tok = token;
2901
2902 return type;
2903}
2904
2905static int event_read_print_args(struct event_format *event, struct print_arg **list)
2906{
2907 enum event_type type = EVENT_ERROR;
2908 struct print_arg *arg;
2909 char *token;
2910 int args = 0;
2911
2912 do {
2913 if (type == EVENT_NEWLINE) {
2914 type = read_token_item(&token);
2915 continue;
2916 }
2917
2918 arg = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002919 if (!arg) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09002920 do_warning_event(event, "%s: not enough memory!",
2921 __func__);
Namhyung Kimb1ac7542012-09-20 11:09:19 +09002922 return -1;
2923 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02002924
2925 type = process_arg(event, arg, &token);
2926
2927 if (type == EVENT_ERROR) {
2928 free_token(token);
2929 free_arg(arg);
2930 return -1;
2931 }
2932
2933 *list = arg;
2934 args++;
2935
2936 if (type == EVENT_OP) {
2937 type = process_op(event, arg, &token);
2938 free_token(token);
2939 if (type == EVENT_ERROR) {
2940 *list = NULL;
2941 free_arg(arg);
2942 return -1;
2943 }
2944 list = &arg->next;
2945 continue;
2946 }
2947
2948 if (type == EVENT_DELIM && strcmp(token, ",") == 0) {
2949 free_token(token);
2950 *list = arg;
2951 list = &arg->next;
2952 continue;
2953 }
2954 break;
2955 } while (type != EVENT_NONE);
2956
2957 if (type != EVENT_NONE && type != EVENT_ERROR)
2958 free_token(token);
2959
2960 return args;
2961}
2962
2963static int event_read_print(struct event_format *event)
2964{
2965 enum event_type type;
2966 char *token;
2967 int ret;
2968
2969 if (read_expected_item(EVENT_ITEM, "print") < 0)
2970 return -1;
2971
2972 if (read_expected(EVENT_ITEM, "fmt") < 0)
2973 return -1;
2974
2975 if (read_expected(EVENT_OP, ":") < 0)
2976 return -1;
2977
2978 if (read_expect_type(EVENT_DQUOTE, &token) < 0)
2979 goto fail;
2980
2981 concat:
2982 event->print_fmt.format = token;
2983 event->print_fmt.args = NULL;
2984
2985 /* ok to have no arg */
2986 type = read_token_item(&token);
2987
2988 if (type == EVENT_NONE)
2989 return 0;
2990
2991 /* Handle concatenation of print lines */
2992 if (type == EVENT_DQUOTE) {
2993 char *cat;
2994
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03002995 if (asprintf(&cat, "%s%s", event->print_fmt.format, token) < 0)
2996 goto fail;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002997 free_token(token);
2998 free_token(event->print_fmt.format);
2999 event->print_fmt.format = NULL;
3000 token = cat;
3001 goto concat;
3002 }
3003
3004 if (test_type_token(type, token, EVENT_DELIM, ","))
3005 goto fail;
3006
3007 free_token(token);
3008
3009 ret = event_read_print_args(event, &event->print_fmt.args);
3010 if (ret < 0)
3011 return -1;
3012
3013 return ret;
3014
3015 fail:
3016 free_token(token);
3017 return -1;
3018}
3019
3020/**
3021 * pevent_find_common_field - return a common field by event
3022 * @event: handle for the event
3023 * @name: the name of the common field to return
3024 *
3025 * Returns a common field from the event by the given @name.
3026 * This only searchs the common fields and not all field.
3027 */
3028struct format_field *
3029pevent_find_common_field(struct event_format *event, const char *name)
3030{
3031 struct format_field *format;
3032
3033 for (format = event->format.common_fields;
3034 format; format = format->next) {
3035 if (strcmp(format->name, name) == 0)
3036 break;
3037 }
3038
3039 return format;
3040}
3041
3042/**
3043 * pevent_find_field - find a non-common field
3044 * @event: handle for the event
3045 * @name: the name of the non-common field
3046 *
3047 * Returns a non-common field by the given @name.
3048 * This does not search common fields.
3049 */
3050struct format_field *
3051pevent_find_field(struct event_format *event, const char *name)
3052{
3053 struct format_field *format;
3054
3055 for (format = event->format.fields;
3056 format; format = format->next) {
3057 if (strcmp(format->name, name) == 0)
3058 break;
3059 }
3060
3061 return format;
3062}
3063
3064/**
3065 * pevent_find_any_field - find any field by name
3066 * @event: handle for the event
3067 * @name: the name of the field
3068 *
3069 * Returns a field by the given @name.
3070 * This searchs the common field names first, then
3071 * the non-common ones if a common one was not found.
3072 */
3073struct format_field *
3074pevent_find_any_field(struct event_format *event, const char *name)
3075{
3076 struct format_field *format;
3077
3078 format = pevent_find_common_field(event, name);
3079 if (format)
3080 return format;
3081 return pevent_find_field(event, name);
3082}
3083
3084/**
3085 * pevent_read_number - read a number from data
3086 * @pevent: handle for the pevent
3087 * @ptr: the raw data
3088 * @size: the size of the data that holds the number
3089 *
3090 * Returns the number (converted to host) from the
3091 * raw data.
3092 */
3093unsigned long long pevent_read_number(struct pevent *pevent,
3094 const void *ptr, int size)
3095{
3096 switch (size) {
3097 case 1:
3098 return *(unsigned char *)ptr;
3099 case 2:
3100 return data2host2(pevent, ptr);
3101 case 4:
3102 return data2host4(pevent, ptr);
3103 case 8:
3104 return data2host8(pevent, ptr);
3105 default:
3106 /* BUG! */
3107 return 0;
3108 }
3109}
3110
3111/**
3112 * pevent_read_number_field - read a number from data
3113 * @field: a handle to the field
3114 * @data: the raw data to read
3115 * @value: the value to place the number in
3116 *
3117 * Reads raw data according to a field offset and size,
3118 * and translates it into @value.
3119 *
3120 * Returns 0 on success, -1 otherwise.
3121 */
3122int pevent_read_number_field(struct format_field *field, const void *data,
3123 unsigned long long *value)
3124{
3125 if (!field)
3126 return -1;
3127 switch (field->size) {
3128 case 1:
3129 case 2:
3130 case 4:
3131 case 8:
3132 *value = pevent_read_number(field->event->pevent,
3133 data + field->offset, field->size);
3134 return 0;
3135 default:
3136 return -1;
3137 }
3138}
3139
3140static int get_common_info(struct pevent *pevent,
3141 const char *type, int *offset, int *size)
3142{
3143 struct event_format *event;
3144 struct format_field *field;
3145
3146 /*
3147 * All events should have the same common elements.
3148 * Pick any event to find where the type is;
3149 */
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003150 if (!pevent->events) {
3151 do_warning("no event_list!");
3152 return -1;
3153 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003154
3155 event = pevent->events[0];
3156 field = pevent_find_common_field(event, type);
3157 if (!field)
Steven Rostedt0866a972012-05-22 14:52:40 +09003158 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003159
3160 *offset = field->offset;
3161 *size = field->size;
3162
3163 return 0;
3164}
3165
3166static int __parse_common(struct pevent *pevent, void *data,
3167 int *size, int *offset, const char *name)
3168{
3169 int ret;
3170
3171 if (!*size) {
3172 ret = get_common_info(pevent, name, offset, size);
3173 if (ret < 0)
3174 return ret;
3175 }
3176 return pevent_read_number(pevent, data + *offset, *size);
3177}
3178
3179static int trace_parse_common_type(struct pevent *pevent, void *data)
3180{
3181 return __parse_common(pevent, data,
3182 &pevent->type_size, &pevent->type_offset,
3183 "common_type");
3184}
3185
3186static int parse_common_pid(struct pevent *pevent, void *data)
3187{
3188 return __parse_common(pevent, data,
3189 &pevent->pid_size, &pevent->pid_offset,
3190 "common_pid");
3191}
3192
3193static int parse_common_pc(struct pevent *pevent, void *data)
3194{
3195 return __parse_common(pevent, data,
3196 &pevent->pc_size, &pevent->pc_offset,
3197 "common_preempt_count");
3198}
3199
3200static int parse_common_flags(struct pevent *pevent, void *data)
3201{
3202 return __parse_common(pevent, data,
3203 &pevent->flags_size, &pevent->flags_offset,
3204 "common_flags");
3205}
3206
3207static int parse_common_lock_depth(struct pevent *pevent, void *data)
3208{
Steven Rostedt0866a972012-05-22 14:52:40 +09003209 return __parse_common(pevent, data,
3210 &pevent->ld_size, &pevent->ld_offset,
3211 "common_lock_depth");
3212}
Steven Rostedtf7d82352012-04-06 00:47:53 +02003213
Steven Rostedt0866a972012-05-22 14:52:40 +09003214static int parse_common_migrate_disable(struct pevent *pevent, void *data)
3215{
3216 return __parse_common(pevent, data,
3217 &pevent->ld_size, &pevent->ld_offset,
3218 "common_migrate_disable");
Steven Rostedtf7d82352012-04-06 00:47:53 +02003219}
3220
3221static int events_id_cmp(const void *a, const void *b);
3222
3223/**
3224 * pevent_find_event - find an event by given id
3225 * @pevent: a handle to the pevent
3226 * @id: the id of the event
3227 *
3228 * Returns an event that has a given @id.
3229 */
3230struct event_format *pevent_find_event(struct pevent *pevent, int id)
3231{
3232 struct event_format **eventptr;
3233 struct event_format key;
3234 struct event_format *pkey = &key;
3235
3236 /* Check cache first */
3237 if (pevent->last_event && pevent->last_event->id == id)
3238 return pevent->last_event;
3239
3240 key.id = id;
3241
3242 eventptr = bsearch(&pkey, pevent->events, pevent->nr_events,
3243 sizeof(*pevent->events), events_id_cmp);
3244
3245 if (eventptr) {
3246 pevent->last_event = *eventptr;
3247 return *eventptr;
3248 }
3249
3250 return NULL;
3251}
3252
3253/**
3254 * pevent_find_event_by_name - find an event by given name
3255 * @pevent: a handle to the pevent
3256 * @sys: the system name to search for
3257 * @name: the name of the event to search for
3258 *
3259 * This returns an event with a given @name and under the system
3260 * @sys. If @sys is NULL the first event with @name is returned.
3261 */
3262struct event_format *
3263pevent_find_event_by_name(struct pevent *pevent,
3264 const char *sys, const char *name)
3265{
3266 struct event_format *event;
3267 int i;
3268
3269 if (pevent->last_event &&
3270 strcmp(pevent->last_event->name, name) == 0 &&
3271 (!sys || strcmp(pevent->last_event->system, sys) == 0))
3272 return pevent->last_event;
3273
3274 for (i = 0; i < pevent->nr_events; i++) {
3275 event = pevent->events[i];
3276 if (strcmp(event->name, name) == 0) {
3277 if (!sys)
3278 break;
3279 if (strcmp(event->system, sys) == 0)
3280 break;
3281 }
3282 }
3283 if (i == pevent->nr_events)
3284 event = NULL;
3285
3286 pevent->last_event = event;
3287 return event;
3288}
3289
3290static unsigned long long
3291eval_num_arg(void *data, int size, struct event_format *event, struct print_arg *arg)
3292{
3293 struct pevent *pevent = event->pevent;
3294 unsigned long long val = 0;
3295 unsigned long long left, right;
3296 struct print_arg *typearg = NULL;
3297 struct print_arg *larg;
3298 unsigned long offset;
3299 unsigned int field_size;
3300
3301 switch (arg->type) {
3302 case PRINT_NULL:
3303 /* ?? */
3304 return 0;
3305 case PRINT_ATOM:
3306 return strtoull(arg->atom.atom, NULL, 0);
3307 case PRINT_FIELD:
3308 if (!arg->field.field) {
3309 arg->field.field = pevent_find_any_field(event, arg->field.name);
3310 if (!arg->field.field)
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003311 goto out_warning_field;
3312
Steven Rostedtf7d82352012-04-06 00:47:53 +02003313 }
3314 /* must be a number */
3315 val = pevent_read_number(pevent, data + arg->field.field->offset,
3316 arg->field.field->size);
3317 break;
3318 case PRINT_FLAGS:
3319 case PRINT_SYMBOL:
Namhyung Kime080e6f2012-06-27 09:41:41 +09003320 case PRINT_HEX:
Steven Rostedtf7d82352012-04-06 00:47:53 +02003321 break;
3322 case PRINT_TYPE:
3323 val = eval_num_arg(data, size, event, arg->typecast.item);
3324 return eval_type(val, arg, 0);
3325 case PRINT_STRING:
3326 case PRINT_BSTRING:
3327 return 0;
3328 case PRINT_FUNC: {
3329 struct trace_seq s;
3330 trace_seq_init(&s);
3331 val = process_defined_func(&s, data, size, event, arg);
3332 trace_seq_destroy(&s);
3333 return val;
3334 }
3335 case PRINT_OP:
3336 if (strcmp(arg->op.op, "[") == 0) {
3337 /*
3338 * Arrays are special, since we don't want
3339 * to read the arg as is.
3340 */
3341 right = eval_num_arg(data, size, event, arg->op.right);
3342
3343 /* handle typecasts */
3344 larg = arg->op.left;
3345 while (larg->type == PRINT_TYPE) {
3346 if (!typearg)
3347 typearg = larg;
3348 larg = larg->typecast.item;
3349 }
3350
3351 /* Default to long size */
3352 field_size = pevent->long_size;
3353
3354 switch (larg->type) {
3355 case PRINT_DYNAMIC_ARRAY:
3356 offset = pevent_read_number(pevent,
3357 data + larg->dynarray.field->offset,
3358 larg->dynarray.field->size);
3359 if (larg->dynarray.field->elementsize)
3360 field_size = larg->dynarray.field->elementsize;
3361 /*
3362 * The actual length of the dynamic array is stored
3363 * in the top half of the field, and the offset
3364 * is in the bottom half of the 32 bit field.
3365 */
3366 offset &= 0xffff;
3367 offset += right;
3368 break;
3369 case PRINT_FIELD:
3370 if (!larg->field.field) {
3371 larg->field.field =
3372 pevent_find_any_field(event, larg->field.name);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003373 if (!larg->field.field) {
3374 arg = larg;
3375 goto out_warning_field;
3376 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003377 }
3378 field_size = larg->field.field->elementsize;
3379 offset = larg->field.field->offset +
3380 right * larg->field.field->elementsize;
3381 break;
3382 default:
3383 goto default_op; /* oops, all bets off */
3384 }
3385 val = pevent_read_number(pevent,
3386 data + offset, field_size);
3387 if (typearg)
3388 val = eval_type(val, typearg, 1);
3389 break;
3390 } else if (strcmp(arg->op.op, "?") == 0) {
3391 left = eval_num_arg(data, size, event, arg->op.left);
3392 arg = arg->op.right;
3393 if (left)
3394 val = eval_num_arg(data, size, event, arg->op.left);
3395 else
3396 val = eval_num_arg(data, size, event, arg->op.right);
3397 break;
3398 }
3399 default_op:
3400 left = eval_num_arg(data, size, event, arg->op.left);
3401 right = eval_num_arg(data, size, event, arg->op.right);
3402 switch (arg->op.op[0]) {
3403 case '!':
3404 switch (arg->op.op[1]) {
3405 case 0:
3406 val = !right;
3407 break;
3408 case '=':
3409 val = left != right;
3410 break;
3411 default:
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003412 goto out_warning_op;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003413 }
3414 break;
3415 case '~':
3416 val = ~right;
3417 break;
3418 case '|':
3419 if (arg->op.op[1])
3420 val = left || right;
3421 else
3422 val = left | right;
3423 break;
3424 case '&':
3425 if (arg->op.op[1])
3426 val = left && right;
3427 else
3428 val = left & right;
3429 break;
3430 case '<':
3431 switch (arg->op.op[1]) {
3432 case 0:
3433 val = left < right;
3434 break;
3435 case '<':
3436 val = left << right;
3437 break;
3438 case '=':
3439 val = left <= right;
3440 break;
3441 default:
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003442 goto out_warning_op;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003443 }
3444 break;
3445 case '>':
3446 switch (arg->op.op[1]) {
3447 case 0:
3448 val = left > right;
3449 break;
3450 case '>':
3451 val = left >> right;
3452 break;
3453 case '=':
3454 val = left >= right;
3455 break;
3456 default:
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003457 goto out_warning_op;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003458 }
3459 break;
3460 case '=':
3461 if (arg->op.op[1] != '=')
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003462 goto out_warning_op;
3463
Steven Rostedtf7d82352012-04-06 00:47:53 +02003464 val = left == right;
3465 break;
3466 case '-':
3467 val = left - right;
3468 break;
3469 case '+':
3470 val = left + right;
3471 break;
Steven Rostedt2e7a5fc2012-04-06 00:48:04 +02003472 case '/':
3473 val = left / right;
3474 break;
3475 case '*':
3476 val = left * right;
3477 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003478 default:
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003479 goto out_warning_op;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003480 }
3481 break;
Steven Rostedt0497a9e2013-11-11 16:08:10 -05003482 case PRINT_DYNAMIC_ARRAY:
3483 /* Without [], we pass the address to the dynamic data */
3484 offset = pevent_read_number(pevent,
3485 data + arg->dynarray.field->offset,
3486 arg->dynarray.field->size);
3487 /*
3488 * The actual length of the dynamic array is stored
3489 * in the top half of the field, and the offset
3490 * is in the bottom half of the 32 bit field.
3491 */
3492 offset &= 0xffff;
Arnaldo Carvalho de Melo6b5fa0b2013-11-19 16:14:51 -03003493 val = (unsigned long long)((unsigned long)data + offset);
Steven Rostedt0497a9e2013-11-11 16:08:10 -05003494 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003495 default: /* not sure what to do there */
3496 return 0;
3497 }
3498 return val;
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003499
3500out_warning_op:
Namhyung Kim3388cc32014-03-19 10:22:53 +09003501 do_warning_event(event, "%s: unknown op '%s'", __func__, arg->op.op);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003502 return 0;
3503
3504out_warning_field:
Namhyung Kim3388cc32014-03-19 10:22:53 +09003505 do_warning_event(event, "%s: field %s not found",
3506 __func__, arg->field.name);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003507 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003508}
3509
3510struct flag {
3511 const char *name;
3512 unsigned long long value;
3513};
3514
3515static const struct flag flags[] = {
3516 { "HI_SOFTIRQ", 0 },
3517 { "TIMER_SOFTIRQ", 1 },
3518 { "NET_TX_SOFTIRQ", 2 },
3519 { "NET_RX_SOFTIRQ", 3 },
3520 { "BLOCK_SOFTIRQ", 4 },
3521 { "BLOCK_IOPOLL_SOFTIRQ", 5 },
3522 { "TASKLET_SOFTIRQ", 6 },
3523 { "SCHED_SOFTIRQ", 7 },
3524 { "HRTIMER_SOFTIRQ", 8 },
3525 { "RCU_SOFTIRQ", 9 },
3526
3527 { "HRTIMER_NORESTART", 0 },
3528 { "HRTIMER_RESTART", 1 },
3529};
3530
3531static unsigned long long eval_flag(const char *flag)
3532{
3533 int i;
3534
3535 /*
3536 * Some flags in the format files do not get converted.
3537 * If the flag is not numeric, see if it is something that
3538 * we already know about.
3539 */
3540 if (isdigit(flag[0]))
3541 return strtoull(flag, NULL, 0);
3542
3543 for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++)
3544 if (strcmp(flags[i].name, flag) == 0)
3545 return flags[i].value;
3546
3547 return 0;
3548}
3549
3550static void print_str_to_seq(struct trace_seq *s, const char *format,
3551 int len_arg, const char *str)
3552{
3553 if (len_arg >= 0)
3554 trace_seq_printf(s, format, len_arg, str);
3555 else
3556 trace_seq_printf(s, format, str);
3557}
3558
3559static void print_str_arg(struct trace_seq *s, void *data, int size,
3560 struct event_format *event, const char *format,
3561 int len_arg, struct print_arg *arg)
3562{
3563 struct pevent *pevent = event->pevent;
3564 struct print_flag_sym *flag;
Namhyung Kimb7008072012-06-27 09:41:40 +09003565 struct format_field *field;
Steven Rostedt (Red Hat)0970b5f2013-11-01 17:53:55 -04003566 struct printk_map *printk;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003567 unsigned long long val, fval;
3568 unsigned long addr;
3569 char *str;
Namhyung Kime080e6f2012-06-27 09:41:41 +09003570 unsigned char *hex;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003571 int print;
Namhyung Kime080e6f2012-06-27 09:41:41 +09003572 int i, len;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003573
3574 switch (arg->type) {
3575 case PRINT_NULL:
3576 /* ?? */
3577 return;
3578 case PRINT_ATOM:
3579 print_str_to_seq(s, format, len_arg, arg->atom.atom);
3580 return;
3581 case PRINT_FIELD:
Namhyung Kimb7008072012-06-27 09:41:40 +09003582 field = arg->field.field;
3583 if (!field) {
3584 field = pevent_find_any_field(event, arg->field.name);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003585 if (!field) {
3586 str = arg->field.name;
3587 goto out_warning_field;
3588 }
Namhyung Kimb7008072012-06-27 09:41:40 +09003589 arg->field.field = field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003590 }
3591 /* Zero sized fields, mean the rest of the data */
Namhyung Kimb7008072012-06-27 09:41:40 +09003592 len = field->size ? : size - field->offset;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003593
3594 /*
3595 * Some events pass in pointers. If this is not an array
3596 * and the size is the same as long_size, assume that it
3597 * is a pointer.
3598 */
Namhyung Kimb7008072012-06-27 09:41:40 +09003599 if (!(field->flags & FIELD_IS_ARRAY) &&
3600 field->size == pevent->long_size) {
3601 addr = *(unsigned long *)(data + field->offset);
Steven Rostedt (Red Hat)0970b5f2013-11-01 17:53:55 -04003602 /* Check if it matches a print format */
3603 printk = find_printk(pevent, addr);
3604 if (printk)
3605 trace_seq_puts(s, printk->printk);
3606 else
3607 trace_seq_printf(s, "%lx", addr);
Steven Rostedtf7d82352012-04-06 00:47:53 +02003608 break;
3609 }
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003610 str = malloc(len + 1);
3611 if (!str) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09003612 do_warning_event(event, "%s: not enough memory!",
3613 __func__);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003614 return;
3615 }
Namhyung Kimb7008072012-06-27 09:41:40 +09003616 memcpy(str, data + field->offset, len);
Steven Rostedtf7d82352012-04-06 00:47:53 +02003617 str[len] = 0;
3618 print_str_to_seq(s, format, len_arg, str);
3619 free(str);
3620 break;
3621 case PRINT_FLAGS:
3622 val = eval_num_arg(data, size, event, arg->flags.field);
3623 print = 0;
3624 for (flag = arg->flags.flags; flag; flag = flag->next) {
3625 fval = eval_flag(flag->value);
3626 if (!val && !fval) {
3627 print_str_to_seq(s, format, len_arg, flag->str);
3628 break;
3629 }
3630 if (fval && (val & fval) == fval) {
3631 if (print && arg->flags.delim)
3632 trace_seq_puts(s, arg->flags.delim);
3633 print_str_to_seq(s, format, len_arg, flag->str);
3634 print = 1;
3635 val &= ~fval;
3636 }
3637 }
3638 break;
3639 case PRINT_SYMBOL:
3640 val = eval_num_arg(data, size, event, arg->symbol.field);
3641 for (flag = arg->symbol.symbols; flag; flag = flag->next) {
3642 fval = eval_flag(flag->value);
3643 if (val == fval) {
3644 print_str_to_seq(s, format, len_arg, flag->str);
3645 break;
3646 }
3647 }
3648 break;
Namhyung Kime080e6f2012-06-27 09:41:41 +09003649 case PRINT_HEX:
Howard Cochranb30f75e2013-11-01 17:53:56 -04003650 if (arg->hex.field->type == PRINT_DYNAMIC_ARRAY) {
3651 unsigned long offset;
3652 offset = pevent_read_number(pevent,
3653 data + arg->hex.field->dynarray.field->offset,
3654 arg->hex.field->dynarray.field->size);
3655 hex = data + (offset & 0xffff);
3656 } else {
3657 field = arg->hex.field->field.field;
3658 if (!field) {
3659 str = arg->hex.field->field.name;
3660 field = pevent_find_any_field(event, str);
3661 if (!field)
3662 goto out_warning_field;
3663 arg->hex.field->field.field = field;
3664 }
3665 hex = data + field->offset;
Namhyung Kime080e6f2012-06-27 09:41:41 +09003666 }
Namhyung Kime080e6f2012-06-27 09:41:41 +09003667 len = eval_num_arg(data, size, event, arg->hex.size);
3668 for (i = 0; i < len; i++) {
3669 if (i)
3670 trace_seq_putc(s, ' ');
3671 trace_seq_printf(s, "%02x", hex[i]);
3672 }
3673 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003674
3675 case PRINT_TYPE:
3676 break;
3677 case PRINT_STRING: {
3678 int str_offset;
3679
3680 if (arg->string.offset == -1) {
3681 struct format_field *f;
3682
3683 f = pevent_find_any_field(event, arg->string.string);
3684 arg->string.offset = f->offset;
3685 }
3686 str_offset = data2host4(pevent, data + arg->string.offset);
3687 str_offset &= 0xffff;
3688 print_str_to_seq(s, format, len_arg, ((char *)data) + str_offset);
3689 break;
3690 }
3691 case PRINT_BSTRING:
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003692 print_str_to_seq(s, format, len_arg, arg->string.string);
Steven Rostedtf7d82352012-04-06 00:47:53 +02003693 break;
3694 case PRINT_OP:
3695 /*
3696 * The only op for string should be ? :
3697 */
3698 if (arg->op.op[0] != '?')
3699 return;
3700 val = eval_num_arg(data, size, event, arg->op.left);
3701 if (val)
3702 print_str_arg(s, data, size, event,
3703 format, len_arg, arg->op.right->op.left);
3704 else
3705 print_str_arg(s, data, size, event,
3706 format, len_arg, arg->op.right->op.right);
3707 break;
3708 case PRINT_FUNC:
3709 process_defined_func(s, data, size, event, arg);
3710 break;
3711 default:
3712 /* well... */
3713 break;
3714 }
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003715
3716 return;
3717
3718out_warning_field:
Namhyung Kim3388cc32014-03-19 10:22:53 +09003719 do_warning_event(event, "%s: field %s not found",
3720 __func__, arg->field.name);
Steven Rostedtf7d82352012-04-06 00:47:53 +02003721}
3722
3723static unsigned long long
3724process_defined_func(struct trace_seq *s, void *data, int size,
3725 struct event_format *event, struct print_arg *arg)
3726{
3727 struct pevent_function_handler *func_handle = arg->func.func;
3728 struct pevent_func_params *param;
3729 unsigned long long *args;
3730 unsigned long long ret;
3731 struct print_arg *farg;
3732 struct trace_seq str;
3733 struct save_str {
3734 struct save_str *next;
3735 char *str;
3736 } *strings = NULL, *string;
3737 int i;
3738
3739 if (!func_handle->nr_args) {
3740 ret = (*func_handle->func)(s, NULL);
3741 goto out;
3742 }
3743
3744 farg = arg->func.args;
3745 param = func_handle->params;
3746
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003747 ret = ULLONG_MAX;
3748 args = malloc(sizeof(*args) * func_handle->nr_args);
3749 if (!args)
3750 goto out;
3751
Steven Rostedtf7d82352012-04-06 00:47:53 +02003752 for (i = 0; i < func_handle->nr_args; i++) {
3753 switch (param->type) {
3754 case PEVENT_FUNC_ARG_INT:
3755 case PEVENT_FUNC_ARG_LONG:
3756 case PEVENT_FUNC_ARG_PTR:
3757 args[i] = eval_num_arg(data, size, event, farg);
3758 break;
3759 case PEVENT_FUNC_ARG_STRING:
3760 trace_seq_init(&str);
3761 print_str_arg(&str, data, size, event, "%s", -1, farg);
3762 trace_seq_terminate(&str);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003763 string = malloc(sizeof(*string));
3764 if (!string) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09003765 do_warning_event(event, "%s(%d): malloc str",
3766 __func__, __LINE__);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003767 goto out_free;
3768 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003769 string->next = strings;
3770 string->str = strdup(str.buffer);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003771 if (!string->str) {
3772 free(string);
Namhyung Kim3388cc32014-03-19 10:22:53 +09003773 do_warning_event(event, "%s(%d): malloc str",
3774 __func__, __LINE__);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003775 goto out_free;
3776 }
Robert Richter0cf26012012-08-07 19:43:14 +02003777 args[i] = (uintptr_t)string->str;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003778 strings = string;
3779 trace_seq_destroy(&str);
3780 break;
3781 default:
3782 /*
3783 * Something went totally wrong, this is not
3784 * an input error, something in this code broke.
3785 */
Namhyung Kim3388cc32014-03-19 10:22:53 +09003786 do_warning_event(event, "Unexpected end of arguments\n");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003787 goto out_free;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003788 }
3789 farg = farg->next;
Namhyung Kim21c69e72012-05-23 11:36:51 +09003790 param = param->next;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003791 }
3792
3793 ret = (*func_handle->func)(s, args);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003794out_free:
Steven Rostedtf7d82352012-04-06 00:47:53 +02003795 free(args);
3796 while (strings) {
3797 string = strings;
3798 strings = string->next;
3799 free(string->str);
3800 free(string);
3801 }
3802
3803 out:
3804 /* TBD : handle return type here */
3805 return ret;
3806}
3807
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003808static void free_args(struct print_arg *args)
3809{
3810 struct print_arg *next;
3811
3812 while (args) {
3813 next = args->next;
3814
3815 free_arg(args);
3816 args = next;
3817 }
3818}
3819
Steven Rostedtf7d82352012-04-06 00:47:53 +02003820static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event_format *event)
3821{
3822 struct pevent *pevent = event->pevent;
3823 struct format_field *field, *ip_field;
3824 struct print_arg *args, *arg, **next;
3825 unsigned long long ip, val;
3826 char *ptr;
3827 void *bptr;
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003828 int vsize;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003829
3830 field = pevent->bprint_buf_field;
3831 ip_field = pevent->bprint_ip_field;
3832
3833 if (!field) {
3834 field = pevent_find_field(event, "buf");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003835 if (!field) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09003836 do_warning_event(event, "can't find buffer field for binary printk");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003837 return NULL;
3838 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003839 ip_field = pevent_find_field(event, "ip");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003840 if (!ip_field) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09003841 do_warning_event(event, "can't find ip field for binary printk");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003842 return NULL;
3843 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003844 pevent->bprint_buf_field = field;
3845 pevent->bprint_ip_field = ip_field;
3846 }
3847
3848 ip = pevent_read_number(pevent, data + ip_field->offset, ip_field->size);
3849
3850 /*
3851 * The first arg is the IP pointer.
3852 */
3853 args = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09003854 if (!args) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09003855 do_warning_event(event, "%s(%d): not enough memory!",
3856 __func__, __LINE__);
Namhyung Kimb1ac7542012-09-20 11:09:19 +09003857 return NULL;
3858 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003859 arg = args;
3860 arg->next = NULL;
3861 next = &arg->next;
3862
3863 arg->type = PRINT_ATOM;
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003864
3865 if (asprintf(&arg->atom.atom, "%lld", ip) < 0)
3866 goto out_free;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003867
Steven Rostedt (Red Hat)0883d9d2013-11-01 17:53:57 -04003868 /* skip the first "%pf: " */
3869 for (ptr = fmt + 5, bptr = data + field->offset;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003870 bptr < data + size && *ptr; ptr++) {
3871 int ls = 0;
3872
3873 if (*ptr == '%') {
3874 process_again:
3875 ptr++;
3876 switch (*ptr) {
3877 case '%':
3878 break;
3879 case 'l':
3880 ls++;
3881 goto process_again;
3882 case 'L':
3883 ls = 2;
3884 goto process_again;
3885 case '0' ... '9':
3886 goto process_again;
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003887 case '.':
3888 goto process_again;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003889 case 'p':
3890 ls = 1;
3891 /* fall through */
3892 case 'd':
3893 case 'u':
3894 case 'x':
3895 case 'i':
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003896 switch (ls) {
3897 case 0:
3898 vsize = 4;
3899 break;
3900 case 1:
3901 vsize = pevent->long_size;
3902 break;
3903 case 2:
3904 vsize = 8;
Peter Huewec9bbabe2012-04-24 23:19:40 +02003905 break;
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003906 default:
3907 vsize = ls; /* ? */
3908 break;
3909 }
3910 /* fall through */
3911 case '*':
3912 if (*ptr == '*')
3913 vsize = 4;
3914
Steven Rostedtf7d82352012-04-06 00:47:53 +02003915 /* the pointers are always 4 bytes aligned */
3916 bptr = (void *)(((unsigned long)bptr + 3) &
3917 ~3);
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003918 val = pevent_read_number(pevent, bptr, vsize);
3919 bptr += vsize;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003920 arg = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09003921 if (!arg) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09003922 do_warning_event(event, "%s(%d): not enough memory!",
Namhyung Kimb1ac7542012-09-20 11:09:19 +09003923 __func__, __LINE__);
3924 goto out_free;
3925 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003926 arg->next = NULL;
3927 arg->type = PRINT_ATOM;
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003928 if (asprintf(&arg->atom.atom, "%lld", val) < 0) {
3929 free(arg);
3930 goto out_free;
3931 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003932 *next = arg;
3933 next = &arg->next;
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003934 /*
3935 * The '*' case means that an arg is used as the length.
3936 * We need to continue to figure out for what.
3937 */
3938 if (*ptr == '*')
3939 goto process_again;
3940
Steven Rostedtf7d82352012-04-06 00:47:53 +02003941 break;
3942 case 's':
3943 arg = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09003944 if (!arg) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09003945 do_warning_event(event, "%s(%d): not enough memory!",
Namhyung Kimb1ac7542012-09-20 11:09:19 +09003946 __func__, __LINE__);
3947 goto out_free;
3948 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003949 arg->next = NULL;
3950 arg->type = PRINT_BSTRING;
3951 arg->string.string = strdup(bptr);
Namhyung Kimca638582012-04-09 11:54:31 +09003952 if (!arg->string.string)
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003953 goto out_free;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003954 bptr += strlen(bptr) + 1;
3955 *next = arg;
3956 next = &arg->next;
3957 default:
3958 break;
3959 }
3960 }
3961 }
3962
3963 return args;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003964
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003965out_free:
3966 free_args(args);
3967 return NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003968}
3969
3970static char *
Irina Tirdea1d037ca2012-09-11 01:15:03 +03003971get_bprint_format(void *data, int size __maybe_unused,
3972 struct event_format *event)
Steven Rostedtf7d82352012-04-06 00:47:53 +02003973{
3974 struct pevent *pevent = event->pevent;
3975 unsigned long long addr;
3976 struct format_field *field;
3977 struct printk_map *printk;
3978 char *format;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003979
3980 field = pevent->bprint_fmt_field;
3981
3982 if (!field) {
3983 field = pevent_find_field(event, "fmt");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003984 if (!field) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09003985 do_warning_event(event, "can't find format field for binary printk");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003986 return NULL;
3987 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003988 pevent->bprint_fmt_field = field;
3989 }
3990
3991 addr = pevent_read_number(pevent, data + field->offset, field->size);
3992
3993 printk = find_printk(pevent, addr);
3994 if (!printk) {
Steven Rostedt (Red Hat)0883d9d2013-11-01 17:53:57 -04003995 if (asprintf(&format, "%%pf: (NO FORMAT FOUND at %llx)\n", addr) < 0)
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003996 return NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003997 return format;
3998 }
3999
Steven Rostedt (Red Hat)0883d9d2013-11-01 17:53:57 -04004000 if (asprintf(&format, "%s: %s", "%pf", printk->printk) < 0)
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03004001 return NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004002
4003 return format;
4004}
4005
4006static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,
4007 struct event_format *event, struct print_arg *arg)
4008{
4009 unsigned char *buf;
Arnaldo Carvalho de Melo27f94d52012-11-09 17:40:47 -03004010 const char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x";
Steven Rostedtf7d82352012-04-06 00:47:53 +02004011
4012 if (arg->type == PRINT_FUNC) {
4013 process_defined_func(s, data, size, event, arg);
4014 return;
4015 }
4016
4017 if (arg->type != PRINT_FIELD) {
4018 trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d",
4019 arg->type);
4020 return;
4021 }
4022
4023 if (mac == 'm')
4024 fmt = "%.2x%.2x%.2x%.2x%.2x%.2x";
4025 if (!arg->field.field) {
4026 arg->field.field =
4027 pevent_find_any_field(event, arg->field.name);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03004028 if (!arg->field.field) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09004029 do_warning_event(event, "%s: field %s not found",
4030 __func__, arg->field.name);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03004031 return;
4032 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004033 }
4034 if (arg->field.field->size != 6) {
4035 trace_seq_printf(s, "INVALIDMAC");
4036 return;
4037 }
4038 buf = data + arg->field.field->offset;
4039 trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
4040}
4041
Namhyung Kim600da3c2012-06-22 17:10:15 +09004042static int is_printable_array(char *p, unsigned int len)
4043{
4044 unsigned int i;
4045
4046 for (i = 0; i < len && p[i]; i++)
Steven Rostedt (Red Hat)5efb9fb2013-11-01 17:53:58 -04004047 if (!isprint(p[i]) && !isspace(p[i]))
Namhyung Kim600da3c2012-06-22 17:10:15 +09004048 return 0;
4049 return 1;
4050}
4051
Arnaldo Carvalho de Meloca383a42012-11-09 15:18:57 -03004052static void print_event_fields(struct trace_seq *s, void *data,
4053 int size __maybe_unused,
Steven Rostedtf7d82352012-04-06 00:47:53 +02004054 struct event_format *event)
4055{
4056 struct format_field *field;
4057 unsigned long long val;
4058 unsigned int offset, len, i;
4059
4060 field = event->format.fields;
4061 while (field) {
4062 trace_seq_printf(s, " %s=", field->name);
4063 if (field->flags & FIELD_IS_ARRAY) {
4064 offset = field->offset;
4065 len = field->size;
4066 if (field->flags & FIELD_IS_DYNAMIC) {
4067 val = pevent_read_number(event->pevent, data + offset, len);
4068 offset = val;
4069 len = offset >> 16;
4070 offset &= 0xffff;
4071 }
Namhyung Kim600da3c2012-06-22 17:10:15 +09004072 if (field->flags & FIELD_IS_STRING &&
4073 is_printable_array(data + offset, len)) {
Steven Rostedtf7d82352012-04-06 00:47:53 +02004074 trace_seq_printf(s, "%s", (char *)data + offset);
4075 } else {
4076 trace_seq_puts(s, "ARRAY[");
4077 for (i = 0; i < len; i++) {
4078 if (i)
4079 trace_seq_puts(s, ", ");
4080 trace_seq_printf(s, "%02x",
4081 *((unsigned char *)data + offset + i));
4082 }
4083 trace_seq_putc(s, ']');
Namhyung Kim600da3c2012-06-22 17:10:15 +09004084 field->flags &= ~FIELD_IS_STRING;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004085 }
4086 } else {
4087 val = pevent_read_number(event->pevent, data + field->offset,
4088 field->size);
4089 if (field->flags & FIELD_IS_POINTER) {
4090 trace_seq_printf(s, "0x%llx", val);
4091 } else if (field->flags & FIELD_IS_SIGNED) {
4092 switch (field->size) {
4093 case 4:
4094 /*
4095 * If field is long then print it in hex.
4096 * A long usually stores pointers.
4097 */
4098 if (field->flags & FIELD_IS_LONG)
4099 trace_seq_printf(s, "0x%x", (int)val);
4100 else
4101 trace_seq_printf(s, "%d", (int)val);
4102 break;
4103 case 2:
4104 trace_seq_printf(s, "%2d", (short)val);
4105 break;
4106 case 1:
4107 trace_seq_printf(s, "%1d", (char)val);
4108 break;
4109 default:
4110 trace_seq_printf(s, "%lld", val);
4111 }
4112 } else {
4113 if (field->flags & FIELD_IS_LONG)
4114 trace_seq_printf(s, "0x%llx", val);
4115 else
4116 trace_seq_printf(s, "%llu", val);
4117 }
4118 }
4119 field = field->next;
4120 }
4121}
4122
4123static void pretty_print(struct trace_seq *s, void *data, int size, struct event_format *event)
4124{
4125 struct pevent *pevent = event->pevent;
4126 struct print_fmt *print_fmt = &event->print_fmt;
4127 struct print_arg *arg = print_fmt->args;
4128 struct print_arg *args = NULL;
4129 const char *ptr = print_fmt->format;
4130 unsigned long long val;
4131 struct func_map *func;
4132 const char *saveptr;
Steven Rostedt12e55562013-11-19 18:29:37 -05004133 struct trace_seq p;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004134 char *bprint_fmt = NULL;
4135 char format[32];
4136 int show_func;
4137 int len_as_arg;
4138 int len_arg;
4139 int len;
4140 int ls;
4141
4142 if (event->flags & EVENT_FL_FAILED) {
4143 trace_seq_printf(s, "[FAILED TO PARSE]");
4144 print_event_fields(s, data, size, event);
4145 return;
4146 }
4147
4148 if (event->flags & EVENT_FL_ISBPRINT) {
4149 bprint_fmt = get_bprint_format(data, size, event);
4150 args = make_bprint_args(bprint_fmt, data, size, event);
4151 arg = args;
4152 ptr = bprint_fmt;
4153 }
4154
4155 for (; *ptr; ptr++) {
4156 ls = 0;
4157 if (*ptr == '\\') {
4158 ptr++;
4159 switch (*ptr) {
4160 case 'n':
4161 trace_seq_putc(s, '\n');
4162 break;
4163 case 't':
4164 trace_seq_putc(s, '\t');
4165 break;
4166 case 'r':
4167 trace_seq_putc(s, '\r');
4168 break;
4169 case '\\':
4170 trace_seq_putc(s, '\\');
4171 break;
4172 default:
4173 trace_seq_putc(s, *ptr);
4174 break;
4175 }
4176
4177 } else if (*ptr == '%') {
4178 saveptr = ptr;
4179 show_func = 0;
4180 len_as_arg = 0;
4181 cont_process:
4182 ptr++;
4183 switch (*ptr) {
4184 case '%':
4185 trace_seq_putc(s, '%');
4186 break;
4187 case '#':
4188 /* FIXME: need to handle properly */
4189 goto cont_process;
4190 case 'h':
4191 ls--;
4192 goto cont_process;
4193 case 'l':
4194 ls++;
4195 goto cont_process;
4196 case 'L':
4197 ls = 2;
4198 goto cont_process;
4199 case '*':
4200 /* The argument is the length. */
Namhyung Kim245c5a12012-09-07 11:49:45 +09004201 if (!arg) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09004202 do_warning_event(event, "no argument match");
Namhyung Kim245c5a12012-09-07 11:49:45 +09004203 event->flags |= EVENT_FL_FAILED;
4204 goto out_failed;
4205 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004206 len_arg = eval_num_arg(data, size, event, arg);
4207 len_as_arg = 1;
4208 arg = arg->next;
4209 goto cont_process;
4210 case '.':
4211 case 'z':
4212 case 'Z':
4213 case '0' ... '9':
4214 goto cont_process;
4215 case 'p':
4216 if (pevent->long_size == 4)
4217 ls = 1;
4218 else
4219 ls = 2;
4220
4221 if (*(ptr+1) == 'F' ||
4222 *(ptr+1) == 'f') {
4223 ptr++;
4224 show_func = *ptr;
4225 } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') {
4226 print_mac_arg(s, *(ptr+1), data, size, event, arg);
4227 ptr++;
Steven Rostedtaaf05c72012-01-09 15:58:09 -05004228 arg = arg->next;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004229 break;
4230 }
4231
4232 /* fall through */
4233 case 'd':
4234 case 'i':
4235 case 'x':
4236 case 'X':
4237 case 'u':
Namhyung Kim245c5a12012-09-07 11:49:45 +09004238 if (!arg) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09004239 do_warning_event(event, "no argument match");
Namhyung Kim245c5a12012-09-07 11:49:45 +09004240 event->flags |= EVENT_FL_FAILED;
4241 goto out_failed;
4242 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004243
4244 len = ((unsigned long)ptr + 1) -
4245 (unsigned long)saveptr;
4246
4247 /* should never happen */
Namhyung Kim245c5a12012-09-07 11:49:45 +09004248 if (len > 31) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09004249 do_warning_event(event, "bad format!");
Namhyung Kim245c5a12012-09-07 11:49:45 +09004250 event->flags |= EVENT_FL_FAILED;
4251 len = 31;
4252 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004253
4254 memcpy(format, saveptr, len);
4255 format[len] = 0;
4256
4257 val = eval_num_arg(data, size, event, arg);
4258 arg = arg->next;
4259
4260 if (show_func) {
4261 func = find_func(pevent, val);
4262 if (func) {
4263 trace_seq_puts(s, func->func);
4264 if (show_func == 'F')
4265 trace_seq_printf(s,
4266 "+0x%llx",
4267 val - func->addr);
4268 break;
4269 }
4270 }
Wolfgang Mauererc5b35b72012-03-22 11:18:21 +01004271 if (pevent->long_size == 8 && ls &&
4272 sizeof(long) != 8) {
Steven Rostedtf7d82352012-04-06 00:47:53 +02004273 char *p;
4274
4275 ls = 2;
4276 /* make %l into %ll */
4277 p = strchr(format, 'l');
4278 if (p)
Wolfgang Mauererc5b35b72012-03-22 11:18:21 +01004279 memmove(p+1, p, strlen(p)+1);
Steven Rostedtf7d82352012-04-06 00:47:53 +02004280 else if (strcmp(format, "%p") == 0)
4281 strcpy(format, "0x%llx");
4282 }
4283 switch (ls) {
4284 case -2:
4285 if (len_as_arg)
4286 trace_seq_printf(s, format, len_arg, (char)val);
4287 else
4288 trace_seq_printf(s, format, (char)val);
4289 break;
4290 case -1:
4291 if (len_as_arg)
4292 trace_seq_printf(s, format, len_arg, (short)val);
4293 else
4294 trace_seq_printf(s, format, (short)val);
4295 break;
4296 case 0:
4297 if (len_as_arg)
4298 trace_seq_printf(s, format, len_arg, (int)val);
4299 else
4300 trace_seq_printf(s, format, (int)val);
4301 break;
4302 case 1:
4303 if (len_as_arg)
4304 trace_seq_printf(s, format, len_arg, (long)val);
4305 else
4306 trace_seq_printf(s, format, (long)val);
4307 break;
4308 case 2:
4309 if (len_as_arg)
4310 trace_seq_printf(s, format, len_arg,
4311 (long long)val);
4312 else
4313 trace_seq_printf(s, format, (long long)val);
4314 break;
4315 default:
Namhyung Kim3388cc32014-03-19 10:22:53 +09004316 do_warning_event(event, "bad count (%d)", ls);
Namhyung Kim245c5a12012-09-07 11:49:45 +09004317 event->flags |= EVENT_FL_FAILED;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004318 }
4319 break;
4320 case 's':
Namhyung Kim245c5a12012-09-07 11:49:45 +09004321 if (!arg) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09004322 do_warning_event(event, "no matching argument");
Namhyung Kim245c5a12012-09-07 11:49:45 +09004323 event->flags |= EVENT_FL_FAILED;
4324 goto out_failed;
4325 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004326
4327 len = ((unsigned long)ptr + 1) -
4328 (unsigned long)saveptr;
4329
4330 /* should never happen */
Namhyung Kim245c5a12012-09-07 11:49:45 +09004331 if (len > 31) {
Namhyung Kim3388cc32014-03-19 10:22:53 +09004332 do_warning_event(event, "bad format!");
Namhyung Kim245c5a12012-09-07 11:49:45 +09004333 event->flags |= EVENT_FL_FAILED;
4334 len = 31;
4335 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004336
4337 memcpy(format, saveptr, len);
4338 format[len] = 0;
4339 if (!len_as_arg)
4340 len_arg = -1;
Steven Rostedt12e55562013-11-19 18:29:37 -05004341 /* Use helper trace_seq */
4342 trace_seq_init(&p);
4343 print_str_arg(&p, data, size, event,
Steven Rostedtf7d82352012-04-06 00:47:53 +02004344 format, len_arg, arg);
Steven Rostedt12e55562013-11-19 18:29:37 -05004345 trace_seq_terminate(&p);
4346 trace_seq_puts(s, p.buffer);
Steven Rostedtf7d82352012-04-06 00:47:53 +02004347 arg = arg->next;
4348 break;
4349 default:
4350 trace_seq_printf(s, ">%c<", *ptr);
4351
4352 }
4353 } else
4354 trace_seq_putc(s, *ptr);
4355 }
4356
Namhyung Kim245c5a12012-09-07 11:49:45 +09004357 if (event->flags & EVENT_FL_FAILED) {
4358out_failed:
4359 trace_seq_printf(s, "[FAILED TO PARSE]");
4360 }
4361
Steven Rostedtf7d82352012-04-06 00:47:53 +02004362 if (args) {
4363 free_args(args);
4364 free(bprint_fmt);
4365 }
4366}
4367
4368/**
4369 * pevent_data_lat_fmt - parse the data for the latency format
4370 * @pevent: a handle to the pevent
4371 * @s: the trace_seq to write to
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09004372 * @record: the record to read from
Steven Rostedtf7d82352012-04-06 00:47:53 +02004373 *
4374 * This parses out the Latency format (interrupts disabled,
4375 * need rescheduling, in hard/soft interrupt, preempt count
4376 * and lock depth) and places it into the trace_seq.
4377 */
4378void pevent_data_lat_fmt(struct pevent *pevent,
Steven Rostedt1c698182012-04-06 00:48:06 +02004379 struct trace_seq *s, struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02004380{
4381 static int check_lock_depth = 1;
Steven Rostedt0866a972012-05-22 14:52:40 +09004382 static int check_migrate_disable = 1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004383 static int lock_depth_exists;
Steven Rostedt0866a972012-05-22 14:52:40 +09004384 static int migrate_disable_exists;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004385 unsigned int lat_flags;
4386 unsigned int pc;
4387 int lock_depth;
Steven Rostedt0866a972012-05-22 14:52:40 +09004388 int migrate_disable;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004389 int hardirq;
4390 int softirq;
4391 void *data = record->data;
4392
4393 lat_flags = parse_common_flags(pevent, data);
4394 pc = parse_common_pc(pevent, data);
4395 /* lock_depth may not always exist */
Steven Rostedtf7d82352012-04-06 00:47:53 +02004396 if (lock_depth_exists)
4397 lock_depth = parse_common_lock_depth(pevent, data);
Steven Rostedt0866a972012-05-22 14:52:40 +09004398 else if (check_lock_depth) {
4399 lock_depth = parse_common_lock_depth(pevent, data);
4400 if (lock_depth < 0)
4401 check_lock_depth = 0;
4402 else
4403 lock_depth_exists = 1;
4404 }
4405
4406 /* migrate_disable may not always exist */
4407 if (migrate_disable_exists)
4408 migrate_disable = parse_common_migrate_disable(pevent, data);
4409 else if (check_migrate_disable) {
4410 migrate_disable = parse_common_migrate_disable(pevent, data);
4411 if (migrate_disable < 0)
4412 check_migrate_disable = 0;
4413 else
4414 migrate_disable_exists = 1;
4415 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004416
4417 hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
4418 softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
4419
4420 trace_seq_printf(s, "%c%c%c",
4421 (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
4422 (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
4423 'X' : '.',
4424 (lat_flags & TRACE_FLAG_NEED_RESCHED) ?
4425 'N' : '.',
4426 (hardirq && softirq) ? 'H' :
4427 hardirq ? 'h' : softirq ? 's' : '.');
4428
4429 if (pc)
4430 trace_seq_printf(s, "%x", pc);
4431 else
4432 trace_seq_putc(s, '.');
4433
Steven Rostedt0866a972012-05-22 14:52:40 +09004434 if (migrate_disable_exists) {
4435 if (migrate_disable < 0)
4436 trace_seq_putc(s, '.');
4437 else
4438 trace_seq_printf(s, "%d", migrate_disable);
4439 }
4440
Steven Rostedtf7d82352012-04-06 00:47:53 +02004441 if (lock_depth_exists) {
4442 if (lock_depth < 0)
4443 trace_seq_putc(s, '.');
4444 else
4445 trace_seq_printf(s, "%d", lock_depth);
4446 }
4447
4448 trace_seq_terminate(s);
4449}
4450
4451/**
4452 * pevent_data_type - parse out the given event type
4453 * @pevent: a handle to the pevent
4454 * @rec: the record to read from
4455 *
4456 * This returns the event id from the @rec.
4457 */
Steven Rostedt1c698182012-04-06 00:48:06 +02004458int pevent_data_type(struct pevent *pevent, struct pevent_record *rec)
Steven Rostedtf7d82352012-04-06 00:47:53 +02004459{
4460 return trace_parse_common_type(pevent, rec->data);
4461}
4462
4463/**
4464 * pevent_data_event_from_type - find the event by a given type
4465 * @pevent: a handle to the pevent
4466 * @type: the type of the event.
4467 *
4468 * This returns the event form a given @type;
4469 */
4470struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type)
4471{
4472 return pevent_find_event(pevent, type);
4473}
4474
4475/**
4476 * pevent_data_pid - parse the PID from raw data
4477 * @pevent: a handle to the pevent
4478 * @rec: the record to parse
4479 *
4480 * This returns the PID from a raw data.
4481 */
Steven Rostedt1c698182012-04-06 00:48:06 +02004482int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec)
Steven Rostedtf7d82352012-04-06 00:47:53 +02004483{
4484 return parse_common_pid(pevent, rec->data);
4485}
4486
4487/**
4488 * pevent_data_comm_from_pid - return the command line from PID
4489 * @pevent: a handle to the pevent
4490 * @pid: the PID of the task to search for
4491 *
4492 * This returns a pointer to the command line that has the given
4493 * @pid.
4494 */
4495const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid)
4496{
4497 const char *comm;
4498
4499 comm = find_cmdline(pevent, pid);
4500 return comm;
4501}
4502
4503/**
4504 * pevent_data_comm_from_pid - parse the data into the print format
4505 * @s: the trace_seq to write to
4506 * @event: the handle to the event
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09004507 * @record: the record to read from
Steven Rostedtf7d82352012-04-06 00:47:53 +02004508 *
4509 * This parses the raw @data using the given @event information and
4510 * writes the print format into the trace_seq.
4511 */
4512void pevent_event_info(struct trace_seq *s, struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02004513 struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02004514{
4515 int print_pretty = 1;
4516
Steven Rostedtc6c2b962013-11-01 17:53:59 -04004517 if (event->pevent->print_raw || (event->flags & EVENT_FL_PRINTRAW))
Steven Rostedtf7d82352012-04-06 00:47:53 +02004518 print_event_fields(s, record->data, record->size, event);
4519 else {
4520
Steven Rostedtc6c2b962013-11-01 17:53:59 -04004521 if (event->handler && !(event->flags & EVENT_FL_NOHANDLE))
Steven Rostedtf7d82352012-04-06 00:47:53 +02004522 print_pretty = event->handler(s, record, event,
4523 event->context);
4524
4525 if (print_pretty)
4526 pretty_print(s, record->data, record->size, event);
4527 }
4528
4529 trace_seq_terminate(s);
4530}
4531
Yoshihiro YUNOMAE1b372ca2013-11-01 17:53:53 -04004532static bool is_timestamp_in_us(char *trace_clock, bool use_trace_clock)
4533{
4534 if (!use_trace_clock)
4535 return true;
4536
4537 if (!strcmp(trace_clock, "local") || !strcmp(trace_clock, "global")
4538 || !strcmp(trace_clock, "uptime") || !strcmp(trace_clock, "perf"))
4539 return true;
4540
4541 /* trace_clock is setting in tsc or counter mode */
4542 return false;
4543}
4544
Steven Rostedtf7d82352012-04-06 00:47:53 +02004545void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
Yoshihiro YUNOMAE1b372ca2013-11-01 17:53:53 -04004546 struct pevent_record *record, bool use_trace_clock)
Steven Rostedtf7d82352012-04-06 00:47:53 +02004547{
Arnaldo Carvalho de Melo27f94d52012-11-09 17:40:47 -03004548 static const char *spaces = " "; /* 20 spaces */
Steven Rostedtf7d82352012-04-06 00:47:53 +02004549 struct event_format *event;
4550 unsigned long secs;
4551 unsigned long usecs;
Steven Rostedt4dc10242012-04-06 00:47:57 +02004552 unsigned long nsecs;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004553 const char *comm;
4554 void *data = record->data;
4555 int type;
4556 int pid;
4557 int len;
Steven Rostedt4dc10242012-04-06 00:47:57 +02004558 int p;
Yoshihiro YUNOMAE1b372ca2013-11-01 17:53:53 -04004559 bool use_usec_format;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004560
Yoshihiro YUNOMAE1b372ca2013-11-01 17:53:53 -04004561 use_usec_format = is_timestamp_in_us(pevent->trace_clock,
4562 use_trace_clock);
4563 if (use_usec_format) {
4564 secs = record->ts / NSECS_PER_SEC;
4565 nsecs = record->ts - secs * NSECS_PER_SEC;
4566 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004567
4568 if (record->size < 0) {
4569 do_warning("ug! negative record size %d", record->size);
4570 return;
4571 }
4572
4573 type = trace_parse_common_type(pevent, data);
4574
4575 event = pevent_find_event(pevent, type);
4576 if (!event) {
4577 do_warning("ug! no event found for type %d", type);
4578 return;
4579 }
4580
4581 pid = parse_common_pid(pevent, data);
4582 comm = find_cmdline(pevent, pid);
4583
4584 if (pevent->latency_format) {
4585 trace_seq_printf(s, "%8.8s-%-5d %3d",
4586 comm, pid, record->cpu);
4587 pevent_data_lat_fmt(pevent, s, record);
4588 } else
4589 trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu);
4590
Yoshihiro YUNOMAE1b372ca2013-11-01 17:53:53 -04004591 if (use_usec_format) {
4592 if (pevent->flags & PEVENT_NSEC_OUTPUT) {
4593 usecs = nsecs;
4594 p = 9;
4595 } else {
4596 usecs = (nsecs + 500) / NSECS_PER_USEC;
4597 p = 6;
4598 }
Steven Rostedt4dc10242012-04-06 00:47:57 +02004599
Yoshihiro YUNOMAE1b372ca2013-11-01 17:53:53 -04004600 trace_seq_printf(s, " %5lu.%0*lu: %s: ",
4601 secs, p, usecs, event->name);
4602 } else
4603 trace_seq_printf(s, " %12llu: %s: ",
4604 record->ts, event->name);
Steven Rostedtf7d82352012-04-06 00:47:53 +02004605
4606 /* Space out the event names evenly. */
4607 len = strlen(event->name);
4608 if (len < 20)
4609 trace_seq_printf(s, "%.*s", 20 - len, spaces);
4610
4611 pevent_event_info(s, event, record);
4612}
4613
4614static int events_id_cmp(const void *a, const void *b)
4615{
4616 struct event_format * const * ea = a;
4617 struct event_format * const * eb = b;
4618
4619 if ((*ea)->id < (*eb)->id)
4620 return -1;
4621
4622 if ((*ea)->id > (*eb)->id)
4623 return 1;
4624
4625 return 0;
4626}
4627
4628static int events_name_cmp(const void *a, const void *b)
4629{
4630 struct event_format * const * ea = a;
4631 struct event_format * const * eb = b;
4632 int res;
4633
4634 res = strcmp((*ea)->name, (*eb)->name);
4635 if (res)
4636 return res;
4637
4638 res = strcmp((*ea)->system, (*eb)->system);
4639 if (res)
4640 return res;
4641
4642 return events_id_cmp(a, b);
4643}
4644
4645static int events_system_cmp(const void *a, const void *b)
4646{
4647 struct event_format * const * ea = a;
4648 struct event_format * const * eb = b;
4649 int res;
4650
4651 res = strcmp((*ea)->system, (*eb)->system);
4652 if (res)
4653 return res;
4654
4655 res = strcmp((*ea)->name, (*eb)->name);
4656 if (res)
4657 return res;
4658
4659 return events_id_cmp(a, b);
4660}
4661
4662struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type sort_type)
4663{
4664 struct event_format **events;
4665 int (*sort)(const void *a, const void *b);
4666
4667 events = pevent->sort_events;
4668
4669 if (events && pevent->last_type == sort_type)
4670 return events;
4671
4672 if (!events) {
4673 events = malloc(sizeof(*events) * (pevent->nr_events + 1));
4674 if (!events)
4675 return NULL;
4676
4677 memcpy(events, pevent->events, sizeof(*events) * pevent->nr_events);
4678 events[pevent->nr_events] = NULL;
4679
4680 pevent->sort_events = events;
4681
4682 /* the internal events are sorted by id */
4683 if (sort_type == EVENT_SORT_ID) {
4684 pevent->last_type = sort_type;
4685 return events;
4686 }
4687 }
4688
4689 switch (sort_type) {
4690 case EVENT_SORT_ID:
4691 sort = events_id_cmp;
4692 break;
4693 case EVENT_SORT_NAME:
4694 sort = events_name_cmp;
4695 break;
4696 case EVENT_SORT_SYSTEM:
4697 sort = events_system_cmp;
4698 break;
4699 default:
4700 return events;
4701 }
4702
4703 qsort(events, pevent->nr_events, sizeof(*events), sort);
4704 pevent->last_type = sort_type;
4705
4706 return events;
4707}
4708
4709static struct format_field **
4710get_event_fields(const char *type, const char *name,
4711 int count, struct format_field *list)
4712{
4713 struct format_field **fields;
4714 struct format_field *field;
4715 int i = 0;
4716
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03004717 fields = malloc(sizeof(*fields) * (count + 1));
4718 if (!fields)
4719 return NULL;
4720
Steven Rostedtf7d82352012-04-06 00:47:53 +02004721 for (field = list; field; field = field->next) {
4722 fields[i++] = field;
4723 if (i == count + 1) {
4724 do_warning("event %s has more %s fields than specified",
4725 name, type);
4726 i--;
4727 break;
4728 }
4729 }
4730
4731 if (i != count)
4732 do_warning("event %s has less %s fields than specified",
4733 name, type);
4734
4735 fields[i] = NULL;
4736
4737 return fields;
4738}
4739
4740/**
4741 * pevent_event_common_fields - return a list of common fields for an event
4742 * @event: the event to return the common fields of.
4743 *
4744 * Returns an allocated array of fields. The last item in the array is NULL.
4745 * The array must be freed with free().
4746 */
4747struct format_field **pevent_event_common_fields(struct event_format *event)
4748{
4749 return get_event_fields("common", event->name,
4750 event->format.nr_common,
4751 event->format.common_fields);
4752}
4753
4754/**
4755 * pevent_event_fields - return a list of event specific fields for an event
4756 * @event: the event to return the fields of.
4757 *
4758 * Returns an allocated array of fields. The last item in the array is NULL.
4759 * The array must be freed with free().
4760 */
4761struct format_field **pevent_event_fields(struct event_format *event)
4762{
4763 return get_event_fields("event", event->name,
4764 event->format.nr_fields,
4765 event->format.fields);
4766}
4767
4768static void print_fields(struct trace_seq *s, struct print_flag_sym *field)
4769{
4770 trace_seq_printf(s, "{ %s, %s }", field->value, field->str);
4771 if (field->next) {
4772 trace_seq_puts(s, ", ");
4773 print_fields(s, field->next);
4774 }
4775}
4776
4777/* for debugging */
4778static void print_args(struct print_arg *args)
4779{
4780 int print_paren = 1;
4781 struct trace_seq s;
4782
4783 switch (args->type) {
4784 case PRINT_NULL:
4785 printf("null");
4786 break;
4787 case PRINT_ATOM:
4788 printf("%s", args->atom.atom);
4789 break;
4790 case PRINT_FIELD:
4791 printf("REC->%s", args->field.name);
4792 break;
4793 case PRINT_FLAGS:
4794 printf("__print_flags(");
4795 print_args(args->flags.field);
4796 printf(", %s, ", args->flags.delim);
4797 trace_seq_init(&s);
4798 print_fields(&s, args->flags.flags);
4799 trace_seq_do_printf(&s);
4800 trace_seq_destroy(&s);
4801 printf(")");
4802 break;
4803 case PRINT_SYMBOL:
4804 printf("__print_symbolic(");
4805 print_args(args->symbol.field);
4806 printf(", ");
4807 trace_seq_init(&s);
4808 print_fields(&s, args->symbol.symbols);
4809 trace_seq_do_printf(&s);
4810 trace_seq_destroy(&s);
4811 printf(")");
4812 break;
Namhyung Kime080e6f2012-06-27 09:41:41 +09004813 case PRINT_HEX:
4814 printf("__print_hex(");
4815 print_args(args->hex.field);
4816 printf(", ");
4817 print_args(args->hex.size);
4818 printf(")");
4819 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004820 case PRINT_STRING:
4821 case PRINT_BSTRING:
4822 printf("__get_str(%s)", args->string.string);
4823 break;
4824 case PRINT_TYPE:
4825 printf("(%s)", args->typecast.type);
4826 print_args(args->typecast.item);
4827 break;
4828 case PRINT_OP:
4829 if (strcmp(args->op.op, ":") == 0)
4830 print_paren = 0;
4831 if (print_paren)
4832 printf("(");
4833 print_args(args->op.left);
4834 printf(" %s ", args->op.op);
4835 print_args(args->op.right);
4836 if (print_paren)
4837 printf(")");
4838 break;
4839 default:
4840 /* we should warn... */
4841 return;
4842 }
4843 if (args->next) {
4844 printf("\n");
4845 print_args(args->next);
4846 }
4847}
4848
4849static void parse_header_field(const char *field,
4850 int *offset, int *size, int mandatory)
4851{
4852 unsigned long long save_input_buf_ptr;
4853 unsigned long long save_input_buf_siz;
4854 char *token;
4855 int type;
4856
4857 save_input_buf_ptr = input_buf_ptr;
4858 save_input_buf_siz = input_buf_siz;
4859
4860 if (read_expected(EVENT_ITEM, "field") < 0)
4861 return;
4862 if (read_expected(EVENT_OP, ":") < 0)
4863 return;
4864
4865 /* type */
4866 if (read_expect_type(EVENT_ITEM, &token) < 0)
4867 goto fail;
4868 free_token(token);
4869
4870 /*
4871 * If this is not a mandatory field, then test it first.
4872 */
4873 if (mandatory) {
4874 if (read_expected(EVENT_ITEM, field) < 0)
4875 return;
4876 } else {
4877 if (read_expect_type(EVENT_ITEM, &token) < 0)
4878 goto fail;
4879 if (strcmp(token, field) != 0)
4880 goto discard;
4881 free_token(token);
4882 }
4883
4884 if (read_expected(EVENT_OP, ";") < 0)
4885 return;
4886 if (read_expected(EVENT_ITEM, "offset") < 0)
4887 return;
4888 if (read_expected(EVENT_OP, ":") < 0)
4889 return;
4890 if (read_expect_type(EVENT_ITEM, &token) < 0)
4891 goto fail;
4892 *offset = atoi(token);
4893 free_token(token);
4894 if (read_expected(EVENT_OP, ";") < 0)
4895 return;
4896 if (read_expected(EVENT_ITEM, "size") < 0)
4897 return;
4898 if (read_expected(EVENT_OP, ":") < 0)
4899 return;
4900 if (read_expect_type(EVENT_ITEM, &token) < 0)
4901 goto fail;
4902 *size = atoi(token);
4903 free_token(token);
4904 if (read_expected(EVENT_OP, ";") < 0)
4905 return;
4906 type = read_token(&token);
4907 if (type != EVENT_NEWLINE) {
4908 /* newer versions of the kernel have a "signed" type */
4909 if (type != EVENT_ITEM)
4910 goto fail;
4911
4912 if (strcmp(token, "signed") != 0)
4913 goto fail;
4914
4915 free_token(token);
4916
4917 if (read_expected(EVENT_OP, ":") < 0)
4918 return;
4919
4920 if (read_expect_type(EVENT_ITEM, &token))
4921 goto fail;
4922
4923 free_token(token);
4924 if (read_expected(EVENT_OP, ";") < 0)
4925 return;
4926
4927 if (read_expect_type(EVENT_NEWLINE, &token))
4928 goto fail;
4929 }
4930 fail:
4931 free_token(token);
4932 return;
4933
4934 discard:
4935 input_buf_ptr = save_input_buf_ptr;
4936 input_buf_siz = save_input_buf_siz;
4937 *offset = 0;
4938 *size = 0;
4939 free_token(token);
4940}
4941
4942/**
4943 * pevent_parse_header_page - parse the data stored in the header page
4944 * @pevent: the handle to the pevent
4945 * @buf: the buffer storing the header page format string
4946 * @size: the size of @buf
4947 * @long_size: the long size to use if there is no header
4948 *
4949 * This parses the header page format for information on the
4950 * ring buffer used. The @buf should be copied from
4951 *
4952 * /sys/kernel/debug/tracing/events/header_page
4953 */
4954int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size,
4955 int long_size)
4956{
4957 int ignore;
4958
4959 if (!size) {
4960 /*
4961 * Old kernels did not have header page info.
4962 * Sorry but we just use what we find here in user space.
4963 */
4964 pevent->header_page_ts_size = sizeof(long long);
4965 pevent->header_page_size_size = long_size;
4966 pevent->header_page_data_offset = sizeof(long long) + long_size;
4967 pevent->old_format = 1;
4968 return -1;
4969 }
4970 init_input_buf(buf, size);
4971
4972 parse_header_field("timestamp", &pevent->header_page_ts_offset,
4973 &pevent->header_page_ts_size, 1);
4974 parse_header_field("commit", &pevent->header_page_size_offset,
4975 &pevent->header_page_size_size, 1);
4976 parse_header_field("overwrite", &pevent->header_page_overwrite,
4977 &ignore, 0);
4978 parse_header_field("data", &pevent->header_page_data_offset,
4979 &pevent->header_page_data_size, 1);
4980
4981 return 0;
4982}
4983
4984static int event_matches(struct event_format *event,
4985 int id, const char *sys_name,
4986 const char *event_name)
4987{
4988 if (id >= 0 && id != event->id)
4989 return 0;
4990
4991 if (event_name && (strcmp(event_name, event->name) != 0))
4992 return 0;
4993
4994 if (sys_name && (strcmp(sys_name, event->system) != 0))
4995 return 0;
4996
4997 return 1;
4998}
4999
5000static void free_handler(struct event_handler *handle)
5001{
5002 free((void *)handle->sys_name);
5003 free((void *)handle->event_name);
5004 free(handle);
5005}
5006
5007static int find_event_handle(struct pevent *pevent, struct event_format *event)
5008{
5009 struct event_handler *handle, **next;
5010
5011 for (next = &pevent->handlers; *next;
5012 next = &(*next)->next) {
5013 handle = *next;
5014 if (event_matches(event, handle->id,
5015 handle->sys_name,
5016 handle->event_name))
5017 break;
5018 }
5019
5020 if (!(*next))
5021 return 0;
5022
5023 pr_stat("overriding event (%d) %s:%s with new print handler",
5024 event->id, event->system, event->name);
5025
5026 event->handler = handle->func;
5027 event->context = handle->context;
5028
5029 *next = handle->next;
5030 free_handler(handle);
5031
5032 return 1;
5033}
5034
5035/**
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005036 * __pevent_parse_format - parse the event format
Steven Rostedtf7d82352012-04-06 00:47:53 +02005037 * @buf: the buffer storing the event format string
5038 * @size: the size of @buf
5039 * @sys: the system the event belongs to
5040 *
5041 * This parses the event format and creates an event structure
5042 * to quickly parse raw data for a given event.
5043 *
5044 * These files currently come from:
5045 *
5046 * /sys/kernel/debug/tracing/events/.../.../format
5047 */
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005048enum pevent_errno __pevent_parse_format(struct event_format **eventp,
5049 struct pevent *pevent, const char *buf,
5050 unsigned long size, const char *sys)
Steven Rostedtf7d82352012-04-06 00:47:53 +02005051{
5052 struct event_format *event;
5053 int ret;
5054
5055 init_input_buf(buf, size);
5056
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005057 *eventp = event = alloc_event();
Steven Rostedtf7d82352012-04-06 00:47:53 +02005058 if (!event)
Namhyung Kimbffddff2012-08-22 16:00:29 +09005059 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005060
5061 event->name = event_read_name();
5062 if (!event->name) {
5063 /* Bad event? */
Namhyung Kimbffddff2012-08-22 16:00:29 +09005064 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
5065 goto event_alloc_failed;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005066 }
5067
5068 if (strcmp(sys, "ftrace") == 0) {
Steven Rostedtf7d82352012-04-06 00:47:53 +02005069 event->flags |= EVENT_FL_ISFTRACE;
5070
5071 if (strcmp(event->name, "bprint") == 0)
5072 event->flags |= EVENT_FL_ISBPRINT;
5073 }
5074
5075 event->id = event_read_id();
Namhyung Kimbffddff2012-08-22 16:00:29 +09005076 if (event->id < 0) {
5077 ret = PEVENT_ERRNO__READ_ID_FAILED;
5078 /*
5079 * This isn't an allocation error actually.
5080 * But as the ID is critical, just bail out.
5081 */
5082 goto event_alloc_failed;
5083 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005084
5085 event->system = strdup(sys);
Namhyung Kimbffddff2012-08-22 16:00:29 +09005086 if (!event->system) {
5087 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
5088 goto event_alloc_failed;
5089 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005090
Steven Rostedt101782e2012-10-01 20:13:51 -04005091 /* Add pevent to event so that it can be referenced */
5092 event->pevent = pevent;
5093
Steven Rostedtf7d82352012-04-06 00:47:53 +02005094 ret = event_read_format(event);
5095 if (ret < 0) {
Namhyung Kimbffddff2012-08-22 16:00:29 +09005096 ret = PEVENT_ERRNO__READ_FORMAT_FAILED;
5097 goto event_parse_failed;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005098 }
5099
5100 /*
5101 * If the event has an override, don't print warnings if the event
5102 * print format fails to parse.
5103 */
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005104 if (pevent && find_event_handle(pevent, event))
Steven Rostedtf7d82352012-04-06 00:47:53 +02005105 show_warning = 0;
5106
5107 ret = event_read_print(event);
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005108 show_warning = 1;
5109
Steven Rostedtf7d82352012-04-06 00:47:53 +02005110 if (ret < 0) {
Namhyung Kimbffddff2012-08-22 16:00:29 +09005111 ret = PEVENT_ERRNO__READ_PRINT_FAILED;
5112 goto event_parse_failed;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005113 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005114
5115 if (!ret && (event->flags & EVENT_FL_ISFTRACE)) {
5116 struct format_field *field;
5117 struct print_arg *arg, **list;
5118
5119 /* old ftrace had no args */
Steven Rostedtf7d82352012-04-06 00:47:53 +02005120 list = &event->print_fmt.args;
5121 for (field = event->format.fields; field; field = field->next) {
5122 arg = alloc_arg();
Namhyung Kimb1ac7542012-09-20 11:09:19 +09005123 if (!arg) {
5124 event->flags |= EVENT_FL_FAILED;
5125 return PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED;
5126 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005127 arg->type = PRINT_FIELD;
5128 arg->field.name = strdup(field->name);
Namhyung Kimca638582012-04-09 11:54:31 +09005129 if (!arg->field.name) {
Namhyung Kim4b5632b2012-04-23 13:58:34 +09005130 event->flags |= EVENT_FL_FAILED;
Namhyung Kimfd34f0b2012-08-22 16:00:28 +09005131 free_arg(arg);
Namhyung Kimbffddff2012-08-22 16:00:29 +09005132 return PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED;
Namhyung Kimca638582012-04-09 11:54:31 +09005133 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005134 arg->field.field = field;
Namhyung Kimfd34f0b2012-08-22 16:00:28 +09005135 *list = arg;
5136 list = &arg->next;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005137 }
5138 return 0;
5139 }
5140
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005141 return 0;
5142
5143 event_parse_failed:
5144 event->flags |= EVENT_FL_FAILED;
5145 return ret;
5146
5147 event_alloc_failed:
5148 free(event->system);
5149 free(event->name);
5150 free(event);
5151 *eventp = NULL;
5152 return ret;
5153}
5154
Jiri Olsa71ad9582013-12-03 14:09:19 +01005155static enum pevent_errno
5156__pevent_parse_event(struct pevent *pevent,
5157 struct event_format **eventp,
5158 const char *buf, unsigned long size,
5159 const char *sys)
5160{
5161 int ret = __pevent_parse_format(eventp, pevent, buf, size, sys);
5162 struct event_format *event = *eventp;
5163
5164 if (event == NULL)
5165 return ret;
5166
5167 if (pevent && add_event(pevent, event)) {
5168 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
5169 goto event_add_failed;
5170 }
5171
5172#define PRINT_ARGS 0
5173 if (PRINT_ARGS && event->print_fmt.args)
5174 print_args(event->print_fmt.args);
5175
5176 return 0;
5177
5178event_add_failed:
5179 pevent_free_format(event);
5180 return ret;
5181}
5182
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005183/**
5184 * pevent_parse_format - parse the event format
Jiri Olsa71ad9582013-12-03 14:09:19 +01005185 * @pevent: the handle to the pevent
5186 * @eventp: returned format
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005187 * @buf: the buffer storing the event format string
5188 * @size: the size of @buf
5189 * @sys: the system the event belongs to
5190 *
5191 * This parses the event format and creates an event structure
5192 * to quickly parse raw data for a given event.
5193 *
5194 * These files currently come from:
5195 *
5196 * /sys/kernel/debug/tracing/events/.../.../format
5197 */
Jiri Olsa71ad9582013-12-03 14:09:19 +01005198enum pevent_errno pevent_parse_format(struct pevent *pevent,
5199 struct event_format **eventp,
5200 const char *buf,
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005201 unsigned long size, const char *sys)
5202{
Jiri Olsa71ad9582013-12-03 14:09:19 +01005203 return __pevent_parse_event(pevent, eventp, buf, size, sys);
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005204}
5205
5206/**
5207 * pevent_parse_event - parse the event format
5208 * @pevent: the handle to the pevent
5209 * @buf: the buffer storing the event format string
5210 * @size: the size of @buf
5211 * @sys: the system the event belongs to
5212 *
5213 * This parses the event format and creates an event structure
5214 * to quickly parse raw data for a given event.
5215 *
5216 * These files currently come from:
5217 *
5218 * /sys/kernel/debug/tracing/events/.../.../format
5219 */
5220enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
5221 unsigned long size, const char *sys)
5222{
5223 struct event_format *event = NULL;
Jiri Olsa71ad9582013-12-03 14:09:19 +01005224 return __pevent_parse_event(pevent, &event, buf, size, sys);
Steven Rostedtf7d82352012-04-06 00:47:53 +02005225}
5226
Namhyung Kim2f197b92012-08-22 16:00:30 +09005227#undef _PE
5228#define _PE(code, str) str
5229static const char * const pevent_error_str[] = {
5230 PEVENT_ERRORS
5231};
5232#undef _PE
5233
Arnaldo Carvalho de Meloca383a42012-11-09 15:18:57 -03005234int pevent_strerror(struct pevent *pevent __maybe_unused,
5235 enum pevent_errno errnum, char *buf, size_t buflen)
Namhyung Kim2f197b92012-08-22 16:00:30 +09005236{
5237 int idx;
5238 const char *msg;
5239
5240 if (errnum >= 0) {
Namhyung Kime1aa7c32012-08-22 16:00:31 +09005241 msg = strerror_r(errnum, buf, buflen);
5242 if (msg != buf) {
5243 size_t len = strlen(msg);
Irina Tirdea9612ef62012-09-08 03:43:22 +03005244 memcpy(buf, msg, min(buflen - 1, len));
5245 *(buf + min(buflen - 1, len)) = '\0';
Namhyung Kime1aa7c32012-08-22 16:00:31 +09005246 }
Namhyung Kim2f197b92012-08-22 16:00:30 +09005247 return 0;
5248 }
5249
5250 if (errnum <= __PEVENT_ERRNO__START ||
5251 errnum >= __PEVENT_ERRNO__END)
5252 return -1;
5253
Namhyung Kimf63fe792012-08-23 16:37:00 +09005254 idx = errnum - __PEVENT_ERRNO__START - 1;
Namhyung Kim2f197b92012-08-22 16:00:30 +09005255 msg = pevent_error_str[idx];
Namhyung Kimbf19b822013-12-12 16:36:17 +09005256 snprintf(buf, buflen, "%s", msg);
Namhyung Kim2f197b92012-08-22 16:00:30 +09005257
5258 return 0;
5259}
5260
Steven Rostedtf7d82352012-04-06 00:47:53 +02005261int get_field_val(struct trace_seq *s, struct format_field *field,
Steven Rostedt1c698182012-04-06 00:48:06 +02005262 const char *name, struct pevent_record *record,
Steven Rostedtf7d82352012-04-06 00:47:53 +02005263 unsigned long long *val, int err)
5264{
5265 if (!field) {
5266 if (err)
5267 trace_seq_printf(s, "<CANT FIND FIELD %s>", name);
5268 return -1;
5269 }
5270
5271 if (pevent_read_number_field(field, record->data, val)) {
5272 if (err)
5273 trace_seq_printf(s, " %s=INVALID", name);
5274 return -1;
5275 }
5276
5277 return 0;
5278}
5279
5280/**
5281 * pevent_get_field_raw - return the raw pointer into the data field
5282 * @s: The seq to print to on error
5283 * @event: the event that the field is for
5284 * @name: The name of the field
5285 * @record: The record with the field name.
5286 * @len: place to store the field length.
5287 * @err: print default error if failed.
5288 *
5289 * Returns a pointer into record->data of the field and places
5290 * the length of the field in @len.
5291 *
5292 * On failure, it returns NULL.
5293 */
5294void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02005295 const char *name, struct pevent_record *record,
Steven Rostedtf7d82352012-04-06 00:47:53 +02005296 int *len, int err)
5297{
5298 struct format_field *field;
5299 void *data = record->data;
5300 unsigned offset;
5301 int dummy;
5302
5303 if (!event)
5304 return NULL;
5305
5306 field = pevent_find_field(event, name);
5307
5308 if (!field) {
5309 if (err)
5310 trace_seq_printf(s, "<CANT FIND FIELD %s>", name);
5311 return NULL;
5312 }
5313
5314 /* Allow @len to be NULL */
5315 if (!len)
5316 len = &dummy;
5317
5318 offset = field->offset;
5319 if (field->flags & FIELD_IS_DYNAMIC) {
5320 offset = pevent_read_number(event->pevent,
5321 data + offset, field->size);
5322 *len = offset >> 16;
5323 offset &= 0xffff;
5324 } else
5325 *len = field->size;
5326
5327 return data + offset;
5328}
5329
5330/**
5331 * pevent_get_field_val - find a field and return its value
5332 * @s: The seq to print to on error
5333 * @event: the event that the field is for
5334 * @name: The name of the field
5335 * @record: The record with the field name.
5336 * @val: place to store the value of the field.
5337 * @err: print default error if failed.
5338 *
5339 * Returns 0 on success -1 on field not found.
5340 */
5341int pevent_get_field_val(struct trace_seq *s, struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02005342 const char *name, struct pevent_record *record,
Steven Rostedtf7d82352012-04-06 00:47:53 +02005343 unsigned long long *val, int err)
5344{
5345 struct format_field *field;
5346
5347 if (!event)
5348 return -1;
5349
5350 field = pevent_find_field(event, name);
5351
5352 return get_field_val(s, field, name, record, val, err);
5353}
5354
5355/**
5356 * pevent_get_common_field_val - find a common field and return its value
5357 * @s: The seq to print to on error
5358 * @event: the event that the field is for
5359 * @name: The name of the field
5360 * @record: The record with the field name.
5361 * @val: place to store the value of the field.
5362 * @err: print default error if failed.
5363 *
5364 * Returns 0 on success -1 on field not found.
5365 */
5366int pevent_get_common_field_val(struct trace_seq *s, struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02005367 const char *name, struct pevent_record *record,
Steven Rostedtf7d82352012-04-06 00:47:53 +02005368 unsigned long long *val, int err)
5369{
5370 struct format_field *field;
5371
5372 if (!event)
5373 return -1;
5374
5375 field = pevent_find_common_field(event, name);
5376
5377 return get_field_val(s, field, name, record, val, err);
5378}
5379
5380/**
5381 * pevent_get_any_field_val - find a any field and return its value
5382 * @s: The seq to print to on error
5383 * @event: the event that the field is for
5384 * @name: The name of the field
5385 * @record: The record with the field name.
5386 * @val: place to store the value of the field.
5387 * @err: print default error if failed.
5388 *
5389 * Returns 0 on success -1 on field not found.
5390 */
5391int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02005392 const char *name, struct pevent_record *record,
Steven Rostedtf7d82352012-04-06 00:47:53 +02005393 unsigned long long *val, int err)
5394{
5395 struct format_field *field;
5396
5397 if (!event)
5398 return -1;
5399
5400 field = pevent_find_any_field(event, name);
5401
5402 return get_field_val(s, field, name, record, val, err);
5403}
5404
5405/**
5406 * pevent_print_num_field - print a field and a format
5407 * @s: The seq to print to
5408 * @fmt: The printf format to print the field with.
5409 * @event: the event that the field is for
5410 * @name: The name of the field
5411 * @record: The record with the field name.
5412 * @err: print default error if failed.
5413 *
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09005414 * Returns: 0 on success, -1 field not found, or 1 if buffer is full.
Steven Rostedtf7d82352012-04-06 00:47:53 +02005415 */
5416int pevent_print_num_field(struct trace_seq *s, const char *fmt,
5417 struct event_format *event, const char *name,
Steven Rostedt1c698182012-04-06 00:48:06 +02005418 struct pevent_record *record, int err)
Steven Rostedtf7d82352012-04-06 00:47:53 +02005419{
5420 struct format_field *field = pevent_find_field(event, name);
5421 unsigned long long val;
5422
5423 if (!field)
5424 goto failed;
5425
5426 if (pevent_read_number_field(field, record->data, &val))
5427 goto failed;
5428
5429 return trace_seq_printf(s, fmt, val);
5430
5431 failed:
5432 if (err)
5433 trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
5434 return -1;
5435}
5436
Steven Rostedt6d862b82013-11-01 17:54:00 -04005437/**
5438 * pevent_print_func_field - print a field and a format for function pointers
5439 * @s: The seq to print to
5440 * @fmt: The printf format to print the field with.
5441 * @event: the event that the field is for
5442 * @name: The name of the field
5443 * @record: The record with the field name.
5444 * @err: print default error if failed.
5445 *
5446 * Returns: 0 on success, -1 field not found, or 1 if buffer is full.
5447 */
5448int pevent_print_func_field(struct trace_seq *s, const char *fmt,
5449 struct event_format *event, const char *name,
5450 struct pevent_record *record, int err)
5451{
5452 struct format_field *field = pevent_find_field(event, name);
5453 struct pevent *pevent = event->pevent;
5454 unsigned long long val;
5455 struct func_map *func;
5456 char tmp[128];
5457
5458 if (!field)
5459 goto failed;
5460
5461 if (pevent_read_number_field(field, record->data, &val))
5462 goto failed;
5463
5464 func = find_func(pevent, val);
5465
5466 if (func)
5467 snprintf(tmp, 128, "%s/0x%llx", func->func, func->addr - val);
5468 else
5469 sprintf(tmp, "0x%08llx", val);
5470
5471 return trace_seq_printf(s, fmt, tmp);
5472
5473 failed:
5474 if (err)
5475 trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
5476 return -1;
5477}
5478
Steven Rostedtf7d82352012-04-06 00:47:53 +02005479static void free_func_handle(struct pevent_function_handler *func)
5480{
5481 struct pevent_func_params *params;
5482
5483 free(func->name);
5484
5485 while (func->params) {
5486 params = func->params;
5487 func->params = params->next;
5488 free(params);
5489 }
5490
5491 free(func);
5492}
5493
5494/**
5495 * pevent_register_print_function - register a helper function
5496 * @pevent: the handle to the pevent
5497 * @func: the function to process the helper function
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09005498 * @ret_type: the return type of the helper function
Steven Rostedtf7d82352012-04-06 00:47:53 +02005499 * @name: the name of the helper function
5500 * @parameters: A list of enum pevent_func_arg_type
5501 *
5502 * Some events may have helper functions in the print format arguments.
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09005503 * This allows a plugin to dynamically create a way to process one
Steven Rostedtf7d82352012-04-06 00:47:53 +02005504 * of these functions.
5505 *
5506 * The @parameters is a variable list of pevent_func_arg_type enums that
5507 * must end with PEVENT_FUNC_ARG_VOID.
5508 */
5509int pevent_register_print_function(struct pevent *pevent,
5510 pevent_func_handler func,
5511 enum pevent_func_arg_type ret_type,
5512 char *name, ...)
5513{
5514 struct pevent_function_handler *func_handle;
5515 struct pevent_func_params **next_param;
5516 struct pevent_func_params *param;
5517 enum pevent_func_arg_type type;
5518 va_list ap;
Namhyung Kim67ed9392012-09-07 11:49:47 +09005519 int ret;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005520
5521 func_handle = find_func_handler(pevent, name);
5522 if (func_handle) {
5523 /*
5524 * This is most like caused by the users own
5525 * plugins updating the function. This overrides the
5526 * system defaults.
5527 */
5528 pr_stat("override of function helper '%s'", name);
5529 remove_func_handler(pevent, name);
5530 }
5531
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -03005532 func_handle = calloc(1, sizeof(*func_handle));
Namhyung Kim67ed9392012-09-07 11:49:47 +09005533 if (!func_handle) {
5534 do_warning("Failed to allocate function handler");
5535 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
5536 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005537
5538 func_handle->ret_type = ret_type;
5539 func_handle->name = strdup(name);
5540 func_handle->func = func;
Namhyung Kim67ed9392012-09-07 11:49:47 +09005541 if (!func_handle->name) {
5542 do_warning("Failed to allocate function name");
5543 free(func_handle);
5544 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
5545 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005546
5547 next_param = &(func_handle->params);
5548 va_start(ap, name);
5549 for (;;) {
5550 type = va_arg(ap, enum pevent_func_arg_type);
5551 if (type == PEVENT_FUNC_ARG_VOID)
5552 break;
5553
Arnaldo Carvalho de Meloe46466b2012-11-09 15:42:26 -03005554 if (type >= PEVENT_FUNC_ARG_MAX_TYPES) {
Namhyung Kim67ed9392012-09-07 11:49:47 +09005555 do_warning("Invalid argument type %d", type);
5556 ret = PEVENT_ERRNO__INVALID_ARG_TYPE;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005557 goto out_free;
5558 }
5559
Namhyung Kim67ed9392012-09-07 11:49:47 +09005560 param = malloc(sizeof(*param));
5561 if (!param) {
5562 do_warning("Failed to allocate function param");
5563 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
5564 goto out_free;
5565 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005566 param->type = type;
5567 param->next = NULL;
5568
5569 *next_param = param;
5570 next_param = &(param->next);
5571
5572 func_handle->nr_args++;
5573 }
5574 va_end(ap);
5575
5576 func_handle->next = pevent->func_handlers;
5577 pevent->func_handlers = func_handle;
5578
5579 return 0;
5580 out_free:
5581 va_end(ap);
5582 free_func_handle(func_handle);
Namhyung Kim67ed9392012-09-07 11:49:47 +09005583 return ret;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005584}
5585
Namhyung Kim20c7e5a2014-01-16 11:31:08 +09005586/**
5587 * pevent_unregister_print_function - unregister a helper function
5588 * @pevent: the handle to the pevent
5589 * @func: the function to process the helper function
5590 * @name: the name of the helper function
5591 *
5592 * This function removes existing print handler for function @name.
5593 *
5594 * Returns 0 if the handler was removed successully, -1 otherwise.
5595 */
5596int pevent_unregister_print_function(struct pevent *pevent,
5597 pevent_func_handler func, char *name)
5598{
5599 struct pevent_function_handler *func_handle;
5600
5601 func_handle = find_func_handler(pevent, name);
5602 if (func_handle && func_handle->func == func) {
5603 remove_func_handler(pevent, name);
5604 return 0;
5605 }
5606 return -1;
5607}
5608
Namhyung Kimad137012014-01-16 11:31:07 +09005609static struct event_format *pevent_search_event(struct pevent *pevent, int id,
5610 const char *sys_name,
5611 const char *event_name)
5612{
5613 struct event_format *event;
5614
5615 if (id >= 0) {
5616 /* search by id */
5617 event = pevent_find_event(pevent, id);
5618 if (!event)
5619 return NULL;
5620 if (event_name && (strcmp(event_name, event->name) != 0))
5621 return NULL;
5622 if (sys_name && (strcmp(sys_name, event->system) != 0))
5623 return NULL;
5624 } else {
5625 event = pevent_find_event_by_name(pevent, sys_name, event_name);
5626 if (!event)
5627 return NULL;
5628 }
5629 return event;
5630}
5631
Steven Rostedtf7d82352012-04-06 00:47:53 +02005632/**
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09005633 * pevent_register_event_handler - register a way to parse an event
Steven Rostedtf7d82352012-04-06 00:47:53 +02005634 * @pevent: the handle to the pevent
5635 * @id: the id of the event to register
5636 * @sys_name: the system name the event belongs to
5637 * @event_name: the name of the event
5638 * @func: the function to call to parse the event information
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09005639 * @context: the data to be passed to @func
Steven Rostedtf7d82352012-04-06 00:47:53 +02005640 *
5641 * This function allows a developer to override the parsing of
5642 * a given event. If for some reason the default print format
5643 * is not sufficient, this function will register a function
5644 * for an event to be used to parse the data instead.
5645 *
5646 * If @id is >= 0, then it is used to find the event.
5647 * else @sys_name and @event_name are used.
5648 */
Namhyung Kim79d5adf2013-06-04 14:20:18 +09005649int pevent_register_event_handler(struct pevent *pevent, int id,
5650 const char *sys_name, const char *event_name,
5651 pevent_event_handler_func func, void *context)
Steven Rostedtf7d82352012-04-06 00:47:53 +02005652{
5653 struct event_format *event;
5654 struct event_handler *handle;
5655
Namhyung Kimad137012014-01-16 11:31:07 +09005656 event = pevent_search_event(pevent, id, sys_name, event_name);
5657 if (event == NULL)
5658 goto not_found;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005659
5660 pr_stat("overriding event (%d) %s:%s with new print handler",
5661 event->id, event->system, event->name);
5662
5663 event->handler = func;
5664 event->context = context;
5665 return 0;
5666
5667 not_found:
5668 /* Save for later use. */
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -03005669 handle = calloc(1, sizeof(*handle));
Namhyung Kim0ca8da02012-09-07 11:49:46 +09005670 if (!handle) {
5671 do_warning("Failed to allocate event handler");
5672 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
5673 }
5674
Steven Rostedtf7d82352012-04-06 00:47:53 +02005675 handle->id = id;
5676 if (event_name)
5677 handle->event_name = strdup(event_name);
5678 if (sys_name)
5679 handle->sys_name = strdup(sys_name);
5680
Namhyung Kimca638582012-04-09 11:54:31 +09005681 if ((event_name && !handle->event_name) ||
5682 (sys_name && !handle->sys_name)) {
Namhyung Kim0ca8da02012-09-07 11:49:46 +09005683 do_warning("Failed to allocate event/sys name");
5684 free((void *)handle->event_name);
5685 free((void *)handle->sys_name);
5686 free(handle);
5687 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
Namhyung Kimca638582012-04-09 11:54:31 +09005688 }
5689
Steven Rostedtf7d82352012-04-06 00:47:53 +02005690 handle->func = func;
5691 handle->next = pevent->handlers;
5692 pevent->handlers = handle;
5693 handle->context = context;
5694
5695 return -1;
5696}
5697
Namhyung Kimad137012014-01-16 11:31:07 +09005698static int handle_matches(struct event_handler *handler, int id,
5699 const char *sys_name, const char *event_name,
5700 pevent_event_handler_func func, void *context)
5701{
5702 if (id >= 0 && id != handler->id)
5703 return 0;
5704
5705 if (event_name && (strcmp(event_name, handler->event_name) != 0))
5706 return 0;
5707
5708 if (sys_name && (strcmp(sys_name, handler->sys_name) != 0))
5709 return 0;
5710
5711 if (func != handler->func || context != handler->context)
5712 return 0;
5713
5714 return 1;
5715}
5716
5717/**
5718 * pevent_unregister_event_handler - unregister an existing event handler
5719 * @pevent: the handle to the pevent
5720 * @id: the id of the event to unregister
5721 * @sys_name: the system name the handler belongs to
5722 * @event_name: the name of the event handler
5723 * @func: the function to call to parse the event information
5724 * @context: the data to be passed to @func
5725 *
5726 * This function removes existing event handler (parser).
5727 *
5728 * If @id is >= 0, then it is used to find the event.
5729 * else @sys_name and @event_name are used.
5730 *
5731 * Returns 0 if handler was removed successfully, -1 if event was not found.
5732 */
5733int pevent_unregister_event_handler(struct pevent *pevent, int id,
5734 const char *sys_name, const char *event_name,
5735 pevent_event_handler_func func, void *context)
5736{
5737 struct event_format *event;
5738 struct event_handler *handle;
5739 struct event_handler **next;
5740
5741 event = pevent_search_event(pevent, id, sys_name, event_name);
5742 if (event == NULL)
5743 goto not_found;
5744
5745 if (event->handler == func && event->context == context) {
5746 pr_stat("removing override handler for event (%d) %s:%s. Going back to default handler.",
5747 event->id, event->system, event->name);
5748
5749 event->handler = NULL;
5750 event->context = NULL;
5751 return 0;
5752 }
5753
5754not_found:
5755 for (next = &pevent->handlers; *next; next = &(*next)->next) {
5756 handle = *next;
5757 if (handle_matches(handle, id, sys_name, event_name,
5758 func, context))
5759 break;
5760 }
5761
5762 if (!(*next))
5763 return -1;
5764
5765 *next = handle->next;
5766 free_handler(handle);
5767
5768 return 0;
5769}
5770
Steven Rostedtf7d82352012-04-06 00:47:53 +02005771/**
5772 * pevent_alloc - create a pevent handle
5773 */
5774struct pevent *pevent_alloc(void)
5775{
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -03005776 struct pevent *pevent = calloc(1, sizeof(*pevent));
Steven Rostedtf7d82352012-04-06 00:47:53 +02005777
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -03005778 if (pevent)
5779 pevent->ref_count = 1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005780
5781 return pevent;
5782}
5783
5784void pevent_ref(struct pevent *pevent)
5785{
5786 pevent->ref_count++;
5787}
5788
5789static void free_format_fields(struct format_field *field)
5790{
5791 struct format_field *next;
5792
5793 while (field) {
5794 next = field->next;
5795 free(field->type);
5796 free(field->name);
5797 free(field);
5798 field = next;
5799 }
5800}
5801
5802static void free_formats(struct format *format)
5803{
5804 free_format_fields(format->common_fields);
5805 free_format_fields(format->fields);
5806}
5807
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005808void pevent_free_format(struct event_format *event)
Steven Rostedtf7d82352012-04-06 00:47:53 +02005809{
5810 free(event->name);
5811 free(event->system);
5812
5813 free_formats(&event->format);
5814
5815 free(event->print_fmt.format);
5816 free_args(event->print_fmt.args);
5817
5818 free(event);
5819}
5820
5821/**
5822 * pevent_free - free a pevent handle
5823 * @pevent: the pevent handle to free
5824 */
5825void pevent_free(struct pevent *pevent)
5826{
Steven Rostedta2525a02012-04-06 00:48:02 +02005827 struct cmdline_list *cmdlist, *cmdnext;
5828 struct func_list *funclist, *funcnext;
5829 struct printk_list *printklist, *printknext;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005830 struct pevent_function_handler *func_handler;
5831 struct event_handler *handle;
5832 int i;
5833
Steven Rostedta2525a02012-04-06 00:48:02 +02005834 if (!pevent)
5835 return;
5836
5837 cmdlist = pevent->cmdlist;
5838 funclist = pevent->funclist;
5839 printklist = pevent->printklist;
5840
Steven Rostedtf7d82352012-04-06 00:47:53 +02005841 pevent->ref_count--;
5842 if (pevent->ref_count)
5843 return;
5844
5845 if (pevent->cmdlines) {
5846 for (i = 0; i < pevent->cmdline_count; i++)
5847 free(pevent->cmdlines[i].comm);
5848 free(pevent->cmdlines);
5849 }
5850
5851 while (cmdlist) {
5852 cmdnext = cmdlist->next;
5853 free(cmdlist->comm);
5854 free(cmdlist);
5855 cmdlist = cmdnext;
5856 }
5857
5858 if (pevent->func_map) {
Arnaldo Carvalho de Melo8a38cce2012-11-09 15:32:00 -03005859 for (i = 0; i < (int)pevent->func_count; i++) {
Steven Rostedtf7d82352012-04-06 00:47:53 +02005860 free(pevent->func_map[i].func);
5861 free(pevent->func_map[i].mod);
5862 }
5863 free(pevent->func_map);
5864 }
5865
5866 while (funclist) {
5867 funcnext = funclist->next;
5868 free(funclist->func);
5869 free(funclist->mod);
5870 free(funclist);
5871 funclist = funcnext;
5872 }
5873
5874 while (pevent->func_handlers) {
5875 func_handler = pevent->func_handlers;
5876 pevent->func_handlers = func_handler->next;
5877 free_func_handle(func_handler);
5878 }
5879
5880 if (pevent->printk_map) {
Arnaldo Carvalho de Melo8a38cce2012-11-09 15:32:00 -03005881 for (i = 0; i < (int)pevent->printk_count; i++)
Steven Rostedtf7d82352012-04-06 00:47:53 +02005882 free(pevent->printk_map[i].printk);
5883 free(pevent->printk_map);
5884 }
5885
5886 while (printklist) {
5887 printknext = printklist->next;
5888 free(printklist->printk);
5889 free(printklist);
5890 printklist = printknext;
5891 }
5892
5893 for (i = 0; i < pevent->nr_events; i++)
Arnaldo Carvalho de Melo2b291752012-09-18 11:13:15 -03005894 pevent_free_format(pevent->events[i]);
Steven Rostedtf7d82352012-04-06 00:47:53 +02005895
5896 while (pevent->handlers) {
5897 handle = pevent->handlers;
5898 pevent->handlers = handle->next;
5899 free_handler(handle);
5900 }
5901
5902 free(pevent->events);
5903 free(pevent->sort_events);
5904
5905 free(pevent);
5906}
5907
5908void pevent_unref(struct pevent *pevent)
5909{
5910 pevent_free(pevent);
5911}