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