blob: d6ef414075a692862fbde75e60a153cab62662fe [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;
Arnaldo Carvalho de Meloe9e94e32010-04-05 18:01:10 -030040int header_page_overwrite_offset;
41int header_page_overwrite_size;
Steven Rostedtea4010d2009-08-17 16:18:07 +020042int header_page_data_offset;
43int header_page_data_size;
44
Ian Munsiec0555642010-04-13 18:37:33 +100045bool latency_format;
Steven Rostedtcda48462009-10-14 15:43:42 -040046
Steven Rostedtea4010d2009-08-17 16:18:07 +020047static char *input_buf;
48static unsigned long long input_buf_ptr;
49static unsigned long long input_buf_siz;
50
51static int cpus;
52static int long_size;
Tom Zanussieb9a42c2009-11-25 01:15:47 -060053static int is_flag_field;
54static int is_symbolic_field;
55
56static struct format_field *
57find_any_field(struct event *event, const char *name);
Steven Rostedtea4010d2009-08-17 16:18:07 +020058
59static void init_input_buf(char *buf, unsigned long long size)
60{
61 input_buf = buf;
62 input_buf_siz = size;
63 input_buf_ptr = 0;
64}
65
66struct cmdline {
67 char *comm;
68 int pid;
69};
70
71static struct cmdline *cmdlines;
72static int cmdline_count;
73
74static int cmdline_cmp(const void *a, const void *b)
75{
76 const struct cmdline *ca = a;
77 const struct cmdline *cb = b;
78
79 if (ca->pid < cb->pid)
80 return -1;
81 if (ca->pid > cb->pid)
82 return 1;
83
84 return 0;
85}
86
87void parse_cmdlines(char *file, int size __unused)
88{
89 struct cmdline_list {
90 struct cmdline_list *next;
91 char *comm;
92 int pid;
93 } *list = NULL, *item;
94 char *line;
95 char *next = NULL;
96 int i;
97
98 line = strtok_r(file, "\n", &next);
99 while (line) {
100 item = malloc_or_die(sizeof(*item));
101 sscanf(line, "%d %as", &item->pid,
Ingo Molnar65014ab2009-09-02 14:55:55 +0200102 (float *)(void *)&item->comm); /* workaround gcc warning */
Steven Rostedtea4010d2009-08-17 16:18:07 +0200103 item->next = list;
104 list = item;
105 line = strtok_r(NULL, "\n", &next);
106 cmdline_count++;
107 }
108
109 cmdlines = malloc_or_die(sizeof(*cmdlines) * cmdline_count);
110
111 i = 0;
112 while (list) {
113 cmdlines[i].pid = list->pid;
114 cmdlines[i].comm = list->comm;
115 i++;
116 item = list;
117 list = list->next;
118 free(item);
119 }
120
121 qsort(cmdlines, cmdline_count, sizeof(*cmdlines), cmdline_cmp);
122}
123
124static struct func_map {
125 unsigned long long addr;
126 char *func;
127 char *mod;
128} *func_list;
129static unsigned int func_count;
130
131static int func_cmp(const void *a, const void *b)
132{
133 const struct func_map *fa = a;
134 const struct func_map *fb = b;
135
136 if (fa->addr < fb->addr)
137 return -1;
138 if (fa->addr > fb->addr)
139 return 1;
140
141 return 0;
142}
143
144void parse_proc_kallsyms(char *file, unsigned int size __unused)
145{
146 struct func_list {
147 struct func_list *next;
148 unsigned long long addr;
149 char *func;
150 char *mod;
151 } *list = NULL, *item;
152 char *line;
153 char *next = NULL;
154 char *addr_str;
155 char ch;
156 int ret;
157 int i;
158
159 line = strtok_r(file, "\n", &next);
160 while (line) {
161 item = malloc_or_die(sizeof(*item));
162 item->mod = NULL;
163 ret = sscanf(line, "%as %c %as\t[%as",
Ingo Molnar65014ab2009-09-02 14:55:55 +0200164 (float *)(void *)&addr_str, /* workaround gcc warning */
Steven Rostedtea4010d2009-08-17 16:18:07 +0200165 &ch,
Ingo Molnar65014ab2009-09-02 14:55:55 +0200166 (float *)(void *)&item->func,
167 (float *)(void *)&item->mod);
Steven Rostedtea4010d2009-08-17 16:18:07 +0200168 item->addr = strtoull(addr_str, NULL, 16);
169 free(addr_str);
170
171 /* truncate the extra ']' */
172 if (item->mod)
173 item->mod[strlen(item->mod) - 1] = 0;
174
175
176 item->next = list;
177 list = item;
178 line = strtok_r(NULL, "\n", &next);
179 func_count++;
180 }
181
OGAWA Hirofumi7691b1e2009-12-06 20:10:49 +0900182 func_list = malloc_or_die(sizeof(*func_list) * (func_count + 1));
Steven Rostedtea4010d2009-08-17 16:18:07 +0200183
184 i = 0;
185 while (list) {
186 func_list[i].func = list->func;
187 func_list[i].addr = list->addr;
188 func_list[i].mod = list->mod;
189 i++;
190 item = list;
191 list = list->next;
192 free(item);
193 }
194
195 qsort(func_list, func_count, sizeof(*func_list), func_cmp);
196
197 /*
198 * Add a special record at the end.
199 */
200 func_list[func_count].func = NULL;
201 func_list[func_count].addr = 0;
202 func_list[func_count].mod = NULL;
203}
204
205/*
206 * We are searching for a record in between, not an exact
207 * match.
208 */
209static int func_bcmp(const void *a, const void *b)
210{
211 const struct func_map *fa = a;
212 const struct func_map *fb = b;
213
214 if ((fa->addr == fb->addr) ||
215
216 (fa->addr > fb->addr &&
217 fa->addr < (fb+1)->addr))
218 return 0;
219
220 if (fa->addr < fb->addr)
221 return -1;
222
223 return 1;
224}
225
226static struct func_map *find_func(unsigned long long addr)
227{
228 struct func_map *func;
229 struct func_map key;
230
231 key.addr = addr;
232
233 func = bsearch(&key, func_list, func_count, sizeof(*func_list),
234 func_bcmp);
235
236 return func;
237}
238
239void print_funcs(void)
240{
241 int i;
242
243 for (i = 0; i < (int)func_count; i++) {
244 printf("%016llx %s",
245 func_list[i].addr,
246 func_list[i].func);
247 if (func_list[i].mod)
248 printf(" [%s]\n", func_list[i].mod);
249 else
250 printf("\n");
251 }
252}
253
254static struct printk_map {
255 unsigned long long addr;
256 char *printk;
257} *printk_list;
258static unsigned int printk_count;
259
260static int printk_cmp(const void *a, const void *b)
261{
262 const struct func_map *fa = a;
263 const struct func_map *fb = b;
264
265 if (fa->addr < fb->addr)
266 return -1;
267 if (fa->addr > fb->addr)
268 return 1;
269
270 return 0;
271}
272
273static struct printk_map *find_printk(unsigned long long addr)
274{
275 struct printk_map *printk;
276 struct printk_map key;
277
278 key.addr = addr;
279
280 printk = bsearch(&key, printk_list, printk_count, sizeof(*printk_list),
281 printk_cmp);
282
283 return printk;
284}
285
286void parse_ftrace_printk(char *file, unsigned int size __unused)
287{
288 struct printk_list {
289 struct printk_list *next;
290 unsigned long long addr;
291 char *printk;
292 } *list = NULL, *item;
293 char *line;
294 char *next = NULL;
295 char *addr_str;
Steven Rostedtea4010d2009-08-17 16:18:07 +0200296 int i;
297
298 line = strtok_r(file, "\n", &next);
299 while (line) {
Steven Rostedt4e3b7992009-10-20 19:19:35 -0400300 addr_str = strsep(&line, ":");
301 if (!line) {
302 warning("error parsing print strings");
303 break;
304 }
Steven Rostedtea4010d2009-08-17 16:18:07 +0200305 item = malloc_or_die(sizeof(*item));
Steven Rostedtea4010d2009-08-17 16:18:07 +0200306 item->addr = strtoull(addr_str, NULL, 16);
Steven Rostedtffa18952009-10-14 15:43:40 -0400307 /* fmt still has a space, skip it */
Steven Rostedt4e3b7992009-10-20 19:19:35 -0400308 item->printk = strdup(line+1);
Steven Rostedtea4010d2009-08-17 16:18:07 +0200309 item->next = list;
310 list = item;
311 line = strtok_r(NULL, "\n", &next);
312 printk_count++;
313 }
314
315 printk_list = malloc_or_die(sizeof(*printk_list) * printk_count + 1);
316
317 i = 0;
318 while (list) {
319 printk_list[i].printk = list->printk;
320 printk_list[i].addr = list->addr;
321 i++;
322 item = list;
323 list = list->next;
324 free(item);
325 }
326
327 qsort(printk_list, printk_count, sizeof(*printk_list), printk_cmp);
328}
329
330void print_printk(void)
331{
332 int i;
333
334 for (i = 0; i < (int)printk_count; i++) {
335 printf("%016llx %s\n",
336 printk_list[i].addr,
337 printk_list[i].printk);
338 }
339}
340
341static struct event *alloc_event(void)
342{
343 struct event *event;
344
345 event = malloc_or_die(sizeof(*event));
346 memset(event, 0, sizeof(*event));
347
348 return event;
349}
350
351enum event_type {
352 EVENT_ERROR,
353 EVENT_NONE,
354 EVENT_SPACE,
355 EVENT_NEWLINE,
356 EVENT_OP,
357 EVENT_DELIM,
358 EVENT_ITEM,
359 EVENT_DQUOTE,
360 EVENT_SQUOTE,
361};
362
363static struct event *event_list;
364
365static void add_event(struct event *event)
366{
367 event->next = event_list;
368 event_list = event;
369}
370
371static int event_item_type(enum event_type type)
372{
373 switch (type) {
374 case EVENT_ITEM ... EVENT_SQUOTE:
375 return 1;
376 case EVENT_ERROR ... EVENT_DELIM:
377 default:
378 return 0;
379 }
380}
381
382static void free_arg(struct print_arg *arg)
383{
384 if (!arg)
385 return;
386
387 switch (arg->type) {
388 case PRINT_ATOM:
389 if (arg->atom.atom)
390 free(arg->atom.atom);
391 break;
392 case PRINT_NULL:
393 case PRINT_FIELD ... PRINT_OP:
394 default:
395 /* todo */
396 break;
397 }
398
399 free(arg);
400}
401
402static enum event_type get_type(int ch)
403{
404 if (ch == '\n')
405 return EVENT_NEWLINE;
406 if (isspace(ch))
407 return EVENT_SPACE;
408 if (isalnum(ch) || ch == '_')
409 return EVENT_ITEM;
410 if (ch == '\'')
411 return EVENT_SQUOTE;
412 if (ch == '"')
413 return EVENT_DQUOTE;
414 if (!isprint(ch))
415 return EVENT_NONE;
416 if (ch == '(' || ch == ')' || ch == ',')
417 return EVENT_DELIM;
418
419 return EVENT_OP;
420}
421
422static int __read_char(void)
423{
424 if (input_buf_ptr >= input_buf_siz)
425 return -1;
426
427 return input_buf[input_buf_ptr++];
428}
429
430static int __peek_char(void)
431{
432 if (input_buf_ptr >= input_buf_siz)
433 return -1;
434
435 return input_buf[input_buf_ptr];
436}
437
438static enum event_type __read_token(char **tok)
439{
440 char buf[BUFSIZ];
441 int ch, last_ch, quote_ch, next_ch;
442 int i = 0;
443 int tok_size = 0;
444 enum event_type type;
445
446 *tok = NULL;
447
448
449 ch = __read_char();
450 if (ch < 0)
451 return EVENT_NONE;
452
453 type = get_type(ch);
454 if (type == EVENT_NONE)
455 return type;
456
457 buf[i++] = ch;
458
459 switch (type) {
460 case EVENT_NEWLINE:
461 case EVENT_DELIM:
462 *tok = malloc_or_die(2);
463 (*tok)[0] = ch;
464 (*tok)[1] = 0;
465 return type;
466
467 case EVENT_OP:
468 switch (ch) {
469 case '-':
470 next_ch = __peek_char();
471 if (next_ch == '>') {
472 buf[i++] = __read_char();
473 break;
474 }
475 /* fall through */
476 case '+':
477 case '|':
478 case '&':
479 case '>':
480 case '<':
481 last_ch = ch;
482 ch = __peek_char();
483 if (ch != last_ch)
484 goto test_equal;
485 buf[i++] = __read_char();
486 switch (last_ch) {
487 case '>':
488 case '<':
489 goto test_equal;
490 default:
491 break;
492 }
493 break;
494 case '!':
495 case '=':
496 goto test_equal;
497 default: /* what should we do instead? */
498 break;
499 }
500 buf[i] = 0;
501 *tok = strdup(buf);
502 return type;
503
504 test_equal:
505 ch = __peek_char();
506 if (ch == '=')
507 buf[i++] = __read_char();
508 break;
509
510 case EVENT_DQUOTE:
511 case EVENT_SQUOTE:
512 /* don't keep quotes */
513 i--;
514 quote_ch = ch;
515 last_ch = 0;
516 do {
517 if (i == (BUFSIZ - 1)) {
518 buf[i] = 0;
519 if (*tok) {
520 *tok = realloc(*tok, tok_size + BUFSIZ);
521 if (!*tok)
522 return EVENT_NONE;
523 strcat(*tok, buf);
524 } else
525 *tok = strdup(buf);
526
527 if (!*tok)
528 return EVENT_NONE;
529 tok_size += BUFSIZ;
530 i = 0;
531 }
532 last_ch = ch;
533 ch = __read_char();
534 buf[i++] = ch;
Steven Rostedt91ff2bc2009-10-14 15:43:33 -0400535 /* the '\' '\' will cancel itself */
536 if (ch == '\\' && last_ch == '\\')
537 last_ch = 0;
538 } while (ch != quote_ch || last_ch == '\\');
Steven Rostedtea4010d2009-08-17 16:18:07 +0200539 /* remove the last quote */
540 i--;
541 goto out;
542
543 case EVENT_ERROR ... EVENT_SPACE:
544 case EVENT_ITEM:
545 default:
546 break;
547 }
548
549 while (get_type(__peek_char()) == type) {
550 if (i == (BUFSIZ - 1)) {
551 buf[i] = 0;
552 if (*tok) {
553 *tok = realloc(*tok, tok_size + BUFSIZ);
554 if (!*tok)
555 return EVENT_NONE;
556 strcat(*tok, buf);
557 } else
558 *tok = strdup(buf);
559
560 if (!*tok)
561 return EVENT_NONE;
562 tok_size += BUFSIZ;
563 i = 0;
564 }
565 ch = __read_char();
566 buf[i++] = ch;
567 }
568
569 out:
570 buf[i] = 0;
571 if (*tok) {
572 *tok = realloc(*tok, tok_size + i);
573 if (!*tok)
574 return EVENT_NONE;
575 strcat(*tok, buf);
576 } else
577 *tok = strdup(buf);
578 if (!*tok)
579 return EVENT_NONE;
580
581 return type;
582}
583
584static void free_token(char *tok)
585{
586 if (tok)
587 free(tok);
588}
589
590static enum event_type read_token(char **tok)
591{
592 enum event_type type;
593
594 for (;;) {
595 type = __read_token(tok);
596 if (type != EVENT_SPACE)
597 return type;
598
599 free_token(*tok);
600 }
601
602 /* not reached */
603 return EVENT_NONE;
604}
605
606/* no newline */
607static enum event_type read_token_item(char **tok)
608{
609 enum event_type type;
610
611 for (;;) {
612 type = __read_token(tok);
613 if (type != EVENT_SPACE && type != EVENT_NEWLINE)
614 return type;
615
616 free_token(*tok);
617 }
618
619 /* not reached */
620 return EVENT_NONE;
621}
622
623static int test_type(enum event_type type, enum event_type expect)
624{
625 if (type != expect) {
Steven Rostedt07a4bdd2009-10-14 15:43:39 -0400626 warning("Error: expected type %d but read %d",
Steven Rostedtea4010d2009-08-17 16:18:07 +0200627 expect, type);
628 return -1;
629 }
630 return 0;
631}
632
Arnaldo Carvalho de Meloe9e94e32010-04-05 18:01:10 -0300633static int __test_type_token(enum event_type type, char *token,
634 enum event_type expect, const char *expect_tok,
635 bool warn)
Steven Rostedtea4010d2009-08-17 16:18:07 +0200636{
637 if (type != expect) {
Arnaldo Carvalho de Meloe9e94e32010-04-05 18:01:10 -0300638 if (warn)
639 warning("Error: expected type %d but read %d",
640 expect, type);
Steven Rostedtea4010d2009-08-17 16:18:07 +0200641 return -1;
642 }
643
644 if (strcmp(token, expect_tok) != 0) {
Arnaldo Carvalho de Meloe9e94e32010-04-05 18:01:10 -0300645 if (warn)
646 warning("Error: expected '%s' but read '%s'",
647 expect_tok, token);
Steven Rostedtea4010d2009-08-17 16:18:07 +0200648 return -1;
649 }
650 return 0;
651}
652
Arnaldo Carvalho de Meloe9e94e32010-04-05 18:01:10 -0300653static int test_type_token(enum event_type type, char *token,
654 enum event_type expect, const char *expect_tok)
655{
656 return __test_type_token(type, token, expect, expect_tok, true);
657}
658
Steven Rostedtea4010d2009-08-17 16:18:07 +0200659static int __read_expect_type(enum event_type expect, char **tok, int newline_ok)
660{
661 enum event_type type;
662
663 if (newline_ok)
664 type = read_token(tok);
665 else
666 type = read_token_item(tok);
667 return test_type(type, expect);
668}
669
670static int read_expect_type(enum event_type expect, char **tok)
671{
672 return __read_expect_type(expect, tok, 1);
673}
674
Arnaldo Carvalho de Meloe9e94e32010-04-05 18:01:10 -0300675static int __read_expected(enum event_type expect, const char *str,
676 int newline_ok, bool warn)
Steven Rostedtea4010d2009-08-17 16:18:07 +0200677{
678 enum event_type type;
679 char *token;
680 int ret;
681
682 if (newline_ok)
683 type = read_token(&token);
684 else
685 type = read_token_item(&token);
686
Arnaldo Carvalho de Meloe9e94e32010-04-05 18:01:10 -0300687 ret = __test_type_token(type, token, expect, str, warn);
Steven Rostedtea4010d2009-08-17 16:18:07 +0200688
689 free_token(token);
690
Steven Rostedt07a4bdd2009-10-14 15:43:39 -0400691 return ret;
Steven Rostedtea4010d2009-08-17 16:18:07 +0200692}
693
Arnaldo Carvalho de Meloe9e94e32010-04-05 18:01:10 -0300694static int read_expected_warn(enum event_type expect, const char *str, bool warn)
695{
696 return __read_expected(expect, str, 1, warn);
697}
698
Randy Dunlapcbef79a2009-10-05 13:17:29 -0700699static int read_expected(enum event_type expect, const char *str)
Steven Rostedtea4010d2009-08-17 16:18:07 +0200700{
Arnaldo Carvalho de Meloe9e94e32010-04-05 18:01:10 -0300701 return __read_expected(expect, str, 1, true);
Steven Rostedtea4010d2009-08-17 16:18:07 +0200702}
703
Randy Dunlapcbef79a2009-10-05 13:17:29 -0700704static int read_expected_item(enum event_type expect, const char *str)
Steven Rostedtea4010d2009-08-17 16:18:07 +0200705{
Arnaldo Carvalho de Meloe9e94e32010-04-05 18:01:10 -0300706 return __read_expected(expect, str, 0, true);
Steven Rostedtea4010d2009-08-17 16:18:07 +0200707}
708
709static char *event_read_name(void)
710{
711 char *token;
712
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400713 if (read_expected(EVENT_ITEM, "name") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +0200714 return NULL;
715
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400716 if (read_expected(EVENT_OP, ":") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +0200717 return NULL;
718
719 if (read_expect_type(EVENT_ITEM, &token) < 0)
720 goto fail;
721
722 return token;
723
724 fail:
725 free_token(token);
726 return NULL;
727}
728
729static int event_read_id(void)
730{
731 char *token;
732 int id;
733
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400734 if (read_expected_item(EVENT_ITEM, "ID") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +0200735 return -1;
736
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400737 if (read_expected(EVENT_OP, ":") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +0200738 return -1;
739
740 if (read_expect_type(EVENT_ITEM, &token) < 0)
741 goto fail;
742
743 id = strtoul(token, NULL, 0);
744 free_token(token);
745 return id;
746
747 fail:
748 free_token(token);
749 return -1;
750}
751
Tom Zanussi064739b2009-10-06 01:09:52 -0500752static int field_is_string(struct format_field *field)
753{
754 if ((field->flags & FIELD_IS_ARRAY) &&
755 (!strstr(field->type, "char") || !strstr(field->type, "u8") ||
756 !strstr(field->type, "s8")))
757 return 1;
758
759 return 0;
760}
761
762static int field_is_dynamic(struct format_field *field)
763{
Thomas Gleixnera1e2f602010-04-14 23:58:03 +0200764 if (!strncmp(field->type, "__data_loc", 10))
Tom Zanussi064739b2009-10-06 01:09:52 -0500765 return 1;
766
767 return 0;
768}
769
Steven Rostedtea4010d2009-08-17 16:18:07 +0200770static int event_read_fields(struct event *event, struct format_field **fields)
771{
772 struct format_field *field = NULL;
773 enum event_type type;
774 char *token;
775 char *last_token;
776 int count = 0;
777
778 do {
779 type = read_token(&token);
780 if (type == EVENT_NEWLINE) {
781 free_token(token);
782 return count;
783 }
784
785 count++;
786
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400787 if (test_type_token(type, token, EVENT_ITEM, "field"))
Steven Rostedtea4010d2009-08-17 16:18:07 +0200788 goto fail;
789 free_token(token);
790
791 type = read_token(&token);
792 /*
793 * The ftrace fields may still use the "special" name.
794 * Just ignore it.
795 */
796 if (event->flags & EVENT_FL_ISFTRACE &&
797 type == EVENT_ITEM && strcmp(token, "special") == 0) {
798 free_token(token);
799 type = read_token(&token);
800 }
801
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400802 if (test_type_token(type, token, EVENT_OP, ":") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +0200803 return -1;
804
805 if (read_expect_type(EVENT_ITEM, &token) < 0)
806 goto fail;
807
808 last_token = token;
809
810 field = malloc_or_die(sizeof(*field));
811 memset(field, 0, sizeof(*field));
812
813 /* read the rest of the type */
814 for (;;) {
815 type = read_token(&token);
816 if (type == EVENT_ITEM ||
817 (type == EVENT_OP && strcmp(token, "*") == 0) ||
818 /*
819 * Some of the ftrace fields are broken and have
820 * an illegal "." in them.
821 */
822 (event->flags & EVENT_FL_ISFTRACE &&
823 type == EVENT_OP && strcmp(token, ".") == 0)) {
824
825 if (strcmp(token, "*") == 0)
826 field->flags |= FIELD_IS_POINTER;
827
828 if (field->type) {
829 field->type = realloc(field->type,
830 strlen(field->type) +
831 strlen(last_token) + 2);
832 strcat(field->type, " ");
833 strcat(field->type, last_token);
834 } else
835 field->type = last_token;
836 last_token = token;
837 continue;
838 }
839
840 break;
841 }
842
843 if (!field->type) {
844 die("no type found");
845 goto fail;
846 }
847 field->name = last_token;
848
849 if (test_type(type, EVENT_OP))
850 goto fail;
851
852 if (strcmp(token, "[") == 0) {
853 enum event_type last_type = type;
854 char *brackets = token;
855 int len;
856
857 field->flags |= FIELD_IS_ARRAY;
858
859 type = read_token(&token);
860 while (strcmp(token, "]") != 0) {
861 if (last_type == EVENT_ITEM &&
862 type == EVENT_ITEM)
863 len = 2;
864 else
865 len = 1;
866 last_type = type;
867
868 brackets = realloc(brackets,
869 strlen(brackets) +
870 strlen(token) + len);
871 if (len == 2)
872 strcat(brackets, " ");
873 strcat(brackets, token);
874 free_token(token);
875 type = read_token(&token);
876 if (type == EVENT_NONE) {
877 die("failed to find token");
878 goto fail;
879 }
880 }
881
882 free_token(token);
883
884 brackets = realloc(brackets, strlen(brackets) + 2);
885 strcat(brackets, "]");
886
887 /* add brackets to type */
888
889 type = read_token(&token);
890 /*
891 * If the next token is not an OP, then it is of
892 * the format: type [] item;
893 */
894 if (type == EVENT_ITEM) {
895 field->type = realloc(field->type,
896 strlen(field->type) +
897 strlen(field->name) +
898 strlen(brackets) + 2);
899 strcat(field->type, " ");
900 strcat(field->type, field->name);
901 free_token(field->name);
902 strcat(field->type, brackets);
903 field->name = token;
904 type = read_token(&token);
905 } else {
906 field->type = realloc(field->type,
907 strlen(field->type) +
908 strlen(brackets) + 1);
909 strcat(field->type, brackets);
910 }
911 free(brackets);
912 }
913
Tom Zanussi064739b2009-10-06 01:09:52 -0500914 if (field_is_string(field)) {
915 field->flags |= FIELD_IS_STRING;
916 if (field_is_dynamic(field))
917 field->flags |= FIELD_IS_DYNAMIC;
918 }
919
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400920 if (test_type_token(type, token, EVENT_OP, ";"))
Steven Rostedtea4010d2009-08-17 16:18:07 +0200921 goto fail;
922 free_token(token);
923
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400924 if (read_expected(EVENT_ITEM, "offset") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +0200925 goto fail_expect;
926
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400927 if (read_expected(EVENT_OP, ":") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +0200928 goto fail_expect;
929
930 if (read_expect_type(EVENT_ITEM, &token))
931 goto fail;
932 field->offset = strtoul(token, NULL, 0);
933 free_token(token);
934
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400935 if (read_expected(EVENT_OP, ";") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +0200936 goto fail_expect;
937
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400938 if (read_expected(EVENT_ITEM, "size") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +0200939 goto fail_expect;
940
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400941 if (read_expected(EVENT_OP, ":") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +0200942 goto fail_expect;
943
944 if (read_expect_type(EVENT_ITEM, &token))
945 goto fail;
946 field->size = strtoul(token, NULL, 0);
947 free_token(token);
948
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400949 if (read_expected(EVENT_OP, ";") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +0200950 goto fail_expect;
951
Steven Rostedt13999e52009-10-14 15:43:38 -0400952 type = read_token(&token);
953 if (type != EVENT_NEWLINE) {
954 /* newer versions of the kernel have a "signed" type */
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400955 if (test_type_token(type, token, EVENT_ITEM, "signed"))
Steven Rostedt13999e52009-10-14 15:43:38 -0400956 goto fail;
Tom Zanussi26a50742009-10-06 01:09:50 -0500957
Steven Rostedt13999e52009-10-14 15:43:38 -0400958 free_token(token);
Tom Zanussi26a50742009-10-06 01:09:50 -0500959
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400960 if (read_expected(EVENT_OP, ":") < 0)
Steven Rostedt13999e52009-10-14 15:43:38 -0400961 goto fail_expect;
Tom Zanussi26a50742009-10-06 01:09:50 -0500962
Steven Rostedt13999e52009-10-14 15:43:38 -0400963 if (read_expect_type(EVENT_ITEM, &token))
964 goto fail;
Tom Zanussi26a50742009-10-06 01:09:50 -0500965
Tom Zanussi0d0bea52009-11-25 01:14:58 -0600966 if (strtoul(token, NULL, 0))
967 field->flags |= FIELD_IS_SIGNED;
Steven Rostedt13999e52009-10-14 15:43:38 -0400968
969 free_token(token);
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400970 if (read_expected(EVENT_OP, ";") < 0)
Steven Rostedt13999e52009-10-14 15:43:38 -0400971 goto fail_expect;
972
973 if (read_expect_type(EVENT_NEWLINE, &token))
974 goto fail;
975 }
976
Steven Rostedtea4010d2009-08-17 16:18:07 +0200977 free_token(token);
978
979 *fields = field;
980 fields = &field->next;
981
982 } while (1);
983
984 return 0;
985
986fail:
987 free_token(token);
988fail_expect:
989 if (field)
990 free(field);
991 return -1;
992}
993
994static int event_read_format(struct event *event)
995{
996 char *token;
997 int ret;
998
Steven Rostedtc4dc7752009-10-14 15:43:44 -0400999 if (read_expected_item(EVENT_ITEM, "format") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02001000 return -1;
1001
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001002 if (read_expected(EVENT_OP, ":") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02001003 return -1;
1004
1005 if (read_expect_type(EVENT_NEWLINE, &token))
1006 goto fail;
1007 free_token(token);
1008
1009 ret = event_read_fields(event, &event->format.common_fields);
1010 if (ret < 0)
1011 return ret;
1012 event->format.nr_common = ret;
1013
1014 ret = event_read_fields(event, &event->format.fields);
1015 if (ret < 0)
1016 return ret;
1017 event->format.nr_fields = ret;
1018
1019 return 0;
1020
1021 fail:
1022 free_token(token);
1023 return -1;
1024}
1025
1026enum event_type
1027process_arg_token(struct event *event, struct print_arg *arg,
1028 char **tok, enum event_type type);
1029
1030static enum event_type
1031process_arg(struct event *event, struct print_arg *arg, char **tok)
1032{
1033 enum event_type type;
1034 char *token;
1035
1036 type = read_token(&token);
1037 *tok = token;
1038
1039 return process_arg_token(event, arg, tok, type);
1040}
1041
1042static enum event_type
1043process_cond(struct event *event, struct print_arg *top, char **tok)
1044{
1045 struct print_arg *arg, *left, *right;
1046 enum event_type type;
1047 char *token = NULL;
1048
1049 arg = malloc_or_die(sizeof(*arg));
1050 memset(arg, 0, sizeof(*arg));
1051
1052 left = malloc_or_die(sizeof(*left));
1053
1054 right = malloc_or_die(sizeof(*right));
1055
1056 arg->type = PRINT_OP;
1057 arg->op.left = left;
1058 arg->op.right = right;
1059
1060 *tok = NULL;
1061 type = process_arg(event, left, &token);
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001062 if (test_type_token(type, token, EVENT_OP, ":"))
Steven Rostedtea4010d2009-08-17 16:18:07 +02001063 goto out_free;
1064
1065 arg->op.op = token;
1066
1067 type = process_arg(event, right, &token);
1068
1069 top->op.right = arg;
1070
1071 *tok = token;
1072 return type;
1073
1074out_free:
1075 free_token(*tok);
1076 free(right);
1077 free(left);
1078 free_arg(arg);
1079 return EVENT_ERROR;
1080}
1081
Steven Rostedt0959b8d2009-10-14 15:43:35 -04001082static enum event_type
1083process_array(struct event *event, struct print_arg *top, char **tok)
1084{
1085 struct print_arg *arg;
1086 enum event_type type;
1087 char *token = NULL;
1088
1089 arg = malloc_or_die(sizeof(*arg));
1090 memset(arg, 0, sizeof(*arg));
1091
1092 *tok = NULL;
1093 type = process_arg(event, arg, &token);
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001094 if (test_type_token(type, token, EVENT_OP, "]"))
Steven Rostedt0959b8d2009-10-14 15:43:35 -04001095 goto out_free;
1096
1097 top->op.right = arg;
1098
1099 free_token(token);
1100 type = read_token_item(&token);
1101 *tok = token;
1102
1103 return type;
1104
1105out_free:
1106 free_token(*tok);
1107 free_arg(arg);
1108 return EVENT_ERROR;
1109}
1110
Steven Rostedtea4010d2009-08-17 16:18:07 +02001111static int get_op_prio(char *op)
1112{
1113 if (!op[1]) {
1114 switch (op[0]) {
1115 case '*':
1116 case '/':
1117 case '%':
1118 return 6;
1119 case '+':
1120 case '-':
1121 return 7;
1122 /* '>>' and '<<' are 8 */
1123 case '<':
1124 case '>':
1125 return 9;
1126 /* '==' and '!=' are 10 */
1127 case '&':
1128 return 11;
1129 case '^':
1130 return 12;
1131 case '|':
1132 return 13;
1133 case '?':
1134 return 16;
1135 default:
1136 die("unknown op '%c'", op[0]);
1137 return -1;
1138 }
1139 } else {
1140 if (strcmp(op, "++") == 0 ||
1141 strcmp(op, "--") == 0) {
1142 return 3;
1143 } else if (strcmp(op, ">>") == 0 ||
1144 strcmp(op, "<<") == 0) {
1145 return 8;
1146 } else if (strcmp(op, ">=") == 0 ||
1147 strcmp(op, "<=") == 0) {
1148 return 9;
1149 } else if (strcmp(op, "==") == 0 ||
1150 strcmp(op, "!=") == 0) {
1151 return 10;
1152 } else if (strcmp(op, "&&") == 0) {
1153 return 14;
1154 } else if (strcmp(op, "||") == 0) {
1155 return 15;
1156 } else {
1157 die("unknown op '%s'", op);
1158 return -1;
1159 }
1160 }
1161}
1162
1163static void set_op_prio(struct print_arg *arg)
1164{
1165
1166 /* single ops are the greatest */
1167 if (!arg->op.left || arg->op.left->type == PRINT_NULL) {
1168 arg->op.prio = 0;
1169 return;
1170 }
1171
1172 arg->op.prio = get_op_prio(arg->op.op);
1173}
1174
1175static enum event_type
1176process_op(struct event *event, struct print_arg *arg, char **tok)
1177{
1178 struct print_arg *left, *right = NULL;
1179 enum event_type type;
1180 char *token;
1181
1182 /* the op is passed in via tok */
1183 token = *tok;
1184
1185 if (arg->type == PRINT_OP && !arg->op.left) {
1186 /* handle single op */
1187 if (token[1]) {
1188 die("bad op token %s", token);
1189 return EVENT_ERROR;
1190 }
1191 switch (token[0]) {
1192 case '!':
1193 case '+':
1194 case '-':
1195 break;
1196 default:
1197 die("bad op token %s", token);
1198 return EVENT_ERROR;
1199 }
1200
1201 /* make an empty left */
1202 left = malloc_or_die(sizeof(*left));
1203 left->type = PRINT_NULL;
1204 arg->op.left = left;
1205
1206 right = malloc_or_die(sizeof(*right));
1207 arg->op.right = right;
1208
1209 type = process_arg(event, right, tok);
1210
1211 } else if (strcmp(token, "?") == 0) {
1212
1213 left = malloc_or_die(sizeof(*left));
1214 /* copy the top arg to the left */
1215 *left = *arg;
1216
1217 arg->type = PRINT_OP;
1218 arg->op.op = token;
1219 arg->op.left = left;
1220 arg->op.prio = 0;
1221
1222 type = process_cond(event, arg, tok);
1223
1224 } else if (strcmp(token, ">>") == 0 ||
1225 strcmp(token, "<<") == 0 ||
1226 strcmp(token, "&") == 0 ||
1227 strcmp(token, "|") == 0 ||
1228 strcmp(token, "&&") == 0 ||
1229 strcmp(token, "||") == 0 ||
1230 strcmp(token, "-") == 0 ||
1231 strcmp(token, "+") == 0 ||
1232 strcmp(token, "*") == 0 ||
1233 strcmp(token, "^") == 0 ||
1234 strcmp(token, "/") == 0 ||
Steven Rostedt298ebc32009-10-14 15:43:34 -04001235 strcmp(token, "<") == 0 ||
1236 strcmp(token, ">") == 0 ||
Steven Rostedtea4010d2009-08-17 16:18:07 +02001237 strcmp(token, "==") == 0 ||
1238 strcmp(token, "!=") == 0) {
1239
1240 left = malloc_or_die(sizeof(*left));
1241
1242 /* copy the top arg to the left */
1243 *left = *arg;
1244
1245 arg->type = PRINT_OP;
1246 arg->op.op = token;
1247 arg->op.left = left;
1248
1249 set_op_prio(arg);
1250
1251 right = malloc_or_die(sizeof(*right));
1252
Steven Rostedtb99af872009-10-14 15:43:36 -04001253 type = read_token_item(&token);
1254 *tok = token;
1255
1256 /* could just be a type pointer */
1257 if ((strcmp(arg->op.op, "*") == 0) &&
1258 type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
1259 if (left->type != PRINT_ATOM)
1260 die("bad pointer type");
1261 left->atom.atom = realloc(left->atom.atom,
1262 sizeof(left->atom.atom) + 3);
1263 strcat(left->atom.atom, " *");
1264 *arg = *left;
1265 free(arg);
1266
1267 return type;
1268 }
1269
1270 type = process_arg_token(event, right, tok, type);
Steven Rostedtea4010d2009-08-17 16:18:07 +02001271
1272 arg->op.right = right;
1273
Steven Rostedt0959b8d2009-10-14 15:43:35 -04001274 } else if (strcmp(token, "[") == 0) {
1275
1276 left = malloc_or_die(sizeof(*left));
1277 *left = *arg;
1278
1279 arg->type = PRINT_OP;
1280 arg->op.op = token;
1281 arg->op.left = left;
1282
1283 arg->op.prio = 0;
1284 type = process_array(event, arg, tok);
1285
Steven Rostedtea4010d2009-08-17 16:18:07 +02001286 } else {
Steven Rostedt07a4bdd2009-10-14 15:43:39 -04001287 warning("unknown op '%s'", token);
1288 event->flags |= EVENT_FL_FAILED;
Steven Rostedtea4010d2009-08-17 16:18:07 +02001289 /* the arg is now the left side */
1290 return EVENT_NONE;
1291 }
1292
Steven Rostedtea4010d2009-08-17 16:18:07 +02001293 if (type == EVENT_OP) {
1294 int prio;
1295
1296 /* higher prios need to be closer to the root */
1297 prio = get_op_prio(*tok);
1298
1299 if (prio > arg->op.prio)
1300 return process_op(event, arg, tok);
1301
1302 return process_op(event, right, tok);
1303 }
1304
1305 return type;
1306}
1307
1308static enum event_type
1309process_entry(struct event *event __unused, struct print_arg *arg,
1310 char **tok)
1311{
1312 enum event_type type;
1313 char *field;
1314 char *token;
1315
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001316 if (read_expected(EVENT_OP, "->") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02001317 return EVENT_ERROR;
1318
1319 if (read_expect_type(EVENT_ITEM, &token) < 0)
1320 goto fail;
1321 field = token;
1322
1323 arg->type = PRINT_FIELD;
1324 arg->field.name = field;
1325
Tom Zanussieb9a42c2009-11-25 01:15:47 -06001326 if (is_flag_field) {
1327 arg->field.field = find_any_field(event, arg->field.name);
1328 arg->field.field->flags |= FIELD_IS_FLAG;
1329 is_flag_field = 0;
1330 } else if (is_symbolic_field) {
1331 arg->field.field = find_any_field(event, arg->field.name);
1332 arg->field.field->flags |= FIELD_IS_SYMBOLIC;
1333 is_symbolic_field = 0;
1334 }
1335
Steven Rostedtea4010d2009-08-17 16:18:07 +02001336 type = read_token(&token);
1337 *tok = token;
1338
1339 return type;
1340
1341fail:
1342 free_token(token);
1343 return EVENT_ERROR;
1344}
1345
1346static char *arg_eval (struct print_arg *arg);
1347
1348static long long arg_num_eval(struct print_arg *arg)
1349{
1350 long long left, right;
1351 long long val = 0;
1352
1353 switch (arg->type) {
1354 case PRINT_ATOM:
1355 val = strtoll(arg->atom.atom, NULL, 0);
1356 break;
1357 case PRINT_TYPE:
1358 val = arg_num_eval(arg->typecast.item);
1359 break;
1360 case PRINT_OP:
1361 switch (arg->op.op[0]) {
1362 case '|':
1363 left = arg_num_eval(arg->op.left);
1364 right = arg_num_eval(arg->op.right);
1365 if (arg->op.op[1])
1366 val = left || right;
1367 else
1368 val = left | right;
1369 break;
1370 case '&':
1371 left = arg_num_eval(arg->op.left);
1372 right = arg_num_eval(arg->op.right);
1373 if (arg->op.op[1])
1374 val = left && right;
1375 else
1376 val = left & right;
1377 break;
1378 case '<':
1379 left = arg_num_eval(arg->op.left);
1380 right = arg_num_eval(arg->op.right);
1381 switch (arg->op.op[1]) {
1382 case 0:
1383 val = left < right;
1384 break;
1385 case '<':
1386 val = left << right;
1387 break;
1388 case '=':
1389 val = left <= right;
1390 break;
1391 default:
1392 die("unknown op '%s'", arg->op.op);
1393 }
1394 break;
1395 case '>':
1396 left = arg_num_eval(arg->op.left);
1397 right = arg_num_eval(arg->op.right);
1398 switch (arg->op.op[1]) {
1399 case 0:
1400 val = left > right;
1401 break;
1402 case '>':
1403 val = left >> right;
1404 break;
1405 case '=':
1406 val = left >= right;
1407 break;
1408 default:
1409 die("unknown op '%s'", arg->op.op);
1410 }
1411 break;
1412 case '=':
1413 left = arg_num_eval(arg->op.left);
1414 right = arg_num_eval(arg->op.right);
1415
1416 if (arg->op.op[1] != '=')
1417 die("unknown op '%s'", arg->op.op);
1418
1419 val = left == right;
1420 break;
1421 case '!':
1422 left = arg_num_eval(arg->op.left);
1423 right = arg_num_eval(arg->op.right);
1424
1425 switch (arg->op.op[1]) {
1426 case '=':
1427 val = left != right;
1428 break;
1429 default:
1430 die("unknown op '%s'", arg->op.op);
1431 }
1432 break;
1433 default:
1434 die("unknown op '%s'", arg->op.op);
1435 }
1436 break;
1437
1438 case PRINT_NULL:
1439 case PRINT_FIELD ... PRINT_SYMBOL:
1440 case PRINT_STRING:
1441 default:
1442 die("invalid eval type %d", arg->type);
1443
1444 }
1445 return val;
1446}
1447
1448static char *arg_eval (struct print_arg *arg)
1449{
1450 long long val;
1451 static char buf[20];
1452
1453 switch (arg->type) {
1454 case PRINT_ATOM:
1455 return arg->atom.atom;
1456 case PRINT_TYPE:
1457 return arg_eval(arg->typecast.item);
1458 case PRINT_OP:
1459 val = arg_num_eval(arg);
1460 sprintf(buf, "%lld", val);
1461 return buf;
1462
1463 case PRINT_NULL:
1464 case PRINT_FIELD ... PRINT_SYMBOL:
1465 case PRINT_STRING:
1466 default:
1467 die("invalid eval type %d", arg->type);
1468 break;
1469 }
1470
1471 return NULL;
1472}
1473
1474static enum event_type
1475process_fields(struct event *event, struct print_flag_sym **list, char **tok)
1476{
1477 enum event_type type;
1478 struct print_arg *arg = NULL;
1479 struct print_flag_sym *field;
1480 char *token = NULL;
1481 char *value;
1482
1483 do {
1484 free_token(token);
1485 type = read_token_item(&token);
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001486 if (test_type_token(type, token, EVENT_OP, "{"))
Steven Rostedtea4010d2009-08-17 16:18:07 +02001487 break;
1488
1489 arg = malloc_or_die(sizeof(*arg));
1490
1491 free_token(token);
1492 type = process_arg(event, arg, &token);
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001493 if (test_type_token(type, token, EVENT_DELIM, ","))
Steven Rostedtea4010d2009-08-17 16:18:07 +02001494 goto out_free;
1495
1496 field = malloc_or_die(sizeof(*field));
Julia Lawall5660ce32009-12-09 20:26:18 +01001497 memset(field, 0, sizeof(*field));
Steven Rostedtea4010d2009-08-17 16:18:07 +02001498
1499 value = arg_eval(arg);
1500 field->value = strdup(value);
1501
1502 free_token(token);
1503 type = process_arg(event, arg, &token);
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001504 if (test_type_token(type, token, EVENT_OP, "}"))
Steven Rostedtea4010d2009-08-17 16:18:07 +02001505 goto out_free;
1506
1507 value = arg_eval(arg);
1508 field->str = strdup(value);
1509 free_arg(arg);
1510 arg = NULL;
1511
1512 *list = field;
1513 list = &field->next;
1514
1515 free_token(token);
1516 type = read_token_item(&token);
1517 } while (type == EVENT_DELIM && strcmp(token, ",") == 0);
1518
1519 *tok = token;
1520 return type;
1521
1522out_free:
1523 free_arg(arg);
1524 free_token(token);
1525
1526 return EVENT_ERROR;
1527}
1528
1529static enum event_type
1530process_flags(struct event *event, struct print_arg *arg, char **tok)
1531{
1532 struct print_arg *field;
1533 enum event_type type;
1534 char *token;
1535
1536 memset(arg, 0, sizeof(*arg));
1537 arg->type = PRINT_FLAGS;
1538
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001539 if (read_expected_item(EVENT_DELIM, "(") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02001540 return EVENT_ERROR;
1541
1542 field = malloc_or_die(sizeof(*field));
1543
1544 type = process_arg(event, field, &token);
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001545 if (test_type_token(type, token, EVENT_DELIM, ","))
Steven Rostedtea4010d2009-08-17 16:18:07 +02001546 goto out_free;
1547
1548 arg->flags.field = field;
1549
1550 type = read_token_item(&token);
1551 if (event_item_type(type)) {
1552 arg->flags.delim = token;
1553 type = read_token_item(&token);
1554 }
1555
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001556 if (test_type_token(type, token, EVENT_DELIM, ","))
Steven Rostedtea4010d2009-08-17 16:18:07 +02001557 goto out_free;
1558
1559 type = process_fields(event, &arg->flags.flags, &token);
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001560 if (test_type_token(type, token, EVENT_DELIM, ")"))
Steven Rostedtea4010d2009-08-17 16:18:07 +02001561 goto out_free;
1562
1563 free_token(token);
1564 type = read_token_item(tok);
1565 return type;
1566
1567out_free:
1568 free_token(token);
1569 return EVENT_ERROR;
1570}
1571
1572static enum event_type
1573process_symbols(struct event *event, struct print_arg *arg, char **tok)
1574{
1575 struct print_arg *field;
1576 enum event_type type;
1577 char *token;
1578
1579 memset(arg, 0, sizeof(*arg));
1580 arg->type = PRINT_SYMBOL;
1581
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001582 if (read_expected_item(EVENT_DELIM, "(") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02001583 return EVENT_ERROR;
1584
1585 field = malloc_or_die(sizeof(*field));
1586
1587 type = process_arg(event, field, &token);
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001588 if (test_type_token(type, token, EVENT_DELIM, ","))
Steven Rostedtea4010d2009-08-17 16:18:07 +02001589 goto out_free;
1590
1591 arg->symbol.field = field;
1592
1593 type = process_fields(event, &arg->symbol.symbols, &token);
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001594 if (test_type_token(type, token, EVENT_DELIM, ")"))
Steven Rostedtea4010d2009-08-17 16:18:07 +02001595 goto out_free;
1596
1597 free_token(token);
1598 type = read_token_item(tok);
1599 return type;
1600
1601out_free:
1602 free_token(token);
1603 return EVENT_ERROR;
1604}
1605
1606static enum event_type
1607process_paren(struct event *event, struct print_arg *arg, char **tok)
1608{
1609 struct print_arg *item_arg;
1610 enum event_type type;
1611 char *token;
1612
1613 type = process_arg(event, arg, &token);
1614
1615 if (type == EVENT_ERROR)
1616 return EVENT_ERROR;
1617
Steven Rostedtb99af872009-10-14 15:43:36 -04001618 if (type == EVENT_OP)
1619 type = process_op(event, arg, &token);
Steven Rostedtea4010d2009-08-17 16:18:07 +02001620
Steven Rostedtb99af872009-10-14 15:43:36 -04001621 if (type == EVENT_ERROR)
1622 return EVENT_ERROR;
Steven Rostedtea4010d2009-08-17 16:18:07 +02001623
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001624 if (test_type_token(type, token, EVENT_DELIM, ")")) {
Steven Rostedtea4010d2009-08-17 16:18:07 +02001625 free_token(token);
1626 return EVENT_ERROR;
1627 }
1628
1629 free_token(token);
1630 type = read_token_item(&token);
1631
1632 /*
1633 * If the next token is an item or another open paren, then
1634 * this was a typecast.
1635 */
1636 if (event_item_type(type) ||
1637 (type == EVENT_DELIM && strcmp(token, "(") == 0)) {
1638
1639 /* make this a typecast and contine */
1640
1641 /* prevous must be an atom */
1642 if (arg->type != PRINT_ATOM)
1643 die("previous needed to be PRINT_ATOM");
1644
1645 item_arg = malloc_or_die(sizeof(*item_arg));
1646
1647 arg->type = PRINT_TYPE;
Steven Rostedtea4010d2009-08-17 16:18:07 +02001648 arg->typecast.type = arg->atom.atom;
1649 arg->typecast.item = item_arg;
1650 type = process_arg_token(event, item_arg, &token, type);
1651
1652 }
1653
1654 *tok = token;
1655 return type;
1656}
1657
1658
1659static enum event_type
1660process_str(struct event *event __unused, struct print_arg *arg, char **tok)
1661{
1662 enum event_type type;
1663 char *token;
1664
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001665 if (read_expected(EVENT_DELIM, "(") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02001666 return EVENT_ERROR;
1667
1668 if (read_expect_type(EVENT_ITEM, &token) < 0)
1669 goto fail;
1670
1671 arg->type = PRINT_STRING;
1672 arg->string.string = token;
Frederic Weisbecker561f7322009-08-31 06:45:21 +02001673 arg->string.offset = -1;
Steven Rostedtea4010d2009-08-17 16:18:07 +02001674
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001675 if (read_expected(EVENT_DELIM, ")") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02001676 return EVENT_ERROR;
1677
1678 type = read_token(&token);
1679 *tok = token;
1680
1681 return type;
1682fail:
1683 free_token(token);
1684 return EVENT_ERROR;
1685}
1686
1687enum event_type
1688process_arg_token(struct event *event, struct print_arg *arg,
1689 char **tok, enum event_type type)
1690{
1691 char *token;
1692 char *atom;
1693
1694 token = *tok;
1695
1696 switch (type) {
1697 case EVENT_ITEM:
1698 if (strcmp(token, "REC") == 0) {
1699 free_token(token);
1700 type = process_entry(event, arg, &token);
1701 } else if (strcmp(token, "__print_flags") == 0) {
1702 free_token(token);
Tom Zanussieb9a42c2009-11-25 01:15:47 -06001703 is_flag_field = 1;
Steven Rostedtea4010d2009-08-17 16:18:07 +02001704 type = process_flags(event, arg, &token);
1705 } else if (strcmp(token, "__print_symbolic") == 0) {
1706 free_token(token);
Tom Zanussieb9a42c2009-11-25 01:15:47 -06001707 is_symbolic_field = 1;
Steven Rostedtea4010d2009-08-17 16:18:07 +02001708 type = process_symbols(event, arg, &token);
1709 } else if (strcmp(token, "__get_str") == 0) {
1710 free_token(token);
1711 type = process_str(event, arg, &token);
1712 } else {
1713 atom = token;
1714 /* test the next token */
1715 type = read_token_item(&token);
1716
1717 /* atoms can be more than one token long */
1718 while (type == EVENT_ITEM) {
1719 atom = realloc(atom, strlen(atom) + strlen(token) + 2);
1720 strcat(atom, " ");
1721 strcat(atom, token);
1722 free_token(token);
1723 type = read_token_item(&token);
1724 }
1725
1726 /* todo, test for function */
1727
1728 arg->type = PRINT_ATOM;
1729 arg->atom.atom = atom;
1730 }
1731 break;
1732 case EVENT_DQUOTE:
1733 case EVENT_SQUOTE:
1734 arg->type = PRINT_ATOM;
1735 arg->atom.atom = token;
1736 type = read_token_item(&token);
1737 break;
1738 case EVENT_DELIM:
1739 if (strcmp(token, "(") == 0) {
1740 free_token(token);
1741 type = process_paren(event, arg, &token);
1742 break;
1743 }
1744 case EVENT_OP:
1745 /* handle single ops */
1746 arg->type = PRINT_OP;
1747 arg->op.op = token;
1748 arg->op.left = NULL;
1749 type = process_op(event, arg, &token);
1750
1751 break;
1752
1753 case EVENT_ERROR ... EVENT_NEWLINE:
1754 default:
1755 die("unexpected type %d", type);
1756 }
1757 *tok = token;
1758
1759 return type;
1760}
1761
1762static int event_read_print_args(struct event *event, struct print_arg **list)
1763{
Steven Rostedtf1d1fee2009-10-14 15:43:37 -04001764 enum event_type type = EVENT_ERROR;
Steven Rostedtea4010d2009-08-17 16:18:07 +02001765 struct print_arg *arg;
1766 char *token;
1767 int args = 0;
1768
1769 do {
Steven Rostedtf1d1fee2009-10-14 15:43:37 -04001770 if (type == EVENT_NEWLINE) {
1771 free_token(token);
1772 type = read_token_item(&token);
1773 continue;
1774 }
1775
Steven Rostedtea4010d2009-08-17 16:18:07 +02001776 arg = malloc_or_die(sizeof(*arg));
1777 memset(arg, 0, sizeof(*arg));
1778
1779 type = process_arg(event, arg, &token);
1780
1781 if (type == EVENT_ERROR) {
1782 free_arg(arg);
1783 return -1;
1784 }
1785
1786 *list = arg;
1787 args++;
1788
1789 if (type == EVENT_OP) {
1790 type = process_op(event, arg, &token);
1791 list = &arg->next;
1792 continue;
1793 }
1794
1795 if (type == EVENT_DELIM && strcmp(token, ",") == 0) {
1796 free_token(token);
1797 *list = arg;
1798 list = &arg->next;
1799 continue;
1800 }
1801 break;
1802 } while (type != EVENT_NONE);
1803
1804 if (type != EVENT_NONE)
1805 free_token(token);
1806
1807 return args;
1808}
1809
1810static int event_read_print(struct event *event)
1811{
1812 enum event_type type;
1813 char *token;
1814 int ret;
1815
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001816 if (read_expected_item(EVENT_ITEM, "print") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02001817 return -1;
1818
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001819 if (read_expected(EVENT_ITEM, "fmt") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02001820 return -1;
1821
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001822 if (read_expected(EVENT_OP, ":") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02001823 return -1;
1824
1825 if (read_expect_type(EVENT_DQUOTE, &token) < 0)
1826 goto fail;
1827
Steven Rostedt924a79a2009-10-14 15:43:32 -04001828 concat:
Steven Rostedtea4010d2009-08-17 16:18:07 +02001829 event->print_fmt.format = token;
1830 event->print_fmt.args = NULL;
1831
1832 /* ok to have no arg */
1833 type = read_token_item(&token);
1834
1835 if (type == EVENT_NONE)
1836 return 0;
1837
Steven Rostedt924a79a2009-10-14 15:43:32 -04001838 /* Handle concatination of print lines */
1839 if (type == EVENT_DQUOTE) {
1840 char *cat;
1841
1842 cat = malloc_or_die(strlen(event->print_fmt.format) +
1843 strlen(token) + 1);
1844 strcpy(cat, event->print_fmt.format);
1845 strcat(cat, token);
1846 free_token(token);
1847 free_token(event->print_fmt.format);
1848 event->print_fmt.format = NULL;
1849 token = cat;
1850 goto concat;
1851 }
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001852
1853 if (test_type_token(type, token, EVENT_DELIM, ","))
Steven Rostedtea4010d2009-08-17 16:18:07 +02001854 goto fail;
1855
1856 free_token(token);
1857
1858 ret = event_read_print_args(event, &event->print_fmt.args);
1859 if (ret < 0)
1860 return -1;
1861
Steven Rostedt0d1da912009-10-14 15:43:41 -04001862 return ret;
Steven Rostedtea4010d2009-08-17 16:18:07 +02001863
1864 fail:
1865 free_token(token);
1866 return -1;
1867}
1868
1869static struct format_field *
1870find_common_field(struct event *event, const char *name)
1871{
1872 struct format_field *format;
1873
1874 for (format = event->format.common_fields;
1875 format; format = format->next) {
1876 if (strcmp(format->name, name) == 0)
1877 break;
1878 }
1879
1880 return format;
1881}
1882
1883static struct format_field *
1884find_field(struct event *event, const char *name)
1885{
1886 struct format_field *format;
1887
1888 for (format = event->format.fields;
1889 format; format = format->next) {
1890 if (strcmp(format->name, name) == 0)
1891 break;
1892 }
1893
1894 return format;
1895}
1896
1897static struct format_field *
1898find_any_field(struct event *event, const char *name)
1899{
1900 struct format_field *format;
1901
1902 format = find_common_field(event, name);
1903 if (format)
1904 return format;
1905 return find_field(event, name);
1906}
1907
Tom Zanussi16c632d2009-11-25 01:15:48 -06001908unsigned long long read_size(void *ptr, int size)
Steven Rostedtea4010d2009-08-17 16:18:07 +02001909{
1910 switch (size) {
1911 case 1:
1912 return *(unsigned char *)ptr;
1913 case 2:
1914 return data2host2(ptr);
1915 case 4:
1916 return data2host4(ptr);
1917 case 8:
1918 return data2host8(ptr);
1919 default:
1920 /* BUG! */
1921 return 0;
1922 }
1923}
1924
Frederic Weisbecker46538812009-09-12 02:43:45 +02001925unsigned long long
1926raw_field_value(struct event *event, const char *name, void *data)
1927{
1928 struct format_field *field;
1929
1930 field = find_any_field(event, name);
1931 if (!field)
1932 return 0ULL;
1933
1934 return read_size(data + field->offset, field->size);
1935}
1936
1937void *raw_field_ptr(struct event *event, const char *name, void *data)
1938{
1939 struct format_field *field;
1940
1941 field = find_any_field(event, name);
1942 if (!field)
1943 return NULL;
1944
Hitoshi Mitake86d8d292010-01-30 20:43:23 +09001945 if (field->flags & FIELD_IS_STRING) {
1946 int offset;
1947
1948 offset = *(int *)(data + field->offset);
1949 offset &= 0xffff;
1950
1951 return data + offset;
1952 }
1953
Frederic Weisbecker46538812009-09-12 02:43:45 +02001954 return data + field->offset;
1955}
1956
Steven Rostedtea4010d2009-08-17 16:18:07 +02001957static int get_common_info(const char *type, int *offset, int *size)
1958{
1959 struct event *event;
1960 struct format_field *field;
1961
1962 /*
1963 * All events should have the same common elements.
1964 * Pick any event to find where the type is;
1965 */
1966 if (!event_list)
1967 die("no event_list!");
1968
1969 event = event_list;
1970 field = find_common_field(event, type);
1971 if (!field)
1972 die("field '%s' not found", type);
1973
1974 *offset = field->offset;
1975 *size = field->size;
1976
1977 return 0;
1978}
1979
Steven Rostedtcda48462009-10-14 15:43:42 -04001980static int __parse_common(void *data, int *size, int *offset,
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001981 const char *name)
Steven Rostedtcda48462009-10-14 15:43:42 -04001982{
1983 int ret;
1984
1985 if (!*size) {
1986 ret = get_common_info(name, offset, size);
1987 if (ret < 0)
1988 return ret;
1989 }
1990 return read_size(data + *offset, *size);
1991}
1992
Ingo Molnarec156762009-09-11 12:12:54 +02001993int trace_parse_common_type(void *data)
Steven Rostedtea4010d2009-08-17 16:18:07 +02001994{
1995 static int type_offset;
1996 static int type_size;
Steven Rostedtea4010d2009-08-17 16:18:07 +02001997
Steven Rostedtcda48462009-10-14 15:43:42 -04001998 return __parse_common(data, &type_size, &type_offset,
Steven Rostedtc4dc7752009-10-14 15:43:44 -04001999 "common_type");
Steven Rostedtea4010d2009-08-17 16:18:07 +02002000}
2001
Tom Zanussi16c632d2009-11-25 01:15:48 -06002002int trace_parse_common_pid(void *data)
Steven Rostedtea4010d2009-08-17 16:18:07 +02002003{
2004 static int pid_offset;
2005 static int pid_size;
Steven Rostedtcda48462009-10-14 15:43:42 -04002006
2007 return __parse_common(data, &pid_size, &pid_offset,
Steven Rostedtc4dc7752009-10-14 15:43:44 -04002008 "common_pid");
Steven Rostedtcda48462009-10-14 15:43:42 -04002009}
2010
Tom Zanussid1b93772009-11-25 01:15:50 -06002011int parse_common_pc(void *data)
Steven Rostedtcda48462009-10-14 15:43:42 -04002012{
2013 static int pc_offset;
2014 static int pc_size;
2015
2016 return __parse_common(data, &pc_size, &pc_offset,
Steven Rostedtc4dc7752009-10-14 15:43:44 -04002017 "common_preempt_count");
Steven Rostedtcda48462009-10-14 15:43:42 -04002018}
2019
Tom Zanussid1b93772009-11-25 01:15:50 -06002020int parse_common_flags(void *data)
Steven Rostedtcda48462009-10-14 15:43:42 -04002021{
2022 static int flags_offset;
2023 static int flags_size;
2024
2025 return __parse_common(data, &flags_size, &flags_offset,
Steven Rostedtc4dc7752009-10-14 15:43:44 -04002026 "common_flags");
Steven Rostedtcda48462009-10-14 15:43:42 -04002027}
2028
Tom Zanussid1b93772009-11-25 01:15:50 -06002029int parse_common_lock_depth(void *data)
Steven Rostedtcda48462009-10-14 15:43:42 -04002030{
2031 static int ld_offset;
2032 static int ld_size;
Steven Rostedtea4010d2009-08-17 16:18:07 +02002033 int ret;
2034
Steven Rostedtcda48462009-10-14 15:43:42 -04002035 ret = __parse_common(data, &ld_size, &ld_offset,
Steven Rostedtc4dc7752009-10-14 15:43:44 -04002036 "common_lock_depth");
Steven Rostedtcda48462009-10-14 15:43:42 -04002037 if (ret < 0)
2038 return -1;
Steven Rostedtea4010d2009-08-17 16:18:07 +02002039
Steven Rostedtcda48462009-10-14 15:43:42 -04002040 return ret;
Steven Rostedtea4010d2009-08-17 16:18:07 +02002041}
2042
Ingo Molnarec156762009-09-11 12:12:54 +02002043struct event *trace_find_event(int id)
Steven Rostedtea4010d2009-08-17 16:18:07 +02002044{
2045 struct event *event;
2046
2047 for (event = event_list; event; event = event->next) {
2048 if (event->id == id)
2049 break;
2050 }
2051 return event;
2052}
2053
Tom Zanussi16c632d2009-11-25 01:15:48 -06002054struct event *trace_find_next_event(struct event *event)
2055{
2056 if (!event)
2057 return event_list;
2058
2059 return event->next;
2060}
2061
Steven Rostedtea4010d2009-08-17 16:18:07 +02002062static unsigned long long eval_num_arg(void *data, int size,
2063 struct event *event, struct print_arg *arg)
2064{
2065 unsigned long long val = 0;
2066 unsigned long long left, right;
Steven Rostedt0959b8d2009-10-14 15:43:35 -04002067 struct print_arg *larg;
Steven Rostedtea4010d2009-08-17 16:18:07 +02002068
2069 switch (arg->type) {
2070 case PRINT_NULL:
2071 /* ?? */
2072 return 0;
2073 case PRINT_ATOM:
2074 return strtoull(arg->atom.atom, NULL, 0);
2075 case PRINT_FIELD:
2076 if (!arg->field.field) {
2077 arg->field.field = find_any_field(event, arg->field.name);
2078 if (!arg->field.field)
2079 die("field %s not found", arg->field.name);
2080 }
2081 /* must be a number */
2082 val = read_size(data + arg->field.field->offset,
2083 arg->field.field->size);
2084 break;
2085 case PRINT_FLAGS:
2086 case PRINT_SYMBOL:
2087 break;
2088 case PRINT_TYPE:
2089 return eval_num_arg(data, size, event, arg->typecast.item);
2090 case PRINT_STRING:
2091 return 0;
2092 break;
2093 case PRINT_OP:
Steven Rostedt0959b8d2009-10-14 15:43:35 -04002094 if (strcmp(arg->op.op, "[") == 0) {
2095 /*
2096 * Arrays are special, since we don't want
2097 * to read the arg as is.
2098 */
2099 if (arg->op.left->type != PRINT_FIELD)
2100 goto default_op; /* oops, all bets off */
2101 larg = arg->op.left;
2102 if (!larg->field.field) {
2103 larg->field.field =
2104 find_any_field(event, larg->field.name);
2105 if (!larg->field.field)
2106 die("field %s not found", larg->field.name);
2107 }
2108 right = eval_num_arg(data, size, event, arg->op.right);
2109 val = read_size(data + larg->field.field->offset +
2110 right * long_size, long_size);
2111 break;
2112 }
2113 default_op:
Steven Rostedtea4010d2009-08-17 16:18:07 +02002114 left = eval_num_arg(data, size, event, arg->op.left);
2115 right = eval_num_arg(data, size, event, arg->op.right);
2116 switch (arg->op.op[0]) {
2117 case '|':
2118 if (arg->op.op[1])
2119 val = left || right;
2120 else
2121 val = left | right;
2122 break;
2123 case '&':
2124 if (arg->op.op[1])
2125 val = left && right;
2126 else
2127 val = left & right;
2128 break;
2129 case '<':
2130 switch (arg->op.op[1]) {
2131 case 0:
2132 val = left < right;
2133 break;
2134 case '<':
2135 val = left << right;
2136 break;
2137 case '=':
2138 val = left <= right;
2139 break;
2140 default:
2141 die("unknown op '%s'", arg->op.op);
2142 }
2143 break;
2144 case '>':
2145 switch (arg->op.op[1]) {
2146 case 0:
2147 val = left > right;
2148 break;
2149 case '>':
2150 val = left >> right;
2151 break;
2152 case '=':
2153 val = left >= right;
2154 break;
2155 default:
2156 die("unknown op '%s'", arg->op.op);
2157 }
2158 break;
2159 case '=':
2160 if (arg->op.op[1] != '=')
2161 die("unknown op '%s'", arg->op.op);
2162 val = left == right;
2163 break;
Steven Rostedtafdf1a42009-10-14 15:43:43 -04002164 case '-':
2165 val = left - right;
2166 break;
2167 case '+':
2168 val = left + right;
2169 break;
Steven Rostedtea4010d2009-08-17 16:18:07 +02002170 default:
2171 die("unknown op '%s'", arg->op.op);
2172 }
2173 break;
2174 default: /* not sure what to do there */
2175 return 0;
2176 }
2177 return val;
2178}
2179
2180struct flag {
2181 const char *name;
2182 unsigned long long value;
2183};
2184
2185static const struct flag flags[] = {
2186 { "HI_SOFTIRQ", 0 },
2187 { "TIMER_SOFTIRQ", 1 },
2188 { "NET_TX_SOFTIRQ", 2 },
2189 { "NET_RX_SOFTIRQ", 3 },
2190 { "BLOCK_SOFTIRQ", 4 },
Tom Zanussib934cdd2009-10-06 01:00:48 -05002191 { "BLOCK_IOPOLL_SOFTIRQ", 5 },
2192 { "TASKLET_SOFTIRQ", 6 },
2193 { "SCHED_SOFTIRQ", 7 },
2194 { "HRTIMER_SOFTIRQ", 8 },
2195 { "RCU_SOFTIRQ", 9 },
Steven Rostedtea4010d2009-08-17 16:18:07 +02002196
2197 { "HRTIMER_NORESTART", 0 },
2198 { "HRTIMER_RESTART", 1 },
2199};
2200
Tom Zanussi16c632d2009-11-25 01:15:48 -06002201unsigned long long eval_flag(const char *flag)
Steven Rostedtea4010d2009-08-17 16:18:07 +02002202{
2203 int i;
2204
2205 /*
2206 * Some flags in the format files do not get converted.
2207 * If the flag is not numeric, see if it is something that
2208 * we already know about.
2209 */
2210 if (isdigit(flag[0]))
2211 return strtoull(flag, NULL, 0);
2212
2213 for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++)
2214 if (strcmp(flags[i].name, flag) == 0)
2215 return flags[i].value;
2216
2217 return 0;
2218}
2219
2220static void print_str_arg(void *data, int size,
2221 struct event *event, struct print_arg *arg)
2222{
2223 struct print_flag_sym *flag;
2224 unsigned long long val, fval;
2225 char *str;
2226 int print;
2227
2228 switch (arg->type) {
2229 case PRINT_NULL:
2230 /* ?? */
2231 return;
2232 case PRINT_ATOM:
2233 printf("%s", arg->atom.atom);
2234 return;
2235 case PRINT_FIELD:
2236 if (!arg->field.field) {
2237 arg->field.field = find_any_field(event, arg->field.name);
2238 if (!arg->field.field)
2239 die("field %s not found", arg->field.name);
2240 }
2241 str = malloc_or_die(arg->field.field->size + 1);
2242 memcpy(str, data + arg->field.field->offset,
2243 arg->field.field->size);
2244 str[arg->field.field->size] = 0;
Frederic Weisbeckerd498bc12009-08-28 04:46:07 +02002245 printf("%s", str);
Steven Rostedtea4010d2009-08-17 16:18:07 +02002246 free(str);
2247 break;
2248 case PRINT_FLAGS:
2249 val = eval_num_arg(data, size, event, arg->flags.field);
2250 print = 0;
2251 for (flag = arg->flags.flags; flag; flag = flag->next) {
2252 fval = eval_flag(flag->value);
2253 if (!val && !fval) {
2254 printf("%s", flag->str);
2255 break;
2256 }
2257 if (fval && (val & fval) == fval) {
2258 if (print && arg->flags.delim)
2259 printf("%s", arg->flags.delim);
2260 printf("%s", flag->str);
2261 print = 1;
2262 val &= ~fval;
2263 }
2264 }
2265 break;
2266 case PRINT_SYMBOL:
2267 val = eval_num_arg(data, size, event, arg->symbol.field);
2268 for (flag = arg->symbol.symbols; flag; flag = flag->next) {
2269 fval = eval_flag(flag->value);
2270 if (val == fval) {
2271 printf("%s", flag->str);
2272 break;
2273 }
2274 }
2275 break;
2276
2277 case PRINT_TYPE:
2278 break;
Frederic Weisbecker561f7322009-08-31 06:45:21 +02002279 case PRINT_STRING: {
2280 int str_offset;
2281
2282 if (arg->string.offset == -1) {
2283 struct format_field *f;
2284
2285 f = find_any_field(event, arg->string.string);
2286 arg->string.offset = f->offset;
2287 }
2288 str_offset = *(int *)(data + arg->string.offset);
2289 str_offset &= 0xffff;
2290 printf("%s", ((char *)data) + str_offset);
Steven Rostedtea4010d2009-08-17 16:18:07 +02002291 break;
Frederic Weisbecker561f7322009-08-31 06:45:21 +02002292 }
Steven Rostedtea4010d2009-08-17 16:18:07 +02002293 case PRINT_OP:
2294 /*
2295 * The only op for string should be ? :
2296 */
2297 if (arg->op.op[0] != '?')
2298 return;
2299 val = eval_num_arg(data, size, event, arg->op.left);
2300 if (val)
2301 print_str_arg(data, size, event, arg->op.right->op.left);
2302 else
2303 print_str_arg(data, size, event, arg->op.right->op.right);
2304 break;
2305 default:
2306 /* well... */
2307 break;
2308 }
2309}
2310
2311static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event *event)
2312{
2313 static struct format_field *field, *ip_field;
2314 struct print_arg *args, *arg, **next;
2315 unsigned long long ip, val;
2316 char *ptr;
2317 void *bptr;
2318
2319 if (!field) {
2320 field = find_field(event, "buf");
2321 if (!field)
2322 die("can't find buffer field for binary printk");
2323 ip_field = find_field(event, "ip");
2324 if (!ip_field)
2325 die("can't find ip field for binary printk");
2326 }
2327
2328 ip = read_size(data + ip_field->offset, ip_field->size);
2329
2330 /*
2331 * The first arg is the IP pointer.
2332 */
2333 args = malloc_or_die(sizeof(*args));
2334 arg = args;
2335 arg->next = NULL;
2336 next = &arg->next;
2337
2338 arg->type = PRINT_ATOM;
2339 arg->atom.atom = malloc_or_die(32);
2340 sprintf(arg->atom.atom, "%lld", ip);
2341
2342 /* skip the first "%pf : " */
2343 for (ptr = fmt + 6, bptr = data + field->offset;
2344 bptr < data + size && *ptr; ptr++) {
2345 int ls = 0;
2346
2347 if (*ptr == '%') {
2348 process_again:
2349 ptr++;
2350 switch (*ptr) {
2351 case '%':
2352 break;
2353 case 'l':
2354 ls++;
2355 goto process_again;
2356 case 'L':
2357 ls = 2;
2358 goto process_again;
2359 case '0' ... '9':
2360 goto process_again;
2361 case 'p':
2362 ls = 1;
2363 /* fall through */
2364 case 'd':
2365 case 'u':
2366 case 'x':
2367 case 'i':
Steven Rostedtffa18952009-10-14 15:43:40 -04002368 /* the pointers are always 4 bytes aligned */
2369 bptr = (void *)(((unsigned long)bptr + 3) &
2370 ~3);
Steven Rostedtea4010d2009-08-17 16:18:07 +02002371 switch (ls) {
2372 case 0:
2373 case 1:
2374 ls = long_size;
2375 break;
2376 case 2:
2377 ls = 8;
2378 default:
2379 break;
2380 }
2381 val = read_size(bptr, ls);
2382 bptr += ls;
2383 arg = malloc_or_die(sizeof(*arg));
2384 arg->next = NULL;
2385 arg->type = PRINT_ATOM;
2386 arg->atom.atom = malloc_or_die(32);
2387 sprintf(arg->atom.atom, "%lld", val);
2388 *next = arg;
2389 next = &arg->next;
2390 break;
2391 case 's':
2392 arg = malloc_or_die(sizeof(*arg));
2393 arg->next = NULL;
2394 arg->type = PRINT_STRING;
2395 arg->string.string = strdup(bptr);
2396 bptr += strlen(bptr) + 1;
2397 *next = arg;
2398 next = &arg->next;
2399 default:
2400 break;
2401 }
2402 }
2403 }
2404
2405 return args;
2406}
2407
2408static void free_args(struct print_arg *args)
2409{
2410 struct print_arg *next;
2411
2412 while (args) {
2413 next = args->next;
2414
2415 if (args->type == PRINT_ATOM)
2416 free(args->atom.atom);
2417 else
2418 free(args->string.string);
2419 free(args);
2420 args = next;
2421 }
2422}
2423
2424static char *get_bprint_format(void *data, int size __unused, struct event *event)
2425{
2426 unsigned long long addr;
2427 static struct format_field *field;
2428 struct printk_map *printk;
2429 char *format;
2430 char *p;
2431
2432 if (!field) {
2433 field = find_field(event, "fmt");
2434 if (!field)
2435 die("can't find format field for binary printk");
2436 printf("field->offset = %d size=%d\n", field->offset, field->size);
2437 }
2438
2439 addr = read_size(data + field->offset, field->size);
2440
2441 printk = find_printk(addr);
2442 if (!printk) {
2443 format = malloc_or_die(45);
2444 sprintf(format, "%%pf : (NO FORMAT FOUND at %llx)\n",
2445 addr);
2446 return format;
2447 }
2448
2449 p = printk->printk;
2450 /* Remove any quotes. */
2451 if (*p == '"')
2452 p++;
2453 format = malloc_or_die(strlen(p) + 10);
2454 sprintf(format, "%s : %s", "%pf", p);
2455 /* remove ending quotes and new line since we will add one too */
2456 p = format + strlen(format) - 1;
2457 if (*p == '"')
2458 *p = 0;
2459
2460 p -= 2;
2461 if (strcmp(p, "\\n") == 0)
2462 *p = 0;
2463
2464 return format;
2465}
2466
2467static void pretty_print(void *data, int size, struct event *event)
2468{
2469 struct print_fmt *print_fmt = &event->print_fmt;
2470 struct print_arg *arg = print_fmt->args;
2471 struct print_arg *args = NULL;
2472 const char *ptr = print_fmt->format;
2473 unsigned long long val;
2474 struct func_map *func;
2475 const char *saveptr;
2476 char *bprint_fmt = NULL;
2477 char format[32];
2478 int show_func;
2479 int len;
2480 int ls;
2481
2482 if (event->flags & EVENT_FL_ISFUNC)
2483 ptr = " %pF <-- %pF";
2484
2485 if (event->flags & EVENT_FL_ISBPRINT) {
2486 bprint_fmt = get_bprint_format(data, size, event);
2487 args = make_bprint_args(bprint_fmt, data, size, event);
2488 arg = args;
2489 ptr = bprint_fmt;
2490 }
2491
2492 for (; *ptr; ptr++) {
2493 ls = 0;
Steven Rostedt91ff2bc2009-10-14 15:43:33 -04002494 if (*ptr == '\\') {
2495 ptr++;
2496 switch (*ptr) {
2497 case 'n':
2498 printf("\n");
2499 break;
2500 case 't':
2501 printf("\t");
2502 break;
2503 case 'r':
2504 printf("\r");
2505 break;
2506 case '\\':
2507 printf("\\");
2508 break;
2509 default:
2510 printf("%c", *ptr);
2511 break;
2512 }
2513
2514 } else if (*ptr == '%') {
Steven Rostedtea4010d2009-08-17 16:18:07 +02002515 saveptr = ptr;
2516 show_func = 0;
2517 cont_process:
2518 ptr++;
2519 switch (*ptr) {
2520 case '%':
2521 printf("%%");
2522 break;
2523 case 'l':
2524 ls++;
2525 goto cont_process;
2526 case 'L':
2527 ls = 2;
2528 goto cont_process;
2529 case 'z':
2530 case 'Z':
2531 case '0' ... '9':
2532 goto cont_process;
2533 case 'p':
2534 if (long_size == 4)
2535 ls = 1;
2536 else
2537 ls = 2;
2538
2539 if (*(ptr+1) == 'F' ||
2540 *(ptr+1) == 'f') {
2541 ptr++;
2542 show_func = *ptr;
2543 }
2544
2545 /* fall through */
2546 case 'd':
2547 case 'i':
2548 case 'x':
2549 case 'X':
2550 case 'u':
2551 if (!arg)
2552 die("no argument match");
2553
2554 len = ((unsigned long)ptr + 1) -
2555 (unsigned long)saveptr;
2556
2557 /* should never happen */
2558 if (len > 32)
2559 die("bad format!");
2560
2561 memcpy(format, saveptr, len);
2562 format[len] = 0;
2563
2564 val = eval_num_arg(data, size, event, arg);
2565 arg = arg->next;
2566
2567 if (show_func) {
2568 func = find_func(val);
2569 if (func) {
2570 printf("%s", func->func);
2571 if (show_func == 'F')
2572 printf("+0x%llx",
2573 val - func->addr);
2574 break;
2575 }
2576 }
2577 switch (ls) {
2578 case 0:
2579 printf(format, (int)val);
2580 break;
2581 case 1:
2582 printf(format, (long)val);
2583 break;
2584 case 2:
2585 printf(format, (long long)val);
2586 break;
2587 default:
2588 die("bad count (%d)", ls);
2589 }
2590 break;
2591 case 's':
2592 if (!arg)
2593 die("no matching argument");
2594
2595 print_str_arg(data, size, event, arg);
2596 arg = arg->next;
2597 break;
2598 default:
2599 printf(">%c<", *ptr);
2600
2601 }
2602 } else
2603 printf("%c", *ptr);
2604 }
2605
2606 if (args) {
2607 free_args(args);
2608 free(bprint_fmt);
2609 }
2610}
2611
2612static inline int log10_cpu(int nb)
2613{
2614 if (nb / 100)
2615 return 3;
2616 if (nb / 10)
2617 return 2;
2618 return 1;
2619}
2620
Steven Rostedtcda48462009-10-14 15:43:42 -04002621static void print_lat_fmt(void *data, int size __unused)
2622{
2623 unsigned int lat_flags;
2624 unsigned int pc;
2625 int lock_depth;
2626 int hardirq;
2627 int softirq;
2628
2629 lat_flags = parse_common_flags(data);
2630 pc = parse_common_pc(data);
2631 lock_depth = parse_common_lock_depth(data);
2632
2633 hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
2634 softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
2635
2636 printf("%c%c%c",
2637 (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
2638 (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
2639 'X' : '.',
2640 (lat_flags & TRACE_FLAG_NEED_RESCHED) ?
2641 'N' : '.',
2642 (hardirq && softirq) ? 'H' :
2643 hardirq ? 'h' : softirq ? 's' : '.');
2644
2645 if (pc)
2646 printf("%x", pc);
2647 else
2648 printf(".");
2649
2650 if (lock_depth < 0)
2651 printf(".");
2652 else
2653 printf("%d", lock_depth);
2654}
2655
Steven Rostedtea4010d2009-08-17 16:18:07 +02002656/* taken from Linux, written by Frederic Weisbecker */
2657static void print_graph_cpu(int cpu)
2658{
2659 int i;
2660 int log10_this = log10_cpu(cpu);
2661 int log10_all = log10_cpu(cpus);
2662
2663
2664 /*
2665 * Start with a space character - to make it stand out
2666 * to the right a bit when trace output is pasted into
2667 * email:
2668 */
2669 printf(" ");
2670
2671 /*
2672 * Tricky - we space the CPU field according to the max
2673 * number of online CPUs. On a 2-cpu system it would take
2674 * a maximum of 1 digit - on a 128 cpu system it would
2675 * take up to 3 digits:
2676 */
2677 for (i = 0; i < log10_all - log10_this; i++)
2678 printf(" ");
2679
2680 printf("%d) ", cpu);
2681}
2682
2683#define TRACE_GRAPH_PROCINFO_LENGTH 14
2684#define TRACE_GRAPH_INDENT 2
2685
2686static void print_graph_proc(int pid, const char *comm)
2687{
2688 /* sign + log10(MAX_INT) + '\0' */
2689 char pid_str[11];
2690 int spaces = 0;
2691 int len;
2692 int i;
2693
2694 sprintf(pid_str, "%d", pid);
2695
2696 /* 1 stands for the "-" character */
2697 len = strlen(comm) + strlen(pid_str) + 1;
2698
2699 if (len < TRACE_GRAPH_PROCINFO_LENGTH)
2700 spaces = TRACE_GRAPH_PROCINFO_LENGTH - len;
2701
2702 /* First spaces to align center */
2703 for (i = 0; i < spaces / 2; i++)
2704 printf(" ");
2705
2706 printf("%s-%s", comm, pid_str);
2707
2708 /* Last spaces to align center */
2709 for (i = 0; i < spaces - (spaces / 2); i++)
2710 printf(" ");
2711}
2712
2713static struct record *
2714get_return_for_leaf(int cpu, int cur_pid, unsigned long long cur_func,
2715 struct record *next)
2716{
2717 struct format_field *field;
2718 struct event *event;
2719 unsigned long val;
2720 int type;
2721 int pid;
2722
Ingo Molnarec156762009-09-11 12:12:54 +02002723 type = trace_parse_common_type(next->data);
2724 event = trace_find_event(type);
Steven Rostedtea4010d2009-08-17 16:18:07 +02002725 if (!event)
2726 return NULL;
2727
2728 if (!(event->flags & EVENT_FL_ISFUNCRET))
2729 return NULL;
2730
Tom Zanussi16c632d2009-11-25 01:15:48 -06002731 pid = trace_parse_common_pid(next->data);
Steven Rostedtea4010d2009-08-17 16:18:07 +02002732 field = find_field(event, "func");
2733 if (!field)
2734 die("function return does not have field func");
2735
2736 val = read_size(next->data + field->offset, field->size);
2737
2738 if (cur_pid != pid || cur_func != val)
2739 return NULL;
2740
2741 /* this is a leaf, now advance the iterator */
2742 return trace_read_data(cpu);
2743}
2744
2745/* Signal a overhead of time execution to the output */
2746static void print_graph_overhead(unsigned long long duration)
2747{
2748 /* Non nested entry or return */
2749 if (duration == ~0ULL)
2750 return (void)printf(" ");
2751
2752 /* Duration exceeded 100 msecs */
2753 if (duration > 100000ULL)
2754 return (void)printf("! ");
2755
2756 /* Duration exceeded 10 msecs */
2757 if (duration > 10000ULL)
2758 return (void)printf("+ ");
2759
2760 printf(" ");
2761}
2762
2763static void print_graph_duration(unsigned long long duration)
2764{
2765 unsigned long usecs = duration / 1000;
2766 unsigned long nsecs_rem = duration % 1000;
2767 /* log10(ULONG_MAX) + '\0' */
2768 char msecs_str[21];
2769 char nsecs_str[5];
2770 int len;
2771 int i;
2772
2773 sprintf(msecs_str, "%lu", usecs);
2774
2775 /* Print msecs */
2776 len = printf("%lu", usecs);
2777
2778 /* Print nsecs (we don't want to exceed 7 numbers) */
2779 if (len < 7) {
2780 snprintf(nsecs_str, 8 - len, "%03lu", nsecs_rem);
2781 len += printf(".%s", nsecs_str);
2782 }
2783
2784 printf(" us ");
2785
2786 /* Print remaining spaces to fit the row's width */
2787 for (i = len; i < 7; i++)
2788 printf(" ");
2789
2790 printf("| ");
2791}
2792
2793static void
2794print_graph_entry_leaf(struct event *event, void *data, struct record *ret_rec)
2795{
2796 unsigned long long rettime, calltime;
2797 unsigned long long duration, depth;
2798 unsigned long long val;
2799 struct format_field *field;
2800 struct func_map *func;
2801 struct event *ret_event;
2802 int type;
2803 int i;
2804
Ingo Molnarec156762009-09-11 12:12:54 +02002805 type = trace_parse_common_type(ret_rec->data);
2806 ret_event = trace_find_event(type);
Steven Rostedtea4010d2009-08-17 16:18:07 +02002807
2808 field = find_field(ret_event, "rettime");
2809 if (!field)
2810 die("can't find rettime in return graph");
2811 rettime = read_size(ret_rec->data + field->offset, field->size);
2812
2813 field = find_field(ret_event, "calltime");
2814 if (!field)
2815 die("can't find rettime in return graph");
2816 calltime = read_size(ret_rec->data + field->offset, field->size);
2817
2818 duration = rettime - calltime;
2819
2820 /* Overhead */
2821 print_graph_overhead(duration);
2822
2823 /* Duration */
2824 print_graph_duration(duration);
2825
2826 field = find_field(event, "depth");
2827 if (!field)
2828 die("can't find depth in entry graph");
2829 depth = read_size(data + field->offset, field->size);
2830
2831 /* Function */
2832 for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++)
2833 printf(" ");
2834
2835 field = find_field(event, "func");
2836 if (!field)
2837 die("can't find func in entry graph");
2838 val = read_size(data + field->offset, field->size);
2839 func = find_func(val);
2840
2841 if (func)
2842 printf("%s();", func->func);
2843 else
2844 printf("%llx();", val);
2845}
2846
2847static void print_graph_nested(struct event *event, void *data)
2848{
2849 struct format_field *field;
2850 unsigned long long depth;
2851 unsigned long long val;
2852 struct func_map *func;
2853 int i;
2854
2855 /* No overhead */
2856 print_graph_overhead(-1);
2857
2858 /* No time */
2859 printf(" | ");
2860
2861 field = find_field(event, "depth");
2862 if (!field)
2863 die("can't find depth in entry graph");
2864 depth = read_size(data + field->offset, field->size);
2865
2866 /* Function */
2867 for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++)
2868 printf(" ");
2869
2870 field = find_field(event, "func");
2871 if (!field)
2872 die("can't find func in entry graph");
2873 val = read_size(data + field->offset, field->size);
2874 func = find_func(val);
2875
2876 if (func)
2877 printf("%s() {", func->func);
2878 else
2879 printf("%llx() {", val);
2880}
2881
2882static void
2883pretty_print_func_ent(void *data, int size, struct event *event,
2884 int cpu, int pid, const char *comm,
2885 unsigned long secs, unsigned long usecs)
2886{
2887 struct format_field *field;
2888 struct record *rec;
2889 void *copy_data;
2890 unsigned long val;
2891
2892 printf("%5lu.%06lu | ", secs, usecs);
2893
2894 print_graph_cpu(cpu);
2895 print_graph_proc(pid, comm);
2896
2897 printf(" | ");
2898
Steven Rostedtcda48462009-10-14 15:43:42 -04002899 if (latency_format) {
2900 print_lat_fmt(data, size);
2901 printf(" | ");
2902 }
2903
Steven Rostedtea4010d2009-08-17 16:18:07 +02002904 field = find_field(event, "func");
2905 if (!field)
2906 die("function entry does not have func field");
2907
2908 val = read_size(data + field->offset, field->size);
2909
2910 /*
2911 * peek_data may unmap the data pointer. Copy it first.
2912 */
2913 copy_data = malloc_or_die(size);
2914 memcpy(copy_data, data, size);
2915 data = copy_data;
2916
2917 rec = trace_peek_data(cpu);
2918 if (rec) {
2919 rec = get_return_for_leaf(cpu, pid, val, rec);
2920 if (rec) {
2921 print_graph_entry_leaf(event, data, rec);
2922 goto out_free;
2923 }
2924 }
2925 print_graph_nested(event, data);
2926out_free:
2927 free(data);
2928}
2929
2930static void
2931pretty_print_func_ret(void *data, int size __unused, struct event *event,
2932 int cpu, int pid, const char *comm,
2933 unsigned long secs, unsigned long usecs)
2934{
2935 unsigned long long rettime, calltime;
2936 unsigned long long duration, depth;
2937 struct format_field *field;
2938 int i;
2939
2940 printf("%5lu.%06lu | ", secs, usecs);
2941
2942 print_graph_cpu(cpu);
2943 print_graph_proc(pid, comm);
2944
2945 printf(" | ");
2946
Steven Rostedtcda48462009-10-14 15:43:42 -04002947 if (latency_format) {
2948 print_lat_fmt(data, size);
2949 printf(" | ");
2950 }
2951
Steven Rostedtea4010d2009-08-17 16:18:07 +02002952 field = find_field(event, "rettime");
2953 if (!field)
2954 die("can't find rettime in return graph");
2955 rettime = read_size(data + field->offset, field->size);
2956
2957 field = find_field(event, "calltime");
2958 if (!field)
2959 die("can't find calltime in return graph");
2960 calltime = read_size(data + field->offset, field->size);
2961
2962 duration = rettime - calltime;
2963
2964 /* Overhead */
2965 print_graph_overhead(duration);
2966
2967 /* Duration */
2968 print_graph_duration(duration);
2969
2970 field = find_field(event, "depth");
2971 if (!field)
2972 die("can't find depth in entry graph");
2973 depth = read_size(data + field->offset, field->size);
2974
2975 /* Function */
2976 for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++)
2977 printf(" ");
2978
2979 printf("}");
2980}
2981
2982static void
2983pretty_print_func_graph(void *data, int size, struct event *event,
2984 int cpu, int pid, const char *comm,
2985 unsigned long secs, unsigned long usecs)
2986{
2987 if (event->flags & EVENT_FL_ISFUNCENT)
2988 pretty_print_func_ent(data, size, event,
2989 cpu, pid, comm, secs, usecs);
2990 else if (event->flags & EVENT_FL_ISFUNCRET)
2991 pretty_print_func_ret(data, size, event,
2992 cpu, pid, comm, secs, usecs);
2993 printf("\n");
2994}
2995
2996void print_event(int cpu, void *data, int size, unsigned long long nsecs,
2997 char *comm)
2998{
2999 struct event *event;
3000 unsigned long secs;
3001 unsigned long usecs;
3002 int type;
3003 int pid;
3004
3005 secs = nsecs / NSECS_PER_SEC;
3006 nsecs -= secs * NSECS_PER_SEC;
3007 usecs = nsecs / NSECS_PER_USEC;
3008
Ingo Molnarec156762009-09-11 12:12:54 +02003009 type = trace_parse_common_type(data);
Steven Rostedtea4010d2009-08-17 16:18:07 +02003010
Ingo Molnarec156762009-09-11 12:12:54 +02003011 event = trace_find_event(type);
Ingo Molnarea57c4f2009-09-13 18:15:54 +02003012 if (!event) {
Steven Rostedt07a4bdd2009-10-14 15:43:39 -04003013 warning("ug! no event found for type %d", type);
Ingo Molnarea57c4f2009-09-13 18:15:54 +02003014 return;
3015 }
Steven Rostedtea4010d2009-08-17 16:18:07 +02003016
Tom Zanussi16c632d2009-11-25 01:15:48 -06003017 pid = trace_parse_common_pid(data);
Steven Rostedtea4010d2009-08-17 16:18:07 +02003018
3019 if (event->flags & (EVENT_FL_ISFUNCENT | EVENT_FL_ISFUNCRET))
3020 return pretty_print_func_graph(data, size, event, cpu,
3021 pid, comm, secs, usecs);
3022
Steven Rostedtcda48462009-10-14 15:43:42 -04003023 if (latency_format) {
3024 printf("%8.8s-%-5d %3d",
3025 comm, pid, cpu);
3026 print_lat_fmt(data, size);
3027 } else
3028 printf("%16s-%-5d [%03d]", comm, pid, cpu);
3029
3030 printf(" %5lu.%06lu: %s: ", secs, usecs, event->name);
Steven Rostedtea4010d2009-08-17 16:18:07 +02003031
Steven Rostedt07a4bdd2009-10-14 15:43:39 -04003032 if (event->flags & EVENT_FL_FAILED) {
3033 printf("EVENT '%s' FAILED TO PARSE\n",
3034 event->name);
3035 return;
3036 }
3037
Steven Rostedtea4010d2009-08-17 16:18:07 +02003038 pretty_print(data, size, event);
3039 printf("\n");
3040}
3041
3042static void print_fields(struct print_flag_sym *field)
3043{
3044 printf("{ %s, %s }", field->value, field->str);
3045 if (field->next) {
3046 printf(", ");
3047 print_fields(field->next);
3048 }
3049}
3050
3051static void print_args(struct print_arg *args)
3052{
3053 int print_paren = 1;
3054
3055 switch (args->type) {
3056 case PRINT_NULL:
3057 printf("null");
3058 break;
3059 case PRINT_ATOM:
3060 printf("%s", args->atom.atom);
3061 break;
3062 case PRINT_FIELD:
3063 printf("REC->%s", args->field.name);
3064 break;
3065 case PRINT_FLAGS:
3066 printf("__print_flags(");
3067 print_args(args->flags.field);
3068 printf(", %s, ", args->flags.delim);
3069 print_fields(args->flags.flags);
3070 printf(")");
3071 break;
3072 case PRINT_SYMBOL:
3073 printf("__print_symbolic(");
3074 print_args(args->symbol.field);
3075 printf(", ");
3076 print_fields(args->symbol.symbols);
3077 printf(")");
3078 break;
3079 case PRINT_STRING:
3080 printf("__get_str(%s)", args->string.string);
3081 break;
3082 case PRINT_TYPE:
3083 printf("(%s)", args->typecast.type);
3084 print_args(args->typecast.item);
3085 break;
3086 case PRINT_OP:
3087 if (strcmp(args->op.op, ":") == 0)
3088 print_paren = 0;
3089 if (print_paren)
3090 printf("(");
3091 print_args(args->op.left);
3092 printf(" %s ", args->op.op);
3093 print_args(args->op.right);
3094 if (print_paren)
3095 printf(")");
3096 break;
3097 default:
3098 /* we should warn... */
3099 return;
3100 }
3101 if (args->next) {
3102 printf("\n");
3103 print_args(args->next);
3104 }
3105}
3106
Steven Rostedtc4dc7752009-10-14 15:43:44 -04003107static void parse_header_field(const char *field,
Arnaldo Carvalho de Meloe9e94e32010-04-05 18:01:10 -03003108 int *offset, int *size, bool warn)
Steven Rostedtea4010d2009-08-17 16:18:07 +02003109{
3110 char *token;
Steven Rostedt13999e52009-10-14 15:43:38 -04003111 int type;
Steven Rostedtea4010d2009-08-17 16:18:07 +02003112
Steven Rostedtc4dc7752009-10-14 15:43:44 -04003113 if (read_expected(EVENT_ITEM, "field") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02003114 return;
Steven Rostedtc4dc7752009-10-14 15:43:44 -04003115 if (read_expected(EVENT_OP, ":") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02003116 return;
Steven Rostedt13999e52009-10-14 15:43:38 -04003117
Steven Rostedtea4010d2009-08-17 16:18:07 +02003118 /* type */
3119 if (read_expect_type(EVENT_ITEM, &token) < 0)
Steven Rostedt13999e52009-10-14 15:43:38 -04003120 goto fail;
Steven Rostedtea4010d2009-08-17 16:18:07 +02003121 free_token(token);
3122
Arnaldo Carvalho de Meloe9e94e32010-04-05 18:01:10 -03003123 if (read_expected_warn(EVENT_ITEM, field, warn) < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02003124 return;
Steven Rostedtc4dc7752009-10-14 15:43:44 -04003125 if (read_expected(EVENT_OP, ";") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02003126 return;
Steven Rostedtc4dc7752009-10-14 15:43:44 -04003127 if (read_expected(EVENT_ITEM, "offset") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02003128 return;
Steven Rostedtc4dc7752009-10-14 15:43:44 -04003129 if (read_expected(EVENT_OP, ":") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02003130 return;
3131 if (read_expect_type(EVENT_ITEM, &token) < 0)
Steven Rostedt13999e52009-10-14 15:43:38 -04003132 goto fail;
Steven Rostedtea4010d2009-08-17 16:18:07 +02003133 *offset = atoi(token);
3134 free_token(token);
Steven Rostedtc4dc7752009-10-14 15:43:44 -04003135 if (read_expected(EVENT_OP, ";") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02003136 return;
Steven Rostedtc4dc7752009-10-14 15:43:44 -04003137 if (read_expected(EVENT_ITEM, "size") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02003138 return;
Steven Rostedtc4dc7752009-10-14 15:43:44 -04003139 if (read_expected(EVENT_OP, ":") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02003140 return;
3141 if (read_expect_type(EVENT_ITEM, &token) < 0)
Steven Rostedt13999e52009-10-14 15:43:38 -04003142 goto fail;
Steven Rostedtea4010d2009-08-17 16:18:07 +02003143 *size = atoi(token);
3144 free_token(token);
Steven Rostedtc4dc7752009-10-14 15:43:44 -04003145 if (read_expected(EVENT_OP, ";") < 0)
Steven Rostedtea4010d2009-08-17 16:18:07 +02003146 return;
Steven Rostedt13999e52009-10-14 15:43:38 -04003147 type = read_token(&token);
3148 if (type != EVENT_NEWLINE) {
3149 /* newer versions of the kernel have a "signed" type */
3150 if (type != EVENT_ITEM)
3151 goto fail;
3152
Steven Rostedtc4dc7752009-10-14 15:43:44 -04003153 if (strcmp(token, "signed") != 0)
Steven Rostedt13999e52009-10-14 15:43:38 -04003154 goto fail;
3155
3156 free_token(token);
3157
Steven Rostedtc4dc7752009-10-14 15:43:44 -04003158 if (read_expected(EVENT_OP, ":") < 0)
Steven Rostedt13999e52009-10-14 15:43:38 -04003159 return;
3160
3161 if (read_expect_type(EVENT_ITEM, &token))
3162 goto fail;
3163
3164 free_token(token);
Steven Rostedtc4dc7752009-10-14 15:43:44 -04003165 if (read_expected(EVENT_OP, ";") < 0)
Steven Rostedt13999e52009-10-14 15:43:38 -04003166 return;
3167
3168 if (read_expect_type(EVENT_NEWLINE, &token))
3169 goto fail;
3170 }
3171 fail:
Steven Rostedtea4010d2009-08-17 16:18:07 +02003172 free_token(token);
3173}
3174
3175int parse_header_page(char *buf, unsigned long size)
3176{
3177 init_input_buf(buf, size);
3178
Steven Rostedtc4dc7752009-10-14 15:43:44 -04003179 parse_header_field("timestamp", &header_page_ts_offset,
Arnaldo Carvalho de Meloe9e94e32010-04-05 18:01:10 -03003180 &header_page_ts_size, true);
Steven Rostedtc4dc7752009-10-14 15:43:44 -04003181 parse_header_field("commit", &header_page_size_offset,
Arnaldo Carvalho de Meloe9e94e32010-04-05 18:01:10 -03003182 &header_page_size_size, true);
3183 parse_header_field("overwrite", &header_page_overwrite_offset,
3184 &header_page_overwrite_size, false);
Steven Rostedtc4dc7752009-10-14 15:43:44 -04003185 parse_header_field("data", &header_page_data_offset,
Arnaldo Carvalho de Meloe9e94e32010-04-05 18:01:10 -03003186 &header_page_data_size, true);
Steven Rostedtea4010d2009-08-17 16:18:07 +02003187
3188 return 0;
3189}
3190
3191int parse_ftrace_file(char *buf, unsigned long size)
3192{
3193 struct format_field *field;
3194 struct print_arg *arg, **list;
3195 struct event *event;
3196 int ret;
3197
3198 init_input_buf(buf, size);
3199
3200 event = alloc_event();
3201 if (!event)
3202 return -ENOMEM;
3203
3204 event->flags |= EVENT_FL_ISFTRACE;
3205
3206 event->name = event_read_name();
3207 if (!event->name)
3208 die("failed to read ftrace event name");
3209
3210 if (strcmp(event->name, "function") == 0)
3211 event->flags |= EVENT_FL_ISFUNC;
3212
3213 else if (strcmp(event->name, "funcgraph_entry") == 0)
3214 event->flags |= EVENT_FL_ISFUNCENT;
3215
3216 else if (strcmp(event->name, "funcgraph_exit") == 0)
3217 event->flags |= EVENT_FL_ISFUNCRET;
3218
3219 else if (strcmp(event->name, "bprint") == 0)
3220 event->flags |= EVENT_FL_ISBPRINT;
3221
3222 event->id = event_read_id();
3223 if (event->id < 0)
3224 die("failed to read ftrace event id");
3225
3226 add_event(event);
3227
3228 ret = event_read_format(event);
3229 if (ret < 0)
3230 die("failed to read ftrace event format");
3231
3232 ret = event_read_print(event);
3233 if (ret < 0)
3234 die("failed to read ftrace event print fmt");
3235
Steven Rostedt0d1da912009-10-14 15:43:41 -04003236 /* New ftrace handles args */
3237 if (ret > 0)
3238 return 0;
Steven Rostedtea4010d2009-08-17 16:18:07 +02003239 /*
3240 * The arguments for ftrace files are parsed by the fields.
3241 * Set up the fields as their arguments.
3242 */
3243 list = &event->print_fmt.args;
3244 for (field = event->format.fields; field; field = field->next) {
3245 arg = malloc_or_die(sizeof(*arg));
3246 memset(arg, 0, sizeof(*arg));
3247 *list = arg;
3248 list = &arg->next;
3249 arg->type = PRINT_FIELD;
3250 arg->field.name = field->name;
3251 arg->field.field = field;
3252 }
3253 return 0;
3254}
3255
Tom Zanussi27746012009-10-06 01:09:51 -05003256int parse_event_file(char *buf, unsigned long size, char *sys)
Steven Rostedtea4010d2009-08-17 16:18:07 +02003257{
3258 struct event *event;
3259 int ret;
3260
3261 init_input_buf(buf, size);
3262
3263 event = alloc_event();
3264 if (!event)
3265 return -ENOMEM;
3266
3267 event->name = event_read_name();
3268 if (!event->name)
3269 die("failed to read event name");
3270
3271 event->id = event_read_id();
3272 if (event->id < 0)
3273 die("failed to read event id");
3274
3275 ret = event_read_format(event);
Steven Rostedt07a4bdd2009-10-14 15:43:39 -04003276 if (ret < 0) {
3277 warning("failed to read event format for %s", event->name);
3278 goto event_failed;
3279 }
Steven Rostedtea4010d2009-08-17 16:18:07 +02003280
3281 ret = event_read_print(event);
Steven Rostedt07a4bdd2009-10-14 15:43:39 -04003282 if (ret < 0) {
3283 warning("failed to read event print fmt for %s", event->name);
3284 goto event_failed;
3285 }
Steven Rostedtea4010d2009-08-17 16:18:07 +02003286
Tom Zanussi27746012009-10-06 01:09:51 -05003287 event->system = strdup(sys);
3288
Steven Rostedtea4010d2009-08-17 16:18:07 +02003289#define PRINT_ARGS 0
3290 if (PRINT_ARGS && event->print_fmt.args)
3291 print_args(event->print_fmt.args);
3292
3293 add_event(event);
3294 return 0;
Steven Rostedt07a4bdd2009-10-14 15:43:39 -04003295
3296 event_failed:
3297 event->flags |= EVENT_FL_FAILED;
3298 /* still add it even if it failed */
3299 add_event(event);
3300 return -1;
Steven Rostedtea4010d2009-08-17 16:18:07 +02003301}
3302
3303void parse_set_info(int nr_cpus, int long_sz)
3304{
3305 cpus = nr_cpus;
3306 long_size = long_sz;
3307}
Tom Zanussi7397d802010-01-27 02:27:54 -06003308
3309int common_pc(struct scripting_context *context)
3310{
3311 return parse_common_pc(context->event_data);
3312}
3313
3314int common_flags(struct scripting_context *context)
3315{
3316 return parse_common_flags(context->event_data);
3317}
3318
3319int common_lock_depth(struct scripting_context *context)
3320{
3321 return parse_common_lock_depth(context->event_data);
3322}