aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorSteven Rostedt <rostedt@goodmis.org>2009-08-17 10:18:07 -0400
committerIngo Molnar <mingo@elte.hu>2009-08-17 10:32:39 -0400
commitea4010d1363699770a9894493bafe556a59a144c (patch)
tree981f2c00b3c7365e2562a3f7b928deec0ecf470a /tools/perf/util
parent538bafb5cc92a86d97b427421231f185574fe3db (diff)
perf tools: Add trace event information parser
Add util/trace-event-parse.c which provides the handlers to parse the ftrace events info from the stream and handles the ftrace perf samples event printing. This file is a rename of the parse-events.c file from the trace-cmd tools, written by Steven Rostedt and Josh Triplett, originated from the git tree: git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git This is a perf tools integration. [ fweisbec@gmail.com: various changes for perf tools integration. ] Signed-off-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: "Luis Claudio R. Goncalves" <lclaudio@uudg.org> Cc: Clark Williams <williams@redhat.com> Cc: Jon Masters <jonathan@jonmasters.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> Cc: Christoph Hellwig <hch@infradead.org> Cc: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> Cc: Zhaolei <zhaolei@cn.fujitsu.com> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Lai Jiangshan <laijs@cn.fujitsu.com> Cc: Masami Hiramatsu <mhiramat@redhat.com> Cc: Tom Zanussi <tzanussi@gmail.com> Cc: "Frank Ch. Eigler" <fche@redhat.com> Cc: Roland McGrath <roland@redhat.com> Cc: Jason Baron <jbaron@redhat.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Jiaying Zhang <jiayingz@google.com> Cc: Anton Blanchard <anton@samba.org> LKML-Reference: <1250518688-7207-3-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/trace-event-parse.c2905
1 files changed, 2905 insertions, 0 deletions
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
new file mode 100644
index 000000000000..ead6a9ad3599
--- /dev/null
+++ b/tools/perf/util/trace-event-parse.c
@@ -0,0 +1,2905 @@
1/*
2 * Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 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 General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 *
21 * The parts for function graph printing was taken and modified from the
22 * Linux Kernel that were written by Frederic Weisbecker.
23 */
24#define _GNU_SOURCE
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <ctype.h>
29#include <errno.h>
30
31#undef _GNU_SOURCE
32#include "util.h"
33#include "trace-event.h"
34
35int header_page_ts_offset;
36int header_page_ts_size;
37int header_page_size_offset;
38int header_page_size_size;
39int header_page_data_offset;
40int header_page_data_size;
41
42static char *input_buf;
43static unsigned long long input_buf_ptr;
44static unsigned long long input_buf_siz;
45
46static int cpus;
47static int long_size;
48
49static void init_input_buf(char *buf, unsigned long long size)
50{
51 input_buf = buf;
52 input_buf_siz = size;
53 input_buf_ptr = 0;
54}
55
56struct cmdline {
57 char *comm;
58 int pid;
59};
60
61static struct cmdline *cmdlines;
62static int cmdline_count;
63
64static int cmdline_cmp(const void *a, const void *b)
65{
66 const struct cmdline *ca = a;
67 const struct cmdline *cb = b;
68
69 if (ca->pid < cb->pid)
70 return -1;
71 if (ca->pid > cb->pid)
72 return 1;
73
74 return 0;
75}
76
77void parse_cmdlines(char *file, int size __unused)
78{
79 struct cmdline_list {
80 struct cmdline_list *next;
81 char *comm;
82 int pid;
83 } *list = NULL, *item;
84 char *line;
85 char *next = NULL;
86 int i;
87
88 line = strtok_r(file, "\n", &next);
89 while (line) {
90 item = malloc_or_die(sizeof(*item));
91 sscanf(line, "%d %as", &item->pid,
92 (float *)&item->comm); /* workaround gcc warning */
93 item->next = list;
94 list = item;
95 line = strtok_r(NULL, "\n", &next);
96 cmdline_count++;
97 }
98
99 cmdlines = malloc_or_die(sizeof(*cmdlines) * cmdline_count);
100
101 i = 0;
102 while (list) {
103 cmdlines[i].pid = list->pid;
104 cmdlines[i].comm = list->comm;
105 i++;
106 item = list;
107 list = list->next;
108 free(item);
109 }
110
111 qsort(cmdlines, cmdline_count, sizeof(*cmdlines), cmdline_cmp);
112}
113
114static struct func_map {
115 unsigned long long addr;
116 char *func;
117 char *mod;
118} *func_list;
119static unsigned int func_count;
120
121static int func_cmp(const void *a, const void *b)
122{
123 const struct func_map *fa = a;
124 const struct func_map *fb = b;
125
126 if (fa->addr < fb->addr)
127 return -1;
128 if (fa->addr > fb->addr)
129 return 1;
130
131 return 0;
132}
133
134void parse_proc_kallsyms(char *file, unsigned int size __unused)
135{
136 struct func_list {
137 struct func_list *next;
138 unsigned long long addr;
139 char *func;
140 char *mod;
141 } *list = NULL, *item;
142 char *line;
143 char *next = NULL;
144 char *addr_str;
145 char ch;
146 int ret;
147 int i;
148
149 line = strtok_r(file, "\n", &next);
150 while (line) {
151 item = malloc_or_die(sizeof(*item));
152 item->mod = NULL;
153 ret = sscanf(line, "%as %c %as\t[%as",
154 (float *)&addr_str, /* workaround gcc warning */
155 &ch,
156 (float *)&item->func,
157 (float *)&item->mod);
158 item->addr = strtoull(addr_str, NULL, 16);
159 free(addr_str);
160
161 /* truncate the extra ']' */
162 if (item->mod)
163 item->mod[strlen(item->mod) - 1] = 0;
164
165
166 item->next = list;
167 list = item;
168 line = strtok_r(NULL, "\n", &next);
169 func_count++;
170 }
171
172 func_list = malloc_or_die(sizeof(*func_list) * func_count + 1);
173
174 i = 0;
175 while (list) {
176 func_list[i].func = list->func;
177 func_list[i].addr = list->addr;
178 func_list[i].mod = list->mod;
179 i++;
180 item = list;
181 list = list->next;
182 free(item);
183 }
184
185 qsort(func_list, func_count, sizeof(*func_list), func_cmp);
186
187 /*
188 * Add a special record at the end.
189 */
190 func_list[func_count].func = NULL;
191 func_list[func_count].addr = 0;
192 func_list[func_count].mod = NULL;
193}
194
195/*
196 * We are searching for a record in between, not an exact
197 * match.
198 */
199static int func_bcmp(const void *a, const void *b)
200{
201 const struct func_map *fa = a;
202 const struct func_map *fb = b;
203
204 if ((fa->addr == fb->addr) ||
205
206 (fa->addr > fb->addr &&
207 fa->addr < (fb+1)->addr))
208 return 0;
209
210 if (fa->addr < fb->addr)
211 return -1;
212
213 return 1;
214}
215
216static struct func_map *find_func(unsigned long long addr)
217{
218 struct func_map *func;
219 struct func_map key;
220
221 key.addr = addr;
222
223 func = bsearch(&key, func_list, func_count, sizeof(*func_list),
224 func_bcmp);
225
226 return func;
227}
228
229void print_funcs(void)
230{
231 int i;
232
233 for (i = 0; i < (int)func_count; i++) {
234 printf("%016llx %s",
235 func_list[i].addr,
236 func_list[i].func);
237 if (func_list[i].mod)
238 printf(" [%s]\n", func_list[i].mod);
239 else
240 printf("\n");
241 }
242}
243
244static struct printk_map {
245 unsigned long long addr;
246 char *printk;
247} *printk_list;
248static unsigned int printk_count;
249
250static int printk_cmp(const void *a, const void *b)
251{
252 const struct func_map *fa = a;
253 const struct func_map *fb = b;
254
255 if (fa->addr < fb->addr)
256 return -1;
257 if (fa->addr > fb->addr)
258 return 1;
259
260 return 0;
261}
262
263static struct printk_map *find_printk(unsigned long long addr)
264{
265 struct printk_map *printk;
266 struct printk_map key;
267
268 key.addr = addr;
269
270 printk = bsearch(&key, printk_list, printk_count, sizeof(*printk_list),
271 printk_cmp);
272
273 return printk;
274}
275
276void parse_ftrace_printk(char *file, unsigned int size __unused)
277{
278 struct printk_list {
279 struct printk_list *next;
280 unsigned long long addr;
281 char *printk;
282 } *list = NULL, *item;
283 char *line;
284 char *next = NULL;
285 char *addr_str;
286 int ret;
287 int i;
288
289 line = strtok_r(file, "\n", &next);
290 while (line) {
291 item = malloc_or_die(sizeof(*item));
292 ret = sscanf(line, "%as : %as",
293 (float *)&addr_str, /* workaround gcc warning */
294 (float *)&item->printk);
295 item->addr = strtoull(addr_str, NULL, 16);
296 free(addr_str);
297
298 item->next = list;
299 list = item;
300 line = strtok_r(NULL, "\n", &next);
301 printk_count++;
302 }
303
304 printk_list = malloc_or_die(sizeof(*printk_list) * printk_count + 1);
305
306 i = 0;
307 while (list) {
308 printk_list[i].printk = list->printk;
309 printk_list[i].addr = list->addr;
310 i++;
311 item = list;
312 list = list->next;
313 free(item);
314 }
315
316 qsort(printk_list, printk_count, sizeof(*printk_list), printk_cmp);
317}
318
319void print_printk(void)
320{
321 int i;
322
323 for (i = 0; i < (int)printk_count; i++) {
324 printf("%016llx %s\n",
325 printk_list[i].addr,
326 printk_list[i].printk);
327 }
328}
329
330static struct event *alloc_event(void)
331{
332 struct event *event;
333
334 event = malloc_or_die(sizeof(*event));
335 memset(event, 0, sizeof(*event));
336
337 return event;
338}
339
340enum event_type {
341 EVENT_ERROR,
342 EVENT_NONE,
343 EVENT_SPACE,
344 EVENT_NEWLINE,
345 EVENT_OP,
346 EVENT_DELIM,
347 EVENT_ITEM,
348 EVENT_DQUOTE,
349 EVENT_SQUOTE,
350};
351
352static struct event *event_list;
353
354static void add_event(struct event *event)
355{
356 event->next = event_list;
357 event_list = event;
358}
359
360static int event_item_type(enum event_type type)
361{
362 switch (type) {
363 case EVENT_ITEM ... EVENT_SQUOTE:
364 return 1;
365 case EVENT_ERROR ... EVENT_DELIM:
366 default:
367 return 0;
368 }
369}
370
371static void free_arg(struct print_arg *arg)
372{
373 if (!arg)
374 return;
375
376 switch (arg->type) {
377 case PRINT_ATOM:
378 if (arg->atom.atom)
379 free(arg->atom.atom);
380 break;
381 case PRINT_NULL:
382 case PRINT_FIELD ... PRINT_OP:
383 default:
384 /* todo */
385 break;
386 }
387
388 free(arg);
389}
390
391static enum event_type get_type(int ch)
392{
393 if (ch == '\n')
394 return EVENT_NEWLINE;
395 if (isspace(ch))
396 return EVENT_SPACE;
397 if (isalnum(ch) || ch == '_')
398 return EVENT_ITEM;
399 if (ch == '\'')
400 return EVENT_SQUOTE;
401 if (ch == '"')
402 return EVENT_DQUOTE;
403 if (!isprint(ch))
404 return EVENT_NONE;
405 if (ch == '(' || ch == ')' || ch == ',')
406 return EVENT_DELIM;
407
408 return EVENT_OP;
409}
410
411static int __read_char(void)
412{
413 if (input_buf_ptr >= input_buf_siz)
414 return -1;
415
416 return input_buf[input_buf_ptr++];
417}
418
419static int __peek_char(void)
420{
421 if (input_buf_ptr >= input_buf_siz)
422 return -1;
423
424 return input_buf[input_buf_ptr];
425}
426
427static enum event_type __read_token(char **tok)
428{
429 char buf[BUFSIZ];
430 int ch, last_ch, quote_ch, next_ch;
431 int i = 0;
432 int tok_size = 0;
433 enum event_type type;
434
435 *tok = NULL;
436
437
438 ch = __read_char();
439 if (ch < 0)
440 return EVENT_NONE;
441
442 type = get_type(ch);
443 if (type == EVENT_NONE)
444 return type;
445
446 buf[i++] = ch;
447
448 switch (type) {
449 case EVENT_NEWLINE:
450 case EVENT_DELIM:
451 *tok = malloc_or_die(2);
452 (*tok)[0] = ch;
453 (*tok)[1] = 0;
454 return type;
455
456 case EVENT_OP:
457 switch (ch) {
458 case '-':
459 next_ch = __peek_char();
460 if (next_ch == '>') {
461 buf[i++] = __read_char();
462 break;
463 }
464 /* fall through */
465 case '+':
466 case '|':
467 case '&':
468 case '>':
469 case '<':
470 last_ch = ch;
471 ch = __peek_char();
472 if (ch != last_ch)
473 goto test_equal;
474 buf[i++] = __read_char();
475 switch (last_ch) {
476 case '>':
477 case '<':
478 goto test_equal;
479 default:
480 break;
481 }
482 break;
483 case '!':
484 case '=':
485 goto test_equal;
486 default: /* what should we do instead? */
487 break;
488 }
489 buf[i] = 0;
490 *tok = strdup(buf);
491 return type;
492
493 test_equal:
494 ch = __peek_char();
495 if (ch == '=')
496 buf[i++] = __read_char();
497 break;
498
499 case EVENT_DQUOTE:
500 case EVENT_SQUOTE:
501 /* don't keep quotes */
502 i--;
503 quote_ch = ch;
504 last_ch = 0;
505 do {
506 if (i == (BUFSIZ - 1)) {
507 buf[i] = 0;
508 if (*tok) {
509 *tok = realloc(*tok, tok_size + BUFSIZ);
510 if (!*tok)
511 return EVENT_NONE;
512 strcat(*tok, buf);
513 } else
514 *tok = strdup(buf);
515
516 if (!*tok)
517 return EVENT_NONE;
518 tok_size += BUFSIZ;
519 i = 0;
520 }
521 last_ch = ch;
522 ch = __read_char();
523 buf[i++] = ch;
524 } while (ch != quote_ch && last_ch != '\\');
525 /* remove the last quote */
526 i--;
527 goto out;
528
529 case EVENT_ERROR ... EVENT_SPACE:
530 case EVENT_ITEM:
531 default:
532 break;
533 }
534
535 while (get_type(__peek_char()) == type) {
536 if (i == (BUFSIZ - 1)) {
537 buf[i] = 0;
538 if (*tok) {
539 *tok = realloc(*tok, tok_size + BUFSIZ);
540 if (!*tok)
541 return EVENT_NONE;
542 strcat(*tok, buf);
543 } else
544 *tok = strdup(buf);
545
546 if (!*tok)
547 return EVENT_NONE;
548 tok_size += BUFSIZ;
549 i = 0;
550 }
551 ch = __read_char();
552 buf[i++] = ch;
553 }
554
555 out:
556 buf[i] = 0;
557 if (*tok) {
558 *tok = realloc(*tok, tok_size + i);
559 if (!*tok)
560 return EVENT_NONE;
561 strcat(*tok, buf);
562 } else
563 *tok = strdup(buf);
564 if (!*tok)
565 return EVENT_NONE;
566
567 return type;
568}
569
570static void free_token(char *tok)
571{
572 if (tok)
573 free(tok);
574}
575
576static enum event_type read_token(char **tok)
577{
578 enum event_type type;
579
580 for (;;) {
581 type = __read_token(tok);
582 if (type != EVENT_SPACE)
583 return type;
584
585 free_token(*tok);
586 }
587
588 /* not reached */
589 return EVENT_NONE;
590}
591
592/* no newline */
593static enum event_type read_token_item(char **tok)
594{
595 enum event_type type;
596
597 for (;;) {
598 type = __read_token(tok);
599 if (type != EVENT_SPACE && type != EVENT_NEWLINE)
600 return type;
601
602 free_token(*tok);
603 }
604
605 /* not reached */
606 return EVENT_NONE;
607}
608
609static int test_type(enum event_type type, enum event_type expect)
610{
611 if (type != expect) {
612 die("Error: expected type %d but read %d",
613 expect, type);
614 return -1;
615 }
616 return 0;
617}
618
619static int test_type_token(enum event_type type, char *token,
620 enum event_type expect, char *expect_tok)
621{
622 if (type != expect) {
623 die("Error: expected type %d but read %d",
624 expect, type);
625 return -1;
626 }
627
628 if (strcmp(token, expect_tok) != 0) {
629 die("Error: expected '%s' but read '%s'",
630 expect_tok, token);
631 return -1;
632 }
633 return 0;
634}
635
636static int __read_expect_type(enum event_type expect, char **tok, int newline_ok)
637{
638 enum event_type type;
639
640 if (newline_ok)
641 type = read_token(tok);
642 else
643 type = read_token_item(tok);
644 return test_type(type, expect);
645}
646
647static int read_expect_type(enum event_type expect, char **tok)
648{
649 return __read_expect_type(expect, tok, 1);
650}
651
652static int __read_expected(enum event_type expect, char *str, int newline_ok)
653{
654 enum event_type type;
655 char *token;
656 int ret;
657
658 if (newline_ok)
659 type = read_token(&token);
660 else
661 type = read_token_item(&token);
662
663 ret = test_type_token(type, token, expect, str);
664
665 free_token(token);
666
667 return 0;
668}
669
670static int read_expected(enum event_type expect, char *str)
671{
672 return __read_expected(expect, str, 1);
673}
674
675static int read_expected_item(enum event_type expect, char *str)
676{
677 return __read_expected(expect, str, 0);
678}
679
680static char *event_read_name(void)
681{
682 char *token;
683
684 if (read_expected(EVENT_ITEM, (char *)"name") < 0)
685 return NULL;
686
687 if (read_expected(EVENT_OP, (char *)":") < 0)
688 return NULL;
689
690 if (read_expect_type(EVENT_ITEM, &token) < 0)
691 goto fail;
692
693 return token;
694
695 fail:
696 free_token(token);
697 return NULL;
698}
699
700static int event_read_id(void)
701{
702 char *token;
703 int id;
704
705 if (read_expected_item(EVENT_ITEM, (char *)"ID") < 0)
706 return -1;
707
708 if (read_expected(EVENT_OP, (char *)":") < 0)
709 return -1;
710
711 if (read_expect_type(EVENT_ITEM, &token) < 0)
712 goto fail;
713
714 id = strtoul(token, NULL, 0);
715 free_token(token);
716 return id;
717
718 fail:
719 free_token(token);
720 return -1;
721}
722
723static int event_read_fields(struct event *event, struct format_field **fields)
724{
725 struct format_field *field = NULL;
726 enum event_type type;
727 char *token;
728 char *last_token;
729 int count = 0;
730
731 do {
732 type = read_token(&token);
733 if (type == EVENT_NEWLINE) {
734 free_token(token);
735 return count;
736 }
737
738 count++;
739
740 if (test_type_token(type, token, EVENT_ITEM, (char *)"field"))
741 goto fail;
742 free_token(token);
743
744 type = read_token(&token);
745 /*
746 * The ftrace fields may still use the "special" name.
747 * Just ignore it.
748 */
749 if (event->flags & EVENT_FL_ISFTRACE &&
750 type == EVENT_ITEM && strcmp(token, "special") == 0) {
751 free_token(token);
752 type = read_token(&token);
753 }
754
755 if (test_type_token(type, token, EVENT_OP, (char *)":") < 0)
756 return -1;
757
758 if (read_expect_type(EVENT_ITEM, &token) < 0)
759 goto fail;
760
761 last_token = token;
762
763 field = malloc_or_die(sizeof(*field));
764 memset(field, 0, sizeof(*field));
765
766 /* read the rest of the type */
767 for (;;) {
768 type = read_token(&token);
769 if (type == EVENT_ITEM ||
770 (type == EVENT_OP && strcmp(token, "*") == 0) ||
771 /*
772 * Some of the ftrace fields are broken and have
773 * an illegal "." in them.
774 */
775 (event->flags & EVENT_FL_ISFTRACE &&
776 type == EVENT_OP && strcmp(token, ".") == 0)) {
777
778 if (strcmp(token, "*") == 0)
779 field->flags |= FIELD_IS_POINTER;
780
781 if (field->type) {
782 field->type = realloc(field->type,
783 strlen(field->type) +
784 strlen(last_token) + 2);
785 strcat(field->type, " ");
786 strcat(field->type, last_token);
787 } else
788 field->type = last_token;
789 last_token = token;
790 continue;
791 }
792
793 break;
794 }
795
796 if (!field->type) {
797 die("no type found");
798 goto fail;
799 }
800 field->name = last_token;
801
802 if (test_type(type, EVENT_OP))
803 goto fail;
804
805 if (strcmp(token, "[") == 0) {
806 enum event_type last_type = type;
807 char *brackets = token;
808 int len;
809
810 field->flags |= FIELD_IS_ARRAY;
811
812 type = read_token(&token);
813 while (strcmp(token, "]") != 0) {
814 if (last_type == EVENT_ITEM &&
815 type == EVENT_ITEM)
816 len = 2;
817 else
818 len = 1;
819 last_type = type;
820
821 brackets = realloc(brackets,
822 strlen(brackets) +
823 strlen(token) + len);
824 if (len == 2)
825 strcat(brackets, " ");
826 strcat(brackets, token);
827 free_token(token);
828 type = read_token(&token);
829 if (type == EVENT_NONE) {
830 die("failed to find token");
831 goto fail;
832 }
833 }
834
835 free_token(token);
836
837 brackets = realloc(brackets, strlen(brackets) + 2);
838 strcat(brackets, "]");
839
840 /* add brackets to type */
841
842 type = read_token(&token);
843 /*
844 * If the next token is not an OP, then it is of
845 * the format: type [] item;
846 */
847 if (type == EVENT_ITEM) {
848 field->type = realloc(field->type,
849 strlen(field->type) +
850 strlen(field->name) +
851 strlen(brackets) + 2);
852 strcat(field->type, " ");
853 strcat(field->type, field->name);
854 free_token(field->name);
855 strcat(field->type, brackets);
856 field->name = token;
857 type = read_token(&token);
858 } else {
859 field->type = realloc(field->type,
860 strlen(field->type) +
861 strlen(brackets) + 1);
862 strcat(field->type, brackets);
863 }
864 free(brackets);
865 }
866
867 if (test_type_token(type, token, EVENT_OP, (char *)";"))
868 goto fail;
869 free_token(token);
870
871 if (read_expected(EVENT_ITEM, (char *)"offset") < 0)
872 goto fail_expect;
873
874 if (read_expected(EVENT_OP, (char *)":") < 0)
875 goto fail_expect;
876
877 if (read_expect_type(EVENT_ITEM, &token))
878 goto fail;
879 field->offset = strtoul(token, NULL, 0);
880 free_token(token);
881
882 if (read_expected(EVENT_OP, (char *)";") < 0)
883 goto fail_expect;
884
885 if (read_expected(EVENT_ITEM, (char *)"size") < 0)
886 goto fail_expect;
887
888 if (read_expected(EVENT_OP, (char *)":") < 0)
889 goto fail_expect;
890
891 if (read_expect_type(EVENT_ITEM, &token))
892 goto fail;
893 field->size = strtoul(token, NULL, 0);
894 free_token(token);
895
896 if (read_expected(EVENT_OP, (char *)";") < 0)
897 goto fail_expect;
898
899 if (read_expect_type(EVENT_NEWLINE, &token) < 0)
900 goto fail;
901 free_token(token);
902
903 *fields = field;
904 fields = &field->next;
905
906 } while (1);
907
908 return 0;
909
910fail:
911 free_token(token);
912fail_expect:
913 if (field)
914 free(field);
915 return -1;
916}
917
918static int event_read_format(struct event *event)
919{
920 char *token;
921 int ret;
922
923 if (read_expected_item(EVENT_ITEM, (char *)"format") < 0)
924 return -1;
925
926 if (read_expected(EVENT_OP, (char *)":") < 0)
927 return -1;
928
929 if (read_expect_type(EVENT_NEWLINE, &token))
930 goto fail;
931 free_token(token);
932
933 ret = event_read_fields(event, &event->format.common_fields);
934 if (ret < 0)
935 return ret;
936 event->format.nr_common = ret;
937
938 ret = event_read_fields(event, &event->format.fields);
939 if (ret < 0)
940 return ret;
941 event->format.nr_fields = ret;
942
943 return 0;
944
945 fail:
946 free_token(token);
947 return -1;
948}
949
950enum event_type
951process_arg_token(struct event *event, struct print_arg *arg,
952 char **tok, enum event_type type);
953
954static enum event_type
955process_arg(struct event *event, struct print_arg *arg, char **tok)
956{
957 enum event_type type;
958 char *token;
959
960 type = read_token(&token);
961 *tok = token;
962
963 return process_arg_token(event, arg, tok, type);
964}
965
966static enum event_type
967process_cond(struct event *event, struct print_arg *top, char **tok)
968{
969 struct print_arg *arg, *left, *right;
970 enum event_type type;
971 char *token = NULL;
972
973 arg = malloc_or_die(sizeof(*arg));
974 memset(arg, 0, sizeof(*arg));
975
976 left = malloc_or_die(sizeof(*left));
977
978 right = malloc_or_die(sizeof(*right));
979
980 arg->type = PRINT_OP;
981 arg->op.left = left;
982 arg->op.right = right;
983
984 *tok = NULL;
985 type = process_arg(event, left, &token);
986 if (test_type_token(type, token, EVENT_OP, (char *)":"))
987 goto out_free;
988
989 arg->op.op = token;
990
991 type = process_arg(event, right, &token);
992
993 top->op.right = arg;
994
995 *tok = token;
996 return type;
997
998out_free:
999 free_token(*tok);
1000 free(right);
1001 free(left);
1002 free_arg(arg);
1003 return EVENT_ERROR;
1004}
1005
1006static int get_op_prio(char *op)
1007{
1008 if (!op[1]) {
1009 switch (op[0]) {
1010 case '*':
1011 case '/':
1012 case '%':
1013 return 6;
1014 case '+':
1015 case '-':
1016 return 7;
1017 /* '>>' and '<<' are 8 */
1018 case '<':
1019 case '>':
1020 return 9;
1021 /* '==' and '!=' are 10 */
1022 case '&':
1023 return 11;
1024 case '^':
1025 return 12;
1026 case '|':
1027 return 13;
1028 case '?':
1029 return 16;
1030 default:
1031 die("unknown op '%c'", op[0]);
1032 return -1;
1033 }
1034 } else {
1035 if (strcmp(op, "++") == 0 ||
1036 strcmp(op, "--") == 0) {
1037 return 3;
1038 } else if (strcmp(op, ">>") == 0 ||
1039 strcmp(op, "<<") == 0) {
1040 return 8;
1041 } else if (strcmp(op, ">=") == 0 ||
1042 strcmp(op, "<=") == 0) {
1043 return 9;
1044 } else if (strcmp(op, "==") == 0 ||
1045 strcmp(op, "!=") == 0) {
1046 return 10;
1047 } else if (strcmp(op, "&&") == 0) {
1048 return 14;
1049 } else if (strcmp(op, "||") == 0) {
1050 return 15;
1051 } else {
1052 die("unknown op '%s'", op);
1053 return -1;
1054 }
1055 }
1056}
1057
1058static void set_op_prio(struct print_arg *arg)
1059{
1060
1061 /* single ops are the greatest */
1062 if (!arg->op.left || arg->op.left->type == PRINT_NULL) {
1063 arg->op.prio = 0;
1064 return;
1065 }
1066
1067 arg->op.prio = get_op_prio(arg->op.op);
1068}
1069
1070static enum event_type
1071process_op(struct event *event, struct print_arg *arg, char **tok)
1072{
1073 struct print_arg *left, *right = NULL;
1074 enum event_type type;
1075 char *token;
1076
1077 /* the op is passed in via tok */
1078 token = *tok;
1079
1080 if (arg->type == PRINT_OP && !arg->op.left) {
1081 /* handle single op */
1082 if (token[1]) {
1083 die("bad op token %s", token);
1084 return EVENT_ERROR;
1085 }
1086 switch (token[0]) {
1087 case '!':
1088 case '+':
1089 case '-':
1090 break;
1091 default:
1092 die("bad op token %s", token);
1093 return EVENT_ERROR;
1094 }
1095
1096 /* make an empty left */
1097 left = malloc_or_die(sizeof(*left));
1098 left->type = PRINT_NULL;
1099 arg->op.left = left;
1100
1101 right = malloc_or_die(sizeof(*right));
1102 arg->op.right = right;
1103
1104 type = process_arg(event, right, tok);
1105
1106 } else if (strcmp(token, "?") == 0) {
1107
1108 left = malloc_or_die(sizeof(*left));
1109 /* copy the top arg to the left */
1110 *left = *arg;
1111
1112 arg->type = PRINT_OP;
1113 arg->op.op = token;
1114 arg->op.left = left;
1115 arg->op.prio = 0;
1116
1117 type = process_cond(event, arg, tok);
1118
1119 } else if (strcmp(token, ">>") == 0 ||
1120 strcmp(token, "<<") == 0 ||
1121 strcmp(token, "&") == 0 ||
1122 strcmp(token, "|") == 0 ||
1123 strcmp(token, "&&") == 0 ||
1124 strcmp(token, "||") == 0 ||
1125 strcmp(token, "-") == 0 ||
1126 strcmp(token, "+") == 0 ||
1127 strcmp(token, "*") == 0 ||
1128 strcmp(token, "^") == 0 ||
1129 strcmp(token, "/") == 0 ||
1130 strcmp(token, "==") == 0 ||
1131 strcmp(token, "!=") == 0) {
1132
1133 left = malloc_or_die(sizeof(*left));
1134
1135 /* copy the top arg to the left */
1136 *left = *arg;
1137
1138 arg->type = PRINT_OP;
1139 arg->op.op = token;
1140 arg->op.left = left;
1141
1142 set_op_prio(arg);
1143
1144 right = malloc_or_die(sizeof(*right));
1145
1146 type = process_arg(event, right, tok);
1147
1148 arg->op.right = right;
1149
1150 } else {
1151 die("unknown op '%s'", token);
1152 /* the arg is now the left side */
1153 return EVENT_NONE;
1154 }
1155
1156
1157 if (type == EVENT_OP) {
1158 int prio;
1159
1160 /* higher prios need to be closer to the root */
1161 prio = get_op_prio(*tok);
1162
1163 if (prio > arg->op.prio)
1164 return process_op(event, arg, tok);
1165
1166 return process_op(event, right, tok);
1167 }
1168
1169 return type;
1170}
1171
1172static enum event_type
1173process_entry(struct event *event __unused, struct print_arg *arg,
1174 char **tok)
1175{
1176 enum event_type type;
1177 char *field;
1178 char *token;
1179
1180 if (read_expected(EVENT_OP, (char *)"->") < 0)
1181 return EVENT_ERROR;
1182
1183 if (read_expect_type(EVENT_ITEM, &token) < 0)
1184 goto fail;
1185 field = token;
1186
1187 arg->type = PRINT_FIELD;
1188 arg->field.name = field;
1189
1190 type = read_token(&token);
1191 *tok = token;
1192
1193 return type;
1194
1195fail:
1196 free_token(token);
1197 return EVENT_ERROR;
1198}
1199
1200static char *arg_eval (struct print_arg *arg);
1201
1202static long long arg_num_eval(struct print_arg *arg)
1203{
1204 long long left, right;
1205 long long val = 0;
1206
1207 switch (arg->type) {
1208 case PRINT_ATOM:
1209 val = strtoll(arg->atom.atom, NULL, 0);
1210 break;
1211 case PRINT_TYPE:
1212 val = arg_num_eval(arg->typecast.item);
1213 break;
1214 case PRINT_OP:
1215 switch (arg->op.op[0]) {
1216 case '|':
1217 left = arg_num_eval(arg->op.left);
1218 right = arg_num_eval(arg->op.right);
1219 if (arg->op.op[1])
1220 val = left || right;
1221 else
1222 val = left | right;
1223 break;
1224 case '&':
1225 left = arg_num_eval(arg->op.left);
1226 right = arg_num_eval(arg->op.right);
1227 if (arg->op.op[1])
1228 val = left && right;
1229 else
1230 val = left & right;
1231 break;
1232 case '<':
1233 left = arg_num_eval(arg->op.left);
1234 right = arg_num_eval(arg->op.right);
1235 switch (arg->op.op[1]) {
1236 case 0:
1237 val = left < right;
1238 break;
1239 case '<':
1240 val = left << right;
1241 break;
1242 case '=':
1243 val = left <= right;
1244 break;
1245 default:
1246 die("unknown op '%s'", arg->op.op);
1247 }
1248 break;
1249 case '>':
1250 left = arg_num_eval(arg->op.left);
1251 right = arg_num_eval(arg->op.right);
1252 switch (arg->op.op[1]) {
1253 case 0:
1254 val = left > right;
1255 break;
1256 case '>':
1257 val = left >> right;
1258 break;
1259 case '=':
1260 val = left >= right;
1261 break;
1262 default:
1263 die("unknown op '%s'", arg->op.op);
1264 }
1265 break;
1266 case '=':
1267 left = arg_num_eval(arg->op.left);
1268 right = arg_num_eval(arg->op.right);
1269
1270 if (arg->op.op[1] != '=')
1271 die("unknown op '%s'", arg->op.op);
1272
1273 val = left == right;
1274 break;
1275 case '!':
1276 left = arg_num_eval(arg->op.left);
1277 right = arg_num_eval(arg->op.right);
1278
1279 switch (arg->op.op[1]) {
1280 case '=':
1281 val = left != right;
1282 break;
1283 default:
1284 die("unknown op '%s'", arg->op.op);
1285 }
1286 break;
1287 default:
1288 die("unknown op '%s'", arg->op.op);
1289 }
1290 break;
1291
1292 case PRINT_NULL:
1293 case PRINT_FIELD ... PRINT_SYMBOL:
1294 case PRINT_STRING:
1295 default:
1296 die("invalid eval type %d", arg->type);
1297
1298 }
1299 return val;
1300}
1301
1302static char *arg_eval (struct print_arg *arg)
1303{
1304 long long val;
1305 static char buf[20];
1306
1307 switch (arg->type) {
1308 case PRINT_ATOM:
1309 return arg->atom.atom;
1310 case PRINT_TYPE:
1311 return arg_eval(arg->typecast.item);
1312 case PRINT_OP:
1313 val = arg_num_eval(arg);
1314 sprintf(buf, "%lld", val);
1315 return buf;
1316
1317 case PRINT_NULL:
1318 case PRINT_FIELD ... PRINT_SYMBOL:
1319 case PRINT_STRING:
1320 default:
1321 die("invalid eval type %d", arg->type);
1322 break;
1323 }
1324
1325 return NULL;
1326}
1327
1328static enum event_type
1329process_fields(struct event *event, struct print_flag_sym **list, char **tok)
1330{
1331 enum event_type type;
1332 struct print_arg *arg = NULL;
1333 struct print_flag_sym *field;
1334 char *token = NULL;
1335 char *value;
1336
1337 do {
1338 free_token(token);
1339 type = read_token_item(&token);
1340 if (test_type_token(type, token, EVENT_OP, (char *)"{"))
1341 break;
1342
1343 arg = malloc_or_die(sizeof(*arg));
1344
1345 free_token(token);
1346 type = process_arg(event, arg, &token);
1347 if (test_type_token(type, token, EVENT_DELIM, (char *)","))
1348 goto out_free;
1349
1350 field = malloc_or_die(sizeof(*field));
1351 memset(field, 0, sizeof(field));
1352
1353 value = arg_eval(arg);
1354 field->value = strdup(value);
1355
1356 free_token(token);
1357 type = process_arg(event, arg, &token);
1358 if (test_type_token(type, token, EVENT_OP, (char *)"}"))
1359 goto out_free;
1360
1361 value = arg_eval(arg);
1362 field->str = strdup(value);
1363 free_arg(arg);
1364 arg = NULL;
1365
1366 *list = field;
1367 list = &field->next;
1368
1369 free_token(token);
1370 type = read_token_item(&token);
1371 } while (type == EVENT_DELIM && strcmp(token, ",") == 0);
1372
1373 *tok = token;
1374 return type;
1375
1376out_free:
1377 free_arg(arg);
1378 free_token(token);
1379
1380 return EVENT_ERROR;
1381}
1382
1383static enum event_type
1384process_flags(struct event *event, struct print_arg *arg, char **tok)
1385{
1386 struct print_arg *field;
1387 enum event_type type;
1388 char *token;
1389
1390 memset(arg, 0, sizeof(*arg));
1391 arg->type = PRINT_FLAGS;
1392
1393 if (read_expected_item(EVENT_DELIM, (char *)"(") < 0)
1394 return EVENT_ERROR;
1395
1396 field = malloc_or_die(sizeof(*field));
1397
1398 type = process_arg(event, field, &token);
1399 if (test_type_token(type, token, EVENT_DELIM, (char *)","))
1400 goto out_free;
1401
1402 arg->flags.field = field;
1403
1404 type = read_token_item(&token);
1405 if (event_item_type(type)) {
1406 arg->flags.delim = token;
1407 type = read_token_item(&token);
1408 }
1409
1410 if (test_type_token(type, token, EVENT_DELIM, (char *)","))
1411 goto out_free;
1412
1413 type = process_fields(event, &arg->flags.flags, &token);
1414 if (test_type_token(type, token, EVENT_DELIM, (char *)")"))
1415 goto out_free;
1416
1417 free_token(token);
1418 type = read_token_item(tok);
1419 return type;
1420
1421out_free:
1422 free_token(token);
1423 return EVENT_ERROR;
1424}
1425
1426static enum event_type
1427process_symbols(struct event *event, struct print_arg *arg, char **tok)
1428{
1429 struct print_arg *field;
1430 enum event_type type;
1431 char *token;
1432
1433 memset(arg, 0, sizeof(*arg));
1434 arg->type = PRINT_SYMBOL;
1435
1436 if (read_expected_item(EVENT_DELIM, (char *)"(") < 0)
1437 return EVENT_ERROR;
1438
1439 field = malloc_or_die(sizeof(*field));
1440
1441 type = process_arg(event, field, &token);
1442 if (test_type_token(type, token, EVENT_DELIM, (char *)","))
1443 goto out_free;
1444
1445 arg->symbol.field = field;
1446
1447 type = process_fields(event, &arg->symbol.symbols, &token);
1448 if (test_type_token(type, token, EVENT_DELIM, (char *)")"))
1449 goto out_free;
1450
1451 free_token(token);
1452 type = read_token_item(tok);
1453 return type;
1454
1455out_free:
1456 free_token(token);
1457 return EVENT_ERROR;
1458}
1459
1460static enum event_type
1461process_paren(struct event *event, struct print_arg *arg, char **tok)
1462{
1463 struct print_arg *item_arg;
1464 enum event_type type;
1465 char *token;
1466
1467 type = process_arg(event, arg, &token);
1468
1469 if (type == EVENT_ERROR)
1470 return EVENT_ERROR;
1471
1472 if (type == EVENT_OP)
1473 type = process_op(event, arg, &token);
1474
1475 if (type == EVENT_ERROR)
1476 return EVENT_ERROR;
1477
1478 if (test_type_token(type, token, EVENT_DELIM, (char *)")")) {
1479 free_token(token);
1480 return EVENT_ERROR;
1481 }
1482
1483 free_token(token);
1484 type = read_token_item(&token);
1485
1486 /*
1487 * If the next token is an item or another open paren, then
1488 * this was a typecast.
1489 */
1490 if (event_item_type(type) ||
1491 (type == EVENT_DELIM && strcmp(token, "(") == 0)) {
1492
1493 /* make this a typecast and contine */
1494
1495 /* prevous must be an atom */
1496 if (arg->type != PRINT_ATOM)
1497 die("previous needed to be PRINT_ATOM");
1498
1499 item_arg = malloc_or_die(sizeof(*item_arg));
1500
1501 arg->type = PRINT_TYPE;
1502 arg->typecast.type = arg->atom.atom;
1503 arg->typecast.item = item_arg;
1504 type = process_arg_token(event, item_arg, &token, type);
1505
1506 }
1507
1508 *tok = token;
1509 return type;
1510}
1511
1512
1513static enum event_type
1514process_str(struct event *event __unused, struct print_arg *arg, char **tok)
1515{
1516 enum event_type type;
1517 char *token;
1518
1519 if (read_expected(EVENT_DELIM, (char *)"(") < 0)
1520 return EVENT_ERROR;
1521
1522 if (read_expect_type(EVENT_ITEM, &token) < 0)
1523 goto fail;
1524
1525 arg->type = PRINT_STRING;
1526 arg->string.string = token;
1527
1528 if (read_expected(EVENT_DELIM, (char *)")") < 0)
1529 return EVENT_ERROR;
1530
1531 type = read_token(&token);
1532 *tok = token;
1533
1534 return type;
1535fail:
1536 free_token(token);
1537 return EVENT_ERROR;
1538}
1539
1540enum event_type
1541process_arg_token(struct event *event, struct print_arg *arg,
1542 char **tok, enum event_type type)
1543{
1544 char *token;
1545 char *atom;
1546
1547 token = *tok;
1548
1549 switch (type) {
1550 case EVENT_ITEM:
1551 if (strcmp(token, "REC") == 0) {
1552 free_token(token);
1553 type = process_entry(event, arg, &token);
1554 } else if (strcmp(token, "__print_flags") == 0) {
1555 free_token(token);
1556 type = process_flags(event, arg, &token);
1557 } else if (strcmp(token, "__print_symbolic") == 0) {
1558 free_token(token);
1559 type = process_symbols(event, arg, &token);
1560 } else if (strcmp(token, "__get_str") == 0) {
1561 free_token(token);
1562 type = process_str(event, arg, &token);
1563 } else {
1564 atom = token;
1565 /* test the next token */
1566 type = read_token_item(&token);
1567
1568 /* atoms can be more than one token long */
1569 while (type == EVENT_ITEM) {
1570 atom = realloc(atom, strlen(atom) + strlen(token) + 2);
1571 strcat(atom, " ");
1572 strcat(atom, token);
1573 free_token(token);
1574 type = read_token_item(&token);
1575 }
1576
1577 /* todo, test for function */
1578
1579 arg->type = PRINT_ATOM;
1580 arg->atom.atom = atom;
1581 }
1582 break;
1583 case EVENT_DQUOTE:
1584 case EVENT_SQUOTE:
1585 arg->type = PRINT_ATOM;
1586 arg->atom.atom = token;
1587 type = read_token_item(&token);
1588 break;
1589 case EVENT_DELIM:
1590 if (strcmp(token, "(") == 0) {
1591 free_token(token);
1592 type = process_paren(event, arg, &token);
1593 break;
1594 }
1595 case EVENT_OP:
1596 /* handle single ops */
1597 arg->type = PRINT_OP;
1598 arg->op.op = token;
1599 arg->op.left = NULL;
1600 type = process_op(event, arg, &token);
1601
1602 break;
1603
1604 case EVENT_ERROR ... EVENT_NEWLINE:
1605 default:
1606 die("unexpected type %d", type);
1607 }
1608 *tok = token;
1609
1610 return type;
1611}
1612
1613static int event_read_print_args(struct event *event, struct print_arg **list)
1614{
1615 enum event_type type;
1616 struct print_arg *arg;
1617 char *token;
1618 int args = 0;
1619
1620 do {
1621 arg = malloc_or_die(sizeof(*arg));
1622 memset(arg, 0, sizeof(*arg));
1623
1624 type = process_arg(event, arg, &token);
1625
1626 if (type == EVENT_ERROR) {
1627 free_arg(arg);
1628 return -1;
1629 }
1630
1631 *list = arg;
1632 args++;
1633
1634 if (type == EVENT_OP) {
1635 type = process_op(event, arg, &token);
1636 list = &arg->next;
1637 continue;
1638 }
1639
1640 if (type == EVENT_DELIM && strcmp(token, ",") == 0) {
1641 free_token(token);
1642 *list = arg;
1643 list = &arg->next;
1644 continue;
1645 }
1646 break;
1647 } while (type != EVENT_NONE);
1648
1649 if (type != EVENT_NONE)
1650 free_token(token);
1651
1652 return args;
1653}
1654
1655static int event_read_print(struct event *event)
1656{
1657 enum event_type type;
1658 char *token;
1659 int ret;
1660
1661 if (read_expected_item(EVENT_ITEM, (char *)"print") < 0)
1662 return -1;
1663
1664 if (read_expected(EVENT_ITEM, (char *)"fmt") < 0)
1665 return -1;
1666
1667 if (read_expected(EVENT_OP, (char *)":") < 0)
1668 return -1;
1669
1670 if (read_expect_type(EVENT_DQUOTE, &token) < 0)
1671 goto fail;
1672
1673 event->print_fmt.format = token;
1674 event->print_fmt.args = NULL;
1675
1676 /* ok to have no arg */
1677 type = read_token_item(&token);
1678
1679 if (type == EVENT_NONE)
1680 return 0;
1681
1682 if (test_type_token(type, token, EVENT_DELIM, (char *)","))
1683 goto fail;
1684
1685 free_token(token);
1686
1687 ret = event_read_print_args(event, &event->print_fmt.args);
1688 if (ret < 0)
1689 return -1;
1690
1691 return 0;
1692
1693 fail:
1694 free_token(token);
1695 return -1;
1696}
1697
1698static struct format_field *
1699find_common_field(struct event *event, const char *name)
1700{
1701 struct format_field *format;
1702
1703 for (format = event->format.common_fields;
1704 format; format = format->next) {
1705 if (strcmp(format->name, name) == 0)
1706 break;
1707 }
1708
1709 return format;
1710}
1711
1712static struct format_field *
1713find_field(struct event *event, const char *name)
1714{
1715 struct format_field *format;
1716
1717 for (format = event->format.fields;
1718 format; format = format->next) {
1719 if (strcmp(format->name, name) == 0)
1720 break;
1721 }
1722
1723 return format;
1724}
1725
1726static struct format_field *
1727find_any_field(struct event *event, const char *name)
1728{
1729 struct format_field *format;
1730
1731 format = find_common_field(event, name);
1732 if (format)
1733 return format;
1734 return find_field(event, name);
1735}
1736
1737static unsigned long long read_size(void *ptr, int size)
1738{
1739 switch (size) {
1740 case 1:
1741 return *(unsigned char *)ptr;
1742 case 2:
1743 return data2host2(ptr);
1744 case 4:
1745 return data2host4(ptr);
1746 case 8:
1747 return data2host8(ptr);
1748 default:
1749 /* BUG! */
1750 return 0;
1751 }
1752}
1753
1754static int get_common_info(const char *type, int *offset, int *size)
1755{
1756 struct event *event;
1757 struct format_field *field;
1758
1759 /*
1760 * All events should have the same common elements.
1761 * Pick any event to find where the type is;
1762 */
1763 if (!event_list)
1764 die("no event_list!");
1765
1766 event = event_list;
1767 field = find_common_field(event, type);
1768 if (!field)
1769 die("field '%s' not found", type);
1770
1771 *offset = field->offset;
1772 *size = field->size;
1773
1774 return 0;
1775}
1776
1777static int parse_common_type(void *data)
1778{
1779 static int type_offset;
1780 static int type_size;
1781 int ret;
1782
1783 if (!type_size) {
1784 ret = get_common_info("common_type",
1785 &type_offset,
1786 &type_size);
1787 if (ret < 0)
1788 return ret;
1789 }
1790 return read_size(data + type_offset, type_size);
1791}
1792
1793static int parse_common_pid(void *data)
1794{
1795 static int pid_offset;
1796 static int pid_size;
1797 int ret;
1798
1799 if (!pid_size) {
1800 ret = get_common_info("common_pid",
1801 &pid_offset,
1802 &pid_size);
1803 if (ret < 0)
1804 return ret;
1805 }
1806
1807 return read_size(data + pid_offset, pid_size);
1808}
1809
1810static struct event *find_event(int id)
1811{
1812 struct event *event;
1813
1814 for (event = event_list; event; event = event->next) {
1815 if (event->id == id)
1816 break;
1817 }
1818 return event;
1819}
1820
1821static unsigned long long eval_num_arg(void *data, int size,
1822 struct event *event, struct print_arg *arg)
1823{
1824 unsigned long long val = 0;
1825 unsigned long long left, right;
1826
1827 switch (arg->type) {
1828 case PRINT_NULL:
1829 /* ?? */
1830 return 0;
1831 case PRINT_ATOM:
1832 return strtoull(arg->atom.atom, NULL, 0);
1833 case PRINT_FIELD:
1834 if (!arg->field.field) {
1835 arg->field.field = find_any_field(event, arg->field.name);
1836 if (!arg->field.field)
1837 die("field %s not found", arg->field.name);
1838 }
1839 /* must be a number */
1840 val = read_size(data + arg->field.field->offset,
1841 arg->field.field->size);
1842 break;
1843 case PRINT_FLAGS:
1844 case PRINT_SYMBOL:
1845 break;
1846 case PRINT_TYPE:
1847 return eval_num_arg(data, size, event, arg->typecast.item);
1848 case PRINT_STRING:
1849 return 0;
1850 break;
1851 case PRINT_OP:
1852 left = eval_num_arg(data, size, event, arg->op.left);
1853 right = eval_num_arg(data, size, event, arg->op.right);
1854 switch (arg->op.op[0]) {
1855 case '|':
1856 if (arg->op.op[1])
1857 val = left || right;
1858 else
1859 val = left | right;
1860 break;
1861 case '&':
1862 if (arg->op.op[1])
1863 val = left && right;
1864 else
1865 val = left & right;
1866 break;
1867 case '<':
1868 switch (arg->op.op[1]) {
1869 case 0:
1870 val = left < right;
1871 break;
1872 case '<':
1873 val = left << right;
1874 break;
1875 case '=':
1876 val = left <= right;
1877 break;
1878 default:
1879 die("unknown op '%s'", arg->op.op);
1880 }
1881 break;
1882 case '>':
1883 switch (arg->op.op[1]) {
1884 case 0:
1885 val = left > right;
1886 break;
1887 case '>':
1888 val = left >> right;
1889 break;
1890 case '=':
1891 val = left >= right;
1892 break;
1893 default:
1894 die("unknown op '%s'", arg->op.op);
1895 }
1896 break;
1897 case '=':
1898 if (arg->op.op[1] != '=')
1899 die("unknown op '%s'", arg->op.op);
1900 val = left == right;
1901 break;
1902 default:
1903 die("unknown op '%s'", arg->op.op);
1904 }
1905 break;
1906 default: /* not sure what to do there */
1907 return 0;
1908 }
1909 return val;
1910}
1911
1912struct flag {
1913 const char *name;
1914 unsigned long long value;
1915};
1916
1917static const struct flag flags[] = {
1918 { "HI_SOFTIRQ", 0 },
1919 { "TIMER_SOFTIRQ", 1 },
1920 { "NET_TX_SOFTIRQ", 2 },
1921 { "NET_RX_SOFTIRQ", 3 },
1922 { "BLOCK_SOFTIRQ", 4 },
1923 { "TASKLET_SOFTIRQ", 5 },
1924 { "SCHED_SOFTIRQ", 6 },
1925 { "HRTIMER_SOFTIRQ", 7 },
1926 { "RCU_SOFTIRQ", 8 },
1927
1928 { "HRTIMER_NORESTART", 0 },
1929 { "HRTIMER_RESTART", 1 },
1930};
1931
1932static unsigned long long eval_flag(const char *flag)
1933{
1934 int i;
1935
1936 /*
1937 * Some flags in the format files do not get converted.
1938 * If the flag is not numeric, see if it is something that
1939 * we already know about.
1940 */
1941 if (isdigit(flag[0]))
1942 return strtoull(flag, NULL, 0);
1943
1944 for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++)
1945 if (strcmp(flags[i].name, flag) == 0)
1946 return flags[i].value;
1947
1948 return 0;
1949}
1950
1951static void print_str_arg(void *data, int size,
1952 struct event *event, struct print_arg *arg)
1953{
1954 struct print_flag_sym *flag;
1955 unsigned long long val, fval;
1956 char *str;
1957 int print;
1958
1959 switch (arg->type) {
1960 case PRINT_NULL:
1961 /* ?? */
1962 return;
1963 case PRINT_ATOM:
1964 printf("%s", arg->atom.atom);
1965 return;
1966 case PRINT_FIELD:
1967 if (!arg->field.field) {
1968 arg->field.field = find_any_field(event, arg->field.name);
1969 if (!arg->field.field)
1970 die("field %s not found", arg->field.name);
1971 }
1972 str = malloc_or_die(arg->field.field->size + 1);
1973 memcpy(str, data + arg->field.field->offset,
1974 arg->field.field->size);
1975 str[arg->field.field->size] = 0;
1976 free(str);
1977 break;
1978 case PRINT_FLAGS:
1979 val = eval_num_arg(data, size, event, arg->flags.field);
1980 print = 0;
1981 for (flag = arg->flags.flags; flag; flag = flag->next) {
1982 fval = eval_flag(flag->value);
1983 if (!val && !fval) {
1984 printf("%s", flag->str);
1985 break;
1986 }
1987 if (fval && (val & fval) == fval) {
1988 if (print && arg->flags.delim)
1989 printf("%s", arg->flags.delim);
1990 printf("%s", flag->str);
1991 print = 1;
1992 val &= ~fval;
1993 }
1994 }
1995 break;
1996 case PRINT_SYMBOL:
1997 val = eval_num_arg(data, size, event, arg->symbol.field);
1998 for (flag = arg->symbol.symbols; flag; flag = flag->next) {
1999 fval = eval_flag(flag->value);
2000 if (val == fval) {
2001 printf("%s", flag->str);
2002 break;
2003 }
2004 }
2005 break;
2006
2007 case PRINT_TYPE:
2008 break;
2009 case PRINT_STRING:
2010 printf("%s", arg->string.string);
2011 break;
2012 case PRINT_OP:
2013 /*
2014 * The only op for string should be ? :
2015 */
2016 if (arg->op.op[0] != '?')
2017 return;
2018 val = eval_num_arg(data, size, event, arg->op.left);
2019 if (val)
2020 print_str_arg(data, size, event, arg->op.right->op.left);
2021 else
2022 print_str_arg(data, size, event, arg->op.right->op.right);
2023 break;
2024 default:
2025 /* well... */
2026 break;
2027 }
2028}
2029
2030static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event *event)
2031{
2032 static struct format_field *field, *ip_field;
2033 struct print_arg *args, *arg, **next;
2034 unsigned long long ip, val;
2035 char *ptr;
2036 void *bptr;
2037
2038 if (!field) {
2039 field = find_field(event, "buf");
2040 if (!field)
2041 die("can't find buffer field for binary printk");
2042 ip_field = find_field(event, "ip");
2043 if (!ip_field)
2044 die("can't find ip field for binary printk");
2045 }
2046
2047 ip = read_size(data + ip_field->offset, ip_field->size);
2048
2049 /*
2050 * The first arg is the IP pointer.
2051 */
2052 args = malloc_or_die(sizeof(*args));
2053 arg = args;
2054 arg->next = NULL;
2055 next = &arg->next;
2056
2057 arg->type = PRINT_ATOM;
2058 arg->atom.atom = malloc_or_die(32);
2059 sprintf(arg->atom.atom, "%lld", ip);
2060
2061 /* skip the first "%pf : " */
2062 for (ptr = fmt + 6, bptr = data + field->offset;
2063 bptr < data + size && *ptr; ptr++) {
2064 int ls = 0;
2065
2066 if (*ptr == '%') {
2067 process_again:
2068 ptr++;
2069 switch (*ptr) {
2070 case '%':
2071 break;
2072 case 'l':
2073 ls++;
2074 goto process_again;
2075 case 'L':
2076 ls = 2;
2077 goto process_again;
2078 case '0' ... '9':
2079 goto process_again;
2080 case 'p':
2081 ls = 1;
2082 /* fall through */
2083 case 'd':
2084 case 'u':
2085 case 'x':
2086 case 'i':
2087 bptr = (void *)(((unsigned long)bptr + (long_size - 1)) &
2088 ~(long_size - 1));
2089 switch (ls) {
2090 case 0:
2091 case 1:
2092 ls = long_size;
2093 break;
2094 case 2:
2095 ls = 8;
2096 default:
2097 break;
2098 }
2099 val = read_size(bptr, ls);
2100 bptr += ls;
2101 arg = malloc_or_die(sizeof(*arg));
2102 arg->next = NULL;
2103 arg->type = PRINT_ATOM;
2104 arg->atom.atom = malloc_or_die(32);
2105 sprintf(arg->atom.atom, "%lld", val);
2106 *next = arg;
2107 next = &arg->next;
2108 break;
2109 case 's':
2110 arg = malloc_or_die(sizeof(*arg));
2111 arg->next = NULL;
2112 arg->type = PRINT_STRING;
2113 arg->string.string = strdup(bptr);
2114 bptr += strlen(bptr) + 1;
2115 *next = arg;
2116 next = &arg->next;
2117 default:
2118 break;
2119 }
2120 }
2121 }
2122
2123 return args;
2124}
2125
2126static void free_args(struct print_arg *args)
2127{
2128 struct print_arg *next;
2129
2130 while (args) {
2131 next = args->next;
2132
2133 if (args->type == PRINT_ATOM)
2134 free(args->atom.atom);
2135 else
2136 free(args->string.string);
2137 free(args);
2138 args = next;
2139 }
2140}
2141
2142static char *get_bprint_format(void *data, int size __unused, struct event *event)
2143{
2144 unsigned long long addr;
2145 static struct format_field *field;
2146 struct printk_map *printk;
2147 char *format;
2148 char *p;
2149
2150 if (!field) {
2151 field = find_field(event, "fmt");
2152 if (!field)
2153 die("can't find format field for binary printk");
2154 printf("field->offset = %d size=%d\n", field->offset, field->size);
2155 }
2156
2157 addr = read_size(data + field->offset, field->size);
2158
2159 printk = find_printk(addr);
2160 if (!printk) {
2161 format = malloc_or_die(45);
2162 sprintf(format, "%%pf : (NO FORMAT FOUND at %llx)\n",
2163 addr);
2164 return format;
2165 }
2166
2167 p = printk->printk;
2168 /* Remove any quotes. */
2169 if (*p == '"')
2170 p++;
2171 format = malloc_or_die(strlen(p) + 10);
2172 sprintf(format, "%s : %s", "%pf", p);
2173 /* remove ending quotes and new line since we will add one too */
2174 p = format + strlen(format) - 1;
2175 if (*p == '"')
2176 *p = 0;
2177
2178 p -= 2;
2179 if (strcmp(p, "\\n") == 0)
2180 *p = 0;
2181
2182 return format;
2183}
2184
2185static void pretty_print(void *data, int size, struct event *event)
2186{
2187 struct print_fmt *print_fmt = &event->print_fmt;
2188 struct print_arg *arg = print_fmt->args;
2189 struct print_arg *args = NULL;
2190 const char *ptr = print_fmt->format;
2191 unsigned long long val;
2192 struct func_map *func;
2193 const char *saveptr;
2194 char *bprint_fmt = NULL;
2195 char format[32];
2196 int show_func;
2197 int len;
2198 int ls;
2199
2200 if (event->flags & EVENT_FL_ISFUNC)
2201 ptr = " %pF <-- %pF";
2202
2203 if (event->flags & EVENT_FL_ISBPRINT) {
2204 bprint_fmt = get_bprint_format(data, size, event);
2205 args = make_bprint_args(bprint_fmt, data, size, event);
2206 arg = args;
2207 ptr = bprint_fmt;
2208 }
2209
2210 for (; *ptr; ptr++) {
2211 ls = 0;
2212 if (*ptr == '%') {
2213 saveptr = ptr;
2214 show_func = 0;
2215 cont_process:
2216 ptr++;
2217 switch (*ptr) {
2218 case '%':
2219 printf("%%");
2220 break;
2221 case 'l':
2222 ls++;
2223 goto cont_process;
2224 case 'L':
2225 ls = 2;
2226 goto cont_process;
2227 case 'z':
2228 case 'Z':
2229 case '0' ... '9':
2230 goto cont_process;
2231 case 'p':
2232 if (long_size == 4)
2233 ls = 1;
2234 else
2235 ls = 2;
2236
2237 if (*(ptr+1) == 'F' ||
2238 *(ptr+1) == 'f') {
2239 ptr++;
2240 show_func = *ptr;
2241 }
2242
2243 /* fall through */
2244 case 'd':
2245 case 'i':
2246 case 'x':
2247 case 'X':
2248 case 'u':
2249 if (!arg)
2250 die("no argument match");
2251
2252 len = ((unsigned long)ptr + 1) -
2253 (unsigned long)saveptr;
2254
2255 /* should never happen */
2256 if (len > 32)
2257 die("bad format!");
2258
2259 memcpy(format, saveptr, len);
2260 format[len] = 0;
2261
2262 val = eval_num_arg(data, size, event, arg);
2263 arg = arg->next;
2264
2265 if (show_func) {
2266 func = find_func(val);
2267 if (func) {
2268 printf("%s", func->func);
2269 if (show_func == 'F')
2270 printf("+0x%llx",
2271 val - func->addr);
2272 break;
2273 }
2274 }
2275 switch (ls) {
2276 case 0:
2277 printf(format, (int)val);
2278 break;
2279 case 1:
2280 printf(format, (long)val);
2281 break;
2282 case 2:
2283 printf(format, (long long)val);
2284 break;
2285 default:
2286 die("bad count (%d)", ls);
2287 }
2288 break;
2289 case 's':
2290 if (!arg)
2291 die("no matching argument");
2292
2293 print_str_arg(data, size, event, arg);
2294 arg = arg->next;
2295 break;
2296 default:
2297 printf(">%c<", *ptr);
2298
2299 }
2300 } else
2301 printf("%c", *ptr);
2302 }
2303
2304 if (args) {
2305 free_args(args);
2306 free(bprint_fmt);
2307 }
2308}
2309
2310static inline int log10_cpu(int nb)
2311{
2312 if (nb / 100)
2313 return 3;
2314 if (nb / 10)
2315 return 2;
2316 return 1;
2317}
2318
2319/* taken from Linux, written by Frederic Weisbecker */
2320static void print_graph_cpu(int cpu)
2321{
2322 int i;
2323 int log10_this = log10_cpu(cpu);
2324 int log10_all = log10_cpu(cpus);
2325
2326
2327 /*
2328 * Start with a space character - to make it stand out
2329 * to the right a bit when trace output is pasted into
2330 * email:
2331 */
2332 printf(" ");
2333
2334 /*
2335 * Tricky - we space the CPU field according to the max
2336 * number of online CPUs. On a 2-cpu system it would take
2337 * a maximum of 1 digit - on a 128 cpu system it would
2338 * take up to 3 digits:
2339 */
2340 for (i = 0; i < log10_all - log10_this; i++)
2341 printf(" ");
2342
2343 printf("%d) ", cpu);
2344}
2345
2346#define TRACE_GRAPH_PROCINFO_LENGTH 14
2347#define TRACE_GRAPH_INDENT 2
2348
2349static void print_graph_proc(int pid, const char *comm)
2350{
2351 /* sign + log10(MAX_INT) + '\0' */
2352 char pid_str[11];
2353 int spaces = 0;
2354 int len;
2355 int i;
2356
2357 sprintf(pid_str, "%d", pid);
2358
2359 /* 1 stands for the "-" character */
2360 len = strlen(comm) + strlen(pid_str) + 1;
2361
2362 if (len < TRACE_GRAPH_PROCINFO_LENGTH)
2363 spaces = TRACE_GRAPH_PROCINFO_LENGTH - len;
2364
2365 /* First spaces to align center */
2366 for (i = 0; i < spaces / 2; i++)
2367 printf(" ");
2368
2369 printf("%s-%s", comm, pid_str);
2370
2371 /* Last spaces to align center */
2372 for (i = 0; i < spaces - (spaces / 2); i++)
2373 printf(" ");
2374}
2375
2376static struct record *
2377get_return_for_leaf(int cpu, int cur_pid, unsigned long long cur_func,
2378 struct record *next)
2379{
2380 struct format_field *field;
2381 struct event *event;
2382 unsigned long val;
2383 int type;
2384 int pid;
2385
2386 type = parse_common_type(next->data);
2387 event = find_event(type);
2388 if (!event)
2389 return NULL;
2390
2391 if (!(event->flags & EVENT_FL_ISFUNCRET))
2392 return NULL;
2393
2394 pid = parse_common_pid(next->data);
2395 field = find_field(event, "func");
2396 if (!field)
2397 die("function return does not have field func");
2398
2399 val = read_size(next->data + field->offset, field->size);
2400
2401 if (cur_pid != pid || cur_func != val)
2402 return NULL;
2403
2404 /* this is a leaf, now advance the iterator */
2405 return trace_read_data(cpu);
2406}
2407
2408/* Signal a overhead of time execution to the output */
2409static void print_graph_overhead(unsigned long long duration)
2410{
2411 /* Non nested entry or return */
2412 if (duration == ~0ULL)
2413 return (void)printf(" ");
2414
2415 /* Duration exceeded 100 msecs */
2416 if (duration > 100000ULL)
2417 return (void)printf("! ");
2418
2419 /* Duration exceeded 10 msecs */
2420 if (duration > 10000ULL)
2421 return (void)printf("+ ");
2422
2423 printf(" ");
2424}
2425
2426static void print_graph_duration(unsigned long long duration)
2427{
2428 unsigned long usecs = duration / 1000;
2429 unsigned long nsecs_rem = duration % 1000;
2430 /* log10(ULONG_MAX) + '\0' */
2431 char msecs_str[21];
2432 char nsecs_str[5];
2433 int len;
2434 int i;
2435
2436 sprintf(msecs_str, "%lu", usecs);
2437
2438 /* Print msecs */
2439 len = printf("%lu", usecs);
2440
2441 /* Print nsecs (we don't want to exceed 7 numbers) */
2442 if (len < 7) {
2443 snprintf(nsecs_str, 8 - len, "%03lu", nsecs_rem);
2444 len += printf(".%s", nsecs_str);
2445 }
2446
2447 printf(" us ");
2448
2449 /* Print remaining spaces to fit the row's width */
2450 for (i = len; i < 7; i++)
2451 printf(" ");
2452
2453 printf("| ");
2454}
2455
2456static void
2457print_graph_entry_leaf(struct event *event, void *data, struct record *ret_rec)
2458{
2459 unsigned long long rettime, calltime;
2460 unsigned long long duration, depth;
2461 unsigned long long val;
2462 struct format_field *field;
2463 struct func_map *func;
2464 struct event *ret_event;
2465 int type;
2466 int i;
2467
2468 type = parse_common_type(ret_rec->data);
2469 ret_event = find_event(type);
2470
2471 field = find_field(ret_event, "rettime");
2472 if (!field)
2473 die("can't find rettime in return graph");
2474 rettime = read_size(ret_rec->data + field->offset, field->size);
2475
2476 field = find_field(ret_event, "calltime");
2477 if (!field)
2478 die("can't find rettime in return graph");
2479 calltime = read_size(ret_rec->data + field->offset, field->size);
2480
2481 duration = rettime - calltime;
2482
2483 /* Overhead */
2484 print_graph_overhead(duration);
2485
2486 /* Duration */
2487 print_graph_duration(duration);
2488
2489 field = find_field(event, "depth");
2490 if (!field)
2491 die("can't find depth in entry graph");
2492 depth = read_size(data + field->offset, field->size);
2493
2494 /* Function */
2495 for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++)
2496 printf(" ");
2497
2498 field = find_field(event, "func");
2499 if (!field)
2500 die("can't find func in entry graph");
2501 val = read_size(data + field->offset, field->size);
2502 func = find_func(val);
2503
2504 if (func)
2505 printf("%s();", func->func);
2506 else
2507 printf("%llx();", val);
2508}
2509
2510static void print_graph_nested(struct event *event, void *data)
2511{
2512 struct format_field *field;
2513 unsigned long long depth;
2514 unsigned long long val;
2515 struct func_map *func;
2516 int i;
2517
2518 /* No overhead */
2519 print_graph_overhead(-1);
2520
2521 /* No time */
2522 printf(" | ");
2523
2524 field = find_field(event, "depth");
2525 if (!field)
2526 die("can't find depth in entry graph");
2527 depth = read_size(data + field->offset, field->size);
2528
2529 /* Function */
2530 for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++)
2531 printf(" ");
2532
2533 field = find_field(event, "func");
2534 if (!field)
2535 die("can't find func in entry graph");
2536 val = read_size(data + field->offset, field->size);
2537 func = find_func(val);
2538
2539 if (func)
2540 printf("%s() {", func->func);
2541 else
2542 printf("%llx() {", val);
2543}
2544
2545static void
2546pretty_print_func_ent(void *data, int size, struct event *event,
2547 int cpu, int pid, const char *comm,
2548 unsigned long secs, unsigned long usecs)
2549{
2550 struct format_field *field;
2551 struct record *rec;
2552 void *copy_data;
2553 unsigned long val;
2554
2555 printf("%5lu.%06lu | ", secs, usecs);
2556
2557 print_graph_cpu(cpu);
2558 print_graph_proc(pid, comm);
2559
2560 printf(" | ");
2561
2562 field = find_field(event, "func");
2563 if (!field)
2564 die("function entry does not have func field");
2565
2566 val = read_size(data + field->offset, field->size);
2567
2568 /*
2569 * peek_data may unmap the data pointer. Copy it first.
2570 */
2571 copy_data = malloc_or_die(size);
2572 memcpy(copy_data, data, size);
2573 data = copy_data;
2574
2575 rec = trace_peek_data(cpu);
2576 if (rec) {
2577 rec = get_return_for_leaf(cpu, pid, val, rec);
2578 if (rec) {
2579 print_graph_entry_leaf(event, data, rec);
2580 goto out_free;
2581 }
2582 }
2583 print_graph_nested(event, data);
2584out_free:
2585 free(data);
2586}
2587
2588static void
2589pretty_print_func_ret(void *data, int size __unused, struct event *event,
2590 int cpu, int pid, const char *comm,
2591 unsigned long secs, unsigned long usecs)
2592{
2593 unsigned long long rettime, calltime;
2594 unsigned long long duration, depth;
2595 struct format_field *field;
2596 int i;
2597
2598 printf("%5lu.%06lu | ", secs, usecs);
2599
2600 print_graph_cpu(cpu);
2601 print_graph_proc(pid, comm);
2602
2603 printf(" | ");
2604
2605 field = find_field(event, "rettime");
2606 if (!field)
2607 die("can't find rettime in return graph");
2608 rettime = read_size(data + field->offset, field->size);
2609
2610 field = find_field(event, "calltime");
2611 if (!field)
2612 die("can't find calltime in return graph");
2613 calltime = read_size(data + field->offset, field->size);
2614
2615 duration = rettime - calltime;
2616
2617 /* Overhead */
2618 print_graph_overhead(duration);
2619
2620 /* Duration */
2621 print_graph_duration(duration);
2622
2623 field = find_field(event, "depth");
2624 if (!field)
2625 die("can't find depth in entry graph");
2626 depth = read_size(data + field->offset, field->size);
2627
2628 /* Function */
2629 for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++)
2630 printf(" ");
2631
2632 printf("}");
2633}
2634
2635static void
2636pretty_print_func_graph(void *data, int size, struct event *event,
2637 int cpu, int pid, const char *comm,
2638 unsigned long secs, unsigned long usecs)
2639{
2640 if (event->flags & EVENT_FL_ISFUNCENT)
2641 pretty_print_func_ent(data, size, event,
2642 cpu, pid, comm, secs, usecs);
2643 else if (event->flags & EVENT_FL_ISFUNCRET)
2644 pretty_print_func_ret(data, size, event,
2645 cpu, pid, comm, secs, usecs);
2646 printf("\n");
2647}
2648
2649void print_event(int cpu, void *data, int size, unsigned long long nsecs,
2650 char *comm)
2651{
2652 struct event *event;
2653 unsigned long secs;
2654 unsigned long usecs;
2655 int type;
2656 int pid;
2657
2658 secs = nsecs / NSECS_PER_SEC;
2659 nsecs -= secs * NSECS_PER_SEC;
2660 usecs = nsecs / NSECS_PER_USEC;
2661
2662 type = parse_common_type(data);
2663
2664 event = find_event(type);
2665 if (!event)
2666 die("ug! no event found for type %d", type);
2667
2668 pid = parse_common_pid(data);
2669
2670 if (event->flags & (EVENT_FL_ISFUNCENT | EVENT_FL_ISFUNCRET))
2671 return pretty_print_func_graph(data, size, event, cpu,
2672 pid, comm, secs, usecs);
2673
2674 printf("%16s-%-5d [%03d] %5lu.%06lu: %s: ",
2675 comm, pid, cpu,
2676 secs, usecs, event->name);
2677
2678 pretty_print(data, size, event);
2679 printf("\n");
2680}
2681
2682static void print_fields(struct print_flag_sym *field)
2683{
2684 printf("{ %s, %s }", field->value, field->str);
2685 if (field->next) {
2686 printf(", ");
2687 print_fields(field->next);
2688 }
2689}
2690
2691static void print_args(struct print_arg *args)
2692{
2693 int print_paren = 1;
2694
2695 switch (args->type) {
2696 case PRINT_NULL:
2697 printf("null");
2698 break;
2699 case PRINT_ATOM:
2700 printf("%s", args->atom.atom);
2701 break;
2702 case PRINT_FIELD:
2703 printf("REC->%s", args->field.name);
2704 break;
2705 case PRINT_FLAGS:
2706 printf("__print_flags(");
2707 print_args(args->flags.field);
2708 printf(", %s, ", args->flags.delim);
2709 print_fields(args->flags.flags);
2710 printf(")");
2711 break;
2712 case PRINT_SYMBOL:
2713 printf("__print_symbolic(");
2714 print_args(args->symbol.field);
2715 printf(", ");
2716 print_fields(args->symbol.symbols);
2717 printf(")");
2718 break;
2719 case PRINT_STRING:
2720 printf("__get_str(%s)", args->string.string);
2721 break;
2722 case PRINT_TYPE:
2723 printf("(%s)", args->typecast.type);
2724 print_args(args->typecast.item);
2725 break;
2726 case PRINT_OP:
2727 if (strcmp(args->op.op, ":") == 0)
2728 print_paren = 0;
2729 if (print_paren)
2730 printf("(");
2731 print_args(args->op.left);
2732 printf(" %s ", args->op.op);
2733 print_args(args->op.right);
2734 if (print_paren)
2735 printf(")");
2736 break;
2737 default:
2738 /* we should warn... */
2739 return;
2740 }
2741 if (args->next) {
2742 printf("\n");
2743 print_args(args->next);
2744 }
2745}
2746
2747static void parse_header_field(char *type,
2748 int *offset, int *size)
2749{
2750 char *token;
2751
2752 if (read_expected(EVENT_ITEM, (char *)"field") < 0)
2753 return;
2754 if (read_expected(EVENT_OP, (char *)":") < 0)
2755 return;
2756 /* type */
2757 if (read_expect_type(EVENT_ITEM, &token) < 0)
2758 return;
2759 free_token(token);
2760
2761 if (read_expected(EVENT_ITEM, type) < 0)
2762 return;
2763 if (read_expected(EVENT_OP, (char *)";") < 0)
2764 return;
2765 if (read_expected(EVENT_ITEM, (char *)"offset") < 0)
2766 return;
2767 if (read_expected(EVENT_OP, (char *)":") < 0)
2768 return;
2769 if (read_expect_type(EVENT_ITEM, &token) < 0)
2770 return;
2771 *offset = atoi(token);
2772 free_token(token);
2773 if (read_expected(EVENT_OP, (char *)";") < 0)
2774 return;
2775 if (read_expected(EVENT_ITEM, (char *)"size") < 0)
2776 return;
2777 if (read_expected(EVENT_OP, (char *)":") < 0)
2778 return;
2779 if (read_expect_type(EVENT_ITEM, &token) < 0)
2780 return;
2781 *size = atoi(token);
2782 free_token(token);
2783 if (read_expected(EVENT_OP, (char *)";") < 0)
2784 return;
2785 if (read_expect_type(EVENT_NEWLINE, &token) < 0)
2786 return;
2787 free_token(token);
2788}
2789
2790int parse_header_page(char *buf, unsigned long size)
2791{
2792 init_input_buf(buf, size);
2793
2794 parse_header_field((char *)"timestamp", &header_page_ts_offset,
2795 &header_page_ts_size);
2796 parse_header_field((char *)"commit", &header_page_size_offset,
2797 &header_page_size_size);
2798 parse_header_field((char *)"data", &header_page_data_offset,
2799 &header_page_data_size);
2800
2801 return 0;
2802}
2803
2804int parse_ftrace_file(char *buf, unsigned long size)
2805{
2806 struct format_field *field;
2807 struct print_arg *arg, **list;
2808 struct event *event;
2809 int ret;
2810
2811 init_input_buf(buf, size);
2812
2813 event = alloc_event();
2814 if (!event)
2815 return -ENOMEM;
2816
2817 event->flags |= EVENT_FL_ISFTRACE;
2818
2819 event->name = event_read_name();
2820 if (!event->name)
2821 die("failed to read ftrace event name");
2822
2823 if (strcmp(event->name, "function") == 0)
2824 event->flags |= EVENT_FL_ISFUNC;
2825
2826 else if (strcmp(event->name, "funcgraph_entry") == 0)
2827 event->flags |= EVENT_FL_ISFUNCENT;
2828
2829 else if (strcmp(event->name, "funcgraph_exit") == 0)
2830 event->flags |= EVENT_FL_ISFUNCRET;
2831
2832 else if (strcmp(event->name, "bprint") == 0)
2833 event->flags |= EVENT_FL_ISBPRINT;
2834
2835 event->id = event_read_id();
2836 if (event->id < 0)
2837 die("failed to read ftrace event id");
2838
2839 add_event(event);
2840
2841 ret = event_read_format(event);
2842 if (ret < 0)
2843 die("failed to read ftrace event format");
2844
2845 ret = event_read_print(event);
2846 if (ret < 0)
2847 die("failed to read ftrace event print fmt");
2848
2849 /*
2850 * The arguments for ftrace files are parsed by the fields.
2851 * Set up the fields as their arguments.
2852 */
2853 list = &event->print_fmt.args;
2854 for (field = event->format.fields; field; field = field->next) {
2855 arg = malloc_or_die(sizeof(*arg));
2856 memset(arg, 0, sizeof(*arg));
2857 *list = arg;
2858 list = &arg->next;
2859 arg->type = PRINT_FIELD;
2860 arg->field.name = field->name;
2861 arg->field.field = field;
2862 }
2863 return 0;
2864}
2865
2866int parse_event_file(char *buf, unsigned long size, char *system__unused __unused)
2867{
2868 struct event *event;
2869 int ret;
2870
2871 init_input_buf(buf, size);
2872
2873 event = alloc_event();
2874 if (!event)
2875 return -ENOMEM;
2876
2877 event->name = event_read_name();
2878 if (!event->name)
2879 die("failed to read event name");
2880
2881 event->id = event_read_id();
2882 if (event->id < 0)
2883 die("failed to read event id");
2884
2885 ret = event_read_format(event);
2886 if (ret < 0)
2887 die("failed to read event format");
2888
2889 ret = event_read_print(event);
2890 if (ret < 0)
2891 die("failed to read event print fmt");
2892
2893#define PRINT_ARGS 0
2894 if (PRINT_ARGS && event->print_fmt.args)
2895 print_args(event->print_fmt.args);
2896
2897 add_event(event);
2898 return 0;
2899}
2900
2901void parse_set_info(int nr_cpus, int long_sz)
2902{
2903 cpus = nr_cpus;
2904 long_size = long_sz;
2905}