blob: b3bc13079c4415a94b0ad330d04be7cd32855863 [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
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 *
21 * The parts for function graph printing was taken and modified from the
22 * Linux Kernel that were written by
23 * - Copyright (C) 2009 Frederic Weisbecker,
24 * Frederic Weisbecker gave his permission to relicense the code to
25 * the Lesser General Public License.
26 */
Steven Rostedtf7d82352012-04-06 00:47:53 +020027#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <stdarg.h>
31#include <ctype.h>
32#include <errno.h>
Robert Richter0cf26012012-08-07 19:43:14 +020033#include <stdint.h>
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -030034#include <limits.h>
Steven Rostedtf7d82352012-04-06 00:47:53 +020035
36#include "event-parse.h"
Steven Rostedt668fe012012-04-06 00:47:55 +020037#include "event-utils.h"
Steven Rostedtf7d82352012-04-06 00:47:53 +020038
39static const char *input_buf;
40static unsigned long long input_buf_ptr;
41static unsigned long long input_buf_siz;
42
Tom Zanussi5205aec2012-04-06 00:47:58 +020043static int is_flag_field;
44static int is_symbolic_field;
45
Steven Rostedtf7d82352012-04-06 00:47:53 +020046static int show_warning = 1;
47
48#define do_warning(fmt, ...) \
49 do { \
50 if (show_warning) \
51 warning(fmt, ##__VA_ARGS__); \
52 } while (0)
53
54static void init_input_buf(const char *buf, unsigned long long size)
55{
56 input_buf = buf;
57 input_buf_siz = size;
58 input_buf_ptr = 0;
59}
60
61const char *pevent_get_input_buf(void)
62{
63 return input_buf;
64}
65
66unsigned long long pevent_get_input_buf_ptr(void)
67{
68 return input_buf_ptr;
69}
70
71struct event_handler {
72 struct event_handler *next;
73 int id;
74 const char *sys_name;
75 const char *event_name;
76 pevent_event_handler_func func;
77 void *context;
78};
79
80struct pevent_func_params {
81 struct pevent_func_params *next;
82 enum pevent_func_arg_type type;
83};
84
85struct pevent_function_handler {
86 struct pevent_function_handler *next;
87 enum pevent_func_arg_type ret_type;
88 char *name;
89 pevent_func_handler func;
90 struct pevent_func_params *params;
91 int nr_args;
92};
93
94static unsigned long long
95process_defined_func(struct trace_seq *s, void *data, int size,
96 struct event_format *event, struct print_arg *arg);
97
98static void free_func_handle(struct pevent_function_handler *func);
99
100/**
101 * pevent_buffer_init - init buffer for parsing
102 * @buf: buffer to parse
103 * @size: the size of the buffer
104 *
105 * For use with pevent_read_token(), this initializes the internal
106 * buffer that pevent_read_token() will parse.
107 */
108void pevent_buffer_init(const char *buf, unsigned long long size)
109{
110 init_input_buf(buf, size);
111}
112
113void breakpoint(void)
114{
115 static int x;
116 x++;
117}
118
119struct print_arg *alloc_arg(void)
120{
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -0300121 return calloc(1, sizeof(struct print_arg));
Steven Rostedtf7d82352012-04-06 00:47:53 +0200122}
123
124struct cmdline {
125 char *comm;
126 int pid;
127};
128
129static int cmdline_cmp(const void *a, const void *b)
130{
131 const struct cmdline *ca = a;
132 const struct cmdline *cb = b;
133
134 if (ca->pid < cb->pid)
135 return -1;
136 if (ca->pid > cb->pid)
137 return 1;
138
139 return 0;
140}
141
142struct cmdline_list {
143 struct cmdline_list *next;
144 char *comm;
145 int pid;
146};
147
148static int cmdline_init(struct pevent *pevent)
149{
150 struct cmdline_list *cmdlist = pevent->cmdlist;
151 struct cmdline_list *item;
152 struct cmdline *cmdlines;
153 int i;
154
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300155 cmdlines = malloc(sizeof(*cmdlines) * pevent->cmdline_count);
156 if (!cmdlines)
157 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200158
159 i = 0;
160 while (cmdlist) {
161 cmdlines[i].pid = cmdlist->pid;
162 cmdlines[i].comm = cmdlist->comm;
163 i++;
164 item = cmdlist;
165 cmdlist = cmdlist->next;
166 free(item);
167 }
168
169 qsort(cmdlines, pevent->cmdline_count, sizeof(*cmdlines), cmdline_cmp);
170
171 pevent->cmdlines = cmdlines;
172 pevent->cmdlist = NULL;
173
174 return 0;
175}
176
177static char *find_cmdline(struct pevent *pevent, int pid)
178{
179 const struct cmdline *comm;
180 struct cmdline key;
181
182 if (!pid)
183 return "<idle>";
184
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300185 if (!pevent->cmdlines && cmdline_init(pevent))
186 return "<not enough memory for cmdlines!>";
Steven Rostedtf7d82352012-04-06 00:47:53 +0200187
188 key.pid = pid;
189
190 comm = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
191 sizeof(*pevent->cmdlines), cmdline_cmp);
192
193 if (comm)
194 return comm->comm;
195 return "<...>";
196}
197
198/**
199 * pevent_pid_is_registered - return if a pid has a cmdline registered
200 * @pevent: handle for the pevent
201 * @pid: The pid to check if it has a cmdline registered with.
202 *
203 * Returns 1 if the pid has a cmdline mapped to it
204 * 0 otherwise.
205 */
206int pevent_pid_is_registered(struct pevent *pevent, int pid)
207{
208 const struct cmdline *comm;
209 struct cmdline key;
210
211 if (!pid)
212 return 1;
213
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300214 if (!pevent->cmdlines && cmdline_init(pevent))
215 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200216
217 key.pid = pid;
218
219 comm = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
220 sizeof(*pevent->cmdlines), cmdline_cmp);
221
222 if (comm)
223 return 1;
224 return 0;
225}
226
227/*
228 * If the command lines have been converted to an array, then
229 * we must add this pid. This is much slower than when cmdlines
230 * are added before the array is initialized.
231 */
232static int add_new_comm(struct pevent *pevent, const char *comm, int pid)
233{
234 struct cmdline *cmdlines = pevent->cmdlines;
235 const struct cmdline *cmdline;
236 struct cmdline key;
237
238 if (!pid)
239 return 0;
240
241 /* avoid duplicates */
242 key.pid = pid;
243
244 cmdline = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
245 sizeof(*pevent->cmdlines), cmdline_cmp);
246 if (cmdline) {
247 errno = EEXIST;
248 return -1;
249 }
250
251 cmdlines = realloc(cmdlines, sizeof(*cmdlines) * (pevent->cmdline_count + 1));
252 if (!cmdlines) {
253 errno = ENOMEM;
254 return -1;
255 }
256
Steven Rostedtf7d82352012-04-06 00:47:53 +0200257 cmdlines[pevent->cmdline_count].comm = strdup(comm);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300258 if (!cmdlines[pevent->cmdline_count].comm) {
259 free(cmdlines);
260 errno = ENOMEM;
261 return -1;
262 }
263
264 cmdlines[pevent->cmdline_count].pid = pid;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200265
266 if (cmdlines[pevent->cmdline_count].comm)
267 pevent->cmdline_count++;
268
269 qsort(cmdlines, pevent->cmdline_count, sizeof(*cmdlines), cmdline_cmp);
270 pevent->cmdlines = cmdlines;
271
272 return 0;
273}
274
275/**
276 * pevent_register_comm - register a pid / comm mapping
277 * @pevent: handle for the pevent
278 * @comm: the command line to register
279 * @pid: the pid to map the command line to
280 *
281 * This adds a mapping to search for command line names with
282 * a given pid. The comm is duplicated.
283 */
284int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
285{
286 struct cmdline_list *item;
287
288 if (pevent->cmdlines)
289 return add_new_comm(pevent, comm, pid);
290
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300291 item = malloc(sizeof(*item));
292 if (!item)
293 return -1;
294
Steven Rostedtf7d82352012-04-06 00:47:53 +0200295 item->comm = strdup(comm);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300296 if (!item->comm) {
297 free(item);
298 return -1;
299 }
Steven Rostedtf7d82352012-04-06 00:47:53 +0200300 item->pid = pid;
301 item->next = pevent->cmdlist;
302
303 pevent->cmdlist = item;
304 pevent->cmdline_count++;
305
306 return 0;
307}
308
309struct func_map {
310 unsigned long long addr;
311 char *func;
312 char *mod;
313};
314
315struct func_list {
316 struct func_list *next;
317 unsigned long long addr;
318 char *func;
319 char *mod;
320};
321
322static int func_cmp(const void *a, const void *b)
323{
324 const struct func_map *fa = a;
325 const struct func_map *fb = b;
326
327 if (fa->addr < fb->addr)
328 return -1;
329 if (fa->addr > fb->addr)
330 return 1;
331
332 return 0;
333}
334
335/*
336 * We are searching for a record in between, not an exact
337 * match.
338 */
339static int func_bcmp(const void *a, const void *b)
340{
341 const struct func_map *fa = a;
342 const struct func_map *fb = b;
343
344 if ((fa->addr == fb->addr) ||
345
346 (fa->addr > fb->addr &&
347 fa->addr < (fb+1)->addr))
348 return 0;
349
350 if (fa->addr < fb->addr)
351 return -1;
352
353 return 1;
354}
355
356static int func_map_init(struct pevent *pevent)
357{
358 struct func_list *funclist;
359 struct func_list *item;
360 struct func_map *func_map;
361 int i;
362
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300363 func_map = malloc(sizeof(*func_map) * (pevent->func_count + 1));
364 if (!func_map)
365 return -1;
366
Steven Rostedtf7d82352012-04-06 00:47:53 +0200367 funclist = pevent->funclist;
368
369 i = 0;
370 while (funclist) {
371 func_map[i].func = funclist->func;
372 func_map[i].addr = funclist->addr;
373 func_map[i].mod = funclist->mod;
374 i++;
375 item = funclist;
376 funclist = funclist->next;
377 free(item);
378 }
379
380 qsort(func_map, pevent->func_count, sizeof(*func_map), func_cmp);
381
382 /*
383 * Add a special record at the end.
384 */
385 func_map[pevent->func_count].func = NULL;
386 func_map[pevent->func_count].addr = 0;
387 func_map[pevent->func_count].mod = NULL;
388
389 pevent->func_map = func_map;
390 pevent->funclist = NULL;
391
392 return 0;
393}
394
395static struct func_map *
396find_func(struct pevent *pevent, unsigned long long addr)
397{
398 struct func_map *func;
399 struct func_map key;
400
401 if (!pevent->func_map)
402 func_map_init(pevent);
403
404 key.addr = addr;
405
406 func = bsearch(&key, pevent->func_map, pevent->func_count,
407 sizeof(*pevent->func_map), func_bcmp);
408
409 return func;
410}
411
412/**
413 * pevent_find_function - find a function by a given address
414 * @pevent: handle for the pevent
415 * @addr: the address to find the function with
416 *
417 * Returns a pointer to the function stored that has the given
418 * address. Note, the address does not have to be exact, it
419 * will select the function that would contain the address.
420 */
421const char *pevent_find_function(struct pevent *pevent, unsigned long long addr)
422{
423 struct func_map *map;
424
425 map = find_func(pevent, addr);
426 if (!map)
427 return NULL;
428
429 return map->func;
430}
431
432/**
433 * pevent_find_function_address - find a function address by a given address
434 * @pevent: handle for the pevent
435 * @addr: the address to find the function with
436 *
437 * Returns the address the function starts at. This can be used in
438 * conjunction with pevent_find_function to print both the function
439 * name and the function offset.
440 */
441unsigned long long
442pevent_find_function_address(struct pevent *pevent, unsigned long long addr)
443{
444 struct func_map *map;
445
446 map = find_func(pevent, addr);
447 if (!map)
448 return 0;
449
450 return map->addr;
451}
452
453/**
454 * pevent_register_function - register a function with a given address
455 * @pevent: handle for the pevent
456 * @function: the function name to register
457 * @addr: the address the function starts at
458 * @mod: the kernel module the function may be in (NULL for none)
459 *
460 * This registers a function name with an address and module.
461 * The @func passed in is duplicated.
462 */
463int pevent_register_function(struct pevent *pevent, char *func,
464 unsigned long long addr, char *mod)
465{
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300466 struct func_list *item = malloc(sizeof(*item));
Steven Rostedtf7d82352012-04-06 00:47:53 +0200467
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300468 if (!item)
469 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200470
471 item->next = pevent->funclist;
472 item->func = strdup(func);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300473 if (!item->func)
474 goto out_free;
475
476 if (mod) {
Steven Rostedtf7d82352012-04-06 00:47:53 +0200477 item->mod = strdup(mod);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300478 if (!item->mod)
479 goto out_free_func;
480 } else
Steven Rostedtf7d82352012-04-06 00:47:53 +0200481 item->mod = NULL;
482 item->addr = addr;
483
Namhyung Kimca638582012-04-09 11:54:31 +0900484 pevent->funclist = item;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200485 pevent->func_count++;
486
487 return 0;
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300488
489out_free_func:
490 free(item->func);
491 item->func = NULL;
492out_free:
493 free(item);
494 errno = ENOMEM;
495 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200496}
497
498/**
499 * pevent_print_funcs - print out the stored functions
500 * @pevent: handle for the pevent
501 *
502 * This prints out the stored functions.
503 */
504void pevent_print_funcs(struct pevent *pevent)
505{
506 int i;
507
508 if (!pevent->func_map)
509 func_map_init(pevent);
510
511 for (i = 0; i < (int)pevent->func_count; i++) {
512 printf("%016llx %s",
513 pevent->func_map[i].addr,
514 pevent->func_map[i].func);
515 if (pevent->func_map[i].mod)
516 printf(" [%s]\n", pevent->func_map[i].mod);
517 else
518 printf("\n");
519 }
520}
521
522struct printk_map {
523 unsigned long long addr;
524 char *printk;
525};
526
527struct printk_list {
528 struct printk_list *next;
529 unsigned long long addr;
530 char *printk;
531};
532
533static int printk_cmp(const void *a, const void *b)
534{
Namhyung Kim0fc45ef2012-04-09 11:54:29 +0900535 const struct printk_map *pa = a;
536 const struct printk_map *pb = b;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200537
Namhyung Kim0fc45ef2012-04-09 11:54:29 +0900538 if (pa->addr < pb->addr)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200539 return -1;
Namhyung Kim0fc45ef2012-04-09 11:54:29 +0900540 if (pa->addr > pb->addr)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200541 return 1;
542
543 return 0;
544}
545
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300546static int printk_map_init(struct pevent *pevent)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200547{
548 struct printk_list *printklist;
549 struct printk_list *item;
550 struct printk_map *printk_map;
551 int i;
552
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300553 printk_map = malloc(sizeof(*printk_map) * (pevent->printk_count + 1));
554 if (!printk_map)
555 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200556
557 printklist = pevent->printklist;
558
559 i = 0;
560 while (printklist) {
561 printk_map[i].printk = printklist->printk;
562 printk_map[i].addr = printklist->addr;
563 i++;
564 item = printklist;
565 printklist = printklist->next;
566 free(item);
567 }
568
569 qsort(printk_map, pevent->printk_count, sizeof(*printk_map), printk_cmp);
570
571 pevent->printk_map = printk_map;
572 pevent->printklist = NULL;
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300573
574 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200575}
576
577static struct printk_map *
578find_printk(struct pevent *pevent, unsigned long long addr)
579{
580 struct printk_map *printk;
581 struct printk_map key;
582
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300583 if (!pevent->printk_map && printk_map_init(pevent))
584 return NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200585
586 key.addr = addr;
587
588 printk = bsearch(&key, pevent->printk_map, pevent->printk_count,
589 sizeof(*pevent->printk_map), printk_cmp);
590
591 return printk;
592}
593
594/**
595 * pevent_register_print_string - register a string by its address
596 * @pevent: handle for the pevent
597 * @fmt: the string format to register
598 * @addr: the address the string was located at
599 *
600 * This registers a string by the address it was stored in the kernel.
601 * The @fmt passed in is duplicated.
602 */
603int pevent_register_print_string(struct pevent *pevent, char *fmt,
604 unsigned long long addr)
605{
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300606 struct printk_list *item = malloc(sizeof(*item));
Steven Rostedtf7d82352012-04-06 00:47:53 +0200607
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300608 if (!item)
609 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200610
611 item->next = pevent->printklist;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200612 item->addr = addr;
613
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300614 item->printk = strdup(fmt);
Namhyung Kimca638582012-04-09 11:54:31 +0900615 if (!item->printk)
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300616 goto out_free;
Namhyung Kimca638582012-04-09 11:54:31 +0900617
618 pevent->printklist = item;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200619 pevent->printk_count++;
620
621 return 0;
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300622
623out_free:
624 free(item);
625 errno = ENOMEM;
626 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200627}
628
629/**
630 * pevent_print_printk - print out the stored strings
631 * @pevent: handle for the pevent
632 *
633 * This prints the string formats that were stored.
634 */
635void pevent_print_printk(struct pevent *pevent)
636{
637 int i;
638
639 if (!pevent->printk_map)
640 printk_map_init(pevent);
641
642 for (i = 0; i < (int)pevent->printk_count; i++) {
643 printf("%016llx %s\n",
644 pevent->printk_map[i].addr,
645 pevent->printk_map[i].printk);
646 }
647}
648
649static struct event_format *alloc_event(void)
650{
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -0300651 return calloc(1, sizeof(struct event_format));
Steven Rostedtf7d82352012-04-06 00:47:53 +0200652}
653
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300654static int add_event(struct pevent *pevent, struct event_format *event)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200655{
656 int i;
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300657 struct event_format **events = realloc(pevent->events, sizeof(event) *
658 (pevent->nr_events + 1));
659 if (!events)
660 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200661
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300662 pevent->events = events;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200663
664 for (i = 0; i < pevent->nr_events; i++) {
665 if (pevent->events[i]->id > event->id)
666 break;
667 }
668 if (i < pevent->nr_events)
669 memmove(&pevent->events[i + 1],
670 &pevent->events[i],
671 sizeof(event) * (pevent->nr_events - i));
672
673 pevent->events[i] = event;
674 pevent->nr_events++;
675
676 event->pevent = pevent;
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -0300677
678 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200679}
680
681static int event_item_type(enum event_type type)
682{
683 switch (type) {
684 case EVENT_ITEM ... EVENT_SQUOTE:
685 return 1;
686 case EVENT_ERROR ... EVENT_DELIM:
687 default:
688 return 0;
689 }
690}
691
692static void free_flag_sym(struct print_flag_sym *fsym)
693{
694 struct print_flag_sym *next;
695
696 while (fsym) {
697 next = fsym->next;
698 free(fsym->value);
699 free(fsym->str);
700 free(fsym);
701 fsym = next;
702 }
703}
704
705static void free_arg(struct print_arg *arg)
706{
707 struct print_arg *farg;
708
709 if (!arg)
710 return;
711
712 switch (arg->type) {
713 case PRINT_ATOM:
714 free(arg->atom.atom);
715 break;
716 case PRINT_FIELD:
717 free(arg->field.name);
718 break;
719 case PRINT_FLAGS:
720 free_arg(arg->flags.field);
721 free(arg->flags.delim);
722 free_flag_sym(arg->flags.flags);
723 break;
724 case PRINT_SYMBOL:
725 free_arg(arg->symbol.field);
726 free_flag_sym(arg->symbol.symbols);
727 break;
Namhyung Kime080e6f2012-06-27 09:41:41 +0900728 case PRINT_HEX:
729 free_arg(arg->hex.field);
730 free_arg(arg->hex.size);
731 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200732 case PRINT_TYPE:
733 free(arg->typecast.type);
734 free_arg(arg->typecast.item);
735 break;
736 case PRINT_STRING:
737 case PRINT_BSTRING:
738 free(arg->string.string);
739 break;
740 case PRINT_DYNAMIC_ARRAY:
741 free(arg->dynarray.index);
742 break;
743 case PRINT_OP:
744 free(arg->op.op);
745 free_arg(arg->op.left);
746 free_arg(arg->op.right);
747 break;
748 case PRINT_FUNC:
749 while (arg->func.args) {
750 farg = arg->func.args;
751 arg->func.args = farg->next;
752 free_arg(farg);
753 }
754 break;
755
756 case PRINT_NULL:
757 default:
758 break;
759 }
760
761 free(arg);
762}
763
764static enum event_type get_type(int ch)
765{
766 if (ch == '\n')
767 return EVENT_NEWLINE;
768 if (isspace(ch))
769 return EVENT_SPACE;
770 if (isalnum(ch) || ch == '_')
771 return EVENT_ITEM;
772 if (ch == '\'')
773 return EVENT_SQUOTE;
774 if (ch == '"')
775 return EVENT_DQUOTE;
776 if (!isprint(ch))
777 return EVENT_NONE;
778 if (ch == '(' || ch == ')' || ch == ',')
779 return EVENT_DELIM;
780
781 return EVENT_OP;
782}
783
784static int __read_char(void)
785{
786 if (input_buf_ptr >= input_buf_siz)
787 return -1;
788
789 return input_buf[input_buf_ptr++];
790}
791
792static int __peek_char(void)
793{
794 if (input_buf_ptr >= input_buf_siz)
795 return -1;
796
797 return input_buf[input_buf_ptr];
798}
799
800/**
801 * pevent_peek_char - peek at the next character that will be read
802 *
803 * Returns the next character read, or -1 if end of buffer.
804 */
805int pevent_peek_char(void)
806{
807 return __peek_char();
808}
809
Namhyung Kimdeba3fb2012-04-09 11:54:30 +0900810static int extend_token(char **tok, char *buf, int size)
811{
812 char *newtok = realloc(*tok, size);
813
814 if (!newtok) {
815 free(*tok);
816 *tok = NULL;
817 return -1;
818 }
819
820 if (!*tok)
821 strcpy(newtok, buf);
822 else
823 strcat(newtok, buf);
824 *tok = newtok;
825
826 return 0;
827}
828
Steven Rostedtf7d82352012-04-06 00:47:53 +0200829static enum event_type force_token(const char *str, char **tok);
830
831static enum event_type __read_token(char **tok)
832{
833 char buf[BUFSIZ];
834 int ch, last_ch, quote_ch, next_ch;
835 int i = 0;
836 int tok_size = 0;
837 enum event_type type;
838
839 *tok = NULL;
840
841
842 ch = __read_char();
843 if (ch < 0)
844 return EVENT_NONE;
845
846 type = get_type(ch);
847 if (type == EVENT_NONE)
848 return type;
849
850 buf[i++] = ch;
851
852 switch (type) {
853 case EVENT_NEWLINE:
854 case EVENT_DELIM:
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -0300855 if (asprintf(tok, "%c", ch) < 0)
856 return EVENT_ERROR;
857
Steven Rostedtf7d82352012-04-06 00:47:53 +0200858 return type;
859
860 case EVENT_OP:
861 switch (ch) {
862 case '-':
863 next_ch = __peek_char();
864 if (next_ch == '>') {
865 buf[i++] = __read_char();
866 break;
867 }
868 /* fall through */
869 case '+':
870 case '|':
871 case '&':
872 case '>':
873 case '<':
874 last_ch = ch;
875 ch = __peek_char();
876 if (ch != last_ch)
877 goto test_equal;
878 buf[i++] = __read_char();
879 switch (last_ch) {
880 case '>':
881 case '<':
882 goto test_equal;
883 default:
884 break;
885 }
886 break;
887 case '!':
888 case '=':
889 goto test_equal;
890 default: /* what should we do instead? */
891 break;
892 }
893 buf[i] = 0;
894 *tok = strdup(buf);
895 return type;
896
897 test_equal:
898 ch = __peek_char();
899 if (ch == '=')
900 buf[i++] = __read_char();
901 goto out;
902
903 case EVENT_DQUOTE:
904 case EVENT_SQUOTE:
905 /* don't keep quotes */
906 i--;
907 quote_ch = ch;
908 last_ch = 0;
909 concat:
910 do {
911 if (i == (BUFSIZ - 1)) {
912 buf[i] = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200913 tok_size += BUFSIZ;
Namhyung Kimdeba3fb2012-04-09 11:54:30 +0900914
915 if (extend_token(tok, buf, tok_size) < 0)
916 return EVENT_NONE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200917 i = 0;
918 }
919 last_ch = ch;
920 ch = __read_char();
921 buf[i++] = ch;
922 /* the '\' '\' will cancel itself */
923 if (ch == '\\' && last_ch == '\\')
924 last_ch = 0;
925 } while (ch != quote_ch || last_ch == '\\');
926 /* remove the last quote */
927 i--;
928
929 /*
930 * For strings (double quotes) check the next token.
931 * If it is another string, concatinate the two.
932 */
933 if (type == EVENT_DQUOTE) {
934 unsigned long long save_input_buf_ptr = input_buf_ptr;
935
936 do {
937 ch = __read_char();
938 } while (isspace(ch));
939 if (ch == '"')
940 goto concat;
941 input_buf_ptr = save_input_buf_ptr;
942 }
943
944 goto out;
945
946 case EVENT_ERROR ... EVENT_SPACE:
947 case EVENT_ITEM:
948 default:
949 break;
950 }
951
952 while (get_type(__peek_char()) == type) {
953 if (i == (BUFSIZ - 1)) {
954 buf[i] = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200955 tok_size += BUFSIZ;
Namhyung Kimdeba3fb2012-04-09 11:54:30 +0900956
957 if (extend_token(tok, buf, tok_size) < 0)
958 return EVENT_NONE;
Steven Rostedtf7d82352012-04-06 00:47:53 +0200959 i = 0;
960 }
961 ch = __read_char();
962 buf[i++] = ch;
963 }
964
965 out:
966 buf[i] = 0;
Namhyung Kimdeba3fb2012-04-09 11:54:30 +0900967 if (extend_token(tok, buf, tok_size + i + 1) < 0)
Steven Rostedtf7d82352012-04-06 00:47:53 +0200968 return EVENT_NONE;
969
970 if (type == EVENT_ITEM) {
971 /*
972 * Older versions of the kernel has a bug that
973 * creates invalid symbols and will break the mac80211
974 * parsing. This is a work around to that bug.
975 *
976 * See Linux kernel commit:
977 * 811cb50baf63461ce0bdb234927046131fc7fa8b
978 */
979 if (strcmp(*tok, "LOCAL_PR_FMT") == 0) {
980 free(*tok);
981 *tok = NULL;
982 return force_token("\"\%s\" ", tok);
983 } else if (strcmp(*tok, "STA_PR_FMT") == 0) {
984 free(*tok);
985 *tok = NULL;
986 return force_token("\" sta:%pM\" ", tok);
987 } else if (strcmp(*tok, "VIF_PR_FMT") == 0) {
988 free(*tok);
989 *tok = NULL;
990 return force_token("\" vif:%p(%d)\" ", tok);
991 }
992 }
993
994 return type;
995}
996
997static enum event_type force_token(const char *str, char **tok)
998{
999 const char *save_input_buf;
1000 unsigned long long save_input_buf_ptr;
1001 unsigned long long save_input_buf_siz;
1002 enum event_type type;
1003
1004 /* save off the current input pointers */
1005 save_input_buf = input_buf;
1006 save_input_buf_ptr = input_buf_ptr;
1007 save_input_buf_siz = input_buf_siz;
1008
1009 init_input_buf(str, strlen(str));
1010
1011 type = __read_token(tok);
1012
1013 /* reset back to original token */
1014 input_buf = save_input_buf;
1015 input_buf_ptr = save_input_buf_ptr;
1016 input_buf_siz = save_input_buf_siz;
1017
1018 return type;
1019}
1020
1021static void free_token(char *tok)
1022{
1023 if (tok)
1024 free(tok);
1025}
1026
1027static enum event_type read_token(char **tok)
1028{
1029 enum event_type type;
1030
1031 for (;;) {
1032 type = __read_token(tok);
1033 if (type != EVENT_SPACE)
1034 return type;
1035
1036 free_token(*tok);
1037 }
1038
1039 /* not reached */
1040 *tok = NULL;
1041 return EVENT_NONE;
1042}
1043
1044/**
1045 * pevent_read_token - access to utilites to use the pevent parser
1046 * @tok: The token to return
1047 *
1048 * This will parse tokens from the string given by
1049 * pevent_init_data().
1050 *
1051 * Returns the token type.
1052 */
1053enum event_type pevent_read_token(char **tok)
1054{
1055 return read_token(tok);
1056}
1057
1058/**
1059 * pevent_free_token - free a token returned by pevent_read_token
1060 * @token: the token to free
1061 */
1062void pevent_free_token(char *token)
1063{
1064 free_token(token);
1065}
1066
1067/* no newline */
1068static enum event_type read_token_item(char **tok)
1069{
1070 enum event_type type;
1071
1072 for (;;) {
1073 type = __read_token(tok);
1074 if (type != EVENT_SPACE && type != EVENT_NEWLINE)
1075 return type;
1076 free_token(*tok);
1077 *tok = NULL;
1078 }
1079
1080 /* not reached */
1081 *tok = NULL;
1082 return EVENT_NONE;
1083}
1084
1085static int test_type(enum event_type type, enum event_type expect)
1086{
1087 if (type != expect) {
1088 do_warning("Error: expected type %d but read %d",
1089 expect, type);
1090 return -1;
1091 }
1092 return 0;
1093}
1094
1095static int test_type_token(enum event_type type, const char *token,
1096 enum event_type expect, const char *expect_tok)
1097{
1098 if (type != expect) {
1099 do_warning("Error: expected type %d but read %d",
1100 expect, type);
1101 return -1;
1102 }
1103
1104 if (strcmp(token, expect_tok) != 0) {
1105 do_warning("Error: expected '%s' but read '%s'",
1106 expect_tok, token);
1107 return -1;
1108 }
1109 return 0;
1110}
1111
1112static int __read_expect_type(enum event_type expect, char **tok, int newline_ok)
1113{
1114 enum event_type type;
1115
1116 if (newline_ok)
1117 type = read_token(tok);
1118 else
1119 type = read_token_item(tok);
1120 return test_type(type, expect);
1121}
1122
1123static int read_expect_type(enum event_type expect, char **tok)
1124{
1125 return __read_expect_type(expect, tok, 1);
1126}
1127
1128static int __read_expected(enum event_type expect, const char *str,
1129 int newline_ok)
1130{
1131 enum event_type type;
1132 char *token;
1133 int ret;
1134
1135 if (newline_ok)
1136 type = read_token(&token);
1137 else
1138 type = read_token_item(&token);
1139
1140 ret = test_type_token(type, token, expect, str);
1141
1142 free_token(token);
1143
1144 return ret;
1145}
1146
1147static int read_expected(enum event_type expect, const char *str)
1148{
1149 return __read_expected(expect, str, 1);
1150}
1151
1152static int read_expected_item(enum event_type expect, const char *str)
1153{
1154 return __read_expected(expect, str, 0);
1155}
1156
1157static char *event_read_name(void)
1158{
1159 char *token;
1160
1161 if (read_expected(EVENT_ITEM, "name") < 0)
1162 return NULL;
1163
1164 if (read_expected(EVENT_OP, ":") < 0)
1165 return NULL;
1166
1167 if (read_expect_type(EVENT_ITEM, &token) < 0)
1168 goto fail;
1169
1170 return token;
1171
1172 fail:
1173 free_token(token);
1174 return NULL;
1175}
1176
1177static int event_read_id(void)
1178{
1179 char *token;
1180 int id;
1181
1182 if (read_expected_item(EVENT_ITEM, "ID") < 0)
1183 return -1;
1184
1185 if (read_expected(EVENT_OP, ":") < 0)
1186 return -1;
1187
1188 if (read_expect_type(EVENT_ITEM, &token) < 0)
1189 goto fail;
1190
1191 id = strtoul(token, NULL, 0);
1192 free_token(token);
1193 return id;
1194
1195 fail:
1196 free_token(token);
1197 return -1;
1198}
1199
1200static int field_is_string(struct format_field *field)
1201{
1202 if ((field->flags & FIELD_IS_ARRAY) &&
1203 (strstr(field->type, "char") || strstr(field->type, "u8") ||
1204 strstr(field->type, "s8")))
1205 return 1;
1206
1207 return 0;
1208}
1209
1210static int field_is_dynamic(struct format_field *field)
1211{
1212 if (strncmp(field->type, "__data_loc", 10) == 0)
1213 return 1;
1214
1215 return 0;
1216}
1217
1218static int field_is_long(struct format_field *field)
1219{
1220 /* includes long long */
1221 if (strstr(field->type, "long"))
1222 return 1;
1223
1224 return 0;
1225}
1226
1227static int event_read_fields(struct event_format *event, struct format_field **fields)
1228{
1229 struct format_field *field = NULL;
1230 enum event_type type;
1231 char *token;
1232 char *last_token;
1233 int count = 0;
1234
1235 do {
1236 type = read_token(&token);
1237 if (type == EVENT_NEWLINE) {
1238 free_token(token);
1239 return count;
1240 }
1241
1242 count++;
1243
1244 if (test_type_token(type, token, EVENT_ITEM, "field"))
1245 goto fail;
1246 free_token(token);
1247
1248 type = read_token(&token);
1249 /*
1250 * The ftrace fields may still use the "special" name.
1251 * Just ignore it.
1252 */
1253 if (event->flags & EVENT_FL_ISFTRACE &&
1254 type == EVENT_ITEM && strcmp(token, "special") == 0) {
1255 free_token(token);
1256 type = read_token(&token);
1257 }
1258
1259 if (test_type_token(type, token, EVENT_OP, ":") < 0)
1260 goto fail;
1261
1262 free_token(token);
1263 if (read_expect_type(EVENT_ITEM, &token) < 0)
1264 goto fail;
1265
1266 last_token = token;
1267
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -03001268 field = calloc(1, sizeof(*field));
1269 if (!field)
1270 goto fail;
1271
Steven Rostedtf7d82352012-04-06 00:47:53 +02001272 field->event = event;
1273
1274 /* read the rest of the type */
1275 for (;;) {
1276 type = read_token(&token);
1277 if (type == EVENT_ITEM ||
1278 (type == EVENT_OP && strcmp(token, "*") == 0) ||
1279 /*
1280 * Some of the ftrace fields are broken and have
1281 * an illegal "." in them.
1282 */
1283 (event->flags & EVENT_FL_ISFTRACE &&
1284 type == EVENT_OP && strcmp(token, ".") == 0)) {
1285
1286 if (strcmp(token, "*") == 0)
1287 field->flags |= FIELD_IS_POINTER;
1288
1289 if (field->type) {
Namhyung Kimd2864472012-04-09 11:54:33 +09001290 char *new_type;
1291 new_type = realloc(field->type,
1292 strlen(field->type) +
1293 strlen(last_token) + 2);
1294 if (!new_type) {
1295 free(last_token);
1296 goto fail;
1297 }
1298 field->type = new_type;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001299 strcat(field->type, " ");
1300 strcat(field->type, last_token);
1301 free(last_token);
1302 } else
1303 field->type = last_token;
1304 last_token = token;
1305 continue;
1306 }
1307
1308 break;
1309 }
1310
1311 if (!field->type) {
Arnaldo Carvalho de Melob8511922012-09-12 15:39:59 -03001312 do_warning("%s: no type found", __func__);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001313 goto fail;
1314 }
1315 field->name = last_token;
1316
1317 if (test_type(type, EVENT_OP))
1318 goto fail;
1319
1320 if (strcmp(token, "[") == 0) {
1321 enum event_type last_type = type;
1322 char *brackets = token;
Namhyung Kimd2864472012-04-09 11:54:33 +09001323 char *new_brackets;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001324 int len;
1325
1326 field->flags |= FIELD_IS_ARRAY;
1327
1328 type = read_token(&token);
1329
1330 if (type == EVENT_ITEM)
1331 field->arraylen = strtoul(token, NULL, 0);
1332 else
1333 field->arraylen = 0;
1334
1335 while (strcmp(token, "]") != 0) {
1336 if (last_type == EVENT_ITEM &&
1337 type == EVENT_ITEM)
1338 len = 2;
1339 else
1340 len = 1;
1341 last_type = type;
1342
Namhyung Kimd2864472012-04-09 11:54:33 +09001343 new_brackets = realloc(brackets,
1344 strlen(brackets) +
1345 strlen(token) + len);
1346 if (!new_brackets) {
1347 free(brackets);
1348 goto fail;
1349 }
1350 brackets = new_brackets;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001351 if (len == 2)
1352 strcat(brackets, " ");
1353 strcat(brackets, token);
1354 /* We only care about the last token */
1355 field->arraylen = strtoul(token, NULL, 0);
1356 free_token(token);
1357 type = read_token(&token);
1358 if (type == EVENT_NONE) {
Arnaldo Carvalho de Melob8511922012-09-12 15:39:59 -03001359 do_warning("failed to find token");
Steven Rostedtf7d82352012-04-06 00:47:53 +02001360 goto fail;
1361 }
1362 }
1363
1364 free_token(token);
1365
Namhyung Kimd2864472012-04-09 11:54:33 +09001366 new_brackets = realloc(brackets, strlen(brackets) + 2);
1367 if (!new_brackets) {
1368 free(brackets);
1369 goto fail;
1370 }
1371 brackets = new_brackets;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001372 strcat(brackets, "]");
1373
1374 /* add brackets to type */
1375
1376 type = read_token(&token);
1377 /*
1378 * If the next token is not an OP, then it is of
1379 * the format: type [] item;
1380 */
1381 if (type == EVENT_ITEM) {
Namhyung Kimd2864472012-04-09 11:54:33 +09001382 char *new_type;
1383 new_type = realloc(field->type,
1384 strlen(field->type) +
1385 strlen(field->name) +
1386 strlen(brackets) + 2);
1387 if (!new_type) {
1388 free(brackets);
1389 goto fail;
1390 }
1391 field->type = new_type;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001392 strcat(field->type, " ");
1393 strcat(field->type, field->name);
1394 free_token(field->name);
1395 strcat(field->type, brackets);
1396 field->name = token;
1397 type = read_token(&token);
1398 } else {
Namhyung Kimd2864472012-04-09 11:54:33 +09001399 char *new_type;
1400 new_type = realloc(field->type,
1401 strlen(field->type) +
1402 strlen(brackets) + 1);
1403 if (!new_type) {
1404 free(brackets);
1405 goto fail;
1406 }
1407 field->type = new_type;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001408 strcat(field->type, brackets);
1409 }
1410 free(brackets);
1411 }
1412
1413 if (field_is_string(field))
1414 field->flags |= FIELD_IS_STRING;
1415 if (field_is_dynamic(field))
1416 field->flags |= FIELD_IS_DYNAMIC;
1417 if (field_is_long(field))
1418 field->flags |= FIELD_IS_LONG;
1419
1420 if (test_type_token(type, token, EVENT_OP, ";"))
1421 goto fail;
1422 free_token(token);
1423
1424 if (read_expected(EVENT_ITEM, "offset") < 0)
1425 goto fail_expect;
1426
1427 if (read_expected(EVENT_OP, ":") < 0)
1428 goto fail_expect;
1429
1430 if (read_expect_type(EVENT_ITEM, &token))
1431 goto fail;
1432 field->offset = strtoul(token, NULL, 0);
1433 free_token(token);
1434
1435 if (read_expected(EVENT_OP, ";") < 0)
1436 goto fail_expect;
1437
1438 if (read_expected(EVENT_ITEM, "size") < 0)
1439 goto fail_expect;
1440
1441 if (read_expected(EVENT_OP, ":") < 0)
1442 goto fail_expect;
1443
1444 if (read_expect_type(EVENT_ITEM, &token))
1445 goto fail;
1446 field->size = strtoul(token, NULL, 0);
1447 free_token(token);
1448
1449 if (read_expected(EVENT_OP, ";") < 0)
1450 goto fail_expect;
1451
1452 type = read_token(&token);
1453 if (type != EVENT_NEWLINE) {
1454 /* newer versions of the kernel have a "signed" type */
1455 if (test_type_token(type, token, EVENT_ITEM, "signed"))
1456 goto fail;
1457
1458 free_token(token);
1459
1460 if (read_expected(EVENT_OP, ":") < 0)
1461 goto fail_expect;
1462
1463 if (read_expect_type(EVENT_ITEM, &token))
1464 goto fail;
1465
1466 /* add signed type */
1467
1468 free_token(token);
1469 if (read_expected(EVENT_OP, ";") < 0)
1470 goto fail_expect;
1471
1472 if (read_expect_type(EVENT_NEWLINE, &token))
1473 goto fail;
1474 }
1475
1476 free_token(token);
1477
1478 if (field->flags & FIELD_IS_ARRAY) {
1479 if (field->arraylen)
1480 field->elementsize = field->size / field->arraylen;
1481 else if (field->flags & FIELD_IS_STRING)
1482 field->elementsize = 1;
1483 else
1484 field->elementsize = event->pevent->long_size;
1485 } else
1486 field->elementsize = field->size;
1487
1488 *fields = field;
1489 fields = &field->next;
1490
1491 } while (1);
1492
1493 return 0;
1494
1495fail:
1496 free_token(token);
1497fail_expect:
Namhyung Kim57d34dc2012-05-23 11:36:47 +09001498 if (field) {
1499 free(field->type);
1500 free(field->name);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001501 free(field);
Namhyung Kim57d34dc2012-05-23 11:36:47 +09001502 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001503 return -1;
1504}
1505
1506static int event_read_format(struct event_format *event)
1507{
1508 char *token;
1509 int ret;
1510
1511 if (read_expected_item(EVENT_ITEM, "format") < 0)
1512 return -1;
1513
1514 if (read_expected(EVENT_OP, ":") < 0)
1515 return -1;
1516
1517 if (read_expect_type(EVENT_NEWLINE, &token))
1518 goto fail;
1519 free_token(token);
1520
1521 ret = event_read_fields(event, &event->format.common_fields);
1522 if (ret < 0)
1523 return ret;
1524 event->format.nr_common = ret;
1525
1526 ret = event_read_fields(event, &event->format.fields);
1527 if (ret < 0)
1528 return ret;
1529 event->format.nr_fields = ret;
1530
1531 return 0;
1532
1533 fail:
1534 free_token(token);
1535 return -1;
1536}
1537
1538static enum event_type
1539process_arg_token(struct event_format *event, struct print_arg *arg,
1540 char **tok, enum event_type type);
1541
1542static enum event_type
1543process_arg(struct event_format *event, struct print_arg *arg, char **tok)
1544{
1545 enum event_type type;
1546 char *token;
1547
1548 type = read_token(&token);
1549 *tok = token;
1550
1551 return process_arg_token(event, arg, tok, type);
1552}
1553
1554static enum event_type
1555process_op(struct event_format *event, struct print_arg *arg, char **tok);
1556
1557static enum event_type
1558process_cond(struct event_format *event, struct print_arg *top, char **tok)
1559{
1560 struct print_arg *arg, *left, *right;
1561 enum event_type type;
1562 char *token = NULL;
1563
1564 arg = alloc_arg();
1565 left = alloc_arg();
1566 right = alloc_arg();
1567
1568 arg->type = PRINT_OP;
1569 arg->op.left = left;
1570 arg->op.right = right;
1571
1572 *tok = NULL;
1573 type = process_arg(event, left, &token);
1574
1575 again:
1576 /* Handle other operations in the arguments */
1577 if (type == EVENT_OP && strcmp(token, ":") != 0) {
1578 type = process_op(event, left, &token);
1579 goto again;
1580 }
1581
1582 if (test_type_token(type, token, EVENT_OP, ":"))
1583 goto out_free;
1584
1585 arg->op.op = token;
1586
1587 type = process_arg(event, right, &token);
1588
1589 top->op.right = arg;
1590
1591 *tok = token;
1592 return type;
1593
1594out_free:
1595 /* Top may point to itself */
1596 top->op.right = NULL;
1597 free_token(token);
1598 free_arg(arg);
1599 return EVENT_ERROR;
1600}
1601
1602static enum event_type
1603process_array(struct event_format *event, struct print_arg *top, char **tok)
1604{
1605 struct print_arg *arg;
1606 enum event_type type;
1607 char *token = NULL;
1608
1609 arg = alloc_arg();
1610
1611 *tok = NULL;
1612 type = process_arg(event, arg, &token);
1613 if (test_type_token(type, token, EVENT_OP, "]"))
1614 goto out_free;
1615
1616 top->op.right = arg;
1617
1618 free_token(token);
1619 type = read_token_item(&token);
1620 *tok = token;
1621
1622 return type;
1623
1624out_free:
Namhyung Kim1bce6e02012-09-19 15:58:41 +09001625 free_token(token);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001626 free_arg(arg);
1627 return EVENT_ERROR;
1628}
1629
1630static int get_op_prio(char *op)
1631{
1632 if (!op[1]) {
1633 switch (op[0]) {
1634 case '~':
1635 case '!':
1636 return 4;
1637 case '*':
1638 case '/':
1639 case '%':
1640 return 6;
1641 case '+':
1642 case '-':
1643 return 7;
1644 /* '>>' and '<<' are 8 */
1645 case '<':
1646 case '>':
1647 return 9;
1648 /* '==' and '!=' are 10 */
1649 case '&':
1650 return 11;
1651 case '^':
1652 return 12;
1653 case '|':
1654 return 13;
1655 case '?':
1656 return 16;
1657 default:
Vaibhav Nagarnaik14ffde02012-04-06 00:48:01 +02001658 do_warning("unknown op '%c'", op[0]);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001659 return -1;
1660 }
1661 } else {
1662 if (strcmp(op, "++") == 0 ||
1663 strcmp(op, "--") == 0) {
1664 return 3;
1665 } else if (strcmp(op, ">>") == 0 ||
1666 strcmp(op, "<<") == 0) {
1667 return 8;
1668 } else if (strcmp(op, ">=") == 0 ||
1669 strcmp(op, "<=") == 0) {
1670 return 9;
1671 } else if (strcmp(op, "==") == 0 ||
1672 strcmp(op, "!=") == 0) {
1673 return 10;
1674 } else if (strcmp(op, "&&") == 0) {
1675 return 14;
1676 } else if (strcmp(op, "||") == 0) {
1677 return 15;
1678 } else {
Vaibhav Nagarnaik14ffde02012-04-06 00:48:01 +02001679 do_warning("unknown op '%s'", op);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001680 return -1;
1681 }
1682 }
1683}
1684
Vaibhav Nagarnaik14ffde02012-04-06 00:48:01 +02001685static int set_op_prio(struct print_arg *arg)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001686{
1687
1688 /* single ops are the greatest */
Vaibhav Nagarnaik14ffde02012-04-06 00:48:01 +02001689 if (!arg->op.left || arg->op.left->type == PRINT_NULL)
Steven Rostedtf7d82352012-04-06 00:47:53 +02001690 arg->op.prio = 0;
Vaibhav Nagarnaik14ffde02012-04-06 00:48:01 +02001691 else
1692 arg->op.prio = get_op_prio(arg->op.op);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001693
Vaibhav Nagarnaik14ffde02012-04-06 00:48:01 +02001694 return arg->op.prio;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001695}
1696
1697/* Note, *tok does not get freed, but will most likely be saved */
1698static enum event_type
1699process_op(struct event_format *event, struct print_arg *arg, char **tok)
1700{
1701 struct print_arg *left, *right = NULL;
1702 enum event_type type;
1703 char *token;
1704
1705 /* the op is passed in via tok */
1706 token = *tok;
1707
1708 if (arg->type == PRINT_OP && !arg->op.left) {
1709 /* handle single op */
1710 if (token[1]) {
Arnaldo Carvalho de Melob8511922012-09-12 15:39:59 -03001711 do_warning("bad op token %s", token);
Steven Rostedtf7d82352012-04-06 00:47:53 +02001712 goto out_free;
1713 }
1714 switch (token[0]) {
1715 case '~':
1716 case '!':
1717 case '+':
1718 case '-':
1719 break;
1720 default:
1721 do_warning("bad op token %s", token);
1722 goto out_free;
1723
1724 }
1725
1726 /* make an empty left */
1727 left = alloc_arg();
1728 left->type = PRINT_NULL;
1729 arg->op.left = left;
1730
1731 right = alloc_arg();
1732 arg->op.right = right;
1733
1734 /* do not free the token, it belongs to an op */
1735 *tok = NULL;
1736 type = process_arg(event, right, tok);
1737
1738 } else if (strcmp(token, "?") == 0) {
1739
1740 left = alloc_arg();
1741 /* copy the top arg to the left */
1742 *left = *arg;
1743
1744 arg->type = PRINT_OP;
1745 arg->op.op = token;
1746 arg->op.left = left;
1747 arg->op.prio = 0;
1748
Namhyung Kim41e51a22012-09-19 15:58:42 +09001749 /* it will set arg->op.right */
Steven Rostedtf7d82352012-04-06 00:47:53 +02001750 type = process_cond(event, arg, tok);
1751
1752 } else if (strcmp(token, ">>") == 0 ||
1753 strcmp(token, "<<") == 0 ||
1754 strcmp(token, "&") == 0 ||
1755 strcmp(token, "|") == 0 ||
1756 strcmp(token, "&&") == 0 ||
1757 strcmp(token, "||") == 0 ||
1758 strcmp(token, "-") == 0 ||
1759 strcmp(token, "+") == 0 ||
1760 strcmp(token, "*") == 0 ||
1761 strcmp(token, "^") == 0 ||
1762 strcmp(token, "/") == 0 ||
1763 strcmp(token, "<") == 0 ||
1764 strcmp(token, ">") == 0 ||
1765 strcmp(token, "==") == 0 ||
1766 strcmp(token, "!=") == 0) {
1767
1768 left = alloc_arg();
1769
1770 /* copy the top arg to the left */
1771 *left = *arg;
1772
1773 arg->type = PRINT_OP;
1774 arg->op.op = token;
1775 arg->op.left = left;
Namhyung Kim41e51a22012-09-19 15:58:42 +09001776 arg->op.right = NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001777
Vaibhav Nagarnaik14ffde02012-04-06 00:48:01 +02001778 if (set_op_prio(arg) == -1) {
1779 event->flags |= EVENT_FL_FAILED;
Namhyung Kimd1de1082012-05-23 11:36:49 +09001780 /* arg->op.op (= token) will be freed at out_free */
1781 arg->op.op = NULL;
Vaibhav Nagarnaik14ffde02012-04-06 00:48:01 +02001782 goto out_free;
1783 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001784
1785 type = read_token_item(&token);
1786 *tok = token;
1787
1788 /* could just be a type pointer */
1789 if ((strcmp(arg->op.op, "*") == 0) &&
1790 type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
Namhyung Kimd2864472012-04-09 11:54:33 +09001791 char *new_atom;
1792
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03001793 if (left->type != PRINT_ATOM) {
1794 do_warning("bad pointer type");
1795 goto out_free;
1796 }
Namhyung Kimd2864472012-04-09 11:54:33 +09001797 new_atom = realloc(left->atom.atom,
Steven Rostedtf7d82352012-04-06 00:47:53 +02001798 strlen(left->atom.atom) + 3);
Namhyung Kimd2864472012-04-09 11:54:33 +09001799 if (!new_atom)
1800 goto out_free;
1801
1802 left->atom.atom = new_atom;
Steven Rostedtf7d82352012-04-06 00:47:53 +02001803 strcat(left->atom.atom, " *");
1804 free(arg->op.op);
1805 *arg = *left;
1806 free(left);
1807
1808 return type;
1809 }
1810
1811 right = alloc_arg();
1812 type = process_arg_token(event, right, tok, type);
1813 arg->op.right = right;
1814
1815 } else if (strcmp(token, "[") == 0) {
1816
1817 left = alloc_arg();
1818 *left = *arg;
1819
1820 arg->type = PRINT_OP;
1821 arg->op.op = token;
1822 arg->op.left = left;
1823
1824 arg->op.prio = 0;
1825
Namhyung Kim41e51a22012-09-19 15:58:42 +09001826 /* it will set arg->op.right */
Steven Rostedtf7d82352012-04-06 00:47:53 +02001827 type = process_array(event, arg, tok);
1828
1829 } else {
1830 do_warning("unknown op '%s'", token);
1831 event->flags |= EVENT_FL_FAILED;
1832 /* the arg is now the left side */
1833 goto out_free;
1834 }
1835
1836 if (type == EVENT_OP && strcmp(*tok, ":") != 0) {
1837 int prio;
1838
1839 /* higher prios need to be closer to the root */
1840 prio = get_op_prio(*tok);
1841
1842 if (prio > arg->op.prio)
1843 return process_op(event, arg, tok);
1844
1845 return process_op(event, right, tok);
1846 }
1847
1848 return type;
1849
1850 out_free:
1851 free_token(token);
1852 *tok = NULL;
1853 return EVENT_ERROR;
1854}
1855
1856static enum event_type
Irina Tirdea1d037ca2012-09-11 01:15:03 +03001857process_entry(struct event_format *event __maybe_unused, struct print_arg *arg,
Steven Rostedtf7d82352012-04-06 00:47:53 +02001858 char **tok)
1859{
1860 enum event_type type;
1861 char *field;
1862 char *token;
1863
1864 if (read_expected(EVENT_OP, "->") < 0)
1865 goto out_err;
1866
1867 if (read_expect_type(EVENT_ITEM, &token) < 0)
1868 goto out_free;
1869 field = token;
1870
1871 arg->type = PRINT_FIELD;
1872 arg->field.name = field;
1873
Tom Zanussi5205aec2012-04-06 00:47:58 +02001874 if (is_flag_field) {
1875 arg->field.field = pevent_find_any_field(event, arg->field.name);
1876 arg->field.field->flags |= FIELD_IS_FLAG;
1877 is_flag_field = 0;
1878 } else if (is_symbolic_field) {
1879 arg->field.field = pevent_find_any_field(event, arg->field.name);
1880 arg->field.field->flags |= FIELD_IS_SYMBOLIC;
1881 is_symbolic_field = 0;
1882 }
1883
Steven Rostedtf7d82352012-04-06 00:47:53 +02001884 type = read_token(&token);
1885 *tok = token;
1886
1887 return type;
1888
1889 out_free:
1890 free_token(token);
1891 out_err:
1892 *tok = NULL;
1893 return EVENT_ERROR;
1894}
1895
1896static char *arg_eval (struct print_arg *arg);
1897
1898static unsigned long long
1899eval_type_str(unsigned long long val, const char *type, int pointer)
1900{
1901 int sign = 0;
1902 char *ref;
1903 int len;
1904
1905 len = strlen(type);
1906
1907 if (pointer) {
1908
1909 if (type[len-1] != '*') {
1910 do_warning("pointer expected with non pointer type");
1911 return val;
1912 }
1913
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03001914 ref = malloc(len);
1915 if (!ref) {
1916 do_warning("%s: not enough memory!", __func__);
1917 return val;
1918 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001919 memcpy(ref, type, len);
1920
1921 /* chop off the " *" */
1922 ref[len - 2] = 0;
1923
1924 val = eval_type_str(val, ref, 0);
1925 free(ref);
1926 return val;
1927 }
1928
1929 /* check if this is a pointer */
1930 if (type[len - 1] == '*')
1931 return val;
1932
1933 /* Try to figure out the arg size*/
1934 if (strncmp(type, "struct", 6) == 0)
1935 /* all bets off */
1936 return val;
1937
1938 if (strcmp(type, "u8") == 0)
1939 return val & 0xff;
1940
1941 if (strcmp(type, "u16") == 0)
1942 return val & 0xffff;
1943
1944 if (strcmp(type, "u32") == 0)
1945 return val & 0xffffffff;
1946
1947 if (strcmp(type, "u64") == 0 ||
1948 strcmp(type, "s64"))
1949 return val;
1950
1951 if (strcmp(type, "s8") == 0)
1952 return (unsigned long long)(char)val & 0xff;
1953
1954 if (strcmp(type, "s16") == 0)
1955 return (unsigned long long)(short)val & 0xffff;
1956
1957 if (strcmp(type, "s32") == 0)
1958 return (unsigned long long)(int)val & 0xffffffff;
1959
1960 if (strncmp(type, "unsigned ", 9) == 0) {
1961 sign = 0;
1962 type += 9;
1963 }
1964
1965 if (strcmp(type, "char") == 0) {
1966 if (sign)
1967 return (unsigned long long)(char)val & 0xff;
1968 else
1969 return val & 0xff;
1970 }
1971
1972 if (strcmp(type, "short") == 0) {
1973 if (sign)
1974 return (unsigned long long)(short)val & 0xffff;
1975 else
1976 return val & 0xffff;
1977 }
1978
1979 if (strcmp(type, "int") == 0) {
1980 if (sign)
1981 return (unsigned long long)(int)val & 0xffffffff;
1982 else
1983 return val & 0xffffffff;
1984 }
1985
1986 return val;
1987}
1988
1989/*
1990 * Try to figure out the type.
1991 */
1992static unsigned long long
1993eval_type(unsigned long long val, struct print_arg *arg, int pointer)
1994{
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03001995 if (arg->type != PRINT_TYPE) {
1996 do_warning("expected type argument");
1997 return 0;
1998 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02001999
2000 return eval_type_str(val, arg->typecast.type, pointer);
2001}
2002
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002003static int arg_num_eval(struct print_arg *arg, long long *val)
Steven Rostedtf7d82352012-04-06 00:47:53 +02002004{
2005 long long left, right;
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002006 int ret = 1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002007
2008 switch (arg->type) {
2009 case PRINT_ATOM:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002010 *val = strtoll(arg->atom.atom, NULL, 0);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002011 break;
2012 case PRINT_TYPE:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002013 ret = arg_num_eval(arg->typecast.item, val);
2014 if (!ret)
2015 break;
2016 *val = eval_type(*val, arg, 0);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002017 break;
2018 case PRINT_OP:
2019 switch (arg->op.op[0]) {
2020 case '|':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002021 ret = arg_num_eval(arg->op.left, &left);
2022 if (!ret)
2023 break;
2024 ret = arg_num_eval(arg->op.right, &right);
2025 if (!ret)
2026 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002027 if (arg->op.op[1])
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002028 *val = left || right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002029 else
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002030 *val = left | right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002031 break;
2032 case '&':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002033 ret = arg_num_eval(arg->op.left, &left);
2034 if (!ret)
2035 break;
2036 ret = arg_num_eval(arg->op.right, &right);
2037 if (!ret)
2038 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002039 if (arg->op.op[1])
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002040 *val = left && right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002041 else
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002042 *val = left & right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002043 break;
2044 case '<':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002045 ret = arg_num_eval(arg->op.left, &left);
2046 if (!ret)
2047 break;
2048 ret = arg_num_eval(arg->op.right, &right);
2049 if (!ret)
2050 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002051 switch (arg->op.op[1]) {
2052 case 0:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002053 *val = left < right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002054 break;
2055 case '<':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002056 *val = left << right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002057 break;
2058 case '=':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002059 *val = left <= right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002060 break;
2061 default:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002062 do_warning("unknown op '%s'", arg->op.op);
2063 ret = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002064 }
2065 break;
2066 case '>':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002067 ret = arg_num_eval(arg->op.left, &left);
2068 if (!ret)
2069 break;
2070 ret = arg_num_eval(arg->op.right, &right);
2071 if (!ret)
2072 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002073 switch (arg->op.op[1]) {
2074 case 0:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002075 *val = left > right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002076 break;
2077 case '>':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002078 *val = left >> right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002079 break;
2080 case '=':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002081 *val = left >= right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002082 break;
2083 default:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002084 do_warning("unknown op '%s'", arg->op.op);
2085 ret = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002086 }
2087 break;
2088 case '=':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002089 ret = arg_num_eval(arg->op.left, &left);
2090 if (!ret)
2091 break;
2092 ret = arg_num_eval(arg->op.right, &right);
2093 if (!ret)
2094 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002095
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002096 if (arg->op.op[1] != '=') {
2097 do_warning("unknown op '%s'", arg->op.op);
2098 ret = 0;
2099 } else
2100 *val = left == right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002101 break;
2102 case '!':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002103 ret = arg_num_eval(arg->op.left, &left);
2104 if (!ret)
2105 break;
2106 ret = arg_num_eval(arg->op.right, &right);
2107 if (!ret)
2108 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002109
2110 switch (arg->op.op[1]) {
2111 case '=':
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002112 *val = left != right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002113 break;
2114 default:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002115 do_warning("unknown op '%s'", arg->op.op);
2116 ret = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002117 }
2118 break;
2119 case '-':
2120 /* check for negative */
2121 if (arg->op.left->type == PRINT_NULL)
2122 left = 0;
2123 else
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002124 ret = arg_num_eval(arg->op.left, &left);
2125 if (!ret)
2126 break;
2127 ret = arg_num_eval(arg->op.right, &right);
2128 if (!ret)
2129 break;
2130 *val = left - right;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002131 break;
Vaibhav Nagarnaikb4828592012-04-06 00:48:03 +02002132 case '+':
2133 if (arg->op.left->type == PRINT_NULL)
2134 left = 0;
2135 else
2136 ret = arg_num_eval(arg->op.left, &left);
2137 if (!ret)
2138 break;
2139 ret = arg_num_eval(arg->op.right, &right);
2140 if (!ret)
2141 break;
2142 *val = left + right;
2143 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002144 default:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002145 do_warning("unknown op '%s'", arg->op.op);
2146 ret = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002147 }
2148 break;
2149
2150 case PRINT_NULL:
2151 case PRINT_FIELD ... PRINT_SYMBOL:
2152 case PRINT_STRING:
2153 case PRINT_BSTRING:
2154 default:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002155 do_warning("invalid eval type %d", arg->type);
2156 ret = 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002157
2158 }
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002159 return ret;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002160}
2161
2162static char *arg_eval (struct print_arg *arg)
2163{
2164 long long val;
2165 static char buf[20];
2166
2167 switch (arg->type) {
2168 case PRINT_ATOM:
2169 return arg->atom.atom;
2170 case PRINT_TYPE:
2171 return arg_eval(arg->typecast.item);
2172 case PRINT_OP:
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002173 if (!arg_num_eval(arg, &val))
2174 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002175 sprintf(buf, "%lld", val);
2176 return buf;
2177
2178 case PRINT_NULL:
2179 case PRINT_FIELD ... PRINT_SYMBOL:
2180 case PRINT_STRING:
2181 case PRINT_BSTRING:
2182 default:
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03002183 do_warning("invalid eval type %d", arg->type);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002184 break;
2185 }
2186
2187 return NULL;
2188}
2189
2190static enum event_type
2191process_fields(struct event_format *event, struct print_flag_sym **list, char **tok)
2192{
2193 enum event_type type;
2194 struct print_arg *arg = NULL;
2195 struct print_flag_sym *field;
2196 char *token = *tok;
2197 char *value;
2198
2199 do {
2200 free_token(token);
2201 type = read_token_item(&token);
2202 if (test_type_token(type, token, EVENT_OP, "{"))
2203 break;
2204
2205 arg = alloc_arg();
2206
2207 free_token(token);
2208 type = process_arg(event, arg, &token);
Stefan Hajnoczi00b9da72012-05-23 11:36:42 +09002209
2210 if (type == EVENT_OP)
2211 type = process_op(event, arg, &token);
2212
2213 if (type == EVENT_ERROR)
2214 goto out_free;
2215
Steven Rostedtf7d82352012-04-06 00:47:53 +02002216 if (test_type_token(type, token, EVENT_DELIM, ","))
2217 goto out_free;
2218
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -03002219 field = calloc(1, sizeof(*field));
2220 if (!field)
2221 goto out_free;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002222
2223 value = arg_eval(arg);
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002224 if (value == NULL)
Namhyung Kimf8c49d22012-09-19 15:58:43 +09002225 goto out_free_field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002226 field->value = strdup(value);
Namhyung Kimca638582012-04-09 11:54:31 +09002227 if (field->value == NULL)
Namhyung Kimf8c49d22012-09-19 15:58:43 +09002228 goto out_free_field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002229
2230 free_arg(arg);
2231 arg = alloc_arg();
2232
2233 free_token(token);
2234 type = process_arg(event, arg, &token);
2235 if (test_type_token(type, token, EVENT_OP, "}"))
Namhyung Kimf8c49d22012-09-19 15:58:43 +09002236 goto out_free_field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002237
2238 value = arg_eval(arg);
Vaibhav Nagarnaikd69afed52012-04-06 00:48:00 +02002239 if (value == NULL)
Namhyung Kimf8c49d22012-09-19 15:58:43 +09002240 goto out_free_field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002241 field->str = strdup(value);
Namhyung Kimca638582012-04-09 11:54:31 +09002242 if (field->str == NULL)
Namhyung Kimf8c49d22012-09-19 15:58:43 +09002243 goto out_free_field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002244 free_arg(arg);
2245 arg = NULL;
2246
2247 *list = field;
2248 list = &field->next;
2249
2250 free_token(token);
2251 type = read_token_item(&token);
2252 } while (type == EVENT_DELIM && strcmp(token, ",") == 0);
2253
2254 *tok = token;
2255 return type;
2256
Namhyung Kimf8c49d22012-09-19 15:58:43 +09002257out_free_field:
2258 free_flag_sym(field);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002259out_free:
2260 free_arg(arg);
2261 free_token(token);
2262 *tok = NULL;
2263
2264 return EVENT_ERROR;
2265}
2266
2267static enum event_type
2268process_flags(struct event_format *event, struct print_arg *arg, char **tok)
2269{
2270 struct print_arg *field;
2271 enum event_type type;
2272 char *token;
2273
2274 memset(arg, 0, sizeof(*arg));
2275 arg->type = PRINT_FLAGS;
2276
2277 field = alloc_arg();
2278
2279 type = process_arg(event, field, &token);
2280
2281 /* Handle operations in the first argument */
2282 while (type == EVENT_OP)
2283 type = process_op(event, field, &token);
2284
2285 if (test_type_token(type, token, EVENT_DELIM, ","))
Namhyung Kim70d93042012-09-19 15:58:44 +09002286 goto out_free_field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002287 free_token(token);
2288
2289 arg->flags.field = field;
2290
2291 type = read_token_item(&token);
2292 if (event_item_type(type)) {
2293 arg->flags.delim = token;
2294 type = read_token_item(&token);
2295 }
2296
2297 if (test_type_token(type, token, EVENT_DELIM, ","))
2298 goto out_free;
2299
2300 type = process_fields(event, &arg->flags.flags, &token);
2301 if (test_type_token(type, token, EVENT_DELIM, ")"))
2302 goto out_free;
2303
2304 free_token(token);
2305 type = read_token_item(tok);
2306 return type;
2307
Namhyung Kim70d93042012-09-19 15:58:44 +09002308out_free_field:
2309 free_arg(field);
2310out_free:
Steven Rostedtf7d82352012-04-06 00:47:53 +02002311 free_token(token);
2312 *tok = NULL;
2313 return EVENT_ERROR;
2314}
2315
2316static enum event_type
2317process_symbols(struct event_format *event, struct print_arg *arg, char **tok)
2318{
2319 struct print_arg *field;
2320 enum event_type type;
2321 char *token;
2322
2323 memset(arg, 0, sizeof(*arg));
2324 arg->type = PRINT_SYMBOL;
2325
2326 field = alloc_arg();
2327
2328 type = process_arg(event, field, &token);
2329 if (test_type_token(type, token, EVENT_DELIM, ","))
Namhyung Kim70d93042012-09-19 15:58:44 +09002330 goto out_free_field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002331
2332 arg->symbol.field = field;
2333
2334 type = process_fields(event, &arg->symbol.symbols, &token);
2335 if (test_type_token(type, token, EVENT_DELIM, ")"))
2336 goto out_free;
2337
2338 free_token(token);
2339 type = read_token_item(tok);
2340 return type;
2341
Namhyung Kim70d93042012-09-19 15:58:44 +09002342out_free_field:
2343 free_arg(field);
2344out_free:
Steven Rostedtf7d82352012-04-06 00:47:53 +02002345 free_token(token);
2346 *tok = NULL;
2347 return EVENT_ERROR;
2348}
2349
2350static enum event_type
Namhyung Kime080e6f2012-06-27 09:41:41 +09002351process_hex(struct event_format *event, struct print_arg *arg, char **tok)
2352{
2353 struct print_arg *field;
2354 enum event_type type;
2355 char *token;
2356
2357 memset(arg, 0, sizeof(*arg));
2358 arg->type = PRINT_HEX;
2359
2360 field = alloc_arg();
2361 type = process_arg(event, field, &token);
2362
2363 if (test_type_token(type, token, EVENT_DELIM, ","))
2364 goto out_free;
2365
2366 arg->hex.field = field;
2367
2368 free_token(token);
2369
2370 field = alloc_arg();
2371 type = process_arg(event, field, &token);
2372
2373 if (test_type_token(type, token, EVENT_DELIM, ")"))
2374 goto out_free;
2375
2376 arg->hex.size = field;
2377
2378 free_token(token);
2379 type = read_token_item(tok);
2380 return type;
2381
2382 out_free:
2383 free_arg(field);
2384 free_token(token);
2385 *tok = NULL;
2386 return EVENT_ERROR;
2387}
2388
2389static enum event_type
Steven Rostedtf7d82352012-04-06 00:47:53 +02002390process_dynamic_array(struct event_format *event, struct print_arg *arg, char **tok)
2391{
2392 struct format_field *field;
2393 enum event_type type;
2394 char *token;
2395
2396 memset(arg, 0, sizeof(*arg));
2397 arg->type = PRINT_DYNAMIC_ARRAY;
2398
2399 /*
2400 * The item within the parenthesis is another field that holds
2401 * the index into where the array starts.
2402 */
2403 type = read_token(&token);
2404 *tok = token;
2405 if (type != EVENT_ITEM)
2406 goto out_free;
2407
2408 /* Find the field */
2409
2410 field = pevent_find_field(event, token);
2411 if (!field)
2412 goto out_free;
2413
2414 arg->dynarray.field = field;
2415 arg->dynarray.index = 0;
2416
2417 if (read_expected(EVENT_DELIM, ")") < 0)
2418 goto out_free;
2419
2420 free_token(token);
2421 type = read_token_item(&token);
2422 *tok = token;
2423 if (type != EVENT_OP || strcmp(token, "[") != 0)
2424 return type;
2425
2426 free_token(token);
2427 arg = alloc_arg();
2428 type = process_arg(event, arg, &token);
2429 if (type == EVENT_ERROR)
Namhyung Kimb3511d02012-05-23 11:36:50 +09002430 goto out_free_arg;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002431
2432 if (!test_type_token(type, token, EVENT_OP, "]"))
Namhyung Kimb3511d02012-05-23 11:36:50 +09002433 goto out_free_arg;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002434
2435 free_token(token);
2436 type = read_token_item(tok);
2437 return type;
2438
Namhyung Kimb3511d02012-05-23 11:36:50 +09002439 out_free_arg:
2440 free_arg(arg);
Steven Rostedtf7d82352012-04-06 00:47:53 +02002441 out_free:
Steven Rostedtf7d82352012-04-06 00:47:53 +02002442 free_token(token);
2443 *tok = NULL;
2444 return EVENT_ERROR;
2445}
2446
2447static enum event_type
2448process_paren(struct event_format *event, struct print_arg *arg, char **tok)
2449{
2450 struct print_arg *item_arg;
2451 enum event_type type;
2452 char *token;
2453
2454 type = process_arg(event, arg, &token);
2455
2456 if (type == EVENT_ERROR)
2457 goto out_free;
2458
2459 if (type == EVENT_OP)
2460 type = process_op(event, arg, &token);
2461
2462 if (type == EVENT_ERROR)
2463 goto out_free;
2464
2465 if (test_type_token(type, token, EVENT_DELIM, ")"))
2466 goto out_free;
2467
2468 free_token(token);
2469 type = read_token_item(&token);
2470
2471 /*
2472 * If the next token is an item or another open paren, then
2473 * this was a typecast.
2474 */
2475 if (event_item_type(type) ||
2476 (type == EVENT_DELIM && strcmp(token, "(") == 0)) {
2477
2478 /* make this a typecast and contine */
2479
2480 /* prevous must be an atom */
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03002481 if (arg->type != PRINT_ATOM) {
2482 do_warning("previous needed to be PRINT_ATOM");
2483 goto out_free;
2484 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02002485
2486 item_arg = alloc_arg();
2487
2488 arg->type = PRINT_TYPE;
2489 arg->typecast.type = arg->atom.atom;
2490 arg->typecast.item = item_arg;
2491 type = process_arg_token(event, item_arg, &token, type);
2492
2493 }
2494
2495 *tok = token;
2496 return type;
2497
2498 out_free:
2499 free_token(token);
2500 *tok = NULL;
2501 return EVENT_ERROR;
2502}
2503
2504
2505static enum event_type
Irina Tirdea1d037ca2012-09-11 01:15:03 +03002506process_str(struct event_format *event __maybe_unused, struct print_arg *arg,
2507 char **tok)
Steven Rostedtf7d82352012-04-06 00:47:53 +02002508{
2509 enum event_type type;
2510 char *token;
2511
2512 if (read_expect_type(EVENT_ITEM, &token) < 0)
2513 goto out_free;
2514
2515 arg->type = PRINT_STRING;
2516 arg->string.string = token;
2517 arg->string.offset = -1;
2518
2519 if (read_expected(EVENT_DELIM, ")") < 0)
2520 goto out_err;
2521
2522 type = read_token(&token);
2523 *tok = token;
2524
2525 return type;
2526
2527 out_free:
2528 free_token(token);
2529 out_err:
2530 *tok = NULL;
2531 return EVENT_ERROR;
2532}
2533
2534static struct pevent_function_handler *
2535find_func_handler(struct pevent *pevent, char *func_name)
2536{
2537 struct pevent_function_handler *func;
2538
2539 for (func = pevent->func_handlers; func; func = func->next) {
2540 if (strcmp(func->name, func_name) == 0)
2541 break;
2542 }
2543
2544 return func;
2545}
2546
2547static void remove_func_handler(struct pevent *pevent, char *func_name)
2548{
2549 struct pevent_function_handler *func;
2550 struct pevent_function_handler **next;
2551
2552 next = &pevent->func_handlers;
2553 while ((func = *next)) {
2554 if (strcmp(func->name, func_name) == 0) {
2555 *next = func->next;
2556 free_func_handle(func);
2557 break;
2558 }
2559 next = &func->next;
2560 }
2561}
2562
2563static enum event_type
2564process_func_handler(struct event_format *event, struct pevent_function_handler *func,
2565 struct print_arg *arg, char **tok)
2566{
2567 struct print_arg **next_arg;
2568 struct print_arg *farg;
2569 enum event_type type;
2570 char *token;
2571 char *test;
2572 int i;
2573
2574 arg->type = PRINT_FUNC;
2575 arg->func.func = func;
2576
2577 *tok = NULL;
2578
2579 next_arg = &(arg->func.args);
2580 for (i = 0; i < func->nr_args; i++) {
2581 farg = alloc_arg();
2582 type = process_arg(event, farg, &token);
2583 if (i < (func->nr_args - 1))
2584 test = ",";
2585 else
2586 test = ")";
2587
2588 if (test_type_token(type, token, EVENT_DELIM, test)) {
2589 free_arg(farg);
2590 free_token(token);
2591 return EVENT_ERROR;
2592 }
2593
2594 *next_arg = farg;
2595 next_arg = &(farg->next);
2596 free_token(token);
2597 }
2598
2599 type = read_token(&token);
2600 *tok = token;
2601
2602 return type;
2603}
2604
2605static enum event_type
2606process_function(struct event_format *event, struct print_arg *arg,
2607 char *token, char **tok)
2608{
2609 struct pevent_function_handler *func;
2610
2611 if (strcmp(token, "__print_flags") == 0) {
2612 free_token(token);
Tom Zanussi5205aec2012-04-06 00:47:58 +02002613 is_flag_field = 1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002614 return process_flags(event, arg, tok);
2615 }
2616 if (strcmp(token, "__print_symbolic") == 0) {
2617 free_token(token);
Tom Zanussi5205aec2012-04-06 00:47:58 +02002618 is_symbolic_field = 1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002619 return process_symbols(event, arg, tok);
2620 }
Namhyung Kime080e6f2012-06-27 09:41:41 +09002621 if (strcmp(token, "__print_hex") == 0) {
2622 free_token(token);
2623 return process_hex(event, arg, tok);
2624 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02002625 if (strcmp(token, "__get_str") == 0) {
2626 free_token(token);
2627 return process_str(event, arg, tok);
2628 }
2629 if (strcmp(token, "__get_dynamic_array") == 0) {
2630 free_token(token);
2631 return process_dynamic_array(event, arg, tok);
2632 }
2633
2634 func = find_func_handler(event->pevent, token);
2635 if (func) {
2636 free_token(token);
2637 return process_func_handler(event, func, arg, tok);
2638 }
2639
2640 do_warning("function %s not defined", token);
2641 free_token(token);
2642 return EVENT_ERROR;
2643}
2644
2645static enum event_type
2646process_arg_token(struct event_format *event, struct print_arg *arg,
2647 char **tok, enum event_type type)
2648{
2649 char *token;
2650 char *atom;
2651
2652 token = *tok;
2653
2654 switch (type) {
2655 case EVENT_ITEM:
2656 if (strcmp(token, "REC") == 0) {
2657 free_token(token);
2658 type = process_entry(event, arg, &token);
2659 break;
2660 }
2661 atom = token;
2662 /* test the next token */
2663 type = read_token_item(&token);
2664
2665 /*
2666 * If the next token is a parenthesis, then this
2667 * is a function.
2668 */
2669 if (type == EVENT_DELIM && strcmp(token, "(") == 0) {
2670 free_token(token);
2671 token = NULL;
2672 /* this will free atom. */
2673 type = process_function(event, arg, atom, &token);
2674 break;
2675 }
2676 /* atoms can be more than one token long */
2677 while (type == EVENT_ITEM) {
Namhyung Kimd2864472012-04-09 11:54:33 +09002678 char *new_atom;
2679 new_atom = realloc(atom,
2680 strlen(atom) + strlen(token) + 2);
2681 if (!new_atom) {
2682 free(atom);
2683 *tok = NULL;
2684 free_token(token);
2685 return EVENT_ERROR;
2686 }
2687 atom = new_atom;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002688 strcat(atom, " ");
2689 strcat(atom, token);
2690 free_token(token);
2691 type = read_token_item(&token);
2692 }
2693
2694 arg->type = PRINT_ATOM;
2695 arg->atom.atom = atom;
2696 break;
2697
2698 case EVENT_DQUOTE:
2699 case EVENT_SQUOTE:
2700 arg->type = PRINT_ATOM;
2701 arg->atom.atom = token;
2702 type = read_token_item(&token);
2703 break;
2704 case EVENT_DELIM:
2705 if (strcmp(token, "(") == 0) {
2706 free_token(token);
2707 type = process_paren(event, arg, &token);
2708 break;
2709 }
2710 case EVENT_OP:
2711 /* handle single ops */
2712 arg->type = PRINT_OP;
2713 arg->op.op = token;
2714 arg->op.left = NULL;
2715 type = process_op(event, arg, &token);
2716
2717 /* On error, the op is freed */
2718 if (type == EVENT_ERROR)
2719 arg->op.op = NULL;
2720
2721 /* return error type if errored */
2722 break;
2723
2724 case EVENT_ERROR ... EVENT_NEWLINE:
2725 default:
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03002726 do_warning("unexpected type %d", type);
2727 return EVENT_ERROR;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002728 }
2729 *tok = token;
2730
2731 return type;
2732}
2733
2734static int event_read_print_args(struct event_format *event, struct print_arg **list)
2735{
2736 enum event_type type = EVENT_ERROR;
2737 struct print_arg *arg;
2738 char *token;
2739 int args = 0;
2740
2741 do {
2742 if (type == EVENT_NEWLINE) {
2743 type = read_token_item(&token);
2744 continue;
2745 }
2746
2747 arg = alloc_arg();
2748
2749 type = process_arg(event, arg, &token);
2750
2751 if (type == EVENT_ERROR) {
2752 free_token(token);
2753 free_arg(arg);
2754 return -1;
2755 }
2756
2757 *list = arg;
2758 args++;
2759
2760 if (type == EVENT_OP) {
2761 type = process_op(event, arg, &token);
2762 free_token(token);
2763 if (type == EVENT_ERROR) {
2764 *list = NULL;
2765 free_arg(arg);
2766 return -1;
2767 }
2768 list = &arg->next;
2769 continue;
2770 }
2771
2772 if (type == EVENT_DELIM && strcmp(token, ",") == 0) {
2773 free_token(token);
2774 *list = arg;
2775 list = &arg->next;
2776 continue;
2777 }
2778 break;
2779 } while (type != EVENT_NONE);
2780
2781 if (type != EVENT_NONE && type != EVENT_ERROR)
2782 free_token(token);
2783
2784 return args;
2785}
2786
2787static int event_read_print(struct event_format *event)
2788{
2789 enum event_type type;
2790 char *token;
2791 int ret;
2792
2793 if (read_expected_item(EVENT_ITEM, "print") < 0)
2794 return -1;
2795
2796 if (read_expected(EVENT_ITEM, "fmt") < 0)
2797 return -1;
2798
2799 if (read_expected(EVENT_OP, ":") < 0)
2800 return -1;
2801
2802 if (read_expect_type(EVENT_DQUOTE, &token) < 0)
2803 goto fail;
2804
2805 concat:
2806 event->print_fmt.format = token;
2807 event->print_fmt.args = NULL;
2808
2809 /* ok to have no arg */
2810 type = read_token_item(&token);
2811
2812 if (type == EVENT_NONE)
2813 return 0;
2814
2815 /* Handle concatenation of print lines */
2816 if (type == EVENT_DQUOTE) {
2817 char *cat;
2818
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03002819 if (asprintf(&cat, "%s%s", event->print_fmt.format, token) < 0)
2820 goto fail;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002821 free_token(token);
2822 free_token(event->print_fmt.format);
2823 event->print_fmt.format = NULL;
2824 token = cat;
2825 goto concat;
2826 }
2827
2828 if (test_type_token(type, token, EVENT_DELIM, ","))
2829 goto fail;
2830
2831 free_token(token);
2832
2833 ret = event_read_print_args(event, &event->print_fmt.args);
2834 if (ret < 0)
2835 return -1;
2836
2837 return ret;
2838
2839 fail:
2840 free_token(token);
2841 return -1;
2842}
2843
2844/**
2845 * pevent_find_common_field - return a common field by event
2846 * @event: handle for the event
2847 * @name: the name of the common field to return
2848 *
2849 * Returns a common field from the event by the given @name.
2850 * This only searchs the common fields and not all field.
2851 */
2852struct format_field *
2853pevent_find_common_field(struct event_format *event, const char *name)
2854{
2855 struct format_field *format;
2856
2857 for (format = event->format.common_fields;
2858 format; format = format->next) {
2859 if (strcmp(format->name, name) == 0)
2860 break;
2861 }
2862
2863 return format;
2864}
2865
2866/**
2867 * pevent_find_field - find a non-common field
2868 * @event: handle for the event
2869 * @name: the name of the non-common field
2870 *
2871 * Returns a non-common field by the given @name.
2872 * This does not search common fields.
2873 */
2874struct format_field *
2875pevent_find_field(struct event_format *event, const char *name)
2876{
2877 struct format_field *format;
2878
2879 for (format = event->format.fields;
2880 format; format = format->next) {
2881 if (strcmp(format->name, name) == 0)
2882 break;
2883 }
2884
2885 return format;
2886}
2887
2888/**
2889 * pevent_find_any_field - find any field by name
2890 * @event: handle for the event
2891 * @name: the name of the field
2892 *
2893 * Returns a field by the given @name.
2894 * This searchs the common field names first, then
2895 * the non-common ones if a common one was not found.
2896 */
2897struct format_field *
2898pevent_find_any_field(struct event_format *event, const char *name)
2899{
2900 struct format_field *format;
2901
2902 format = pevent_find_common_field(event, name);
2903 if (format)
2904 return format;
2905 return pevent_find_field(event, name);
2906}
2907
2908/**
2909 * pevent_read_number - read a number from data
2910 * @pevent: handle for the pevent
2911 * @ptr: the raw data
2912 * @size: the size of the data that holds the number
2913 *
2914 * Returns the number (converted to host) from the
2915 * raw data.
2916 */
2917unsigned long long pevent_read_number(struct pevent *pevent,
2918 const void *ptr, int size)
2919{
2920 switch (size) {
2921 case 1:
2922 return *(unsigned char *)ptr;
2923 case 2:
2924 return data2host2(pevent, ptr);
2925 case 4:
2926 return data2host4(pevent, ptr);
2927 case 8:
2928 return data2host8(pevent, ptr);
2929 default:
2930 /* BUG! */
2931 return 0;
2932 }
2933}
2934
2935/**
2936 * pevent_read_number_field - read a number from data
2937 * @field: a handle to the field
2938 * @data: the raw data to read
2939 * @value: the value to place the number in
2940 *
2941 * Reads raw data according to a field offset and size,
2942 * and translates it into @value.
2943 *
2944 * Returns 0 on success, -1 otherwise.
2945 */
2946int pevent_read_number_field(struct format_field *field, const void *data,
2947 unsigned long long *value)
2948{
2949 if (!field)
2950 return -1;
2951 switch (field->size) {
2952 case 1:
2953 case 2:
2954 case 4:
2955 case 8:
2956 *value = pevent_read_number(field->event->pevent,
2957 data + field->offset, field->size);
2958 return 0;
2959 default:
2960 return -1;
2961 }
2962}
2963
2964static int get_common_info(struct pevent *pevent,
2965 const char *type, int *offset, int *size)
2966{
2967 struct event_format *event;
2968 struct format_field *field;
2969
2970 /*
2971 * All events should have the same common elements.
2972 * Pick any event to find where the type is;
2973 */
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03002974 if (!pevent->events) {
2975 do_warning("no event_list!");
2976 return -1;
2977 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02002978
2979 event = pevent->events[0];
2980 field = pevent_find_common_field(event, type);
2981 if (!field)
Steven Rostedt0866a972012-05-22 14:52:40 +09002982 return -1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02002983
2984 *offset = field->offset;
2985 *size = field->size;
2986
2987 return 0;
2988}
2989
2990static int __parse_common(struct pevent *pevent, void *data,
2991 int *size, int *offset, const char *name)
2992{
2993 int ret;
2994
2995 if (!*size) {
2996 ret = get_common_info(pevent, name, offset, size);
2997 if (ret < 0)
2998 return ret;
2999 }
3000 return pevent_read_number(pevent, data + *offset, *size);
3001}
3002
3003static int trace_parse_common_type(struct pevent *pevent, void *data)
3004{
3005 return __parse_common(pevent, data,
3006 &pevent->type_size, &pevent->type_offset,
3007 "common_type");
3008}
3009
3010static int parse_common_pid(struct pevent *pevent, void *data)
3011{
3012 return __parse_common(pevent, data,
3013 &pevent->pid_size, &pevent->pid_offset,
3014 "common_pid");
3015}
3016
3017static int parse_common_pc(struct pevent *pevent, void *data)
3018{
3019 return __parse_common(pevent, data,
3020 &pevent->pc_size, &pevent->pc_offset,
3021 "common_preempt_count");
3022}
3023
3024static int parse_common_flags(struct pevent *pevent, void *data)
3025{
3026 return __parse_common(pevent, data,
3027 &pevent->flags_size, &pevent->flags_offset,
3028 "common_flags");
3029}
3030
3031static int parse_common_lock_depth(struct pevent *pevent, void *data)
3032{
Steven Rostedt0866a972012-05-22 14:52:40 +09003033 return __parse_common(pevent, data,
3034 &pevent->ld_size, &pevent->ld_offset,
3035 "common_lock_depth");
3036}
Steven Rostedtf7d82352012-04-06 00:47:53 +02003037
Steven Rostedt0866a972012-05-22 14:52:40 +09003038static int parse_common_migrate_disable(struct pevent *pevent, void *data)
3039{
3040 return __parse_common(pevent, data,
3041 &pevent->ld_size, &pevent->ld_offset,
3042 "common_migrate_disable");
Steven Rostedtf7d82352012-04-06 00:47:53 +02003043}
3044
3045static int events_id_cmp(const void *a, const void *b);
3046
3047/**
3048 * pevent_find_event - find an event by given id
3049 * @pevent: a handle to the pevent
3050 * @id: the id of the event
3051 *
3052 * Returns an event that has a given @id.
3053 */
3054struct event_format *pevent_find_event(struct pevent *pevent, int id)
3055{
3056 struct event_format **eventptr;
3057 struct event_format key;
3058 struct event_format *pkey = &key;
3059
3060 /* Check cache first */
3061 if (pevent->last_event && pevent->last_event->id == id)
3062 return pevent->last_event;
3063
3064 key.id = id;
3065
3066 eventptr = bsearch(&pkey, pevent->events, pevent->nr_events,
3067 sizeof(*pevent->events), events_id_cmp);
3068
3069 if (eventptr) {
3070 pevent->last_event = *eventptr;
3071 return *eventptr;
3072 }
3073
3074 return NULL;
3075}
3076
3077/**
3078 * pevent_find_event_by_name - find an event by given name
3079 * @pevent: a handle to the pevent
3080 * @sys: the system name to search for
3081 * @name: the name of the event to search for
3082 *
3083 * This returns an event with a given @name and under the system
3084 * @sys. If @sys is NULL the first event with @name is returned.
3085 */
3086struct event_format *
3087pevent_find_event_by_name(struct pevent *pevent,
3088 const char *sys, const char *name)
3089{
3090 struct event_format *event;
3091 int i;
3092
3093 if (pevent->last_event &&
3094 strcmp(pevent->last_event->name, name) == 0 &&
3095 (!sys || strcmp(pevent->last_event->system, sys) == 0))
3096 return pevent->last_event;
3097
3098 for (i = 0; i < pevent->nr_events; i++) {
3099 event = pevent->events[i];
3100 if (strcmp(event->name, name) == 0) {
3101 if (!sys)
3102 break;
3103 if (strcmp(event->system, sys) == 0)
3104 break;
3105 }
3106 }
3107 if (i == pevent->nr_events)
3108 event = NULL;
3109
3110 pevent->last_event = event;
3111 return event;
3112}
3113
3114static unsigned long long
3115eval_num_arg(void *data, int size, struct event_format *event, struct print_arg *arg)
3116{
3117 struct pevent *pevent = event->pevent;
3118 unsigned long long val = 0;
3119 unsigned long long left, right;
3120 struct print_arg *typearg = NULL;
3121 struct print_arg *larg;
3122 unsigned long offset;
3123 unsigned int field_size;
3124
3125 switch (arg->type) {
3126 case PRINT_NULL:
3127 /* ?? */
3128 return 0;
3129 case PRINT_ATOM:
3130 return strtoull(arg->atom.atom, NULL, 0);
3131 case PRINT_FIELD:
3132 if (!arg->field.field) {
3133 arg->field.field = pevent_find_any_field(event, arg->field.name);
3134 if (!arg->field.field)
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003135 goto out_warning_field;
3136
Steven Rostedtf7d82352012-04-06 00:47:53 +02003137 }
3138 /* must be a number */
3139 val = pevent_read_number(pevent, data + arg->field.field->offset,
3140 arg->field.field->size);
3141 break;
3142 case PRINT_FLAGS:
3143 case PRINT_SYMBOL:
Namhyung Kime080e6f2012-06-27 09:41:41 +09003144 case PRINT_HEX:
Steven Rostedtf7d82352012-04-06 00:47:53 +02003145 break;
3146 case PRINT_TYPE:
3147 val = eval_num_arg(data, size, event, arg->typecast.item);
3148 return eval_type(val, arg, 0);
3149 case PRINT_STRING:
3150 case PRINT_BSTRING:
3151 return 0;
3152 case PRINT_FUNC: {
3153 struct trace_seq s;
3154 trace_seq_init(&s);
3155 val = process_defined_func(&s, data, size, event, arg);
3156 trace_seq_destroy(&s);
3157 return val;
3158 }
3159 case PRINT_OP:
3160 if (strcmp(arg->op.op, "[") == 0) {
3161 /*
3162 * Arrays are special, since we don't want
3163 * to read the arg as is.
3164 */
3165 right = eval_num_arg(data, size, event, arg->op.right);
3166
3167 /* handle typecasts */
3168 larg = arg->op.left;
3169 while (larg->type == PRINT_TYPE) {
3170 if (!typearg)
3171 typearg = larg;
3172 larg = larg->typecast.item;
3173 }
3174
3175 /* Default to long size */
3176 field_size = pevent->long_size;
3177
3178 switch (larg->type) {
3179 case PRINT_DYNAMIC_ARRAY:
3180 offset = pevent_read_number(pevent,
3181 data + larg->dynarray.field->offset,
3182 larg->dynarray.field->size);
3183 if (larg->dynarray.field->elementsize)
3184 field_size = larg->dynarray.field->elementsize;
3185 /*
3186 * The actual length of the dynamic array is stored
3187 * in the top half of the field, and the offset
3188 * is in the bottom half of the 32 bit field.
3189 */
3190 offset &= 0xffff;
3191 offset += right;
3192 break;
3193 case PRINT_FIELD:
3194 if (!larg->field.field) {
3195 larg->field.field =
3196 pevent_find_any_field(event, larg->field.name);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003197 if (!larg->field.field) {
3198 arg = larg;
3199 goto out_warning_field;
3200 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003201 }
3202 field_size = larg->field.field->elementsize;
3203 offset = larg->field.field->offset +
3204 right * larg->field.field->elementsize;
3205 break;
3206 default:
3207 goto default_op; /* oops, all bets off */
3208 }
3209 val = pevent_read_number(pevent,
3210 data + offset, field_size);
3211 if (typearg)
3212 val = eval_type(val, typearg, 1);
3213 break;
3214 } else if (strcmp(arg->op.op, "?") == 0) {
3215 left = eval_num_arg(data, size, event, arg->op.left);
3216 arg = arg->op.right;
3217 if (left)
3218 val = eval_num_arg(data, size, event, arg->op.left);
3219 else
3220 val = eval_num_arg(data, size, event, arg->op.right);
3221 break;
3222 }
3223 default_op:
3224 left = eval_num_arg(data, size, event, arg->op.left);
3225 right = eval_num_arg(data, size, event, arg->op.right);
3226 switch (arg->op.op[0]) {
3227 case '!':
3228 switch (arg->op.op[1]) {
3229 case 0:
3230 val = !right;
3231 break;
3232 case '=':
3233 val = left != right;
3234 break;
3235 default:
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003236 goto out_warning_op;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003237 }
3238 break;
3239 case '~':
3240 val = ~right;
3241 break;
3242 case '|':
3243 if (arg->op.op[1])
3244 val = left || right;
3245 else
3246 val = left | right;
3247 break;
3248 case '&':
3249 if (arg->op.op[1])
3250 val = left && right;
3251 else
3252 val = left & right;
3253 break;
3254 case '<':
3255 switch (arg->op.op[1]) {
3256 case 0:
3257 val = left < right;
3258 break;
3259 case '<':
3260 val = left << right;
3261 break;
3262 case '=':
3263 val = left <= right;
3264 break;
3265 default:
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003266 goto out_warning_op;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003267 }
3268 break;
3269 case '>':
3270 switch (arg->op.op[1]) {
3271 case 0:
3272 val = left > right;
3273 break;
3274 case '>':
3275 val = left >> right;
3276 break;
3277 case '=':
3278 val = left >= right;
3279 break;
3280 default:
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003281 goto out_warning_op;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003282 }
3283 break;
3284 case '=':
3285 if (arg->op.op[1] != '=')
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003286 goto out_warning_op;
3287
Steven Rostedtf7d82352012-04-06 00:47:53 +02003288 val = left == right;
3289 break;
3290 case '-':
3291 val = left - right;
3292 break;
3293 case '+':
3294 val = left + right;
3295 break;
Steven Rostedt2e7a5fc2012-04-06 00:48:04 +02003296 case '/':
3297 val = left / right;
3298 break;
3299 case '*':
3300 val = left * right;
3301 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003302 default:
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003303 goto out_warning_op;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003304 }
3305 break;
3306 default: /* not sure what to do there */
3307 return 0;
3308 }
3309 return val;
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003310
3311out_warning_op:
3312 do_warning("%s: unknown op '%s'", __func__, arg->op.op);
3313 return 0;
3314
3315out_warning_field:
3316 do_warning("%s: field %s not found", __func__, arg->field.name);
3317 return 0;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003318}
3319
3320struct flag {
3321 const char *name;
3322 unsigned long long value;
3323};
3324
3325static const struct flag flags[] = {
3326 { "HI_SOFTIRQ", 0 },
3327 { "TIMER_SOFTIRQ", 1 },
3328 { "NET_TX_SOFTIRQ", 2 },
3329 { "NET_RX_SOFTIRQ", 3 },
3330 { "BLOCK_SOFTIRQ", 4 },
3331 { "BLOCK_IOPOLL_SOFTIRQ", 5 },
3332 { "TASKLET_SOFTIRQ", 6 },
3333 { "SCHED_SOFTIRQ", 7 },
3334 { "HRTIMER_SOFTIRQ", 8 },
3335 { "RCU_SOFTIRQ", 9 },
3336
3337 { "HRTIMER_NORESTART", 0 },
3338 { "HRTIMER_RESTART", 1 },
3339};
3340
3341static unsigned long long eval_flag(const char *flag)
3342{
3343 int i;
3344
3345 /*
3346 * Some flags in the format files do not get converted.
3347 * If the flag is not numeric, see if it is something that
3348 * we already know about.
3349 */
3350 if (isdigit(flag[0]))
3351 return strtoull(flag, NULL, 0);
3352
3353 for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++)
3354 if (strcmp(flags[i].name, flag) == 0)
3355 return flags[i].value;
3356
3357 return 0;
3358}
3359
3360static void print_str_to_seq(struct trace_seq *s, const char *format,
3361 int len_arg, const char *str)
3362{
3363 if (len_arg >= 0)
3364 trace_seq_printf(s, format, len_arg, str);
3365 else
3366 trace_seq_printf(s, format, str);
3367}
3368
3369static void print_str_arg(struct trace_seq *s, void *data, int size,
3370 struct event_format *event, const char *format,
3371 int len_arg, struct print_arg *arg)
3372{
3373 struct pevent *pevent = event->pevent;
3374 struct print_flag_sym *flag;
Namhyung Kimb7008072012-06-27 09:41:40 +09003375 struct format_field *field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003376 unsigned long long val, fval;
3377 unsigned long addr;
3378 char *str;
Namhyung Kime080e6f2012-06-27 09:41:41 +09003379 unsigned char *hex;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003380 int print;
Namhyung Kime080e6f2012-06-27 09:41:41 +09003381 int i, len;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003382
3383 switch (arg->type) {
3384 case PRINT_NULL:
3385 /* ?? */
3386 return;
3387 case PRINT_ATOM:
3388 print_str_to_seq(s, format, len_arg, arg->atom.atom);
3389 return;
3390 case PRINT_FIELD:
Namhyung Kimb7008072012-06-27 09:41:40 +09003391 field = arg->field.field;
3392 if (!field) {
3393 field = pevent_find_any_field(event, arg->field.name);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003394 if (!field) {
3395 str = arg->field.name;
3396 goto out_warning_field;
3397 }
Namhyung Kimb7008072012-06-27 09:41:40 +09003398 arg->field.field = field;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003399 }
3400 /* Zero sized fields, mean the rest of the data */
Namhyung Kimb7008072012-06-27 09:41:40 +09003401 len = field->size ? : size - field->offset;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003402
3403 /*
3404 * Some events pass in pointers. If this is not an array
3405 * and the size is the same as long_size, assume that it
3406 * is a pointer.
3407 */
Namhyung Kimb7008072012-06-27 09:41:40 +09003408 if (!(field->flags & FIELD_IS_ARRAY) &&
3409 field->size == pevent->long_size) {
3410 addr = *(unsigned long *)(data + field->offset);
Steven Rostedtf7d82352012-04-06 00:47:53 +02003411 trace_seq_printf(s, "%lx", addr);
3412 break;
3413 }
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003414 str = malloc(len + 1);
3415 if (!str) {
3416 do_warning("%s: not enough memory!", __func__);
3417 return;
3418 }
Namhyung Kimb7008072012-06-27 09:41:40 +09003419 memcpy(str, data + field->offset, len);
Steven Rostedtf7d82352012-04-06 00:47:53 +02003420 str[len] = 0;
3421 print_str_to_seq(s, format, len_arg, str);
3422 free(str);
3423 break;
3424 case PRINT_FLAGS:
3425 val = eval_num_arg(data, size, event, arg->flags.field);
3426 print = 0;
3427 for (flag = arg->flags.flags; flag; flag = flag->next) {
3428 fval = eval_flag(flag->value);
3429 if (!val && !fval) {
3430 print_str_to_seq(s, format, len_arg, flag->str);
3431 break;
3432 }
3433 if (fval && (val & fval) == fval) {
3434 if (print && arg->flags.delim)
3435 trace_seq_puts(s, arg->flags.delim);
3436 print_str_to_seq(s, format, len_arg, flag->str);
3437 print = 1;
3438 val &= ~fval;
3439 }
3440 }
3441 break;
3442 case PRINT_SYMBOL:
3443 val = eval_num_arg(data, size, event, arg->symbol.field);
3444 for (flag = arg->symbol.symbols; flag; flag = flag->next) {
3445 fval = eval_flag(flag->value);
3446 if (val == fval) {
3447 print_str_to_seq(s, format, len_arg, flag->str);
3448 break;
3449 }
3450 }
3451 break;
Namhyung Kime080e6f2012-06-27 09:41:41 +09003452 case PRINT_HEX:
3453 field = arg->hex.field->field.field;
3454 if (!field) {
3455 str = arg->hex.field->field.name;
3456 field = pevent_find_any_field(event, str);
3457 if (!field)
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003458 goto out_warning_field;
Namhyung Kime080e6f2012-06-27 09:41:41 +09003459 arg->hex.field->field.field = field;
3460 }
3461 hex = data + field->offset;
3462 len = eval_num_arg(data, size, event, arg->hex.size);
3463 for (i = 0; i < len; i++) {
3464 if (i)
3465 trace_seq_putc(s, ' ');
3466 trace_seq_printf(s, "%02x", hex[i]);
3467 }
3468 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003469
3470 case PRINT_TYPE:
3471 break;
3472 case PRINT_STRING: {
3473 int str_offset;
3474
3475 if (arg->string.offset == -1) {
3476 struct format_field *f;
3477
3478 f = pevent_find_any_field(event, arg->string.string);
3479 arg->string.offset = f->offset;
3480 }
3481 str_offset = data2host4(pevent, data + arg->string.offset);
3482 str_offset &= 0xffff;
3483 print_str_to_seq(s, format, len_arg, ((char *)data) + str_offset);
3484 break;
3485 }
3486 case PRINT_BSTRING:
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003487 print_str_to_seq(s, format, len_arg, arg->string.string);
Steven Rostedtf7d82352012-04-06 00:47:53 +02003488 break;
3489 case PRINT_OP:
3490 /*
3491 * The only op for string should be ? :
3492 */
3493 if (arg->op.op[0] != '?')
3494 return;
3495 val = eval_num_arg(data, size, event, arg->op.left);
3496 if (val)
3497 print_str_arg(s, data, size, event,
3498 format, len_arg, arg->op.right->op.left);
3499 else
3500 print_str_arg(s, data, size, event,
3501 format, len_arg, arg->op.right->op.right);
3502 break;
3503 case PRINT_FUNC:
3504 process_defined_func(s, data, size, event, arg);
3505 break;
3506 default:
3507 /* well... */
3508 break;
3509 }
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003510
3511 return;
3512
3513out_warning_field:
3514 do_warning("%s: field %s not found", __func__, arg->field.name);
Steven Rostedtf7d82352012-04-06 00:47:53 +02003515}
3516
3517static unsigned long long
3518process_defined_func(struct trace_seq *s, void *data, int size,
3519 struct event_format *event, struct print_arg *arg)
3520{
3521 struct pevent_function_handler *func_handle = arg->func.func;
3522 struct pevent_func_params *param;
3523 unsigned long long *args;
3524 unsigned long long ret;
3525 struct print_arg *farg;
3526 struct trace_seq str;
3527 struct save_str {
3528 struct save_str *next;
3529 char *str;
3530 } *strings = NULL, *string;
3531 int i;
3532
3533 if (!func_handle->nr_args) {
3534 ret = (*func_handle->func)(s, NULL);
3535 goto out;
3536 }
3537
3538 farg = arg->func.args;
3539 param = func_handle->params;
3540
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003541 ret = ULLONG_MAX;
3542 args = malloc(sizeof(*args) * func_handle->nr_args);
3543 if (!args)
3544 goto out;
3545
Steven Rostedtf7d82352012-04-06 00:47:53 +02003546 for (i = 0; i < func_handle->nr_args; i++) {
3547 switch (param->type) {
3548 case PEVENT_FUNC_ARG_INT:
3549 case PEVENT_FUNC_ARG_LONG:
3550 case PEVENT_FUNC_ARG_PTR:
3551 args[i] = eval_num_arg(data, size, event, farg);
3552 break;
3553 case PEVENT_FUNC_ARG_STRING:
3554 trace_seq_init(&str);
3555 print_str_arg(&str, data, size, event, "%s", -1, farg);
3556 trace_seq_terminate(&str);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003557 string = malloc(sizeof(*string));
3558 if (!string) {
3559 do_warning("%s(%d): malloc str", __func__, __LINE__);
3560 goto out_free;
3561 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003562 string->next = strings;
3563 string->str = strdup(str.buffer);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003564 if (!string->str) {
3565 free(string);
3566 do_warning("%s(%d): malloc str", __func__, __LINE__);
3567 goto out_free;
3568 }
Robert Richter0cf26012012-08-07 19:43:14 +02003569 args[i] = (uintptr_t)string->str;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003570 strings = string;
3571 trace_seq_destroy(&str);
3572 break;
3573 default:
3574 /*
3575 * Something went totally wrong, this is not
3576 * an input error, something in this code broke.
3577 */
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003578 do_warning("Unexpected end of arguments\n");
3579 goto out_free;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003580 }
3581 farg = farg->next;
Namhyung Kim21c69e72012-05-23 11:36:51 +09003582 param = param->next;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003583 }
3584
3585 ret = (*func_handle->func)(s, args);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003586out_free:
Steven Rostedtf7d82352012-04-06 00:47:53 +02003587 free(args);
3588 while (strings) {
3589 string = strings;
3590 strings = string->next;
3591 free(string->str);
3592 free(string);
3593 }
3594
3595 out:
3596 /* TBD : handle return type here */
3597 return ret;
3598}
3599
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003600static void free_args(struct print_arg *args)
3601{
3602 struct print_arg *next;
3603
3604 while (args) {
3605 next = args->next;
3606
3607 free_arg(args);
3608 args = next;
3609 }
3610}
3611
Steven Rostedtf7d82352012-04-06 00:47:53 +02003612static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event_format *event)
3613{
3614 struct pevent *pevent = event->pevent;
3615 struct format_field *field, *ip_field;
3616 struct print_arg *args, *arg, **next;
3617 unsigned long long ip, val;
3618 char *ptr;
3619 void *bptr;
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003620 int vsize;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003621
3622 field = pevent->bprint_buf_field;
3623 ip_field = pevent->bprint_ip_field;
3624
3625 if (!field) {
3626 field = pevent_find_field(event, "buf");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003627 if (!field) {
3628 do_warning("can't find buffer field for binary printk");
3629 return NULL;
3630 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003631 ip_field = pevent_find_field(event, "ip");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003632 if (!ip_field) {
3633 do_warning("can't find ip field for binary printk");
3634 return NULL;
3635 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003636 pevent->bprint_buf_field = field;
3637 pevent->bprint_ip_field = ip_field;
3638 }
3639
3640 ip = pevent_read_number(pevent, data + ip_field->offset, ip_field->size);
3641
3642 /*
3643 * The first arg is the IP pointer.
3644 */
3645 args = alloc_arg();
3646 arg = args;
3647 arg->next = NULL;
3648 next = &arg->next;
3649
3650 arg->type = PRINT_ATOM;
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003651
3652 if (asprintf(&arg->atom.atom, "%lld", ip) < 0)
3653 goto out_free;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003654
3655 /* skip the first "%pf : " */
3656 for (ptr = fmt + 6, bptr = data + field->offset;
3657 bptr < data + size && *ptr; ptr++) {
3658 int ls = 0;
3659
3660 if (*ptr == '%') {
3661 process_again:
3662 ptr++;
3663 switch (*ptr) {
3664 case '%':
3665 break;
3666 case 'l':
3667 ls++;
3668 goto process_again;
3669 case 'L':
3670 ls = 2;
3671 goto process_again;
3672 case '0' ... '9':
3673 goto process_again;
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003674 case '.':
3675 goto process_again;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003676 case 'p':
3677 ls = 1;
3678 /* fall through */
3679 case 'd':
3680 case 'u':
3681 case 'x':
3682 case 'i':
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003683 switch (ls) {
3684 case 0:
3685 vsize = 4;
3686 break;
3687 case 1:
3688 vsize = pevent->long_size;
3689 break;
3690 case 2:
3691 vsize = 8;
Peter Huewec9bbabe2012-04-24 23:19:40 +02003692 break;
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003693 default:
3694 vsize = ls; /* ? */
3695 break;
3696 }
3697 /* fall through */
3698 case '*':
3699 if (*ptr == '*')
3700 vsize = 4;
3701
Steven Rostedtf7d82352012-04-06 00:47:53 +02003702 /* the pointers are always 4 bytes aligned */
3703 bptr = (void *)(((unsigned long)bptr + 3) &
3704 ~3);
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003705 val = pevent_read_number(pevent, bptr, vsize);
3706 bptr += vsize;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003707 arg = alloc_arg();
3708 arg->next = NULL;
3709 arg->type = PRINT_ATOM;
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003710 if (asprintf(&arg->atom.atom, "%lld", val) < 0) {
3711 free(arg);
3712 goto out_free;
3713 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003714 *next = arg;
3715 next = &arg->next;
Steven Rostedtc2e6dc22011-11-15 18:47:48 -05003716 /*
3717 * The '*' case means that an arg is used as the length.
3718 * We need to continue to figure out for what.
3719 */
3720 if (*ptr == '*')
3721 goto process_again;
3722
Steven Rostedtf7d82352012-04-06 00:47:53 +02003723 break;
3724 case 's':
3725 arg = alloc_arg();
3726 arg->next = NULL;
3727 arg->type = PRINT_BSTRING;
3728 arg->string.string = strdup(bptr);
Namhyung Kimca638582012-04-09 11:54:31 +09003729 if (!arg->string.string)
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003730 goto out_free;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003731 bptr += strlen(bptr) + 1;
3732 *next = arg;
3733 next = &arg->next;
3734 default:
3735 break;
3736 }
3737 }
3738 }
3739
3740 return args;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003741
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003742out_free:
3743 free_args(args);
3744 return NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003745}
3746
3747static char *
Irina Tirdea1d037ca2012-09-11 01:15:03 +03003748get_bprint_format(void *data, int size __maybe_unused,
3749 struct event_format *event)
Steven Rostedtf7d82352012-04-06 00:47:53 +02003750{
3751 struct pevent *pevent = event->pevent;
3752 unsigned long long addr;
3753 struct format_field *field;
3754 struct printk_map *printk;
3755 char *format;
3756 char *p;
3757
3758 field = pevent->bprint_fmt_field;
3759
3760 if (!field) {
3761 field = pevent_find_field(event, "fmt");
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003762 if (!field) {
3763 do_warning("can't find format field for binary printk");
3764 return NULL;
3765 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003766 pevent->bprint_fmt_field = field;
3767 }
3768
3769 addr = pevent_read_number(pevent, data + field->offset, field->size);
3770
3771 printk = find_printk(pevent, addr);
3772 if (!printk) {
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003773 if (asprintf(&format, "%%pf : (NO FORMAT FOUND at %llx)\n", addr) < 0)
3774 return NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003775 return format;
3776 }
3777
3778 p = printk->printk;
3779 /* Remove any quotes. */
3780 if (*p == '"')
3781 p++;
Arnaldo Carvalho de Melo0dbca1e2012-09-12 15:39:59 -03003782 if (asprintf(&format, "%s : %s", "%pf", p) < 0)
3783 return NULL;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003784 /* remove ending quotes and new line since we will add one too */
3785 p = format + strlen(format) - 1;
3786 if (*p == '"')
3787 *p = 0;
3788
3789 p -= 2;
3790 if (strcmp(p, "\\n") == 0)
3791 *p = 0;
3792
3793 return format;
3794}
3795
3796static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,
3797 struct event_format *event, struct print_arg *arg)
3798{
3799 unsigned char *buf;
3800 char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x";
3801
3802 if (arg->type == PRINT_FUNC) {
3803 process_defined_func(s, data, size, event, arg);
3804 return;
3805 }
3806
3807 if (arg->type != PRINT_FIELD) {
3808 trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d",
3809 arg->type);
3810 return;
3811 }
3812
3813 if (mac == 'm')
3814 fmt = "%.2x%.2x%.2x%.2x%.2x%.2x";
3815 if (!arg->field.field) {
3816 arg->field.field =
3817 pevent_find_any_field(event, arg->field.name);
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03003818 if (!arg->field.field) {
3819 do_warning("%s: field %s not found",
3820 __func__, arg->field.name);
3821 return;
3822 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003823 }
3824 if (arg->field.field->size != 6) {
3825 trace_seq_printf(s, "INVALIDMAC");
3826 return;
3827 }
3828 buf = data + arg->field.field->offset;
3829 trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
3830}
3831
Namhyung Kim600da3c2012-06-22 17:10:15 +09003832static int is_printable_array(char *p, unsigned int len)
3833{
3834 unsigned int i;
3835
3836 for (i = 0; i < len && p[i]; i++)
3837 if (!isprint(p[i]))
3838 return 0;
3839 return 1;
3840}
3841
Steven Rostedtf7d82352012-04-06 00:47:53 +02003842static void print_event_fields(struct trace_seq *s, void *data, int size,
3843 struct event_format *event)
3844{
3845 struct format_field *field;
3846 unsigned long long val;
3847 unsigned int offset, len, i;
3848
3849 field = event->format.fields;
3850 while (field) {
3851 trace_seq_printf(s, " %s=", field->name);
3852 if (field->flags & FIELD_IS_ARRAY) {
3853 offset = field->offset;
3854 len = field->size;
3855 if (field->flags & FIELD_IS_DYNAMIC) {
3856 val = pevent_read_number(event->pevent, data + offset, len);
3857 offset = val;
3858 len = offset >> 16;
3859 offset &= 0xffff;
3860 }
Namhyung Kim600da3c2012-06-22 17:10:15 +09003861 if (field->flags & FIELD_IS_STRING &&
3862 is_printable_array(data + offset, len)) {
Steven Rostedtf7d82352012-04-06 00:47:53 +02003863 trace_seq_printf(s, "%s", (char *)data + offset);
3864 } else {
3865 trace_seq_puts(s, "ARRAY[");
3866 for (i = 0; i < len; i++) {
3867 if (i)
3868 trace_seq_puts(s, ", ");
3869 trace_seq_printf(s, "%02x",
3870 *((unsigned char *)data + offset + i));
3871 }
3872 trace_seq_putc(s, ']');
Namhyung Kim600da3c2012-06-22 17:10:15 +09003873 field->flags &= ~FIELD_IS_STRING;
Steven Rostedtf7d82352012-04-06 00:47:53 +02003874 }
3875 } else {
3876 val = pevent_read_number(event->pevent, data + field->offset,
3877 field->size);
3878 if (field->flags & FIELD_IS_POINTER) {
3879 trace_seq_printf(s, "0x%llx", val);
3880 } else if (field->flags & FIELD_IS_SIGNED) {
3881 switch (field->size) {
3882 case 4:
3883 /*
3884 * If field is long then print it in hex.
3885 * A long usually stores pointers.
3886 */
3887 if (field->flags & FIELD_IS_LONG)
3888 trace_seq_printf(s, "0x%x", (int)val);
3889 else
3890 trace_seq_printf(s, "%d", (int)val);
3891 break;
3892 case 2:
3893 trace_seq_printf(s, "%2d", (short)val);
3894 break;
3895 case 1:
3896 trace_seq_printf(s, "%1d", (char)val);
3897 break;
3898 default:
3899 trace_seq_printf(s, "%lld", val);
3900 }
3901 } else {
3902 if (field->flags & FIELD_IS_LONG)
3903 trace_seq_printf(s, "0x%llx", val);
3904 else
3905 trace_seq_printf(s, "%llu", val);
3906 }
3907 }
3908 field = field->next;
3909 }
3910}
3911
3912static void pretty_print(struct trace_seq *s, void *data, int size, struct event_format *event)
3913{
3914 struct pevent *pevent = event->pevent;
3915 struct print_fmt *print_fmt = &event->print_fmt;
3916 struct print_arg *arg = print_fmt->args;
3917 struct print_arg *args = NULL;
3918 const char *ptr = print_fmt->format;
3919 unsigned long long val;
3920 struct func_map *func;
3921 const char *saveptr;
3922 char *bprint_fmt = NULL;
3923 char format[32];
3924 int show_func;
3925 int len_as_arg;
3926 int len_arg;
3927 int len;
3928 int ls;
3929
3930 if (event->flags & EVENT_FL_FAILED) {
3931 trace_seq_printf(s, "[FAILED TO PARSE]");
3932 print_event_fields(s, data, size, event);
3933 return;
3934 }
3935
3936 if (event->flags & EVENT_FL_ISBPRINT) {
3937 bprint_fmt = get_bprint_format(data, size, event);
3938 args = make_bprint_args(bprint_fmt, data, size, event);
3939 arg = args;
3940 ptr = bprint_fmt;
3941 }
3942
3943 for (; *ptr; ptr++) {
3944 ls = 0;
3945 if (*ptr == '\\') {
3946 ptr++;
3947 switch (*ptr) {
3948 case 'n':
3949 trace_seq_putc(s, '\n');
3950 break;
3951 case 't':
3952 trace_seq_putc(s, '\t');
3953 break;
3954 case 'r':
3955 trace_seq_putc(s, '\r');
3956 break;
3957 case '\\':
3958 trace_seq_putc(s, '\\');
3959 break;
3960 default:
3961 trace_seq_putc(s, *ptr);
3962 break;
3963 }
3964
3965 } else if (*ptr == '%') {
3966 saveptr = ptr;
3967 show_func = 0;
3968 len_as_arg = 0;
3969 cont_process:
3970 ptr++;
3971 switch (*ptr) {
3972 case '%':
3973 trace_seq_putc(s, '%');
3974 break;
3975 case '#':
3976 /* FIXME: need to handle properly */
3977 goto cont_process;
3978 case 'h':
3979 ls--;
3980 goto cont_process;
3981 case 'l':
3982 ls++;
3983 goto cont_process;
3984 case 'L':
3985 ls = 2;
3986 goto cont_process;
3987 case '*':
3988 /* The argument is the length. */
Namhyung Kim245c5a12012-09-07 11:49:45 +09003989 if (!arg) {
3990 do_warning("no argument match");
3991 event->flags |= EVENT_FL_FAILED;
3992 goto out_failed;
3993 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02003994 len_arg = eval_num_arg(data, size, event, arg);
3995 len_as_arg = 1;
3996 arg = arg->next;
3997 goto cont_process;
3998 case '.':
3999 case 'z':
4000 case 'Z':
4001 case '0' ... '9':
4002 goto cont_process;
4003 case 'p':
4004 if (pevent->long_size == 4)
4005 ls = 1;
4006 else
4007 ls = 2;
4008
4009 if (*(ptr+1) == 'F' ||
4010 *(ptr+1) == 'f') {
4011 ptr++;
4012 show_func = *ptr;
4013 } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') {
4014 print_mac_arg(s, *(ptr+1), data, size, event, arg);
4015 ptr++;
Steven Rostedtaaf05c72012-01-09 15:58:09 -05004016 arg = arg->next;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004017 break;
4018 }
4019
4020 /* fall through */
4021 case 'd':
4022 case 'i':
4023 case 'x':
4024 case 'X':
4025 case 'u':
Namhyung Kim245c5a12012-09-07 11:49:45 +09004026 if (!arg) {
4027 do_warning("no argument match");
4028 event->flags |= EVENT_FL_FAILED;
4029 goto out_failed;
4030 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004031
4032 len = ((unsigned long)ptr + 1) -
4033 (unsigned long)saveptr;
4034
4035 /* should never happen */
Namhyung Kim245c5a12012-09-07 11:49:45 +09004036 if (len > 31) {
4037 do_warning("bad format!");
4038 event->flags |= EVENT_FL_FAILED;
4039 len = 31;
4040 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004041
4042 memcpy(format, saveptr, len);
4043 format[len] = 0;
4044
4045 val = eval_num_arg(data, size, event, arg);
4046 arg = arg->next;
4047
4048 if (show_func) {
4049 func = find_func(pevent, val);
4050 if (func) {
4051 trace_seq_puts(s, func->func);
4052 if (show_func == 'F')
4053 trace_seq_printf(s,
4054 "+0x%llx",
4055 val - func->addr);
4056 break;
4057 }
4058 }
Wolfgang Mauererc5b35b72012-03-22 11:18:21 +01004059 if (pevent->long_size == 8 && ls &&
4060 sizeof(long) != 8) {
Steven Rostedtf7d82352012-04-06 00:47:53 +02004061 char *p;
4062
4063 ls = 2;
4064 /* make %l into %ll */
4065 p = strchr(format, 'l');
4066 if (p)
Wolfgang Mauererc5b35b72012-03-22 11:18:21 +01004067 memmove(p+1, p, strlen(p)+1);
Steven Rostedtf7d82352012-04-06 00:47:53 +02004068 else if (strcmp(format, "%p") == 0)
4069 strcpy(format, "0x%llx");
4070 }
4071 switch (ls) {
4072 case -2:
4073 if (len_as_arg)
4074 trace_seq_printf(s, format, len_arg, (char)val);
4075 else
4076 trace_seq_printf(s, format, (char)val);
4077 break;
4078 case -1:
4079 if (len_as_arg)
4080 trace_seq_printf(s, format, len_arg, (short)val);
4081 else
4082 trace_seq_printf(s, format, (short)val);
4083 break;
4084 case 0:
4085 if (len_as_arg)
4086 trace_seq_printf(s, format, len_arg, (int)val);
4087 else
4088 trace_seq_printf(s, format, (int)val);
4089 break;
4090 case 1:
4091 if (len_as_arg)
4092 trace_seq_printf(s, format, len_arg, (long)val);
4093 else
4094 trace_seq_printf(s, format, (long)val);
4095 break;
4096 case 2:
4097 if (len_as_arg)
4098 trace_seq_printf(s, format, len_arg,
4099 (long long)val);
4100 else
4101 trace_seq_printf(s, format, (long long)val);
4102 break;
4103 default:
Namhyung Kim245c5a12012-09-07 11:49:45 +09004104 do_warning("bad count (%d)", ls);
4105 event->flags |= EVENT_FL_FAILED;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004106 }
4107 break;
4108 case 's':
Namhyung Kim245c5a12012-09-07 11:49:45 +09004109 if (!arg) {
4110 do_warning("no matching argument");
4111 event->flags |= EVENT_FL_FAILED;
4112 goto out_failed;
4113 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004114
4115 len = ((unsigned long)ptr + 1) -
4116 (unsigned long)saveptr;
4117
4118 /* should never happen */
Namhyung Kim245c5a12012-09-07 11:49:45 +09004119 if (len > 31) {
4120 do_warning("bad format!");
4121 event->flags |= EVENT_FL_FAILED;
4122 len = 31;
4123 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004124
4125 memcpy(format, saveptr, len);
4126 format[len] = 0;
4127 if (!len_as_arg)
4128 len_arg = -1;
4129 print_str_arg(s, data, size, event,
4130 format, len_arg, arg);
4131 arg = arg->next;
4132 break;
4133 default:
4134 trace_seq_printf(s, ">%c<", *ptr);
4135
4136 }
4137 } else
4138 trace_seq_putc(s, *ptr);
4139 }
4140
Namhyung Kim245c5a12012-09-07 11:49:45 +09004141 if (event->flags & EVENT_FL_FAILED) {
4142out_failed:
4143 trace_seq_printf(s, "[FAILED TO PARSE]");
4144 }
4145
Steven Rostedtf7d82352012-04-06 00:47:53 +02004146 if (args) {
4147 free_args(args);
4148 free(bprint_fmt);
4149 }
4150}
4151
4152/**
4153 * pevent_data_lat_fmt - parse the data for the latency format
4154 * @pevent: a handle to the pevent
4155 * @s: the trace_seq to write to
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09004156 * @record: the record to read from
Steven Rostedtf7d82352012-04-06 00:47:53 +02004157 *
4158 * This parses out the Latency format (interrupts disabled,
4159 * need rescheduling, in hard/soft interrupt, preempt count
4160 * and lock depth) and places it into the trace_seq.
4161 */
4162void pevent_data_lat_fmt(struct pevent *pevent,
Steven Rostedt1c698182012-04-06 00:48:06 +02004163 struct trace_seq *s, struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02004164{
4165 static int check_lock_depth = 1;
Steven Rostedt0866a972012-05-22 14:52:40 +09004166 static int check_migrate_disable = 1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004167 static int lock_depth_exists;
Steven Rostedt0866a972012-05-22 14:52:40 +09004168 static int migrate_disable_exists;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004169 unsigned int lat_flags;
4170 unsigned int pc;
4171 int lock_depth;
Steven Rostedt0866a972012-05-22 14:52:40 +09004172 int migrate_disable;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004173 int hardirq;
4174 int softirq;
4175 void *data = record->data;
4176
4177 lat_flags = parse_common_flags(pevent, data);
4178 pc = parse_common_pc(pevent, data);
4179 /* lock_depth may not always exist */
Steven Rostedtf7d82352012-04-06 00:47:53 +02004180 if (lock_depth_exists)
4181 lock_depth = parse_common_lock_depth(pevent, data);
Steven Rostedt0866a972012-05-22 14:52:40 +09004182 else if (check_lock_depth) {
4183 lock_depth = parse_common_lock_depth(pevent, data);
4184 if (lock_depth < 0)
4185 check_lock_depth = 0;
4186 else
4187 lock_depth_exists = 1;
4188 }
4189
4190 /* migrate_disable may not always exist */
4191 if (migrate_disable_exists)
4192 migrate_disable = parse_common_migrate_disable(pevent, data);
4193 else if (check_migrate_disable) {
4194 migrate_disable = parse_common_migrate_disable(pevent, data);
4195 if (migrate_disable < 0)
4196 check_migrate_disable = 0;
4197 else
4198 migrate_disable_exists = 1;
4199 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004200
4201 hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
4202 softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
4203
4204 trace_seq_printf(s, "%c%c%c",
4205 (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
4206 (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
4207 'X' : '.',
4208 (lat_flags & TRACE_FLAG_NEED_RESCHED) ?
4209 'N' : '.',
4210 (hardirq && softirq) ? 'H' :
4211 hardirq ? 'h' : softirq ? 's' : '.');
4212
4213 if (pc)
4214 trace_seq_printf(s, "%x", pc);
4215 else
4216 trace_seq_putc(s, '.');
4217
Steven Rostedt0866a972012-05-22 14:52:40 +09004218 if (migrate_disable_exists) {
4219 if (migrate_disable < 0)
4220 trace_seq_putc(s, '.');
4221 else
4222 trace_seq_printf(s, "%d", migrate_disable);
4223 }
4224
Steven Rostedtf7d82352012-04-06 00:47:53 +02004225 if (lock_depth_exists) {
4226 if (lock_depth < 0)
4227 trace_seq_putc(s, '.');
4228 else
4229 trace_seq_printf(s, "%d", lock_depth);
4230 }
4231
4232 trace_seq_terminate(s);
4233}
4234
4235/**
4236 * pevent_data_type - parse out the given event type
4237 * @pevent: a handle to the pevent
4238 * @rec: the record to read from
4239 *
4240 * This returns the event id from the @rec.
4241 */
Steven Rostedt1c698182012-04-06 00:48:06 +02004242int pevent_data_type(struct pevent *pevent, struct pevent_record *rec)
Steven Rostedtf7d82352012-04-06 00:47:53 +02004243{
4244 return trace_parse_common_type(pevent, rec->data);
4245}
4246
4247/**
4248 * pevent_data_event_from_type - find the event by a given type
4249 * @pevent: a handle to the pevent
4250 * @type: the type of the event.
4251 *
4252 * This returns the event form a given @type;
4253 */
4254struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type)
4255{
4256 return pevent_find_event(pevent, type);
4257}
4258
4259/**
4260 * pevent_data_pid - parse the PID from raw data
4261 * @pevent: a handle to the pevent
4262 * @rec: the record to parse
4263 *
4264 * This returns the PID from a raw data.
4265 */
Steven Rostedt1c698182012-04-06 00:48:06 +02004266int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec)
Steven Rostedtf7d82352012-04-06 00:47:53 +02004267{
4268 return parse_common_pid(pevent, rec->data);
4269}
4270
4271/**
4272 * pevent_data_comm_from_pid - return the command line from PID
4273 * @pevent: a handle to the pevent
4274 * @pid: the PID of the task to search for
4275 *
4276 * This returns a pointer to the command line that has the given
4277 * @pid.
4278 */
4279const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid)
4280{
4281 const char *comm;
4282
4283 comm = find_cmdline(pevent, pid);
4284 return comm;
4285}
4286
4287/**
4288 * pevent_data_comm_from_pid - parse the data into the print format
4289 * @s: the trace_seq to write to
4290 * @event: the handle to the event
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09004291 * @record: the record to read from
Steven Rostedtf7d82352012-04-06 00:47:53 +02004292 *
4293 * This parses the raw @data using the given @event information and
4294 * writes the print format into the trace_seq.
4295 */
4296void pevent_event_info(struct trace_seq *s, struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02004297 struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02004298{
4299 int print_pretty = 1;
4300
4301 if (event->pevent->print_raw)
4302 print_event_fields(s, record->data, record->size, event);
4303 else {
4304
4305 if (event->handler)
4306 print_pretty = event->handler(s, record, event,
4307 event->context);
4308
4309 if (print_pretty)
4310 pretty_print(s, record->data, record->size, event);
4311 }
4312
4313 trace_seq_terminate(s);
4314}
4315
4316void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
Steven Rostedt1c698182012-04-06 00:48:06 +02004317 struct pevent_record *record)
Steven Rostedtf7d82352012-04-06 00:47:53 +02004318{
4319 static char *spaces = " "; /* 20 spaces */
4320 struct event_format *event;
4321 unsigned long secs;
4322 unsigned long usecs;
Steven Rostedt4dc10242012-04-06 00:47:57 +02004323 unsigned long nsecs;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004324 const char *comm;
4325 void *data = record->data;
4326 int type;
4327 int pid;
4328 int len;
Steven Rostedt4dc10242012-04-06 00:47:57 +02004329 int p;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004330
4331 secs = record->ts / NSECS_PER_SEC;
Steven Rostedt4dc10242012-04-06 00:47:57 +02004332 nsecs = record->ts - secs * NSECS_PER_SEC;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004333
4334 if (record->size < 0) {
4335 do_warning("ug! negative record size %d", record->size);
4336 return;
4337 }
4338
4339 type = trace_parse_common_type(pevent, data);
4340
4341 event = pevent_find_event(pevent, type);
4342 if (!event) {
4343 do_warning("ug! no event found for type %d", type);
4344 return;
4345 }
4346
4347 pid = parse_common_pid(pevent, data);
4348 comm = find_cmdline(pevent, pid);
4349
4350 if (pevent->latency_format) {
4351 trace_seq_printf(s, "%8.8s-%-5d %3d",
4352 comm, pid, record->cpu);
4353 pevent_data_lat_fmt(pevent, s, record);
4354 } else
4355 trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu);
4356
Steven Rostedt4dc10242012-04-06 00:47:57 +02004357 if (pevent->flags & PEVENT_NSEC_OUTPUT) {
4358 usecs = nsecs;
4359 p = 9;
4360 } else {
4361 usecs = (nsecs + 500) / NSECS_PER_USEC;
4362 p = 6;
4363 }
4364
4365 trace_seq_printf(s, " %5lu.%0*lu: %s: ", secs, p, usecs, event->name);
Steven Rostedtf7d82352012-04-06 00:47:53 +02004366
4367 /* Space out the event names evenly. */
4368 len = strlen(event->name);
4369 if (len < 20)
4370 trace_seq_printf(s, "%.*s", 20 - len, spaces);
4371
4372 pevent_event_info(s, event, record);
4373}
4374
4375static int events_id_cmp(const void *a, const void *b)
4376{
4377 struct event_format * const * ea = a;
4378 struct event_format * const * eb = b;
4379
4380 if ((*ea)->id < (*eb)->id)
4381 return -1;
4382
4383 if ((*ea)->id > (*eb)->id)
4384 return 1;
4385
4386 return 0;
4387}
4388
4389static int events_name_cmp(const void *a, const void *b)
4390{
4391 struct event_format * const * ea = a;
4392 struct event_format * const * eb = b;
4393 int res;
4394
4395 res = strcmp((*ea)->name, (*eb)->name);
4396 if (res)
4397 return res;
4398
4399 res = strcmp((*ea)->system, (*eb)->system);
4400 if (res)
4401 return res;
4402
4403 return events_id_cmp(a, b);
4404}
4405
4406static int events_system_cmp(const void *a, const void *b)
4407{
4408 struct event_format * const * ea = a;
4409 struct event_format * const * eb = b;
4410 int res;
4411
4412 res = strcmp((*ea)->system, (*eb)->system);
4413 if (res)
4414 return res;
4415
4416 res = strcmp((*ea)->name, (*eb)->name);
4417 if (res)
4418 return res;
4419
4420 return events_id_cmp(a, b);
4421}
4422
4423struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type sort_type)
4424{
4425 struct event_format **events;
4426 int (*sort)(const void *a, const void *b);
4427
4428 events = pevent->sort_events;
4429
4430 if (events && pevent->last_type == sort_type)
4431 return events;
4432
4433 if (!events) {
4434 events = malloc(sizeof(*events) * (pevent->nr_events + 1));
4435 if (!events)
4436 return NULL;
4437
4438 memcpy(events, pevent->events, sizeof(*events) * pevent->nr_events);
4439 events[pevent->nr_events] = NULL;
4440
4441 pevent->sort_events = events;
4442
4443 /* the internal events are sorted by id */
4444 if (sort_type == EVENT_SORT_ID) {
4445 pevent->last_type = sort_type;
4446 return events;
4447 }
4448 }
4449
4450 switch (sort_type) {
4451 case EVENT_SORT_ID:
4452 sort = events_id_cmp;
4453 break;
4454 case EVENT_SORT_NAME:
4455 sort = events_name_cmp;
4456 break;
4457 case EVENT_SORT_SYSTEM:
4458 sort = events_system_cmp;
4459 break;
4460 default:
4461 return events;
4462 }
4463
4464 qsort(events, pevent->nr_events, sizeof(*events), sort);
4465 pevent->last_type = sort_type;
4466
4467 return events;
4468}
4469
4470static struct format_field **
4471get_event_fields(const char *type, const char *name,
4472 int count, struct format_field *list)
4473{
4474 struct format_field **fields;
4475 struct format_field *field;
4476 int i = 0;
4477
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03004478 fields = malloc(sizeof(*fields) * (count + 1));
4479 if (!fields)
4480 return NULL;
4481
Steven Rostedtf7d82352012-04-06 00:47:53 +02004482 for (field = list; field; field = field->next) {
4483 fields[i++] = field;
4484 if (i == count + 1) {
4485 do_warning("event %s has more %s fields than specified",
4486 name, type);
4487 i--;
4488 break;
4489 }
4490 }
4491
4492 if (i != count)
4493 do_warning("event %s has less %s fields than specified",
4494 name, type);
4495
4496 fields[i] = NULL;
4497
4498 return fields;
4499}
4500
4501/**
4502 * pevent_event_common_fields - return a list of common fields for an event
4503 * @event: the event to return the common fields of.
4504 *
4505 * Returns an allocated array of fields. The last item in the array is NULL.
4506 * The array must be freed with free().
4507 */
4508struct format_field **pevent_event_common_fields(struct event_format *event)
4509{
4510 return get_event_fields("common", event->name,
4511 event->format.nr_common,
4512 event->format.common_fields);
4513}
4514
4515/**
4516 * pevent_event_fields - return a list of event specific fields for an event
4517 * @event: the event to return the fields of.
4518 *
4519 * Returns an allocated array of fields. The last item in the array is NULL.
4520 * The array must be freed with free().
4521 */
4522struct format_field **pevent_event_fields(struct event_format *event)
4523{
4524 return get_event_fields("event", event->name,
4525 event->format.nr_fields,
4526 event->format.fields);
4527}
4528
4529static void print_fields(struct trace_seq *s, struct print_flag_sym *field)
4530{
4531 trace_seq_printf(s, "{ %s, %s }", field->value, field->str);
4532 if (field->next) {
4533 trace_seq_puts(s, ", ");
4534 print_fields(s, field->next);
4535 }
4536}
4537
4538/* for debugging */
4539static void print_args(struct print_arg *args)
4540{
4541 int print_paren = 1;
4542 struct trace_seq s;
4543
4544 switch (args->type) {
4545 case PRINT_NULL:
4546 printf("null");
4547 break;
4548 case PRINT_ATOM:
4549 printf("%s", args->atom.atom);
4550 break;
4551 case PRINT_FIELD:
4552 printf("REC->%s", args->field.name);
4553 break;
4554 case PRINT_FLAGS:
4555 printf("__print_flags(");
4556 print_args(args->flags.field);
4557 printf(", %s, ", args->flags.delim);
4558 trace_seq_init(&s);
4559 print_fields(&s, args->flags.flags);
4560 trace_seq_do_printf(&s);
4561 trace_seq_destroy(&s);
4562 printf(")");
4563 break;
4564 case PRINT_SYMBOL:
4565 printf("__print_symbolic(");
4566 print_args(args->symbol.field);
4567 printf(", ");
4568 trace_seq_init(&s);
4569 print_fields(&s, args->symbol.symbols);
4570 trace_seq_do_printf(&s);
4571 trace_seq_destroy(&s);
4572 printf(")");
4573 break;
Namhyung Kime080e6f2012-06-27 09:41:41 +09004574 case PRINT_HEX:
4575 printf("__print_hex(");
4576 print_args(args->hex.field);
4577 printf(", ");
4578 print_args(args->hex.size);
4579 printf(")");
4580 break;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004581 case PRINT_STRING:
4582 case PRINT_BSTRING:
4583 printf("__get_str(%s)", args->string.string);
4584 break;
4585 case PRINT_TYPE:
4586 printf("(%s)", args->typecast.type);
4587 print_args(args->typecast.item);
4588 break;
4589 case PRINT_OP:
4590 if (strcmp(args->op.op, ":") == 0)
4591 print_paren = 0;
4592 if (print_paren)
4593 printf("(");
4594 print_args(args->op.left);
4595 printf(" %s ", args->op.op);
4596 print_args(args->op.right);
4597 if (print_paren)
4598 printf(")");
4599 break;
4600 default:
4601 /* we should warn... */
4602 return;
4603 }
4604 if (args->next) {
4605 printf("\n");
4606 print_args(args->next);
4607 }
4608}
4609
4610static void parse_header_field(const char *field,
4611 int *offset, int *size, int mandatory)
4612{
4613 unsigned long long save_input_buf_ptr;
4614 unsigned long long save_input_buf_siz;
4615 char *token;
4616 int type;
4617
4618 save_input_buf_ptr = input_buf_ptr;
4619 save_input_buf_siz = input_buf_siz;
4620
4621 if (read_expected(EVENT_ITEM, "field") < 0)
4622 return;
4623 if (read_expected(EVENT_OP, ":") < 0)
4624 return;
4625
4626 /* type */
4627 if (read_expect_type(EVENT_ITEM, &token) < 0)
4628 goto fail;
4629 free_token(token);
4630
4631 /*
4632 * If this is not a mandatory field, then test it first.
4633 */
4634 if (mandatory) {
4635 if (read_expected(EVENT_ITEM, field) < 0)
4636 return;
4637 } else {
4638 if (read_expect_type(EVENT_ITEM, &token) < 0)
4639 goto fail;
4640 if (strcmp(token, field) != 0)
4641 goto discard;
4642 free_token(token);
4643 }
4644
4645 if (read_expected(EVENT_OP, ";") < 0)
4646 return;
4647 if (read_expected(EVENT_ITEM, "offset") < 0)
4648 return;
4649 if (read_expected(EVENT_OP, ":") < 0)
4650 return;
4651 if (read_expect_type(EVENT_ITEM, &token) < 0)
4652 goto fail;
4653 *offset = atoi(token);
4654 free_token(token);
4655 if (read_expected(EVENT_OP, ";") < 0)
4656 return;
4657 if (read_expected(EVENT_ITEM, "size") < 0)
4658 return;
4659 if (read_expected(EVENT_OP, ":") < 0)
4660 return;
4661 if (read_expect_type(EVENT_ITEM, &token) < 0)
4662 goto fail;
4663 *size = atoi(token);
4664 free_token(token);
4665 if (read_expected(EVENT_OP, ";") < 0)
4666 return;
4667 type = read_token(&token);
4668 if (type != EVENT_NEWLINE) {
4669 /* newer versions of the kernel have a "signed" type */
4670 if (type != EVENT_ITEM)
4671 goto fail;
4672
4673 if (strcmp(token, "signed") != 0)
4674 goto fail;
4675
4676 free_token(token);
4677
4678 if (read_expected(EVENT_OP, ":") < 0)
4679 return;
4680
4681 if (read_expect_type(EVENT_ITEM, &token))
4682 goto fail;
4683
4684 free_token(token);
4685 if (read_expected(EVENT_OP, ";") < 0)
4686 return;
4687
4688 if (read_expect_type(EVENT_NEWLINE, &token))
4689 goto fail;
4690 }
4691 fail:
4692 free_token(token);
4693 return;
4694
4695 discard:
4696 input_buf_ptr = save_input_buf_ptr;
4697 input_buf_siz = save_input_buf_siz;
4698 *offset = 0;
4699 *size = 0;
4700 free_token(token);
4701}
4702
4703/**
4704 * pevent_parse_header_page - parse the data stored in the header page
4705 * @pevent: the handle to the pevent
4706 * @buf: the buffer storing the header page format string
4707 * @size: the size of @buf
4708 * @long_size: the long size to use if there is no header
4709 *
4710 * This parses the header page format for information on the
4711 * ring buffer used. The @buf should be copied from
4712 *
4713 * /sys/kernel/debug/tracing/events/header_page
4714 */
4715int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size,
4716 int long_size)
4717{
4718 int ignore;
4719
4720 if (!size) {
4721 /*
4722 * Old kernels did not have header page info.
4723 * Sorry but we just use what we find here in user space.
4724 */
4725 pevent->header_page_ts_size = sizeof(long long);
4726 pevent->header_page_size_size = long_size;
4727 pevent->header_page_data_offset = sizeof(long long) + long_size;
4728 pevent->old_format = 1;
4729 return -1;
4730 }
4731 init_input_buf(buf, size);
4732
4733 parse_header_field("timestamp", &pevent->header_page_ts_offset,
4734 &pevent->header_page_ts_size, 1);
4735 parse_header_field("commit", &pevent->header_page_size_offset,
4736 &pevent->header_page_size_size, 1);
4737 parse_header_field("overwrite", &pevent->header_page_overwrite,
4738 &ignore, 0);
4739 parse_header_field("data", &pevent->header_page_data_offset,
4740 &pevent->header_page_data_size, 1);
4741
4742 return 0;
4743}
4744
4745static int event_matches(struct event_format *event,
4746 int id, const char *sys_name,
4747 const char *event_name)
4748{
4749 if (id >= 0 && id != event->id)
4750 return 0;
4751
4752 if (event_name && (strcmp(event_name, event->name) != 0))
4753 return 0;
4754
4755 if (sys_name && (strcmp(sys_name, event->system) != 0))
4756 return 0;
4757
4758 return 1;
4759}
4760
4761static void free_handler(struct event_handler *handle)
4762{
4763 free((void *)handle->sys_name);
4764 free((void *)handle->event_name);
4765 free(handle);
4766}
4767
4768static int find_event_handle(struct pevent *pevent, struct event_format *event)
4769{
4770 struct event_handler *handle, **next;
4771
4772 for (next = &pevent->handlers; *next;
4773 next = &(*next)->next) {
4774 handle = *next;
4775 if (event_matches(event, handle->id,
4776 handle->sys_name,
4777 handle->event_name))
4778 break;
4779 }
4780
4781 if (!(*next))
4782 return 0;
4783
4784 pr_stat("overriding event (%d) %s:%s with new print handler",
4785 event->id, event->system, event->name);
4786
4787 event->handler = handle->func;
4788 event->context = handle->context;
4789
4790 *next = handle->next;
4791 free_handler(handle);
4792
4793 return 1;
4794}
4795
4796/**
4797 * pevent_parse_event - parse the event format
4798 * @pevent: the handle to the pevent
4799 * @buf: the buffer storing the event format string
4800 * @size: the size of @buf
4801 * @sys: the system the event belongs to
4802 *
4803 * This parses the event format and creates an event structure
4804 * to quickly parse raw data for a given event.
4805 *
4806 * These files currently come from:
4807 *
4808 * /sys/kernel/debug/tracing/events/.../.../format
4809 */
Namhyung Kimbffddff2012-08-22 16:00:29 +09004810enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
4811 unsigned long size, const char *sys)
Steven Rostedtf7d82352012-04-06 00:47:53 +02004812{
4813 struct event_format *event;
4814 int ret;
4815
4816 init_input_buf(buf, size);
4817
4818 event = alloc_event();
4819 if (!event)
Namhyung Kimbffddff2012-08-22 16:00:29 +09004820 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004821
4822 event->name = event_read_name();
4823 if (!event->name) {
4824 /* Bad event? */
Namhyung Kimbffddff2012-08-22 16:00:29 +09004825 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
4826 goto event_alloc_failed;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004827 }
4828
4829 if (strcmp(sys, "ftrace") == 0) {
Steven Rostedtf7d82352012-04-06 00:47:53 +02004830 event->flags |= EVENT_FL_ISFTRACE;
4831
4832 if (strcmp(event->name, "bprint") == 0)
4833 event->flags |= EVENT_FL_ISBPRINT;
4834 }
4835
4836 event->id = event_read_id();
Namhyung Kimbffddff2012-08-22 16:00:29 +09004837 if (event->id < 0) {
4838 ret = PEVENT_ERRNO__READ_ID_FAILED;
4839 /*
4840 * This isn't an allocation error actually.
4841 * But as the ID is critical, just bail out.
4842 */
4843 goto event_alloc_failed;
4844 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004845
4846 event->system = strdup(sys);
Namhyung Kimbffddff2012-08-22 16:00:29 +09004847 if (!event->system) {
4848 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
4849 goto event_alloc_failed;
4850 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004851
4852 /* Add pevent to event so that it can be referenced */
4853 event->pevent = pevent;
4854
4855 ret = event_read_format(event);
4856 if (ret < 0) {
Namhyung Kimbffddff2012-08-22 16:00:29 +09004857 ret = PEVENT_ERRNO__READ_FORMAT_FAILED;
4858 goto event_parse_failed;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004859 }
4860
4861 /*
4862 * If the event has an override, don't print warnings if the event
4863 * print format fails to parse.
4864 */
4865 if (find_event_handle(pevent, event))
4866 show_warning = 0;
4867
4868 ret = event_read_print(event);
4869 if (ret < 0) {
Steven Rostedtf7d82352012-04-06 00:47:53 +02004870 show_warning = 1;
Namhyung Kimbffddff2012-08-22 16:00:29 +09004871 ret = PEVENT_ERRNO__READ_PRINT_FAILED;
4872 goto event_parse_failed;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004873 }
4874 show_warning = 1;
4875
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03004876 if (add_event(pevent, event))
4877 goto event_alloc_failed;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004878
4879 if (!ret && (event->flags & EVENT_FL_ISFTRACE)) {
4880 struct format_field *field;
4881 struct print_arg *arg, **list;
4882
4883 /* old ftrace had no args */
Steven Rostedtf7d82352012-04-06 00:47:53 +02004884 list = &event->print_fmt.args;
4885 for (field = event->format.fields; field; field = field->next) {
4886 arg = alloc_arg();
Steven Rostedtf7d82352012-04-06 00:47:53 +02004887 arg->type = PRINT_FIELD;
4888 arg->field.name = strdup(field->name);
Namhyung Kimca638582012-04-09 11:54:31 +09004889 if (!arg->field.name) {
Namhyung Kim4b5632b2012-04-23 13:58:34 +09004890 event->flags |= EVENT_FL_FAILED;
Namhyung Kimfd34f0b2012-08-22 16:00:28 +09004891 free_arg(arg);
Namhyung Kimbffddff2012-08-22 16:00:29 +09004892 return PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED;
Namhyung Kimca638582012-04-09 11:54:31 +09004893 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02004894 arg->field.field = field;
Namhyung Kimfd34f0b2012-08-22 16:00:28 +09004895 *list = arg;
4896 list = &arg->next;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004897 }
4898 return 0;
4899 }
4900
4901#define PRINT_ARGS 0
4902 if (PRINT_ARGS && event->print_fmt.args)
4903 print_args(event->print_fmt.args);
4904
4905 return 0;
4906
Namhyung Kimbffddff2012-08-22 16:00:29 +09004907 event_parse_failed:
Steven Rostedtf7d82352012-04-06 00:47:53 +02004908 event->flags |= EVENT_FL_FAILED;
4909 /* still add it even if it failed */
Arnaldo Carvalho de Meloa6d2a612012-09-12 17:30:50 -03004910 if (add_event(pevent, event))
4911 goto event_alloc_failed;
4912
Namhyung Kimbffddff2012-08-22 16:00:29 +09004913 return ret;
4914
4915 event_alloc_failed:
4916 free(event->system);
4917 free(event->name);
4918 free(event);
4919 return ret;
Steven Rostedtf7d82352012-04-06 00:47:53 +02004920}
4921
Namhyung Kim2f197b92012-08-22 16:00:30 +09004922#undef _PE
4923#define _PE(code, str) str
4924static const char * const pevent_error_str[] = {
4925 PEVENT_ERRORS
4926};
4927#undef _PE
4928
4929int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum,
4930 char *buf, size_t buflen)
4931{
4932 int idx;
4933 const char *msg;
4934
4935 if (errnum >= 0) {
Namhyung Kime1aa7c32012-08-22 16:00:31 +09004936 msg = strerror_r(errnum, buf, buflen);
4937 if (msg != buf) {
4938 size_t len = strlen(msg);
Irina Tirdea9612ef62012-09-08 03:43:22 +03004939 memcpy(buf, msg, min(buflen - 1, len));
4940 *(buf + min(buflen - 1, len)) = '\0';
Namhyung Kime1aa7c32012-08-22 16:00:31 +09004941 }
Namhyung Kim2f197b92012-08-22 16:00:30 +09004942 return 0;
4943 }
4944
4945 if (errnum <= __PEVENT_ERRNO__START ||
4946 errnum >= __PEVENT_ERRNO__END)
4947 return -1;
4948
Namhyung Kimf63fe792012-08-23 16:37:00 +09004949 idx = errnum - __PEVENT_ERRNO__START - 1;
Namhyung Kim2f197b92012-08-22 16:00:30 +09004950 msg = pevent_error_str[idx];
4951
4952 switch (errnum) {
4953 case PEVENT_ERRNO__MEM_ALLOC_FAILED:
4954 case PEVENT_ERRNO__PARSE_EVENT_FAILED:
4955 case PEVENT_ERRNO__READ_ID_FAILED:
4956 case PEVENT_ERRNO__READ_FORMAT_FAILED:
4957 case PEVENT_ERRNO__READ_PRINT_FAILED:
4958 case PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED:
4959 snprintf(buf, buflen, "%s", msg);
4960 break;
4961
4962 default:
4963 /* cannot reach here */
4964 break;
4965 }
4966
4967 return 0;
4968}
4969
Steven Rostedtf7d82352012-04-06 00:47:53 +02004970int get_field_val(struct trace_seq *s, struct format_field *field,
Steven Rostedt1c698182012-04-06 00:48:06 +02004971 const char *name, struct pevent_record *record,
Steven Rostedtf7d82352012-04-06 00:47:53 +02004972 unsigned long long *val, int err)
4973{
4974 if (!field) {
4975 if (err)
4976 trace_seq_printf(s, "<CANT FIND FIELD %s>", name);
4977 return -1;
4978 }
4979
4980 if (pevent_read_number_field(field, record->data, val)) {
4981 if (err)
4982 trace_seq_printf(s, " %s=INVALID", name);
4983 return -1;
4984 }
4985
4986 return 0;
4987}
4988
4989/**
4990 * pevent_get_field_raw - return the raw pointer into the data field
4991 * @s: The seq to print to on error
4992 * @event: the event that the field is for
4993 * @name: The name of the field
4994 * @record: The record with the field name.
4995 * @len: place to store the field length.
4996 * @err: print default error if failed.
4997 *
4998 * Returns a pointer into record->data of the field and places
4999 * the length of the field in @len.
5000 *
5001 * On failure, it returns NULL.
5002 */
5003void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02005004 const char *name, struct pevent_record *record,
Steven Rostedtf7d82352012-04-06 00:47:53 +02005005 int *len, int err)
5006{
5007 struct format_field *field;
5008 void *data = record->data;
5009 unsigned offset;
5010 int dummy;
5011
5012 if (!event)
5013 return NULL;
5014
5015 field = pevent_find_field(event, name);
5016
5017 if (!field) {
5018 if (err)
5019 trace_seq_printf(s, "<CANT FIND FIELD %s>", name);
5020 return NULL;
5021 }
5022
5023 /* Allow @len to be NULL */
5024 if (!len)
5025 len = &dummy;
5026
5027 offset = field->offset;
5028 if (field->flags & FIELD_IS_DYNAMIC) {
5029 offset = pevent_read_number(event->pevent,
5030 data + offset, field->size);
5031 *len = offset >> 16;
5032 offset &= 0xffff;
5033 } else
5034 *len = field->size;
5035
5036 return data + offset;
5037}
5038
5039/**
5040 * pevent_get_field_val - find a field and return its value
5041 * @s: The seq to print to on error
5042 * @event: the event that the field is for
5043 * @name: The name of the field
5044 * @record: The record with the field name.
5045 * @val: place to store the value of the field.
5046 * @err: print default error if failed.
5047 *
5048 * Returns 0 on success -1 on field not found.
5049 */
5050int pevent_get_field_val(struct trace_seq *s, struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02005051 const char *name, struct pevent_record *record,
Steven Rostedtf7d82352012-04-06 00:47:53 +02005052 unsigned long long *val, int err)
5053{
5054 struct format_field *field;
5055
5056 if (!event)
5057 return -1;
5058
5059 field = pevent_find_field(event, name);
5060
5061 return get_field_val(s, field, name, record, val, err);
5062}
5063
5064/**
5065 * pevent_get_common_field_val - find a common field and return its value
5066 * @s: The seq to print to on error
5067 * @event: the event that the field is for
5068 * @name: The name of the field
5069 * @record: The record with the field name.
5070 * @val: place to store the value of the field.
5071 * @err: print default error if failed.
5072 *
5073 * Returns 0 on success -1 on field not found.
5074 */
5075int pevent_get_common_field_val(struct trace_seq *s, struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02005076 const char *name, struct pevent_record *record,
Steven Rostedtf7d82352012-04-06 00:47:53 +02005077 unsigned long long *val, int err)
5078{
5079 struct format_field *field;
5080
5081 if (!event)
5082 return -1;
5083
5084 field = pevent_find_common_field(event, name);
5085
5086 return get_field_val(s, field, name, record, val, err);
5087}
5088
5089/**
5090 * pevent_get_any_field_val - find a any field and return its value
5091 * @s: The seq to print to on error
5092 * @event: the event that the field is for
5093 * @name: The name of the field
5094 * @record: The record with the field name.
5095 * @val: place to store the value of the field.
5096 * @err: print default error if failed.
5097 *
5098 * Returns 0 on success -1 on field not found.
5099 */
5100int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
Steven Rostedt1c698182012-04-06 00:48:06 +02005101 const char *name, struct pevent_record *record,
Steven Rostedtf7d82352012-04-06 00:47:53 +02005102 unsigned long long *val, int err)
5103{
5104 struct format_field *field;
5105
5106 if (!event)
5107 return -1;
5108
5109 field = pevent_find_any_field(event, name);
5110
5111 return get_field_val(s, field, name, record, val, err);
5112}
5113
5114/**
5115 * pevent_print_num_field - print a field and a format
5116 * @s: The seq to print to
5117 * @fmt: The printf format to print the field with.
5118 * @event: the event that the field is for
5119 * @name: The name of the field
5120 * @record: The record with the field name.
5121 * @err: print default error if failed.
5122 *
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09005123 * Returns: 0 on success, -1 field not found, or 1 if buffer is full.
Steven Rostedtf7d82352012-04-06 00:47:53 +02005124 */
5125int pevent_print_num_field(struct trace_seq *s, const char *fmt,
5126 struct event_format *event, const char *name,
Steven Rostedt1c698182012-04-06 00:48:06 +02005127 struct pevent_record *record, int err)
Steven Rostedtf7d82352012-04-06 00:47:53 +02005128{
5129 struct format_field *field = pevent_find_field(event, name);
5130 unsigned long long val;
5131
5132 if (!field)
5133 goto failed;
5134
5135 if (pevent_read_number_field(field, record->data, &val))
5136 goto failed;
5137
5138 return trace_seq_printf(s, fmt, val);
5139
5140 failed:
5141 if (err)
5142 trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
5143 return -1;
5144}
5145
5146static void free_func_handle(struct pevent_function_handler *func)
5147{
5148 struct pevent_func_params *params;
5149
5150 free(func->name);
5151
5152 while (func->params) {
5153 params = func->params;
5154 func->params = params->next;
5155 free(params);
5156 }
5157
5158 free(func);
5159}
5160
5161/**
5162 * pevent_register_print_function - register a helper function
5163 * @pevent: the handle to the pevent
5164 * @func: the function to process the helper function
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09005165 * @ret_type: the return type of the helper function
Steven Rostedtf7d82352012-04-06 00:47:53 +02005166 * @name: the name of the helper function
5167 * @parameters: A list of enum pevent_func_arg_type
5168 *
5169 * Some events may have helper functions in the print format arguments.
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09005170 * This allows a plugin to dynamically create a way to process one
Steven Rostedtf7d82352012-04-06 00:47:53 +02005171 * of these functions.
5172 *
5173 * The @parameters is a variable list of pevent_func_arg_type enums that
5174 * must end with PEVENT_FUNC_ARG_VOID.
5175 */
5176int pevent_register_print_function(struct pevent *pevent,
5177 pevent_func_handler func,
5178 enum pevent_func_arg_type ret_type,
5179 char *name, ...)
5180{
5181 struct pevent_function_handler *func_handle;
5182 struct pevent_func_params **next_param;
5183 struct pevent_func_params *param;
5184 enum pevent_func_arg_type type;
5185 va_list ap;
Namhyung Kim67ed9392012-09-07 11:49:47 +09005186 int ret;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005187
5188 func_handle = find_func_handler(pevent, name);
5189 if (func_handle) {
5190 /*
5191 * This is most like caused by the users own
5192 * plugins updating the function. This overrides the
5193 * system defaults.
5194 */
5195 pr_stat("override of function helper '%s'", name);
5196 remove_func_handler(pevent, name);
5197 }
5198
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -03005199 func_handle = calloc(1, sizeof(*func_handle));
Namhyung Kim67ed9392012-09-07 11:49:47 +09005200 if (!func_handle) {
5201 do_warning("Failed to allocate function handler");
5202 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
5203 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005204
5205 func_handle->ret_type = ret_type;
5206 func_handle->name = strdup(name);
5207 func_handle->func = func;
Namhyung Kim67ed9392012-09-07 11:49:47 +09005208 if (!func_handle->name) {
5209 do_warning("Failed to allocate function name");
5210 free(func_handle);
5211 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
5212 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005213
5214 next_param = &(func_handle->params);
5215 va_start(ap, name);
5216 for (;;) {
5217 type = va_arg(ap, enum pevent_func_arg_type);
5218 if (type == PEVENT_FUNC_ARG_VOID)
5219 break;
5220
5221 if (type < 0 || type >= PEVENT_FUNC_ARG_MAX_TYPES) {
Namhyung Kim67ed9392012-09-07 11:49:47 +09005222 do_warning("Invalid argument type %d", type);
5223 ret = PEVENT_ERRNO__INVALID_ARG_TYPE;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005224 goto out_free;
5225 }
5226
Namhyung Kim67ed9392012-09-07 11:49:47 +09005227 param = malloc(sizeof(*param));
5228 if (!param) {
5229 do_warning("Failed to allocate function param");
5230 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
5231 goto out_free;
5232 }
Steven Rostedtf7d82352012-04-06 00:47:53 +02005233 param->type = type;
5234 param->next = NULL;
5235
5236 *next_param = param;
5237 next_param = &(param->next);
5238
5239 func_handle->nr_args++;
5240 }
5241 va_end(ap);
5242
5243 func_handle->next = pevent->func_handlers;
5244 pevent->func_handlers = func_handle;
5245
5246 return 0;
5247 out_free:
5248 va_end(ap);
5249 free_func_handle(func_handle);
Namhyung Kim67ed9392012-09-07 11:49:47 +09005250 return ret;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005251}
5252
5253/**
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09005254 * pevent_register_event_handler - register a way to parse an event
Steven Rostedtf7d82352012-04-06 00:47:53 +02005255 * @pevent: the handle to the pevent
5256 * @id: the id of the event to register
5257 * @sys_name: the system name the event belongs to
5258 * @event_name: the name of the event
5259 * @func: the function to call to parse the event information
Namhyung Kim16e6b8f2012-04-23 13:58:35 +09005260 * @context: the data to be passed to @func
Steven Rostedtf7d82352012-04-06 00:47:53 +02005261 *
5262 * This function allows a developer to override the parsing of
5263 * a given event. If for some reason the default print format
5264 * is not sufficient, this function will register a function
5265 * for an event to be used to parse the data instead.
5266 *
5267 * If @id is >= 0, then it is used to find the event.
5268 * else @sys_name and @event_name are used.
5269 */
5270int pevent_register_event_handler(struct pevent *pevent,
5271 int id, char *sys_name, char *event_name,
5272 pevent_event_handler_func func,
5273 void *context)
5274{
5275 struct event_format *event;
5276 struct event_handler *handle;
5277
5278 if (id >= 0) {
5279 /* search by id */
5280 event = pevent_find_event(pevent, id);
5281 if (!event)
5282 goto not_found;
5283 if (event_name && (strcmp(event_name, event->name) != 0))
5284 goto not_found;
5285 if (sys_name && (strcmp(sys_name, event->system) != 0))
5286 goto not_found;
5287 } else {
5288 event = pevent_find_event_by_name(pevent, sys_name, event_name);
5289 if (!event)
5290 goto not_found;
5291 }
5292
5293 pr_stat("overriding event (%d) %s:%s with new print handler",
5294 event->id, event->system, event->name);
5295
5296 event->handler = func;
5297 event->context = context;
5298 return 0;
5299
5300 not_found:
5301 /* Save for later use. */
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -03005302 handle = calloc(1, sizeof(*handle));
Namhyung Kim0ca8da02012-09-07 11:49:46 +09005303 if (!handle) {
5304 do_warning("Failed to allocate event handler");
5305 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
5306 }
5307
Steven Rostedtf7d82352012-04-06 00:47:53 +02005308 handle->id = id;
5309 if (event_name)
5310 handle->event_name = strdup(event_name);
5311 if (sys_name)
5312 handle->sys_name = strdup(sys_name);
5313
Namhyung Kimca638582012-04-09 11:54:31 +09005314 if ((event_name && !handle->event_name) ||
5315 (sys_name && !handle->sys_name)) {
Namhyung Kim0ca8da02012-09-07 11:49:46 +09005316 do_warning("Failed to allocate event/sys name");
5317 free((void *)handle->event_name);
5318 free((void *)handle->sys_name);
5319 free(handle);
5320 return PEVENT_ERRNO__MEM_ALLOC_FAILED;
Namhyung Kimca638582012-04-09 11:54:31 +09005321 }
5322
Steven Rostedtf7d82352012-04-06 00:47:53 +02005323 handle->func = func;
5324 handle->next = pevent->handlers;
5325 pevent->handlers = handle;
5326 handle->context = context;
5327
5328 return -1;
5329}
5330
5331/**
5332 * pevent_alloc - create a pevent handle
5333 */
5334struct pevent *pevent_alloc(void)
5335{
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -03005336 struct pevent *pevent = calloc(1, sizeof(*pevent));
Steven Rostedtf7d82352012-04-06 00:47:53 +02005337
Arnaldo Carvalho de Melo87162d82012-09-12 15:39:59 -03005338 if (pevent)
5339 pevent->ref_count = 1;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005340
5341 return pevent;
5342}
5343
5344void pevent_ref(struct pevent *pevent)
5345{
5346 pevent->ref_count++;
5347}
5348
5349static void free_format_fields(struct format_field *field)
5350{
5351 struct format_field *next;
5352
5353 while (field) {
5354 next = field->next;
5355 free(field->type);
5356 free(field->name);
5357 free(field);
5358 field = next;
5359 }
5360}
5361
5362static void free_formats(struct format *format)
5363{
5364 free_format_fields(format->common_fields);
5365 free_format_fields(format->fields);
5366}
5367
5368static void free_event(struct event_format *event)
5369{
5370 free(event->name);
5371 free(event->system);
5372
5373 free_formats(&event->format);
5374
5375 free(event->print_fmt.format);
5376 free_args(event->print_fmt.args);
5377
5378 free(event);
5379}
5380
5381/**
5382 * pevent_free - free a pevent handle
5383 * @pevent: the pevent handle to free
5384 */
5385void pevent_free(struct pevent *pevent)
5386{
Steven Rostedta2525a02012-04-06 00:48:02 +02005387 struct cmdline_list *cmdlist, *cmdnext;
5388 struct func_list *funclist, *funcnext;
5389 struct printk_list *printklist, *printknext;
Steven Rostedtf7d82352012-04-06 00:47:53 +02005390 struct pevent_function_handler *func_handler;
5391 struct event_handler *handle;
5392 int i;
5393
Steven Rostedta2525a02012-04-06 00:48:02 +02005394 if (!pevent)
5395 return;
5396
5397 cmdlist = pevent->cmdlist;
5398 funclist = pevent->funclist;
5399 printklist = pevent->printklist;
5400
Steven Rostedtf7d82352012-04-06 00:47:53 +02005401 pevent->ref_count--;
5402 if (pevent->ref_count)
5403 return;
5404
5405 if (pevent->cmdlines) {
5406 for (i = 0; i < pevent->cmdline_count; i++)
5407 free(pevent->cmdlines[i].comm);
5408 free(pevent->cmdlines);
5409 }
5410
5411 while (cmdlist) {
5412 cmdnext = cmdlist->next;
5413 free(cmdlist->comm);
5414 free(cmdlist);
5415 cmdlist = cmdnext;
5416 }
5417
5418 if (pevent->func_map) {
5419 for (i = 0; i < pevent->func_count; i++) {
5420 free(pevent->func_map[i].func);
5421 free(pevent->func_map[i].mod);
5422 }
5423 free(pevent->func_map);
5424 }
5425
5426 while (funclist) {
5427 funcnext = funclist->next;
5428 free(funclist->func);
5429 free(funclist->mod);
5430 free(funclist);
5431 funclist = funcnext;
5432 }
5433
5434 while (pevent->func_handlers) {
5435 func_handler = pevent->func_handlers;
5436 pevent->func_handlers = func_handler->next;
5437 free_func_handle(func_handler);
5438 }
5439
5440 if (pevent->printk_map) {
5441 for (i = 0; i < pevent->printk_count; i++)
5442 free(pevent->printk_map[i].printk);
5443 free(pevent->printk_map);
5444 }
5445
5446 while (printklist) {
5447 printknext = printklist->next;
5448 free(printklist->printk);
5449 free(printklist);
5450 printklist = printknext;
5451 }
5452
5453 for (i = 0; i < pevent->nr_events; i++)
5454 free_event(pevent->events[i]);
5455
5456 while (pevent->handlers) {
5457 handle = pevent->handlers;
5458 pevent->handlers = handle->next;
5459 free_handler(handle);
5460 }
5461
5462 free(pevent->events);
5463 free(pevent->sort_events);
5464
5465 free(pevent);
5466}
5467
5468void pevent_unref(struct pevent *pevent)
5469{
5470 pevent_free(pevent);
5471}