1ea4010d1SSteven Rostedt /* 2ea4010d1SSteven Rostedt * Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com> 3ea4010d1SSteven Rostedt * 4ea4010d1SSteven Rostedt * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5ea4010d1SSteven Rostedt * 6ea4010d1SSteven Rostedt * This program is free software; you can redistribute it and/or modify 7ea4010d1SSteven Rostedt * it under the terms of the GNU General Public License as published by 8ea4010d1SSteven Rostedt * the Free Software Foundation; version 2 of the License (not later!) 9ea4010d1SSteven Rostedt * 10ea4010d1SSteven Rostedt * This program is distributed in the hope that it will be useful, 11ea4010d1SSteven Rostedt * but WITHOUT ANY WARRANTY; without even the implied warranty of 12ea4010d1SSteven Rostedt * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13ea4010d1SSteven Rostedt * GNU General Public License for more details. 14ea4010d1SSteven Rostedt * 15ea4010d1SSteven Rostedt * You should have received a copy of the GNU General Public License 16ea4010d1SSteven Rostedt * along with this program; if not, write to the Free Software 17ea4010d1SSteven Rostedt * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18ea4010d1SSteven Rostedt * 19ea4010d1SSteven Rostedt * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 20ea4010d1SSteven Rostedt * 21ea4010d1SSteven Rostedt * The parts for function graph printing was taken and modified from the 22ea4010d1SSteven Rostedt * Linux Kernel that were written by Frederic Weisbecker. 23ea4010d1SSteven Rostedt */ 24ea4010d1SSteven Rostedt #define _GNU_SOURCE 25ea4010d1SSteven Rostedt #include <stdio.h> 26ea4010d1SSteven Rostedt #include <stdlib.h> 27ea4010d1SSteven Rostedt #include <string.h> 28ea4010d1SSteven Rostedt #include <ctype.h> 29ea4010d1SSteven Rostedt #include <errno.h> 30ea4010d1SSteven Rostedt 31ea4010d1SSteven Rostedt #undef _GNU_SOURCE 321ef2ed10SFrederic Weisbecker #include "../perf.h" 33ea4010d1SSteven Rostedt #include "util.h" 34ea4010d1SSteven Rostedt #include "trace-event.h" 35ea4010d1SSteven Rostedt 36ea4010d1SSteven Rostedt int header_page_ts_offset; 37ea4010d1SSteven Rostedt int header_page_ts_size; 38ea4010d1SSteven Rostedt int header_page_size_offset; 39ea4010d1SSteven Rostedt int header_page_size_size; 40ea4010d1SSteven Rostedt int header_page_data_offset; 41ea4010d1SSteven Rostedt int header_page_data_size; 42ea4010d1SSteven Rostedt 43cda48461SSteven Rostedt int latency_format; 44cda48461SSteven Rostedt 45ea4010d1SSteven Rostedt static char *input_buf; 46ea4010d1SSteven Rostedt static unsigned long long input_buf_ptr; 47ea4010d1SSteven Rostedt static unsigned long long input_buf_siz; 48ea4010d1SSteven Rostedt 49ea4010d1SSteven Rostedt static int cpus; 50ea4010d1SSteven Rostedt static int long_size; 51eb9a42caSTom Zanussi static int is_flag_field; 52eb9a42caSTom Zanussi static int is_symbolic_field; 53eb9a42caSTom Zanussi 54eb9a42caSTom Zanussi static struct format_field * 55eb9a42caSTom Zanussi find_any_field(struct event *event, const char *name); 56ea4010d1SSteven Rostedt 57ea4010d1SSteven Rostedt static void init_input_buf(char *buf, unsigned long long size) 58ea4010d1SSteven Rostedt { 59ea4010d1SSteven Rostedt input_buf = buf; 60ea4010d1SSteven Rostedt input_buf_siz = size; 61ea4010d1SSteven Rostedt input_buf_ptr = 0; 62ea4010d1SSteven Rostedt } 63ea4010d1SSteven Rostedt 64ea4010d1SSteven Rostedt struct cmdline { 65ea4010d1SSteven Rostedt char *comm; 66ea4010d1SSteven Rostedt int pid; 67ea4010d1SSteven Rostedt }; 68ea4010d1SSteven Rostedt 69ea4010d1SSteven Rostedt static struct cmdline *cmdlines; 70ea4010d1SSteven Rostedt static int cmdline_count; 71ea4010d1SSteven Rostedt 72ea4010d1SSteven Rostedt static int cmdline_cmp(const void *a, const void *b) 73ea4010d1SSteven Rostedt { 74ea4010d1SSteven Rostedt const struct cmdline *ca = a; 75ea4010d1SSteven Rostedt const struct cmdline *cb = b; 76ea4010d1SSteven Rostedt 77ea4010d1SSteven Rostedt if (ca->pid < cb->pid) 78ea4010d1SSteven Rostedt return -1; 79ea4010d1SSteven Rostedt if (ca->pid > cb->pid) 80ea4010d1SSteven Rostedt return 1; 81ea4010d1SSteven Rostedt 82ea4010d1SSteven Rostedt return 0; 83ea4010d1SSteven Rostedt } 84ea4010d1SSteven Rostedt 85ea4010d1SSteven Rostedt void parse_cmdlines(char *file, int size __unused) 86ea4010d1SSteven Rostedt { 87ea4010d1SSteven Rostedt struct cmdline_list { 88ea4010d1SSteven Rostedt struct cmdline_list *next; 89ea4010d1SSteven Rostedt char *comm; 90ea4010d1SSteven Rostedt int pid; 91ea4010d1SSteven Rostedt } *list = NULL, *item; 92ea4010d1SSteven Rostedt char *line; 93ea4010d1SSteven Rostedt char *next = NULL; 94ea4010d1SSteven Rostedt int i; 95ea4010d1SSteven Rostedt 96ea4010d1SSteven Rostedt line = strtok_r(file, "\n", &next); 97ea4010d1SSteven Rostedt while (line) { 98ea4010d1SSteven Rostedt item = malloc_or_die(sizeof(*item)); 99ea4010d1SSteven Rostedt sscanf(line, "%d %as", &item->pid, 10065014ab3SIngo Molnar (float *)(void *)&item->comm); /* workaround gcc warning */ 101ea4010d1SSteven Rostedt item->next = list; 102ea4010d1SSteven Rostedt list = item; 103ea4010d1SSteven Rostedt line = strtok_r(NULL, "\n", &next); 104ea4010d1SSteven Rostedt cmdline_count++; 105ea4010d1SSteven Rostedt } 106ea4010d1SSteven Rostedt 107ea4010d1SSteven Rostedt cmdlines = malloc_or_die(sizeof(*cmdlines) * cmdline_count); 108ea4010d1SSteven Rostedt 109ea4010d1SSteven Rostedt i = 0; 110ea4010d1SSteven Rostedt while (list) { 111ea4010d1SSteven Rostedt cmdlines[i].pid = list->pid; 112ea4010d1SSteven Rostedt cmdlines[i].comm = list->comm; 113ea4010d1SSteven Rostedt i++; 114ea4010d1SSteven Rostedt item = list; 115ea4010d1SSteven Rostedt list = list->next; 116ea4010d1SSteven Rostedt free(item); 117ea4010d1SSteven Rostedt } 118ea4010d1SSteven Rostedt 119ea4010d1SSteven Rostedt qsort(cmdlines, cmdline_count, sizeof(*cmdlines), cmdline_cmp); 120ea4010d1SSteven Rostedt } 121ea4010d1SSteven Rostedt 122ea4010d1SSteven Rostedt static struct func_map { 123ea4010d1SSteven Rostedt unsigned long long addr; 124ea4010d1SSteven Rostedt char *func; 125ea4010d1SSteven Rostedt char *mod; 126ea4010d1SSteven Rostedt } *func_list; 127ea4010d1SSteven Rostedt static unsigned int func_count; 128ea4010d1SSteven Rostedt 129ea4010d1SSteven Rostedt static int func_cmp(const void *a, const void *b) 130ea4010d1SSteven Rostedt { 131ea4010d1SSteven Rostedt const struct func_map *fa = a; 132ea4010d1SSteven Rostedt const struct func_map *fb = b; 133ea4010d1SSteven Rostedt 134ea4010d1SSteven Rostedt if (fa->addr < fb->addr) 135ea4010d1SSteven Rostedt return -1; 136ea4010d1SSteven Rostedt if (fa->addr > fb->addr) 137ea4010d1SSteven Rostedt return 1; 138ea4010d1SSteven Rostedt 139ea4010d1SSteven Rostedt return 0; 140ea4010d1SSteven Rostedt } 141ea4010d1SSteven Rostedt 142ea4010d1SSteven Rostedt void parse_proc_kallsyms(char *file, unsigned int size __unused) 143ea4010d1SSteven Rostedt { 144ea4010d1SSteven Rostedt struct func_list { 145ea4010d1SSteven Rostedt struct func_list *next; 146ea4010d1SSteven Rostedt unsigned long long addr; 147ea4010d1SSteven Rostedt char *func; 148ea4010d1SSteven Rostedt char *mod; 149ea4010d1SSteven Rostedt } *list = NULL, *item; 150ea4010d1SSteven Rostedt char *line; 151ea4010d1SSteven Rostedt char *next = NULL; 152ea4010d1SSteven Rostedt char *addr_str; 153ea4010d1SSteven Rostedt char ch; 154ea4010d1SSteven Rostedt int ret; 155ea4010d1SSteven Rostedt int i; 156ea4010d1SSteven Rostedt 157ea4010d1SSteven Rostedt line = strtok_r(file, "\n", &next); 158ea4010d1SSteven Rostedt while (line) { 159ea4010d1SSteven Rostedt item = malloc_or_die(sizeof(*item)); 160ea4010d1SSteven Rostedt item->mod = NULL; 161ea4010d1SSteven Rostedt ret = sscanf(line, "%as %c %as\t[%as", 16265014ab3SIngo Molnar (float *)(void *)&addr_str, /* workaround gcc warning */ 163ea4010d1SSteven Rostedt &ch, 16465014ab3SIngo Molnar (float *)(void *)&item->func, 16565014ab3SIngo Molnar (float *)(void *)&item->mod); 166ea4010d1SSteven Rostedt item->addr = strtoull(addr_str, NULL, 16); 167ea4010d1SSteven Rostedt free(addr_str); 168ea4010d1SSteven Rostedt 169ea4010d1SSteven Rostedt /* truncate the extra ']' */ 170ea4010d1SSteven Rostedt if (item->mod) 171ea4010d1SSteven Rostedt item->mod[strlen(item->mod) - 1] = 0; 172ea4010d1SSteven Rostedt 173ea4010d1SSteven Rostedt 174ea4010d1SSteven Rostedt item->next = list; 175ea4010d1SSteven Rostedt list = item; 176ea4010d1SSteven Rostedt line = strtok_r(NULL, "\n", &next); 177ea4010d1SSteven Rostedt func_count++; 178ea4010d1SSteven Rostedt } 179ea4010d1SSteven Rostedt 1807691b1ecSOGAWA Hirofumi func_list = malloc_or_die(sizeof(*func_list) * (func_count + 1)); 181ea4010d1SSteven Rostedt 182ea4010d1SSteven Rostedt i = 0; 183ea4010d1SSteven Rostedt while (list) { 184ea4010d1SSteven Rostedt func_list[i].func = list->func; 185ea4010d1SSteven Rostedt func_list[i].addr = list->addr; 186ea4010d1SSteven Rostedt func_list[i].mod = list->mod; 187ea4010d1SSteven Rostedt i++; 188ea4010d1SSteven Rostedt item = list; 189ea4010d1SSteven Rostedt list = list->next; 190ea4010d1SSteven Rostedt free(item); 191ea4010d1SSteven Rostedt } 192ea4010d1SSteven Rostedt 193ea4010d1SSteven Rostedt qsort(func_list, func_count, sizeof(*func_list), func_cmp); 194ea4010d1SSteven Rostedt 195ea4010d1SSteven Rostedt /* 196ea4010d1SSteven Rostedt * Add a special record at the end. 197ea4010d1SSteven Rostedt */ 198ea4010d1SSteven Rostedt func_list[func_count].func = NULL; 199ea4010d1SSteven Rostedt func_list[func_count].addr = 0; 200ea4010d1SSteven Rostedt func_list[func_count].mod = NULL; 201ea4010d1SSteven Rostedt } 202ea4010d1SSteven Rostedt 203ea4010d1SSteven Rostedt /* 204ea4010d1SSteven Rostedt * We are searching for a record in between, not an exact 205ea4010d1SSteven Rostedt * match. 206ea4010d1SSteven Rostedt */ 207ea4010d1SSteven Rostedt static int func_bcmp(const void *a, const void *b) 208ea4010d1SSteven Rostedt { 209ea4010d1SSteven Rostedt const struct func_map *fa = a; 210ea4010d1SSteven Rostedt const struct func_map *fb = b; 211ea4010d1SSteven Rostedt 212ea4010d1SSteven Rostedt if ((fa->addr == fb->addr) || 213ea4010d1SSteven Rostedt 214ea4010d1SSteven Rostedt (fa->addr > fb->addr && 215ea4010d1SSteven Rostedt fa->addr < (fb+1)->addr)) 216ea4010d1SSteven Rostedt return 0; 217ea4010d1SSteven Rostedt 218ea4010d1SSteven Rostedt if (fa->addr < fb->addr) 219ea4010d1SSteven Rostedt return -1; 220ea4010d1SSteven Rostedt 221ea4010d1SSteven Rostedt return 1; 222ea4010d1SSteven Rostedt } 223ea4010d1SSteven Rostedt 224ea4010d1SSteven Rostedt static struct func_map *find_func(unsigned long long addr) 225ea4010d1SSteven Rostedt { 226ea4010d1SSteven Rostedt struct func_map *func; 227ea4010d1SSteven Rostedt struct func_map key; 228ea4010d1SSteven Rostedt 229ea4010d1SSteven Rostedt key.addr = addr; 230ea4010d1SSteven Rostedt 231ea4010d1SSteven Rostedt func = bsearch(&key, func_list, func_count, sizeof(*func_list), 232ea4010d1SSteven Rostedt func_bcmp); 233ea4010d1SSteven Rostedt 234ea4010d1SSteven Rostedt return func; 235ea4010d1SSteven Rostedt } 236ea4010d1SSteven Rostedt 237ea4010d1SSteven Rostedt void print_funcs(void) 238ea4010d1SSteven Rostedt { 239ea4010d1SSteven Rostedt int i; 240ea4010d1SSteven Rostedt 241ea4010d1SSteven Rostedt for (i = 0; i < (int)func_count; i++) { 242ea4010d1SSteven Rostedt printf("%016llx %s", 243ea4010d1SSteven Rostedt func_list[i].addr, 244ea4010d1SSteven Rostedt func_list[i].func); 245ea4010d1SSteven Rostedt if (func_list[i].mod) 246ea4010d1SSteven Rostedt printf(" [%s]\n", func_list[i].mod); 247ea4010d1SSteven Rostedt else 248ea4010d1SSteven Rostedt printf("\n"); 249ea4010d1SSteven Rostedt } 250ea4010d1SSteven Rostedt } 251ea4010d1SSteven Rostedt 252ea4010d1SSteven Rostedt static struct printk_map { 253ea4010d1SSteven Rostedt unsigned long long addr; 254ea4010d1SSteven Rostedt char *printk; 255ea4010d1SSteven Rostedt } *printk_list; 256ea4010d1SSteven Rostedt static unsigned int printk_count; 257ea4010d1SSteven Rostedt 258ea4010d1SSteven Rostedt static int printk_cmp(const void *a, const void *b) 259ea4010d1SSteven Rostedt { 260ea4010d1SSteven Rostedt const struct func_map *fa = a; 261ea4010d1SSteven Rostedt const struct func_map *fb = b; 262ea4010d1SSteven Rostedt 263ea4010d1SSteven Rostedt if (fa->addr < fb->addr) 264ea4010d1SSteven Rostedt return -1; 265ea4010d1SSteven Rostedt if (fa->addr > fb->addr) 266ea4010d1SSteven Rostedt return 1; 267ea4010d1SSteven Rostedt 268ea4010d1SSteven Rostedt return 0; 269ea4010d1SSteven Rostedt } 270ea4010d1SSteven Rostedt 271ea4010d1SSteven Rostedt static struct printk_map *find_printk(unsigned long long addr) 272ea4010d1SSteven Rostedt { 273ea4010d1SSteven Rostedt struct printk_map *printk; 274ea4010d1SSteven Rostedt struct printk_map key; 275ea4010d1SSteven Rostedt 276ea4010d1SSteven Rostedt key.addr = addr; 277ea4010d1SSteven Rostedt 278ea4010d1SSteven Rostedt printk = bsearch(&key, printk_list, printk_count, sizeof(*printk_list), 279ea4010d1SSteven Rostedt printk_cmp); 280ea4010d1SSteven Rostedt 281ea4010d1SSteven Rostedt return printk; 282ea4010d1SSteven Rostedt } 283ea4010d1SSteven Rostedt 284ea4010d1SSteven Rostedt void parse_ftrace_printk(char *file, unsigned int size __unused) 285ea4010d1SSteven Rostedt { 286ea4010d1SSteven Rostedt struct printk_list { 287ea4010d1SSteven Rostedt struct printk_list *next; 288ea4010d1SSteven Rostedt unsigned long long addr; 289ea4010d1SSteven Rostedt char *printk; 290ea4010d1SSteven Rostedt } *list = NULL, *item; 291ea4010d1SSteven Rostedt char *line; 292ea4010d1SSteven Rostedt char *next = NULL; 293ea4010d1SSteven Rostedt char *addr_str; 294ea4010d1SSteven Rostedt int i; 295ea4010d1SSteven Rostedt 296ea4010d1SSteven Rostedt line = strtok_r(file, "\n", &next); 297ea4010d1SSteven Rostedt while (line) { 2984e3b799dSSteven Rostedt addr_str = strsep(&line, ":"); 2994e3b799dSSteven Rostedt if (!line) { 3004e3b799dSSteven Rostedt warning("error parsing print strings"); 3014e3b799dSSteven Rostedt break; 3024e3b799dSSteven Rostedt } 303ea4010d1SSteven Rostedt item = malloc_or_die(sizeof(*item)); 304ea4010d1SSteven Rostedt item->addr = strtoull(addr_str, NULL, 16); 305ffa18955SSteven Rostedt /* fmt still has a space, skip it */ 3064e3b799dSSteven Rostedt item->printk = strdup(line+1); 307ea4010d1SSteven Rostedt item->next = list; 308ea4010d1SSteven Rostedt list = item; 309ea4010d1SSteven Rostedt line = strtok_r(NULL, "\n", &next); 310ea4010d1SSteven Rostedt printk_count++; 311ea4010d1SSteven Rostedt } 312ea4010d1SSteven Rostedt 313ea4010d1SSteven Rostedt printk_list = malloc_or_die(sizeof(*printk_list) * printk_count + 1); 314ea4010d1SSteven Rostedt 315ea4010d1SSteven Rostedt i = 0; 316ea4010d1SSteven Rostedt while (list) { 317ea4010d1SSteven Rostedt printk_list[i].printk = list->printk; 318ea4010d1SSteven Rostedt printk_list[i].addr = list->addr; 319ea4010d1SSteven Rostedt i++; 320ea4010d1SSteven Rostedt item = list; 321ea4010d1SSteven Rostedt list = list->next; 322ea4010d1SSteven Rostedt free(item); 323ea4010d1SSteven Rostedt } 324ea4010d1SSteven Rostedt 325ea4010d1SSteven Rostedt qsort(printk_list, printk_count, sizeof(*printk_list), printk_cmp); 326ea4010d1SSteven Rostedt } 327ea4010d1SSteven Rostedt 328ea4010d1SSteven Rostedt void print_printk(void) 329ea4010d1SSteven Rostedt { 330ea4010d1SSteven Rostedt int i; 331ea4010d1SSteven Rostedt 332ea4010d1SSteven Rostedt for (i = 0; i < (int)printk_count; i++) { 333ea4010d1SSteven Rostedt printf("%016llx %s\n", 334ea4010d1SSteven Rostedt printk_list[i].addr, 335ea4010d1SSteven Rostedt printk_list[i].printk); 336ea4010d1SSteven Rostedt } 337ea4010d1SSteven Rostedt } 338ea4010d1SSteven Rostedt 339ea4010d1SSteven Rostedt static struct event *alloc_event(void) 340ea4010d1SSteven Rostedt { 341ea4010d1SSteven Rostedt struct event *event; 342ea4010d1SSteven Rostedt 343ea4010d1SSteven Rostedt event = malloc_or_die(sizeof(*event)); 344ea4010d1SSteven Rostedt memset(event, 0, sizeof(*event)); 345ea4010d1SSteven Rostedt 346ea4010d1SSteven Rostedt return event; 347ea4010d1SSteven Rostedt } 348ea4010d1SSteven Rostedt 349ea4010d1SSteven Rostedt enum event_type { 350ea4010d1SSteven Rostedt EVENT_ERROR, 351ea4010d1SSteven Rostedt EVENT_NONE, 352ea4010d1SSteven Rostedt EVENT_SPACE, 353ea4010d1SSteven Rostedt EVENT_NEWLINE, 354ea4010d1SSteven Rostedt EVENT_OP, 355ea4010d1SSteven Rostedt EVENT_DELIM, 356ea4010d1SSteven Rostedt EVENT_ITEM, 357ea4010d1SSteven Rostedt EVENT_DQUOTE, 358ea4010d1SSteven Rostedt EVENT_SQUOTE, 359ea4010d1SSteven Rostedt }; 360ea4010d1SSteven Rostedt 361ea4010d1SSteven Rostedt static struct event *event_list; 362ea4010d1SSteven Rostedt 363ea4010d1SSteven Rostedt static void add_event(struct event *event) 364ea4010d1SSteven Rostedt { 365ea4010d1SSteven Rostedt event->next = event_list; 366ea4010d1SSteven Rostedt event_list = event; 367ea4010d1SSteven Rostedt } 368ea4010d1SSteven Rostedt 369ea4010d1SSteven Rostedt static int event_item_type(enum event_type type) 370ea4010d1SSteven Rostedt { 371ea4010d1SSteven Rostedt switch (type) { 372ea4010d1SSteven Rostedt case EVENT_ITEM ... EVENT_SQUOTE: 373ea4010d1SSteven Rostedt return 1; 374ea4010d1SSteven Rostedt case EVENT_ERROR ... EVENT_DELIM: 375ea4010d1SSteven Rostedt default: 376ea4010d1SSteven Rostedt return 0; 377ea4010d1SSteven Rostedt } 378ea4010d1SSteven Rostedt } 379ea4010d1SSteven Rostedt 380ea4010d1SSteven Rostedt static void free_arg(struct print_arg *arg) 381ea4010d1SSteven Rostedt { 382ea4010d1SSteven Rostedt if (!arg) 383ea4010d1SSteven Rostedt return; 384ea4010d1SSteven Rostedt 385ea4010d1SSteven Rostedt switch (arg->type) { 386ea4010d1SSteven Rostedt case PRINT_ATOM: 387ea4010d1SSteven Rostedt if (arg->atom.atom) 388ea4010d1SSteven Rostedt free(arg->atom.atom); 389ea4010d1SSteven Rostedt break; 390ea4010d1SSteven Rostedt case PRINT_NULL: 391ea4010d1SSteven Rostedt case PRINT_FIELD ... PRINT_OP: 392ea4010d1SSteven Rostedt default: 393ea4010d1SSteven Rostedt /* todo */ 394ea4010d1SSteven Rostedt break; 395ea4010d1SSteven Rostedt } 396ea4010d1SSteven Rostedt 397ea4010d1SSteven Rostedt free(arg); 398ea4010d1SSteven Rostedt } 399ea4010d1SSteven Rostedt 400ea4010d1SSteven Rostedt static enum event_type get_type(int ch) 401ea4010d1SSteven Rostedt { 402ea4010d1SSteven Rostedt if (ch == '\n') 403ea4010d1SSteven Rostedt return EVENT_NEWLINE; 404ea4010d1SSteven Rostedt if (isspace(ch)) 405ea4010d1SSteven Rostedt return EVENT_SPACE; 406ea4010d1SSteven Rostedt if (isalnum(ch) || ch == '_') 407ea4010d1SSteven Rostedt return EVENT_ITEM; 408ea4010d1SSteven Rostedt if (ch == '\'') 409ea4010d1SSteven Rostedt return EVENT_SQUOTE; 410ea4010d1SSteven Rostedt if (ch == '"') 411ea4010d1SSteven Rostedt return EVENT_DQUOTE; 412ea4010d1SSteven Rostedt if (!isprint(ch)) 413ea4010d1SSteven Rostedt return EVENT_NONE; 414ea4010d1SSteven Rostedt if (ch == '(' || ch == ')' || ch == ',') 415ea4010d1SSteven Rostedt return EVENT_DELIM; 416ea4010d1SSteven Rostedt 417ea4010d1SSteven Rostedt return EVENT_OP; 418ea4010d1SSteven Rostedt } 419ea4010d1SSteven Rostedt 420ea4010d1SSteven Rostedt static int __read_char(void) 421ea4010d1SSteven Rostedt { 422ea4010d1SSteven Rostedt if (input_buf_ptr >= input_buf_siz) 423ea4010d1SSteven Rostedt return -1; 424ea4010d1SSteven Rostedt 425ea4010d1SSteven Rostedt return input_buf[input_buf_ptr++]; 426ea4010d1SSteven Rostedt } 427ea4010d1SSteven Rostedt 428ea4010d1SSteven Rostedt static int __peek_char(void) 429ea4010d1SSteven Rostedt { 430ea4010d1SSteven Rostedt if (input_buf_ptr >= input_buf_siz) 431ea4010d1SSteven Rostedt return -1; 432ea4010d1SSteven Rostedt 433ea4010d1SSteven Rostedt return input_buf[input_buf_ptr]; 434ea4010d1SSteven Rostedt } 435ea4010d1SSteven Rostedt 436ea4010d1SSteven Rostedt static enum event_type __read_token(char **tok) 437ea4010d1SSteven Rostedt { 438ea4010d1SSteven Rostedt char buf[BUFSIZ]; 439ea4010d1SSteven Rostedt int ch, last_ch, quote_ch, next_ch; 440ea4010d1SSteven Rostedt int i = 0; 441ea4010d1SSteven Rostedt int tok_size = 0; 442ea4010d1SSteven Rostedt enum event_type type; 443ea4010d1SSteven Rostedt 444ea4010d1SSteven Rostedt *tok = NULL; 445ea4010d1SSteven Rostedt 446ea4010d1SSteven Rostedt 447ea4010d1SSteven Rostedt ch = __read_char(); 448ea4010d1SSteven Rostedt if (ch < 0) 449ea4010d1SSteven Rostedt return EVENT_NONE; 450ea4010d1SSteven Rostedt 451ea4010d1SSteven Rostedt type = get_type(ch); 452ea4010d1SSteven Rostedt if (type == EVENT_NONE) 453ea4010d1SSteven Rostedt return type; 454ea4010d1SSteven Rostedt 455ea4010d1SSteven Rostedt buf[i++] = ch; 456ea4010d1SSteven Rostedt 457ea4010d1SSteven Rostedt switch (type) { 458ea4010d1SSteven Rostedt case EVENT_NEWLINE: 459ea4010d1SSteven Rostedt case EVENT_DELIM: 460ea4010d1SSteven Rostedt *tok = malloc_or_die(2); 461ea4010d1SSteven Rostedt (*tok)[0] = ch; 462ea4010d1SSteven Rostedt (*tok)[1] = 0; 463ea4010d1SSteven Rostedt return type; 464ea4010d1SSteven Rostedt 465ea4010d1SSteven Rostedt case EVENT_OP: 466ea4010d1SSteven Rostedt switch (ch) { 467ea4010d1SSteven Rostedt case '-': 468ea4010d1SSteven Rostedt next_ch = __peek_char(); 469ea4010d1SSteven Rostedt if (next_ch == '>') { 470ea4010d1SSteven Rostedt buf[i++] = __read_char(); 471ea4010d1SSteven Rostedt break; 472ea4010d1SSteven Rostedt } 473ea4010d1SSteven Rostedt /* fall through */ 474ea4010d1SSteven Rostedt case '+': 475ea4010d1SSteven Rostedt case '|': 476ea4010d1SSteven Rostedt case '&': 477ea4010d1SSteven Rostedt case '>': 478ea4010d1SSteven Rostedt case '<': 479ea4010d1SSteven Rostedt last_ch = ch; 480ea4010d1SSteven Rostedt ch = __peek_char(); 481ea4010d1SSteven Rostedt if (ch != last_ch) 482ea4010d1SSteven Rostedt goto test_equal; 483ea4010d1SSteven Rostedt buf[i++] = __read_char(); 484ea4010d1SSteven Rostedt switch (last_ch) { 485ea4010d1SSteven Rostedt case '>': 486ea4010d1SSteven Rostedt case '<': 487ea4010d1SSteven Rostedt goto test_equal; 488ea4010d1SSteven Rostedt default: 489ea4010d1SSteven Rostedt break; 490ea4010d1SSteven Rostedt } 491ea4010d1SSteven Rostedt break; 492ea4010d1SSteven Rostedt case '!': 493ea4010d1SSteven Rostedt case '=': 494ea4010d1SSteven Rostedt goto test_equal; 495ea4010d1SSteven Rostedt default: /* what should we do instead? */ 496ea4010d1SSteven Rostedt break; 497ea4010d1SSteven Rostedt } 498ea4010d1SSteven Rostedt buf[i] = 0; 499ea4010d1SSteven Rostedt *tok = strdup(buf); 500ea4010d1SSteven Rostedt return type; 501ea4010d1SSteven Rostedt 502ea4010d1SSteven Rostedt test_equal: 503ea4010d1SSteven Rostedt ch = __peek_char(); 504ea4010d1SSteven Rostedt if (ch == '=') 505ea4010d1SSteven Rostedt buf[i++] = __read_char(); 506ea4010d1SSteven Rostedt break; 507ea4010d1SSteven Rostedt 508ea4010d1SSteven Rostedt case EVENT_DQUOTE: 509ea4010d1SSteven Rostedt case EVENT_SQUOTE: 510ea4010d1SSteven Rostedt /* don't keep quotes */ 511ea4010d1SSteven Rostedt i--; 512ea4010d1SSteven Rostedt quote_ch = ch; 513ea4010d1SSteven Rostedt last_ch = 0; 514ea4010d1SSteven Rostedt do { 515ea4010d1SSteven Rostedt if (i == (BUFSIZ - 1)) { 516ea4010d1SSteven Rostedt buf[i] = 0; 517ea4010d1SSteven Rostedt if (*tok) { 518ea4010d1SSteven Rostedt *tok = realloc(*tok, tok_size + BUFSIZ); 519ea4010d1SSteven Rostedt if (!*tok) 520ea4010d1SSteven Rostedt return EVENT_NONE; 521ea4010d1SSteven Rostedt strcat(*tok, buf); 522ea4010d1SSteven Rostedt } else 523ea4010d1SSteven Rostedt *tok = strdup(buf); 524ea4010d1SSteven Rostedt 525ea4010d1SSteven Rostedt if (!*tok) 526ea4010d1SSteven Rostedt return EVENT_NONE; 527ea4010d1SSteven Rostedt tok_size += BUFSIZ; 528ea4010d1SSteven Rostedt i = 0; 529ea4010d1SSteven Rostedt } 530ea4010d1SSteven Rostedt last_ch = ch; 531ea4010d1SSteven Rostedt ch = __read_char(); 532ea4010d1SSteven Rostedt buf[i++] = ch; 53391ff2bc1SSteven Rostedt /* the '\' '\' will cancel itself */ 53491ff2bc1SSteven Rostedt if (ch == '\\' && last_ch == '\\') 53591ff2bc1SSteven Rostedt last_ch = 0; 53691ff2bc1SSteven Rostedt } while (ch != quote_ch || last_ch == '\\'); 537ea4010d1SSteven Rostedt /* remove the last quote */ 538ea4010d1SSteven Rostedt i--; 539ea4010d1SSteven Rostedt goto out; 540ea4010d1SSteven Rostedt 541ea4010d1SSteven Rostedt case EVENT_ERROR ... EVENT_SPACE: 542ea4010d1SSteven Rostedt case EVENT_ITEM: 543ea4010d1SSteven Rostedt default: 544ea4010d1SSteven Rostedt break; 545ea4010d1SSteven Rostedt } 546ea4010d1SSteven Rostedt 547ea4010d1SSteven Rostedt while (get_type(__peek_char()) == type) { 548ea4010d1SSteven Rostedt if (i == (BUFSIZ - 1)) { 549ea4010d1SSteven Rostedt buf[i] = 0; 550ea4010d1SSteven Rostedt if (*tok) { 551ea4010d1SSteven Rostedt *tok = realloc(*tok, tok_size + BUFSIZ); 552ea4010d1SSteven Rostedt if (!*tok) 553ea4010d1SSteven Rostedt return EVENT_NONE; 554ea4010d1SSteven Rostedt strcat(*tok, buf); 555ea4010d1SSteven Rostedt } else 556ea4010d1SSteven Rostedt *tok = strdup(buf); 557ea4010d1SSteven Rostedt 558ea4010d1SSteven Rostedt if (!*tok) 559ea4010d1SSteven Rostedt return EVENT_NONE; 560ea4010d1SSteven Rostedt tok_size += BUFSIZ; 561ea4010d1SSteven Rostedt i = 0; 562ea4010d1SSteven Rostedt } 563ea4010d1SSteven Rostedt ch = __read_char(); 564ea4010d1SSteven Rostedt buf[i++] = ch; 565ea4010d1SSteven Rostedt } 566ea4010d1SSteven Rostedt 567ea4010d1SSteven Rostedt out: 568ea4010d1SSteven Rostedt buf[i] = 0; 569ea4010d1SSteven Rostedt if (*tok) { 570ea4010d1SSteven Rostedt *tok = realloc(*tok, tok_size + i); 571ea4010d1SSteven Rostedt if (!*tok) 572ea4010d1SSteven Rostedt return EVENT_NONE; 573ea4010d1SSteven Rostedt strcat(*tok, buf); 574ea4010d1SSteven Rostedt } else 575ea4010d1SSteven Rostedt *tok = strdup(buf); 576ea4010d1SSteven Rostedt if (!*tok) 577ea4010d1SSteven Rostedt return EVENT_NONE; 578ea4010d1SSteven Rostedt 579ea4010d1SSteven Rostedt return type; 580ea4010d1SSteven Rostedt } 581ea4010d1SSteven Rostedt 582ea4010d1SSteven Rostedt static void free_token(char *tok) 583ea4010d1SSteven Rostedt { 584ea4010d1SSteven Rostedt if (tok) 585ea4010d1SSteven Rostedt free(tok); 586ea4010d1SSteven Rostedt } 587ea4010d1SSteven Rostedt 588ea4010d1SSteven Rostedt static enum event_type read_token(char **tok) 589ea4010d1SSteven Rostedt { 590ea4010d1SSteven Rostedt enum event_type type; 591ea4010d1SSteven Rostedt 592ea4010d1SSteven Rostedt for (;;) { 593ea4010d1SSteven Rostedt type = __read_token(tok); 594ea4010d1SSteven Rostedt if (type != EVENT_SPACE) 595ea4010d1SSteven Rostedt return type; 596ea4010d1SSteven Rostedt 597ea4010d1SSteven Rostedt free_token(*tok); 598ea4010d1SSteven Rostedt } 599ea4010d1SSteven Rostedt 600ea4010d1SSteven Rostedt /* not reached */ 601ea4010d1SSteven Rostedt return EVENT_NONE; 602ea4010d1SSteven Rostedt } 603ea4010d1SSteven Rostedt 604ea4010d1SSteven Rostedt /* no newline */ 605ea4010d1SSteven Rostedt static enum event_type read_token_item(char **tok) 606ea4010d1SSteven Rostedt { 607ea4010d1SSteven Rostedt enum event_type type; 608ea4010d1SSteven Rostedt 609ea4010d1SSteven Rostedt for (;;) { 610ea4010d1SSteven Rostedt type = __read_token(tok); 611ea4010d1SSteven Rostedt if (type != EVENT_SPACE && type != EVENT_NEWLINE) 612ea4010d1SSteven Rostedt return type; 613ea4010d1SSteven Rostedt 614ea4010d1SSteven Rostedt free_token(*tok); 615ea4010d1SSteven Rostedt } 616ea4010d1SSteven Rostedt 617ea4010d1SSteven Rostedt /* not reached */ 618ea4010d1SSteven Rostedt return EVENT_NONE; 619ea4010d1SSteven Rostedt } 620ea4010d1SSteven Rostedt 621ea4010d1SSteven Rostedt static int test_type(enum event_type type, enum event_type expect) 622ea4010d1SSteven Rostedt { 623ea4010d1SSteven Rostedt if (type != expect) { 62407a4bdddSSteven Rostedt warning("Error: expected type %d but read %d", 625ea4010d1SSteven Rostedt expect, type); 626ea4010d1SSteven Rostedt return -1; 627ea4010d1SSteven Rostedt } 628ea4010d1SSteven Rostedt return 0; 629ea4010d1SSteven Rostedt } 630ea4010d1SSteven Rostedt 631ea4010d1SSteven Rostedt static int test_type_token(enum event_type type, char *token, 632cbef79a8SRandy Dunlap enum event_type expect, const char *expect_tok) 633ea4010d1SSteven Rostedt { 634ea4010d1SSteven Rostedt if (type != expect) { 63507a4bdddSSteven Rostedt warning("Error: expected type %d but read %d", 636ea4010d1SSteven Rostedt expect, type); 637ea4010d1SSteven Rostedt return -1; 638ea4010d1SSteven Rostedt } 639ea4010d1SSteven Rostedt 640ea4010d1SSteven Rostedt if (strcmp(token, expect_tok) != 0) { 64107a4bdddSSteven Rostedt warning("Error: expected '%s' but read '%s'", 642ea4010d1SSteven Rostedt expect_tok, token); 643ea4010d1SSteven Rostedt return -1; 644ea4010d1SSteven Rostedt } 645ea4010d1SSteven Rostedt return 0; 646ea4010d1SSteven Rostedt } 647ea4010d1SSteven Rostedt 648ea4010d1SSteven Rostedt static int __read_expect_type(enum event_type expect, char **tok, int newline_ok) 649ea4010d1SSteven Rostedt { 650ea4010d1SSteven Rostedt enum event_type type; 651ea4010d1SSteven Rostedt 652ea4010d1SSteven Rostedt if (newline_ok) 653ea4010d1SSteven Rostedt type = read_token(tok); 654ea4010d1SSteven Rostedt else 655ea4010d1SSteven Rostedt type = read_token_item(tok); 656ea4010d1SSteven Rostedt return test_type(type, expect); 657ea4010d1SSteven Rostedt } 658ea4010d1SSteven Rostedt 659ea4010d1SSteven Rostedt static int read_expect_type(enum event_type expect, char **tok) 660ea4010d1SSteven Rostedt { 661ea4010d1SSteven Rostedt return __read_expect_type(expect, tok, 1); 662ea4010d1SSteven Rostedt } 663ea4010d1SSteven Rostedt 664cbef79a8SRandy Dunlap static int __read_expected(enum event_type expect, const char *str, int newline_ok) 665ea4010d1SSteven Rostedt { 666ea4010d1SSteven Rostedt enum event_type type; 667ea4010d1SSteven Rostedt char *token; 668ea4010d1SSteven Rostedt int ret; 669ea4010d1SSteven Rostedt 670ea4010d1SSteven Rostedt if (newline_ok) 671ea4010d1SSteven Rostedt type = read_token(&token); 672ea4010d1SSteven Rostedt else 673ea4010d1SSteven Rostedt type = read_token_item(&token); 674ea4010d1SSteven Rostedt 675ea4010d1SSteven Rostedt ret = test_type_token(type, token, expect, str); 676ea4010d1SSteven Rostedt 677ea4010d1SSteven Rostedt free_token(token); 678ea4010d1SSteven Rostedt 67907a4bdddSSteven Rostedt return ret; 680ea4010d1SSteven Rostedt } 681ea4010d1SSteven Rostedt 682cbef79a8SRandy Dunlap static int read_expected(enum event_type expect, const char *str) 683ea4010d1SSteven Rostedt { 684ea4010d1SSteven Rostedt return __read_expected(expect, str, 1); 685ea4010d1SSteven Rostedt } 686ea4010d1SSteven Rostedt 687cbef79a8SRandy Dunlap static int read_expected_item(enum event_type expect, const char *str) 688ea4010d1SSteven Rostedt { 689ea4010d1SSteven Rostedt return __read_expected(expect, str, 0); 690ea4010d1SSteven Rostedt } 691ea4010d1SSteven Rostedt 692ea4010d1SSteven Rostedt static char *event_read_name(void) 693ea4010d1SSteven Rostedt { 694ea4010d1SSteven Rostedt char *token; 695ea4010d1SSteven Rostedt 696c4dc775fSSteven Rostedt if (read_expected(EVENT_ITEM, "name") < 0) 697ea4010d1SSteven Rostedt return NULL; 698ea4010d1SSteven Rostedt 699c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ":") < 0) 700ea4010d1SSteven Rostedt return NULL; 701ea4010d1SSteven Rostedt 702ea4010d1SSteven Rostedt if (read_expect_type(EVENT_ITEM, &token) < 0) 703ea4010d1SSteven Rostedt goto fail; 704ea4010d1SSteven Rostedt 705ea4010d1SSteven Rostedt return token; 706ea4010d1SSteven Rostedt 707ea4010d1SSteven Rostedt fail: 708ea4010d1SSteven Rostedt free_token(token); 709ea4010d1SSteven Rostedt return NULL; 710ea4010d1SSteven Rostedt } 711ea4010d1SSteven Rostedt 712ea4010d1SSteven Rostedt static int event_read_id(void) 713ea4010d1SSteven Rostedt { 714ea4010d1SSteven Rostedt char *token; 715ea4010d1SSteven Rostedt int id; 716ea4010d1SSteven Rostedt 717c4dc775fSSteven Rostedt if (read_expected_item(EVENT_ITEM, "ID") < 0) 718ea4010d1SSteven Rostedt return -1; 719ea4010d1SSteven Rostedt 720c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ":") < 0) 721ea4010d1SSteven Rostedt return -1; 722ea4010d1SSteven Rostedt 723ea4010d1SSteven Rostedt if (read_expect_type(EVENT_ITEM, &token) < 0) 724ea4010d1SSteven Rostedt goto fail; 725ea4010d1SSteven Rostedt 726ea4010d1SSteven Rostedt id = strtoul(token, NULL, 0); 727ea4010d1SSteven Rostedt free_token(token); 728ea4010d1SSteven Rostedt return id; 729ea4010d1SSteven Rostedt 730ea4010d1SSteven Rostedt fail: 731ea4010d1SSteven Rostedt free_token(token); 732ea4010d1SSteven Rostedt return -1; 733ea4010d1SSteven Rostedt } 734ea4010d1SSteven Rostedt 735064739bcSTom Zanussi static int field_is_string(struct format_field *field) 736064739bcSTom Zanussi { 737064739bcSTom Zanussi if ((field->flags & FIELD_IS_ARRAY) && 738064739bcSTom Zanussi (!strstr(field->type, "char") || !strstr(field->type, "u8") || 739064739bcSTom Zanussi !strstr(field->type, "s8"))) 740064739bcSTom Zanussi return 1; 741064739bcSTom Zanussi 742064739bcSTom Zanussi return 0; 743064739bcSTom Zanussi } 744064739bcSTom Zanussi 745064739bcSTom Zanussi static int field_is_dynamic(struct format_field *field) 746064739bcSTom Zanussi { 747064739bcSTom Zanussi if (!strcmp(field->type, "__data_loc")) 748064739bcSTom Zanussi return 1; 749064739bcSTom Zanussi 750064739bcSTom Zanussi return 0; 751064739bcSTom Zanussi } 752064739bcSTom Zanussi 753ea4010d1SSteven Rostedt static int event_read_fields(struct event *event, struct format_field **fields) 754ea4010d1SSteven Rostedt { 755ea4010d1SSteven Rostedt struct format_field *field = NULL; 756ea4010d1SSteven Rostedt enum event_type type; 757ea4010d1SSteven Rostedt char *token; 758ea4010d1SSteven Rostedt char *last_token; 759ea4010d1SSteven Rostedt int count = 0; 760ea4010d1SSteven Rostedt 761ea4010d1SSteven Rostedt do { 762ea4010d1SSteven Rostedt type = read_token(&token); 763ea4010d1SSteven Rostedt if (type == EVENT_NEWLINE) { 764ea4010d1SSteven Rostedt free_token(token); 765ea4010d1SSteven Rostedt return count; 766ea4010d1SSteven Rostedt } 767ea4010d1SSteven Rostedt 768ea4010d1SSteven Rostedt count++; 769ea4010d1SSteven Rostedt 770c4dc775fSSteven Rostedt if (test_type_token(type, token, EVENT_ITEM, "field")) 771ea4010d1SSteven Rostedt goto fail; 772ea4010d1SSteven Rostedt free_token(token); 773ea4010d1SSteven Rostedt 774ea4010d1SSteven Rostedt type = read_token(&token); 775ea4010d1SSteven Rostedt /* 776ea4010d1SSteven Rostedt * The ftrace fields may still use the "special" name. 777ea4010d1SSteven Rostedt * Just ignore it. 778ea4010d1SSteven Rostedt */ 779ea4010d1SSteven Rostedt if (event->flags & EVENT_FL_ISFTRACE && 780ea4010d1SSteven Rostedt type == EVENT_ITEM && strcmp(token, "special") == 0) { 781ea4010d1SSteven Rostedt free_token(token); 782ea4010d1SSteven Rostedt type = read_token(&token); 783ea4010d1SSteven Rostedt } 784ea4010d1SSteven Rostedt 785c4dc775fSSteven Rostedt if (test_type_token(type, token, EVENT_OP, ":") < 0) 786ea4010d1SSteven Rostedt return -1; 787ea4010d1SSteven Rostedt 788ea4010d1SSteven Rostedt if (read_expect_type(EVENT_ITEM, &token) < 0) 789ea4010d1SSteven Rostedt goto fail; 790ea4010d1SSteven Rostedt 791ea4010d1SSteven Rostedt last_token = token; 792ea4010d1SSteven Rostedt 793ea4010d1SSteven Rostedt field = malloc_or_die(sizeof(*field)); 794ea4010d1SSteven Rostedt memset(field, 0, sizeof(*field)); 795ea4010d1SSteven Rostedt 796ea4010d1SSteven Rostedt /* read the rest of the type */ 797ea4010d1SSteven Rostedt for (;;) { 798ea4010d1SSteven Rostedt type = read_token(&token); 799ea4010d1SSteven Rostedt if (type == EVENT_ITEM || 800ea4010d1SSteven Rostedt (type == EVENT_OP && strcmp(token, "*") == 0) || 801ea4010d1SSteven Rostedt /* 802ea4010d1SSteven Rostedt * Some of the ftrace fields are broken and have 803ea4010d1SSteven Rostedt * an illegal "." in them. 804ea4010d1SSteven Rostedt */ 805ea4010d1SSteven Rostedt (event->flags & EVENT_FL_ISFTRACE && 806ea4010d1SSteven Rostedt type == EVENT_OP && strcmp(token, ".") == 0)) { 807ea4010d1SSteven Rostedt 808ea4010d1SSteven Rostedt if (strcmp(token, "*") == 0) 809ea4010d1SSteven Rostedt field->flags |= FIELD_IS_POINTER; 810ea4010d1SSteven Rostedt 811ea4010d1SSteven Rostedt if (field->type) { 812ea4010d1SSteven Rostedt field->type = realloc(field->type, 813ea4010d1SSteven Rostedt strlen(field->type) + 814ea4010d1SSteven Rostedt strlen(last_token) + 2); 815ea4010d1SSteven Rostedt strcat(field->type, " "); 816ea4010d1SSteven Rostedt strcat(field->type, last_token); 817ea4010d1SSteven Rostedt } else 818ea4010d1SSteven Rostedt field->type = last_token; 819ea4010d1SSteven Rostedt last_token = token; 820ea4010d1SSteven Rostedt continue; 821ea4010d1SSteven Rostedt } 822ea4010d1SSteven Rostedt 823ea4010d1SSteven Rostedt break; 824ea4010d1SSteven Rostedt } 825ea4010d1SSteven Rostedt 826ea4010d1SSteven Rostedt if (!field->type) { 827ea4010d1SSteven Rostedt die("no type found"); 828ea4010d1SSteven Rostedt goto fail; 829ea4010d1SSteven Rostedt } 830ea4010d1SSteven Rostedt field->name = last_token; 831ea4010d1SSteven Rostedt 832ea4010d1SSteven Rostedt if (test_type(type, EVENT_OP)) 833ea4010d1SSteven Rostedt goto fail; 834ea4010d1SSteven Rostedt 835ea4010d1SSteven Rostedt if (strcmp(token, "[") == 0) { 836ea4010d1SSteven Rostedt enum event_type last_type = type; 837ea4010d1SSteven Rostedt char *brackets = token; 838ea4010d1SSteven Rostedt int len; 839ea4010d1SSteven Rostedt 840ea4010d1SSteven Rostedt field->flags |= FIELD_IS_ARRAY; 841ea4010d1SSteven Rostedt 842ea4010d1SSteven Rostedt type = read_token(&token); 843ea4010d1SSteven Rostedt while (strcmp(token, "]") != 0) { 844ea4010d1SSteven Rostedt if (last_type == EVENT_ITEM && 845ea4010d1SSteven Rostedt type == EVENT_ITEM) 846ea4010d1SSteven Rostedt len = 2; 847ea4010d1SSteven Rostedt else 848ea4010d1SSteven Rostedt len = 1; 849ea4010d1SSteven Rostedt last_type = type; 850ea4010d1SSteven Rostedt 851ea4010d1SSteven Rostedt brackets = realloc(brackets, 852ea4010d1SSteven Rostedt strlen(brackets) + 853ea4010d1SSteven Rostedt strlen(token) + len); 854ea4010d1SSteven Rostedt if (len == 2) 855ea4010d1SSteven Rostedt strcat(brackets, " "); 856ea4010d1SSteven Rostedt strcat(brackets, token); 857ea4010d1SSteven Rostedt free_token(token); 858ea4010d1SSteven Rostedt type = read_token(&token); 859ea4010d1SSteven Rostedt if (type == EVENT_NONE) { 860ea4010d1SSteven Rostedt die("failed to find token"); 861ea4010d1SSteven Rostedt goto fail; 862ea4010d1SSteven Rostedt } 863ea4010d1SSteven Rostedt } 864ea4010d1SSteven Rostedt 865ea4010d1SSteven Rostedt free_token(token); 866ea4010d1SSteven Rostedt 867ea4010d1SSteven Rostedt brackets = realloc(brackets, strlen(brackets) + 2); 868ea4010d1SSteven Rostedt strcat(brackets, "]"); 869ea4010d1SSteven Rostedt 870ea4010d1SSteven Rostedt /* add brackets to type */ 871ea4010d1SSteven Rostedt 872ea4010d1SSteven Rostedt type = read_token(&token); 873ea4010d1SSteven Rostedt /* 874ea4010d1SSteven Rostedt * If the next token is not an OP, then it is of 875ea4010d1SSteven Rostedt * the format: type [] item; 876ea4010d1SSteven Rostedt */ 877ea4010d1SSteven Rostedt if (type == EVENT_ITEM) { 878ea4010d1SSteven Rostedt field->type = realloc(field->type, 879ea4010d1SSteven Rostedt strlen(field->type) + 880ea4010d1SSteven Rostedt strlen(field->name) + 881ea4010d1SSteven Rostedt strlen(brackets) + 2); 882ea4010d1SSteven Rostedt strcat(field->type, " "); 883ea4010d1SSteven Rostedt strcat(field->type, field->name); 884ea4010d1SSteven Rostedt free_token(field->name); 885ea4010d1SSteven Rostedt strcat(field->type, brackets); 886ea4010d1SSteven Rostedt field->name = token; 887ea4010d1SSteven Rostedt type = read_token(&token); 888ea4010d1SSteven Rostedt } else { 889ea4010d1SSteven Rostedt field->type = realloc(field->type, 890ea4010d1SSteven Rostedt strlen(field->type) + 891ea4010d1SSteven Rostedt strlen(brackets) + 1); 892ea4010d1SSteven Rostedt strcat(field->type, brackets); 893ea4010d1SSteven Rostedt } 894ea4010d1SSteven Rostedt free(brackets); 895ea4010d1SSteven Rostedt } 896ea4010d1SSteven Rostedt 897064739bcSTom Zanussi if (field_is_string(field)) { 898064739bcSTom Zanussi field->flags |= FIELD_IS_STRING; 899064739bcSTom Zanussi if (field_is_dynamic(field)) 900064739bcSTom Zanussi field->flags |= FIELD_IS_DYNAMIC; 901064739bcSTom Zanussi } 902064739bcSTom Zanussi 903c4dc775fSSteven Rostedt if (test_type_token(type, token, EVENT_OP, ";")) 904ea4010d1SSteven Rostedt goto fail; 905ea4010d1SSteven Rostedt free_token(token); 906ea4010d1SSteven Rostedt 907c4dc775fSSteven Rostedt if (read_expected(EVENT_ITEM, "offset") < 0) 908ea4010d1SSteven Rostedt goto fail_expect; 909ea4010d1SSteven Rostedt 910c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ":") < 0) 911ea4010d1SSteven Rostedt goto fail_expect; 912ea4010d1SSteven Rostedt 913ea4010d1SSteven Rostedt if (read_expect_type(EVENT_ITEM, &token)) 914ea4010d1SSteven Rostedt goto fail; 915ea4010d1SSteven Rostedt field->offset = strtoul(token, NULL, 0); 916ea4010d1SSteven Rostedt free_token(token); 917ea4010d1SSteven Rostedt 918c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ";") < 0) 919ea4010d1SSteven Rostedt goto fail_expect; 920ea4010d1SSteven Rostedt 921c4dc775fSSteven Rostedt if (read_expected(EVENT_ITEM, "size") < 0) 922ea4010d1SSteven Rostedt goto fail_expect; 923ea4010d1SSteven Rostedt 924c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ":") < 0) 925ea4010d1SSteven Rostedt goto fail_expect; 926ea4010d1SSteven Rostedt 927ea4010d1SSteven Rostedt if (read_expect_type(EVENT_ITEM, &token)) 928ea4010d1SSteven Rostedt goto fail; 929ea4010d1SSteven Rostedt field->size = strtoul(token, NULL, 0); 930ea4010d1SSteven Rostedt free_token(token); 931ea4010d1SSteven Rostedt 932c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ";") < 0) 933ea4010d1SSteven Rostedt goto fail_expect; 934ea4010d1SSteven Rostedt 93513999e59SSteven Rostedt type = read_token(&token); 93613999e59SSteven Rostedt if (type != EVENT_NEWLINE) { 93713999e59SSteven Rostedt /* newer versions of the kernel have a "signed" type */ 938c4dc775fSSteven Rostedt if (test_type_token(type, token, EVENT_ITEM, "signed")) 93913999e59SSteven Rostedt goto fail; 94013999e59SSteven Rostedt 94113999e59SSteven Rostedt free_token(token); 94226a50744STom Zanussi 943c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ":") < 0) 94426a50744STom Zanussi goto fail_expect; 94526a50744STom Zanussi 94626a50744STom Zanussi if (read_expect_type(EVENT_ITEM, &token)) 94726a50744STom Zanussi goto fail; 94826a50744STom Zanussi 9490d0bea5eSTom Zanussi if (strtoul(token, NULL, 0)) 9500d0bea5eSTom Zanussi field->flags |= FIELD_IS_SIGNED; 95113999e59SSteven Rostedt 95213999e59SSteven Rostedt free_token(token); 953c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ";") < 0) 95426a50744STom Zanussi goto fail_expect; 95526a50744STom Zanussi 95613999e59SSteven Rostedt if (read_expect_type(EVENT_NEWLINE, &token)) 957ea4010d1SSteven Rostedt goto fail; 95813999e59SSteven Rostedt } 95913999e59SSteven Rostedt 960ea4010d1SSteven Rostedt free_token(token); 961ea4010d1SSteven Rostedt 962ea4010d1SSteven Rostedt *fields = field; 963ea4010d1SSteven Rostedt fields = &field->next; 964ea4010d1SSteven Rostedt 965ea4010d1SSteven Rostedt } while (1); 966ea4010d1SSteven Rostedt 967ea4010d1SSteven Rostedt return 0; 968ea4010d1SSteven Rostedt 969ea4010d1SSteven Rostedt fail: 970ea4010d1SSteven Rostedt free_token(token); 971ea4010d1SSteven Rostedt fail_expect: 972ea4010d1SSteven Rostedt if (field) 973ea4010d1SSteven Rostedt free(field); 974ea4010d1SSteven Rostedt return -1; 975ea4010d1SSteven Rostedt } 976ea4010d1SSteven Rostedt 977ea4010d1SSteven Rostedt static int event_read_format(struct event *event) 978ea4010d1SSteven Rostedt { 979ea4010d1SSteven Rostedt char *token; 980ea4010d1SSteven Rostedt int ret; 981ea4010d1SSteven Rostedt 982c4dc775fSSteven Rostedt if (read_expected_item(EVENT_ITEM, "format") < 0) 983ea4010d1SSteven Rostedt return -1; 984ea4010d1SSteven Rostedt 985c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ":") < 0) 986ea4010d1SSteven Rostedt return -1; 987ea4010d1SSteven Rostedt 988ea4010d1SSteven Rostedt if (read_expect_type(EVENT_NEWLINE, &token)) 989ea4010d1SSteven Rostedt goto fail; 990ea4010d1SSteven Rostedt free_token(token); 991ea4010d1SSteven Rostedt 992ea4010d1SSteven Rostedt ret = event_read_fields(event, &event->format.common_fields); 993ea4010d1SSteven Rostedt if (ret < 0) 994ea4010d1SSteven Rostedt return ret; 995ea4010d1SSteven Rostedt event->format.nr_common = ret; 996ea4010d1SSteven Rostedt 997ea4010d1SSteven Rostedt ret = event_read_fields(event, &event->format.fields); 998ea4010d1SSteven Rostedt if (ret < 0) 999ea4010d1SSteven Rostedt return ret; 1000ea4010d1SSteven Rostedt event->format.nr_fields = ret; 1001ea4010d1SSteven Rostedt 1002ea4010d1SSteven Rostedt return 0; 1003ea4010d1SSteven Rostedt 1004ea4010d1SSteven Rostedt fail: 1005ea4010d1SSteven Rostedt free_token(token); 1006ea4010d1SSteven Rostedt return -1; 1007ea4010d1SSteven Rostedt } 1008ea4010d1SSteven Rostedt 1009ea4010d1SSteven Rostedt enum event_type 1010ea4010d1SSteven Rostedt process_arg_token(struct event *event, struct print_arg *arg, 1011ea4010d1SSteven Rostedt char **tok, enum event_type type); 1012ea4010d1SSteven Rostedt 1013ea4010d1SSteven Rostedt static enum event_type 1014ea4010d1SSteven Rostedt process_arg(struct event *event, struct print_arg *arg, char **tok) 1015ea4010d1SSteven Rostedt { 1016ea4010d1SSteven Rostedt enum event_type type; 1017ea4010d1SSteven Rostedt char *token; 1018ea4010d1SSteven Rostedt 1019ea4010d1SSteven Rostedt type = read_token(&token); 1020ea4010d1SSteven Rostedt *tok = token; 1021ea4010d1SSteven Rostedt 1022ea4010d1SSteven Rostedt return process_arg_token(event, arg, tok, type); 1023ea4010d1SSteven Rostedt } 1024ea4010d1SSteven Rostedt 1025ea4010d1SSteven Rostedt static enum event_type 1026ea4010d1SSteven Rostedt process_cond(struct event *event, struct print_arg *top, char **tok) 1027ea4010d1SSteven Rostedt { 1028ea4010d1SSteven Rostedt struct print_arg *arg, *left, *right; 1029ea4010d1SSteven Rostedt enum event_type type; 1030ea4010d1SSteven Rostedt char *token = NULL; 1031ea4010d1SSteven Rostedt 1032ea4010d1SSteven Rostedt arg = malloc_or_die(sizeof(*arg)); 1033ea4010d1SSteven Rostedt memset(arg, 0, sizeof(*arg)); 1034ea4010d1SSteven Rostedt 1035ea4010d1SSteven Rostedt left = malloc_or_die(sizeof(*left)); 1036ea4010d1SSteven Rostedt 1037ea4010d1SSteven Rostedt right = malloc_or_die(sizeof(*right)); 1038ea4010d1SSteven Rostedt 1039ea4010d1SSteven Rostedt arg->type = PRINT_OP; 1040ea4010d1SSteven Rostedt arg->op.left = left; 1041ea4010d1SSteven Rostedt arg->op.right = right; 1042ea4010d1SSteven Rostedt 1043ea4010d1SSteven Rostedt *tok = NULL; 1044ea4010d1SSteven Rostedt type = process_arg(event, left, &token); 1045c4dc775fSSteven Rostedt if (test_type_token(type, token, EVENT_OP, ":")) 1046ea4010d1SSteven Rostedt goto out_free; 1047ea4010d1SSteven Rostedt 1048ea4010d1SSteven Rostedt arg->op.op = token; 1049ea4010d1SSteven Rostedt 1050ea4010d1SSteven Rostedt type = process_arg(event, right, &token); 1051ea4010d1SSteven Rostedt 1052ea4010d1SSteven Rostedt top->op.right = arg; 1053ea4010d1SSteven Rostedt 1054ea4010d1SSteven Rostedt *tok = token; 1055ea4010d1SSteven Rostedt return type; 1056ea4010d1SSteven Rostedt 1057ea4010d1SSteven Rostedt out_free: 1058ea4010d1SSteven Rostedt free_token(*tok); 1059ea4010d1SSteven Rostedt free(right); 1060ea4010d1SSteven Rostedt free(left); 1061ea4010d1SSteven Rostedt free_arg(arg); 1062ea4010d1SSteven Rostedt return EVENT_ERROR; 1063ea4010d1SSteven Rostedt } 1064ea4010d1SSteven Rostedt 10650959b8d6SSteven Rostedt static enum event_type 10660959b8d6SSteven Rostedt process_array(struct event *event, struct print_arg *top, char **tok) 10670959b8d6SSteven Rostedt { 10680959b8d6SSteven Rostedt struct print_arg *arg; 10690959b8d6SSteven Rostedt enum event_type type; 10700959b8d6SSteven Rostedt char *token = NULL; 10710959b8d6SSteven Rostedt 10720959b8d6SSteven Rostedt arg = malloc_or_die(sizeof(*arg)); 10730959b8d6SSteven Rostedt memset(arg, 0, sizeof(*arg)); 10740959b8d6SSteven Rostedt 10750959b8d6SSteven Rostedt *tok = NULL; 10760959b8d6SSteven Rostedt type = process_arg(event, arg, &token); 1077c4dc775fSSteven Rostedt if (test_type_token(type, token, EVENT_OP, "]")) 10780959b8d6SSteven Rostedt goto out_free; 10790959b8d6SSteven Rostedt 10800959b8d6SSteven Rostedt top->op.right = arg; 10810959b8d6SSteven Rostedt 10820959b8d6SSteven Rostedt free_token(token); 10830959b8d6SSteven Rostedt type = read_token_item(&token); 10840959b8d6SSteven Rostedt *tok = token; 10850959b8d6SSteven Rostedt 10860959b8d6SSteven Rostedt return type; 10870959b8d6SSteven Rostedt 10880959b8d6SSteven Rostedt out_free: 10890959b8d6SSteven Rostedt free_token(*tok); 10900959b8d6SSteven Rostedt free_arg(arg); 10910959b8d6SSteven Rostedt return EVENT_ERROR; 10920959b8d6SSteven Rostedt } 10930959b8d6SSteven Rostedt 1094ea4010d1SSteven Rostedt static int get_op_prio(char *op) 1095ea4010d1SSteven Rostedt { 1096ea4010d1SSteven Rostedt if (!op[1]) { 1097ea4010d1SSteven Rostedt switch (op[0]) { 1098ea4010d1SSteven Rostedt case '*': 1099ea4010d1SSteven Rostedt case '/': 1100ea4010d1SSteven Rostedt case '%': 1101ea4010d1SSteven Rostedt return 6; 1102ea4010d1SSteven Rostedt case '+': 1103ea4010d1SSteven Rostedt case '-': 1104ea4010d1SSteven Rostedt return 7; 1105ea4010d1SSteven Rostedt /* '>>' and '<<' are 8 */ 1106ea4010d1SSteven Rostedt case '<': 1107ea4010d1SSteven Rostedt case '>': 1108ea4010d1SSteven Rostedt return 9; 1109ea4010d1SSteven Rostedt /* '==' and '!=' are 10 */ 1110ea4010d1SSteven Rostedt case '&': 1111ea4010d1SSteven Rostedt return 11; 1112ea4010d1SSteven Rostedt case '^': 1113ea4010d1SSteven Rostedt return 12; 1114ea4010d1SSteven Rostedt case '|': 1115ea4010d1SSteven Rostedt return 13; 1116ea4010d1SSteven Rostedt case '?': 1117ea4010d1SSteven Rostedt return 16; 1118ea4010d1SSteven Rostedt default: 1119ea4010d1SSteven Rostedt die("unknown op '%c'", op[0]); 1120ea4010d1SSteven Rostedt return -1; 1121ea4010d1SSteven Rostedt } 1122ea4010d1SSteven Rostedt } else { 1123ea4010d1SSteven Rostedt if (strcmp(op, "++") == 0 || 1124ea4010d1SSteven Rostedt strcmp(op, "--") == 0) { 1125ea4010d1SSteven Rostedt return 3; 1126ea4010d1SSteven Rostedt } else if (strcmp(op, ">>") == 0 || 1127ea4010d1SSteven Rostedt strcmp(op, "<<") == 0) { 1128ea4010d1SSteven Rostedt return 8; 1129ea4010d1SSteven Rostedt } else if (strcmp(op, ">=") == 0 || 1130ea4010d1SSteven Rostedt strcmp(op, "<=") == 0) { 1131ea4010d1SSteven Rostedt return 9; 1132ea4010d1SSteven Rostedt } else if (strcmp(op, "==") == 0 || 1133ea4010d1SSteven Rostedt strcmp(op, "!=") == 0) { 1134ea4010d1SSteven Rostedt return 10; 1135ea4010d1SSteven Rostedt } else if (strcmp(op, "&&") == 0) { 1136ea4010d1SSteven Rostedt return 14; 1137ea4010d1SSteven Rostedt } else if (strcmp(op, "||") == 0) { 1138ea4010d1SSteven Rostedt return 15; 1139ea4010d1SSteven Rostedt } else { 1140ea4010d1SSteven Rostedt die("unknown op '%s'", op); 1141ea4010d1SSteven Rostedt return -1; 1142ea4010d1SSteven Rostedt } 1143ea4010d1SSteven Rostedt } 1144ea4010d1SSteven Rostedt } 1145ea4010d1SSteven Rostedt 1146ea4010d1SSteven Rostedt static void set_op_prio(struct print_arg *arg) 1147ea4010d1SSteven Rostedt { 1148ea4010d1SSteven Rostedt 1149ea4010d1SSteven Rostedt /* single ops are the greatest */ 1150ea4010d1SSteven Rostedt if (!arg->op.left || arg->op.left->type == PRINT_NULL) { 1151ea4010d1SSteven Rostedt arg->op.prio = 0; 1152ea4010d1SSteven Rostedt return; 1153ea4010d1SSteven Rostedt } 1154ea4010d1SSteven Rostedt 1155ea4010d1SSteven Rostedt arg->op.prio = get_op_prio(arg->op.op); 1156ea4010d1SSteven Rostedt } 1157ea4010d1SSteven Rostedt 1158ea4010d1SSteven Rostedt static enum event_type 1159ea4010d1SSteven Rostedt process_op(struct event *event, struct print_arg *arg, char **tok) 1160ea4010d1SSteven Rostedt { 1161ea4010d1SSteven Rostedt struct print_arg *left, *right = NULL; 1162ea4010d1SSteven Rostedt enum event_type type; 1163ea4010d1SSteven Rostedt char *token; 1164ea4010d1SSteven Rostedt 1165ea4010d1SSteven Rostedt /* the op is passed in via tok */ 1166ea4010d1SSteven Rostedt token = *tok; 1167ea4010d1SSteven Rostedt 1168ea4010d1SSteven Rostedt if (arg->type == PRINT_OP && !arg->op.left) { 1169ea4010d1SSteven Rostedt /* handle single op */ 1170ea4010d1SSteven Rostedt if (token[1]) { 1171ea4010d1SSteven Rostedt die("bad op token %s", token); 1172ea4010d1SSteven Rostedt return EVENT_ERROR; 1173ea4010d1SSteven Rostedt } 1174ea4010d1SSteven Rostedt switch (token[0]) { 1175ea4010d1SSteven Rostedt case '!': 1176ea4010d1SSteven Rostedt case '+': 1177ea4010d1SSteven Rostedt case '-': 1178ea4010d1SSteven Rostedt break; 1179ea4010d1SSteven Rostedt default: 1180ea4010d1SSteven Rostedt die("bad op token %s", token); 1181ea4010d1SSteven Rostedt return EVENT_ERROR; 1182ea4010d1SSteven Rostedt } 1183ea4010d1SSteven Rostedt 1184ea4010d1SSteven Rostedt /* make an empty left */ 1185ea4010d1SSteven Rostedt left = malloc_or_die(sizeof(*left)); 1186ea4010d1SSteven Rostedt left->type = PRINT_NULL; 1187ea4010d1SSteven Rostedt arg->op.left = left; 1188ea4010d1SSteven Rostedt 1189ea4010d1SSteven Rostedt right = malloc_or_die(sizeof(*right)); 1190ea4010d1SSteven Rostedt arg->op.right = right; 1191ea4010d1SSteven Rostedt 1192ea4010d1SSteven Rostedt type = process_arg(event, right, tok); 1193ea4010d1SSteven Rostedt 1194ea4010d1SSteven Rostedt } else if (strcmp(token, "?") == 0) { 1195ea4010d1SSteven Rostedt 1196ea4010d1SSteven Rostedt left = malloc_or_die(sizeof(*left)); 1197ea4010d1SSteven Rostedt /* copy the top arg to the left */ 1198ea4010d1SSteven Rostedt *left = *arg; 1199ea4010d1SSteven Rostedt 1200ea4010d1SSteven Rostedt arg->type = PRINT_OP; 1201ea4010d1SSteven Rostedt arg->op.op = token; 1202ea4010d1SSteven Rostedt arg->op.left = left; 1203ea4010d1SSteven Rostedt arg->op.prio = 0; 1204ea4010d1SSteven Rostedt 1205ea4010d1SSteven Rostedt type = process_cond(event, arg, tok); 1206ea4010d1SSteven Rostedt 1207ea4010d1SSteven Rostedt } else if (strcmp(token, ">>") == 0 || 1208ea4010d1SSteven Rostedt strcmp(token, "<<") == 0 || 1209ea4010d1SSteven Rostedt strcmp(token, "&") == 0 || 1210ea4010d1SSteven Rostedt strcmp(token, "|") == 0 || 1211ea4010d1SSteven Rostedt strcmp(token, "&&") == 0 || 1212ea4010d1SSteven Rostedt strcmp(token, "||") == 0 || 1213ea4010d1SSteven Rostedt strcmp(token, "-") == 0 || 1214ea4010d1SSteven Rostedt strcmp(token, "+") == 0 || 1215ea4010d1SSteven Rostedt strcmp(token, "*") == 0 || 1216ea4010d1SSteven Rostedt strcmp(token, "^") == 0 || 1217ea4010d1SSteven Rostedt strcmp(token, "/") == 0 || 1218298ebc3eSSteven Rostedt strcmp(token, "<") == 0 || 1219298ebc3eSSteven Rostedt strcmp(token, ">") == 0 || 1220ea4010d1SSteven Rostedt strcmp(token, "==") == 0 || 1221ea4010d1SSteven Rostedt strcmp(token, "!=") == 0) { 1222ea4010d1SSteven Rostedt 1223ea4010d1SSteven Rostedt left = malloc_or_die(sizeof(*left)); 1224ea4010d1SSteven Rostedt 1225ea4010d1SSteven Rostedt /* copy the top arg to the left */ 1226ea4010d1SSteven Rostedt *left = *arg; 1227ea4010d1SSteven Rostedt 1228ea4010d1SSteven Rostedt arg->type = PRINT_OP; 1229ea4010d1SSteven Rostedt arg->op.op = token; 1230ea4010d1SSteven Rostedt arg->op.left = left; 1231ea4010d1SSteven Rostedt 1232ea4010d1SSteven Rostedt set_op_prio(arg); 1233ea4010d1SSteven Rostedt 1234ea4010d1SSteven Rostedt right = malloc_or_die(sizeof(*right)); 1235ea4010d1SSteven Rostedt 1236b99af874SSteven Rostedt type = read_token_item(&token); 1237b99af874SSteven Rostedt *tok = token; 1238b99af874SSteven Rostedt 1239b99af874SSteven Rostedt /* could just be a type pointer */ 1240b99af874SSteven Rostedt if ((strcmp(arg->op.op, "*") == 0) && 1241b99af874SSteven Rostedt type == EVENT_DELIM && (strcmp(token, ")") == 0)) { 1242b99af874SSteven Rostedt if (left->type != PRINT_ATOM) 1243b99af874SSteven Rostedt die("bad pointer type"); 1244b99af874SSteven Rostedt left->atom.atom = realloc(left->atom.atom, 1245b99af874SSteven Rostedt sizeof(left->atom.atom) + 3); 1246b99af874SSteven Rostedt strcat(left->atom.atom, " *"); 1247b99af874SSteven Rostedt *arg = *left; 1248b99af874SSteven Rostedt free(arg); 1249b99af874SSteven Rostedt 1250b99af874SSteven Rostedt return type; 1251b99af874SSteven Rostedt } 1252b99af874SSteven Rostedt 1253b99af874SSteven Rostedt type = process_arg_token(event, right, tok, type); 1254ea4010d1SSteven Rostedt 1255ea4010d1SSteven Rostedt arg->op.right = right; 1256ea4010d1SSteven Rostedt 12570959b8d6SSteven Rostedt } else if (strcmp(token, "[") == 0) { 12580959b8d6SSteven Rostedt 12590959b8d6SSteven Rostedt left = malloc_or_die(sizeof(*left)); 12600959b8d6SSteven Rostedt *left = *arg; 12610959b8d6SSteven Rostedt 12620959b8d6SSteven Rostedt arg->type = PRINT_OP; 12630959b8d6SSteven Rostedt arg->op.op = token; 12640959b8d6SSteven Rostedt arg->op.left = left; 12650959b8d6SSteven Rostedt 12660959b8d6SSteven Rostedt arg->op.prio = 0; 12670959b8d6SSteven Rostedt type = process_array(event, arg, tok); 12680959b8d6SSteven Rostedt 1269ea4010d1SSteven Rostedt } else { 127007a4bdddSSteven Rostedt warning("unknown op '%s'", token); 127107a4bdddSSteven Rostedt event->flags |= EVENT_FL_FAILED; 1272ea4010d1SSteven Rostedt /* the arg is now the left side */ 1273ea4010d1SSteven Rostedt return EVENT_NONE; 1274ea4010d1SSteven Rostedt } 1275ea4010d1SSteven Rostedt 1276ea4010d1SSteven Rostedt if (type == EVENT_OP) { 1277ea4010d1SSteven Rostedt int prio; 1278ea4010d1SSteven Rostedt 1279ea4010d1SSteven Rostedt /* higher prios need to be closer to the root */ 1280ea4010d1SSteven Rostedt prio = get_op_prio(*tok); 1281ea4010d1SSteven Rostedt 1282ea4010d1SSteven Rostedt if (prio > arg->op.prio) 1283ea4010d1SSteven Rostedt return process_op(event, arg, tok); 1284ea4010d1SSteven Rostedt 1285ea4010d1SSteven Rostedt return process_op(event, right, tok); 1286ea4010d1SSteven Rostedt } 1287ea4010d1SSteven Rostedt 1288ea4010d1SSteven Rostedt return type; 1289ea4010d1SSteven Rostedt } 1290ea4010d1SSteven Rostedt 1291ea4010d1SSteven Rostedt static enum event_type 1292ea4010d1SSteven Rostedt process_entry(struct event *event __unused, struct print_arg *arg, 1293ea4010d1SSteven Rostedt char **tok) 1294ea4010d1SSteven Rostedt { 1295ea4010d1SSteven Rostedt enum event_type type; 1296ea4010d1SSteven Rostedt char *field; 1297ea4010d1SSteven Rostedt char *token; 1298ea4010d1SSteven Rostedt 1299c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, "->") < 0) 1300ea4010d1SSteven Rostedt return EVENT_ERROR; 1301ea4010d1SSteven Rostedt 1302ea4010d1SSteven Rostedt if (read_expect_type(EVENT_ITEM, &token) < 0) 1303ea4010d1SSteven Rostedt goto fail; 1304ea4010d1SSteven Rostedt field = token; 1305ea4010d1SSteven Rostedt 1306ea4010d1SSteven Rostedt arg->type = PRINT_FIELD; 1307ea4010d1SSteven Rostedt arg->field.name = field; 1308ea4010d1SSteven Rostedt 1309eb9a42caSTom Zanussi if (is_flag_field) { 1310eb9a42caSTom Zanussi arg->field.field = find_any_field(event, arg->field.name); 1311eb9a42caSTom Zanussi arg->field.field->flags |= FIELD_IS_FLAG; 1312eb9a42caSTom Zanussi is_flag_field = 0; 1313eb9a42caSTom Zanussi } else if (is_symbolic_field) { 1314eb9a42caSTom Zanussi arg->field.field = find_any_field(event, arg->field.name); 1315eb9a42caSTom Zanussi arg->field.field->flags |= FIELD_IS_SYMBOLIC; 1316eb9a42caSTom Zanussi is_symbolic_field = 0; 1317eb9a42caSTom Zanussi } 1318eb9a42caSTom Zanussi 1319ea4010d1SSteven Rostedt type = read_token(&token); 1320ea4010d1SSteven Rostedt *tok = token; 1321ea4010d1SSteven Rostedt 1322ea4010d1SSteven Rostedt return type; 1323ea4010d1SSteven Rostedt 1324ea4010d1SSteven Rostedt fail: 1325ea4010d1SSteven Rostedt free_token(token); 1326ea4010d1SSteven Rostedt return EVENT_ERROR; 1327ea4010d1SSteven Rostedt } 1328ea4010d1SSteven Rostedt 1329ea4010d1SSteven Rostedt static char *arg_eval (struct print_arg *arg); 1330ea4010d1SSteven Rostedt 1331ea4010d1SSteven Rostedt static long long arg_num_eval(struct print_arg *arg) 1332ea4010d1SSteven Rostedt { 1333ea4010d1SSteven Rostedt long long left, right; 1334ea4010d1SSteven Rostedt long long val = 0; 1335ea4010d1SSteven Rostedt 1336ea4010d1SSteven Rostedt switch (arg->type) { 1337ea4010d1SSteven Rostedt case PRINT_ATOM: 1338ea4010d1SSteven Rostedt val = strtoll(arg->atom.atom, NULL, 0); 1339ea4010d1SSteven Rostedt break; 1340ea4010d1SSteven Rostedt case PRINT_TYPE: 1341ea4010d1SSteven Rostedt val = arg_num_eval(arg->typecast.item); 1342ea4010d1SSteven Rostedt break; 1343ea4010d1SSteven Rostedt case PRINT_OP: 1344ea4010d1SSteven Rostedt switch (arg->op.op[0]) { 1345ea4010d1SSteven Rostedt case '|': 1346ea4010d1SSteven Rostedt left = arg_num_eval(arg->op.left); 1347ea4010d1SSteven Rostedt right = arg_num_eval(arg->op.right); 1348ea4010d1SSteven Rostedt if (arg->op.op[1]) 1349ea4010d1SSteven Rostedt val = left || right; 1350ea4010d1SSteven Rostedt else 1351ea4010d1SSteven Rostedt val = left | right; 1352ea4010d1SSteven Rostedt break; 1353ea4010d1SSteven Rostedt case '&': 1354ea4010d1SSteven Rostedt left = arg_num_eval(arg->op.left); 1355ea4010d1SSteven Rostedt right = arg_num_eval(arg->op.right); 1356ea4010d1SSteven Rostedt if (arg->op.op[1]) 1357ea4010d1SSteven Rostedt val = left && right; 1358ea4010d1SSteven Rostedt else 1359ea4010d1SSteven Rostedt val = left & right; 1360ea4010d1SSteven Rostedt break; 1361ea4010d1SSteven Rostedt case '<': 1362ea4010d1SSteven Rostedt left = arg_num_eval(arg->op.left); 1363ea4010d1SSteven Rostedt right = arg_num_eval(arg->op.right); 1364ea4010d1SSteven Rostedt switch (arg->op.op[1]) { 1365ea4010d1SSteven Rostedt case 0: 1366ea4010d1SSteven Rostedt val = left < right; 1367ea4010d1SSteven Rostedt break; 1368ea4010d1SSteven Rostedt case '<': 1369ea4010d1SSteven Rostedt val = left << right; 1370ea4010d1SSteven Rostedt break; 1371ea4010d1SSteven Rostedt case '=': 1372ea4010d1SSteven Rostedt val = left <= right; 1373ea4010d1SSteven Rostedt break; 1374ea4010d1SSteven Rostedt default: 1375ea4010d1SSteven Rostedt die("unknown op '%s'", arg->op.op); 1376ea4010d1SSteven Rostedt } 1377ea4010d1SSteven Rostedt break; 1378ea4010d1SSteven Rostedt case '>': 1379ea4010d1SSteven Rostedt left = arg_num_eval(arg->op.left); 1380ea4010d1SSteven Rostedt right = arg_num_eval(arg->op.right); 1381ea4010d1SSteven Rostedt switch (arg->op.op[1]) { 1382ea4010d1SSteven Rostedt case 0: 1383ea4010d1SSteven Rostedt val = left > right; 1384ea4010d1SSteven Rostedt break; 1385ea4010d1SSteven Rostedt case '>': 1386ea4010d1SSteven Rostedt val = left >> right; 1387ea4010d1SSteven Rostedt break; 1388ea4010d1SSteven Rostedt case '=': 1389ea4010d1SSteven Rostedt val = left >= right; 1390ea4010d1SSteven Rostedt break; 1391ea4010d1SSteven Rostedt default: 1392ea4010d1SSteven Rostedt die("unknown op '%s'", arg->op.op); 1393ea4010d1SSteven Rostedt } 1394ea4010d1SSteven Rostedt break; 1395ea4010d1SSteven Rostedt case '=': 1396ea4010d1SSteven Rostedt left = arg_num_eval(arg->op.left); 1397ea4010d1SSteven Rostedt right = arg_num_eval(arg->op.right); 1398ea4010d1SSteven Rostedt 1399ea4010d1SSteven Rostedt if (arg->op.op[1] != '=') 1400ea4010d1SSteven Rostedt die("unknown op '%s'", arg->op.op); 1401ea4010d1SSteven Rostedt 1402ea4010d1SSteven Rostedt val = left == right; 1403ea4010d1SSteven Rostedt break; 1404ea4010d1SSteven Rostedt case '!': 1405ea4010d1SSteven Rostedt left = arg_num_eval(arg->op.left); 1406ea4010d1SSteven Rostedt right = arg_num_eval(arg->op.right); 1407ea4010d1SSteven Rostedt 1408ea4010d1SSteven Rostedt switch (arg->op.op[1]) { 1409ea4010d1SSteven Rostedt case '=': 1410ea4010d1SSteven Rostedt val = left != right; 1411ea4010d1SSteven Rostedt break; 1412ea4010d1SSteven Rostedt default: 1413ea4010d1SSteven Rostedt die("unknown op '%s'", arg->op.op); 1414ea4010d1SSteven Rostedt } 1415ea4010d1SSteven Rostedt break; 1416ea4010d1SSteven Rostedt default: 1417ea4010d1SSteven Rostedt die("unknown op '%s'", arg->op.op); 1418ea4010d1SSteven Rostedt } 1419ea4010d1SSteven Rostedt break; 1420ea4010d1SSteven Rostedt 1421ea4010d1SSteven Rostedt case PRINT_NULL: 1422ea4010d1SSteven Rostedt case PRINT_FIELD ... PRINT_SYMBOL: 1423ea4010d1SSteven Rostedt case PRINT_STRING: 1424ea4010d1SSteven Rostedt default: 1425ea4010d1SSteven Rostedt die("invalid eval type %d", arg->type); 1426ea4010d1SSteven Rostedt 1427ea4010d1SSteven Rostedt } 1428ea4010d1SSteven Rostedt return val; 1429ea4010d1SSteven Rostedt } 1430ea4010d1SSteven Rostedt 1431ea4010d1SSteven Rostedt static char *arg_eval (struct print_arg *arg) 1432ea4010d1SSteven Rostedt { 1433ea4010d1SSteven Rostedt long long val; 1434ea4010d1SSteven Rostedt static char buf[20]; 1435ea4010d1SSteven Rostedt 1436ea4010d1SSteven Rostedt switch (arg->type) { 1437ea4010d1SSteven Rostedt case PRINT_ATOM: 1438ea4010d1SSteven Rostedt return arg->atom.atom; 1439ea4010d1SSteven Rostedt case PRINT_TYPE: 1440ea4010d1SSteven Rostedt return arg_eval(arg->typecast.item); 1441ea4010d1SSteven Rostedt case PRINT_OP: 1442ea4010d1SSteven Rostedt val = arg_num_eval(arg); 1443ea4010d1SSteven Rostedt sprintf(buf, "%lld", val); 1444ea4010d1SSteven Rostedt return buf; 1445ea4010d1SSteven Rostedt 1446ea4010d1SSteven Rostedt case PRINT_NULL: 1447ea4010d1SSteven Rostedt case PRINT_FIELD ... PRINT_SYMBOL: 1448ea4010d1SSteven Rostedt case PRINT_STRING: 1449ea4010d1SSteven Rostedt default: 1450ea4010d1SSteven Rostedt die("invalid eval type %d", arg->type); 1451ea4010d1SSteven Rostedt break; 1452ea4010d1SSteven Rostedt } 1453ea4010d1SSteven Rostedt 1454ea4010d1SSteven Rostedt return NULL; 1455ea4010d1SSteven Rostedt } 1456ea4010d1SSteven Rostedt 1457ea4010d1SSteven Rostedt static enum event_type 1458ea4010d1SSteven Rostedt process_fields(struct event *event, struct print_flag_sym **list, char **tok) 1459ea4010d1SSteven Rostedt { 1460ea4010d1SSteven Rostedt enum event_type type; 1461ea4010d1SSteven Rostedt struct print_arg *arg = NULL; 1462ea4010d1SSteven Rostedt struct print_flag_sym *field; 1463ea4010d1SSteven Rostedt char *token = NULL; 1464ea4010d1SSteven Rostedt char *value; 1465ea4010d1SSteven Rostedt 1466ea4010d1SSteven Rostedt do { 1467ea4010d1SSteven Rostedt free_token(token); 1468ea4010d1SSteven Rostedt type = read_token_item(&token); 1469c4dc775fSSteven Rostedt if (test_type_token(type, token, EVENT_OP, "{")) 1470ea4010d1SSteven Rostedt break; 1471ea4010d1SSteven Rostedt 1472ea4010d1SSteven Rostedt arg = malloc_or_die(sizeof(*arg)); 1473ea4010d1SSteven Rostedt 1474ea4010d1SSteven Rostedt free_token(token); 1475ea4010d1SSteven Rostedt type = process_arg(event, arg, &token); 1476c4dc775fSSteven Rostedt if (test_type_token(type, token, EVENT_DELIM, ",")) 1477ea4010d1SSteven Rostedt goto out_free; 1478ea4010d1SSteven Rostedt 1479ea4010d1SSteven Rostedt field = malloc_or_die(sizeof(*field)); 14805660ce34SJulia Lawall memset(field, 0, sizeof(*field)); 1481ea4010d1SSteven Rostedt 1482ea4010d1SSteven Rostedt value = arg_eval(arg); 1483ea4010d1SSteven Rostedt field->value = strdup(value); 1484ea4010d1SSteven Rostedt 1485ea4010d1SSteven Rostedt free_token(token); 1486ea4010d1SSteven Rostedt type = process_arg(event, arg, &token); 1487c4dc775fSSteven Rostedt if (test_type_token(type, token, EVENT_OP, "}")) 1488ea4010d1SSteven Rostedt goto out_free; 1489ea4010d1SSteven Rostedt 1490ea4010d1SSteven Rostedt value = arg_eval(arg); 1491ea4010d1SSteven Rostedt field->str = strdup(value); 1492ea4010d1SSteven Rostedt free_arg(arg); 1493ea4010d1SSteven Rostedt arg = NULL; 1494ea4010d1SSteven Rostedt 1495ea4010d1SSteven Rostedt *list = field; 1496ea4010d1SSteven Rostedt list = &field->next; 1497ea4010d1SSteven Rostedt 1498ea4010d1SSteven Rostedt free_token(token); 1499ea4010d1SSteven Rostedt type = read_token_item(&token); 1500ea4010d1SSteven Rostedt } while (type == EVENT_DELIM && strcmp(token, ",") == 0); 1501ea4010d1SSteven Rostedt 1502ea4010d1SSteven Rostedt *tok = token; 1503ea4010d1SSteven Rostedt return type; 1504ea4010d1SSteven Rostedt 1505ea4010d1SSteven Rostedt out_free: 1506ea4010d1SSteven Rostedt free_arg(arg); 1507ea4010d1SSteven Rostedt free_token(token); 1508ea4010d1SSteven Rostedt 1509ea4010d1SSteven Rostedt return EVENT_ERROR; 1510ea4010d1SSteven Rostedt } 1511ea4010d1SSteven Rostedt 1512ea4010d1SSteven Rostedt static enum event_type 1513ea4010d1SSteven Rostedt process_flags(struct event *event, struct print_arg *arg, char **tok) 1514ea4010d1SSteven Rostedt { 1515ea4010d1SSteven Rostedt struct print_arg *field; 1516ea4010d1SSteven Rostedt enum event_type type; 1517ea4010d1SSteven Rostedt char *token; 1518ea4010d1SSteven Rostedt 1519ea4010d1SSteven Rostedt memset(arg, 0, sizeof(*arg)); 1520ea4010d1SSteven Rostedt arg->type = PRINT_FLAGS; 1521ea4010d1SSteven Rostedt 1522c4dc775fSSteven Rostedt if (read_expected_item(EVENT_DELIM, "(") < 0) 1523ea4010d1SSteven Rostedt return EVENT_ERROR; 1524ea4010d1SSteven Rostedt 1525ea4010d1SSteven Rostedt field = malloc_or_die(sizeof(*field)); 1526ea4010d1SSteven Rostedt 1527ea4010d1SSteven Rostedt type = process_arg(event, field, &token); 1528c4dc775fSSteven Rostedt if (test_type_token(type, token, EVENT_DELIM, ",")) 1529ea4010d1SSteven Rostedt goto out_free; 1530ea4010d1SSteven Rostedt 1531ea4010d1SSteven Rostedt arg->flags.field = field; 1532ea4010d1SSteven Rostedt 1533ea4010d1SSteven Rostedt type = read_token_item(&token); 1534ea4010d1SSteven Rostedt if (event_item_type(type)) { 1535ea4010d1SSteven Rostedt arg->flags.delim = token; 1536ea4010d1SSteven Rostedt type = read_token_item(&token); 1537ea4010d1SSteven Rostedt } 1538ea4010d1SSteven Rostedt 1539c4dc775fSSteven Rostedt if (test_type_token(type, token, EVENT_DELIM, ",")) 1540ea4010d1SSteven Rostedt goto out_free; 1541ea4010d1SSteven Rostedt 1542ea4010d1SSteven Rostedt type = process_fields(event, &arg->flags.flags, &token); 1543c4dc775fSSteven Rostedt if (test_type_token(type, token, EVENT_DELIM, ")")) 1544ea4010d1SSteven Rostedt goto out_free; 1545ea4010d1SSteven Rostedt 1546ea4010d1SSteven Rostedt free_token(token); 1547ea4010d1SSteven Rostedt type = read_token_item(tok); 1548ea4010d1SSteven Rostedt return type; 1549ea4010d1SSteven Rostedt 1550ea4010d1SSteven Rostedt out_free: 1551ea4010d1SSteven Rostedt free_token(token); 1552ea4010d1SSteven Rostedt return EVENT_ERROR; 1553ea4010d1SSteven Rostedt } 1554ea4010d1SSteven Rostedt 1555ea4010d1SSteven Rostedt static enum event_type 1556ea4010d1SSteven Rostedt process_symbols(struct event *event, struct print_arg *arg, char **tok) 1557ea4010d1SSteven Rostedt { 1558ea4010d1SSteven Rostedt struct print_arg *field; 1559ea4010d1SSteven Rostedt enum event_type type; 1560ea4010d1SSteven Rostedt char *token; 1561ea4010d1SSteven Rostedt 1562ea4010d1SSteven Rostedt memset(arg, 0, sizeof(*arg)); 1563ea4010d1SSteven Rostedt arg->type = PRINT_SYMBOL; 1564ea4010d1SSteven Rostedt 1565c4dc775fSSteven Rostedt if (read_expected_item(EVENT_DELIM, "(") < 0) 1566ea4010d1SSteven Rostedt return EVENT_ERROR; 1567ea4010d1SSteven Rostedt 1568ea4010d1SSteven Rostedt field = malloc_or_die(sizeof(*field)); 1569ea4010d1SSteven Rostedt 1570ea4010d1SSteven Rostedt type = process_arg(event, field, &token); 1571c4dc775fSSteven Rostedt if (test_type_token(type, token, EVENT_DELIM, ",")) 1572ea4010d1SSteven Rostedt goto out_free; 1573ea4010d1SSteven Rostedt 1574ea4010d1SSteven Rostedt arg->symbol.field = field; 1575ea4010d1SSteven Rostedt 1576ea4010d1SSteven Rostedt type = process_fields(event, &arg->symbol.symbols, &token); 1577c4dc775fSSteven Rostedt if (test_type_token(type, token, EVENT_DELIM, ")")) 1578ea4010d1SSteven Rostedt goto out_free; 1579ea4010d1SSteven Rostedt 1580ea4010d1SSteven Rostedt free_token(token); 1581ea4010d1SSteven Rostedt type = read_token_item(tok); 1582ea4010d1SSteven Rostedt return type; 1583ea4010d1SSteven Rostedt 1584ea4010d1SSteven Rostedt out_free: 1585ea4010d1SSteven Rostedt free_token(token); 1586ea4010d1SSteven Rostedt return EVENT_ERROR; 1587ea4010d1SSteven Rostedt } 1588ea4010d1SSteven Rostedt 1589ea4010d1SSteven Rostedt static enum event_type 1590ea4010d1SSteven Rostedt process_paren(struct event *event, struct print_arg *arg, char **tok) 1591ea4010d1SSteven Rostedt { 1592ea4010d1SSteven Rostedt struct print_arg *item_arg; 1593ea4010d1SSteven Rostedt enum event_type type; 1594ea4010d1SSteven Rostedt char *token; 1595ea4010d1SSteven Rostedt 1596ea4010d1SSteven Rostedt type = process_arg(event, arg, &token); 1597ea4010d1SSteven Rostedt 1598ea4010d1SSteven Rostedt if (type == EVENT_ERROR) 1599ea4010d1SSteven Rostedt return EVENT_ERROR; 1600ea4010d1SSteven Rostedt 1601b99af874SSteven Rostedt if (type == EVENT_OP) 1602ea4010d1SSteven Rostedt type = process_op(event, arg, &token); 1603ea4010d1SSteven Rostedt 1604ea4010d1SSteven Rostedt if (type == EVENT_ERROR) 1605ea4010d1SSteven Rostedt return EVENT_ERROR; 1606ea4010d1SSteven Rostedt 1607c4dc775fSSteven Rostedt if (test_type_token(type, token, EVENT_DELIM, ")")) { 1608ea4010d1SSteven Rostedt free_token(token); 1609ea4010d1SSteven Rostedt return EVENT_ERROR; 1610ea4010d1SSteven Rostedt } 1611ea4010d1SSteven Rostedt 1612ea4010d1SSteven Rostedt free_token(token); 1613ea4010d1SSteven Rostedt type = read_token_item(&token); 1614ea4010d1SSteven Rostedt 1615ea4010d1SSteven Rostedt /* 1616ea4010d1SSteven Rostedt * If the next token is an item or another open paren, then 1617ea4010d1SSteven Rostedt * this was a typecast. 1618ea4010d1SSteven Rostedt */ 1619ea4010d1SSteven Rostedt if (event_item_type(type) || 1620ea4010d1SSteven Rostedt (type == EVENT_DELIM && strcmp(token, "(") == 0)) { 1621ea4010d1SSteven Rostedt 1622ea4010d1SSteven Rostedt /* make this a typecast and contine */ 1623ea4010d1SSteven Rostedt 1624ea4010d1SSteven Rostedt /* prevous must be an atom */ 1625ea4010d1SSteven Rostedt if (arg->type != PRINT_ATOM) 1626ea4010d1SSteven Rostedt die("previous needed to be PRINT_ATOM"); 1627ea4010d1SSteven Rostedt 1628ea4010d1SSteven Rostedt item_arg = malloc_or_die(sizeof(*item_arg)); 1629ea4010d1SSteven Rostedt 1630ea4010d1SSteven Rostedt arg->type = PRINT_TYPE; 1631ea4010d1SSteven Rostedt arg->typecast.type = arg->atom.atom; 1632ea4010d1SSteven Rostedt arg->typecast.item = item_arg; 1633ea4010d1SSteven Rostedt type = process_arg_token(event, item_arg, &token, type); 1634ea4010d1SSteven Rostedt 1635ea4010d1SSteven Rostedt } 1636ea4010d1SSteven Rostedt 1637ea4010d1SSteven Rostedt *tok = token; 1638ea4010d1SSteven Rostedt return type; 1639ea4010d1SSteven Rostedt } 1640ea4010d1SSteven Rostedt 1641ea4010d1SSteven Rostedt 1642ea4010d1SSteven Rostedt static enum event_type 1643ea4010d1SSteven Rostedt process_str(struct event *event __unused, struct print_arg *arg, char **tok) 1644ea4010d1SSteven Rostedt { 1645ea4010d1SSteven Rostedt enum event_type type; 1646ea4010d1SSteven Rostedt char *token; 1647ea4010d1SSteven Rostedt 1648c4dc775fSSteven Rostedt if (read_expected(EVENT_DELIM, "(") < 0) 1649ea4010d1SSteven Rostedt return EVENT_ERROR; 1650ea4010d1SSteven Rostedt 1651ea4010d1SSteven Rostedt if (read_expect_type(EVENT_ITEM, &token) < 0) 1652ea4010d1SSteven Rostedt goto fail; 1653ea4010d1SSteven Rostedt 1654ea4010d1SSteven Rostedt arg->type = PRINT_STRING; 1655ea4010d1SSteven Rostedt arg->string.string = token; 1656561f732cSFrederic Weisbecker arg->string.offset = -1; 1657ea4010d1SSteven Rostedt 1658c4dc775fSSteven Rostedt if (read_expected(EVENT_DELIM, ")") < 0) 1659ea4010d1SSteven Rostedt return EVENT_ERROR; 1660ea4010d1SSteven Rostedt 1661ea4010d1SSteven Rostedt type = read_token(&token); 1662ea4010d1SSteven Rostedt *tok = token; 1663ea4010d1SSteven Rostedt 1664ea4010d1SSteven Rostedt return type; 1665ea4010d1SSteven Rostedt fail: 1666ea4010d1SSteven Rostedt free_token(token); 1667ea4010d1SSteven Rostedt return EVENT_ERROR; 1668ea4010d1SSteven Rostedt } 1669ea4010d1SSteven Rostedt 1670ea4010d1SSteven Rostedt enum event_type 1671ea4010d1SSteven Rostedt process_arg_token(struct event *event, struct print_arg *arg, 1672ea4010d1SSteven Rostedt char **tok, enum event_type type) 1673ea4010d1SSteven Rostedt { 1674ea4010d1SSteven Rostedt char *token; 1675ea4010d1SSteven Rostedt char *atom; 1676ea4010d1SSteven Rostedt 1677ea4010d1SSteven Rostedt token = *tok; 1678ea4010d1SSteven Rostedt 1679ea4010d1SSteven Rostedt switch (type) { 1680ea4010d1SSteven Rostedt case EVENT_ITEM: 1681ea4010d1SSteven Rostedt if (strcmp(token, "REC") == 0) { 1682ea4010d1SSteven Rostedt free_token(token); 1683ea4010d1SSteven Rostedt type = process_entry(event, arg, &token); 1684ea4010d1SSteven Rostedt } else if (strcmp(token, "__print_flags") == 0) { 1685ea4010d1SSteven Rostedt free_token(token); 1686eb9a42caSTom Zanussi is_flag_field = 1; 1687ea4010d1SSteven Rostedt type = process_flags(event, arg, &token); 1688ea4010d1SSteven Rostedt } else if (strcmp(token, "__print_symbolic") == 0) { 1689ea4010d1SSteven Rostedt free_token(token); 1690eb9a42caSTom Zanussi is_symbolic_field = 1; 1691ea4010d1SSteven Rostedt type = process_symbols(event, arg, &token); 1692ea4010d1SSteven Rostedt } else if (strcmp(token, "__get_str") == 0) { 1693ea4010d1SSteven Rostedt free_token(token); 1694ea4010d1SSteven Rostedt type = process_str(event, arg, &token); 1695ea4010d1SSteven Rostedt } else { 1696ea4010d1SSteven Rostedt atom = token; 1697ea4010d1SSteven Rostedt /* test the next token */ 1698ea4010d1SSteven Rostedt type = read_token_item(&token); 1699ea4010d1SSteven Rostedt 1700ea4010d1SSteven Rostedt /* atoms can be more than one token long */ 1701ea4010d1SSteven Rostedt while (type == EVENT_ITEM) { 1702ea4010d1SSteven Rostedt atom = realloc(atom, strlen(atom) + strlen(token) + 2); 1703ea4010d1SSteven Rostedt strcat(atom, " "); 1704ea4010d1SSteven Rostedt strcat(atom, token); 1705ea4010d1SSteven Rostedt free_token(token); 1706ea4010d1SSteven Rostedt type = read_token_item(&token); 1707ea4010d1SSteven Rostedt } 1708ea4010d1SSteven Rostedt 1709ea4010d1SSteven Rostedt /* todo, test for function */ 1710ea4010d1SSteven Rostedt 1711ea4010d1SSteven Rostedt arg->type = PRINT_ATOM; 1712ea4010d1SSteven Rostedt arg->atom.atom = atom; 1713ea4010d1SSteven Rostedt } 1714ea4010d1SSteven Rostedt break; 1715ea4010d1SSteven Rostedt case EVENT_DQUOTE: 1716ea4010d1SSteven Rostedt case EVENT_SQUOTE: 1717ea4010d1SSteven Rostedt arg->type = PRINT_ATOM; 1718ea4010d1SSteven Rostedt arg->atom.atom = token; 1719ea4010d1SSteven Rostedt type = read_token_item(&token); 1720ea4010d1SSteven Rostedt break; 1721ea4010d1SSteven Rostedt case EVENT_DELIM: 1722ea4010d1SSteven Rostedt if (strcmp(token, "(") == 0) { 1723ea4010d1SSteven Rostedt free_token(token); 1724ea4010d1SSteven Rostedt type = process_paren(event, arg, &token); 1725ea4010d1SSteven Rostedt break; 1726ea4010d1SSteven Rostedt } 1727ea4010d1SSteven Rostedt case EVENT_OP: 1728ea4010d1SSteven Rostedt /* handle single ops */ 1729ea4010d1SSteven Rostedt arg->type = PRINT_OP; 1730ea4010d1SSteven Rostedt arg->op.op = token; 1731ea4010d1SSteven Rostedt arg->op.left = NULL; 1732ea4010d1SSteven Rostedt type = process_op(event, arg, &token); 1733ea4010d1SSteven Rostedt 1734ea4010d1SSteven Rostedt break; 1735ea4010d1SSteven Rostedt 1736ea4010d1SSteven Rostedt case EVENT_ERROR ... EVENT_NEWLINE: 1737ea4010d1SSteven Rostedt default: 1738ea4010d1SSteven Rostedt die("unexpected type %d", type); 1739ea4010d1SSteven Rostedt } 1740ea4010d1SSteven Rostedt *tok = token; 1741ea4010d1SSteven Rostedt 1742ea4010d1SSteven Rostedt return type; 1743ea4010d1SSteven Rostedt } 1744ea4010d1SSteven Rostedt 1745ea4010d1SSteven Rostedt static int event_read_print_args(struct event *event, struct print_arg **list) 1746ea4010d1SSteven Rostedt { 1747f1d1feecSSteven Rostedt enum event_type type = EVENT_ERROR; 1748ea4010d1SSteven Rostedt struct print_arg *arg; 1749ea4010d1SSteven Rostedt char *token; 1750ea4010d1SSteven Rostedt int args = 0; 1751ea4010d1SSteven Rostedt 1752ea4010d1SSteven Rostedt do { 1753f1d1feecSSteven Rostedt if (type == EVENT_NEWLINE) { 1754f1d1feecSSteven Rostedt free_token(token); 1755f1d1feecSSteven Rostedt type = read_token_item(&token); 1756f1d1feecSSteven Rostedt continue; 1757f1d1feecSSteven Rostedt } 1758f1d1feecSSteven Rostedt 1759ea4010d1SSteven Rostedt arg = malloc_or_die(sizeof(*arg)); 1760ea4010d1SSteven Rostedt memset(arg, 0, sizeof(*arg)); 1761ea4010d1SSteven Rostedt 1762ea4010d1SSteven Rostedt type = process_arg(event, arg, &token); 1763ea4010d1SSteven Rostedt 1764ea4010d1SSteven Rostedt if (type == EVENT_ERROR) { 1765ea4010d1SSteven Rostedt free_arg(arg); 1766ea4010d1SSteven Rostedt return -1; 1767ea4010d1SSteven Rostedt } 1768ea4010d1SSteven Rostedt 1769ea4010d1SSteven Rostedt *list = arg; 1770ea4010d1SSteven Rostedt args++; 1771ea4010d1SSteven Rostedt 1772ea4010d1SSteven Rostedt if (type == EVENT_OP) { 1773ea4010d1SSteven Rostedt type = process_op(event, arg, &token); 1774ea4010d1SSteven Rostedt list = &arg->next; 1775ea4010d1SSteven Rostedt continue; 1776ea4010d1SSteven Rostedt } 1777ea4010d1SSteven Rostedt 1778ea4010d1SSteven Rostedt if (type == EVENT_DELIM && strcmp(token, ",") == 0) { 1779ea4010d1SSteven Rostedt free_token(token); 1780ea4010d1SSteven Rostedt *list = arg; 1781ea4010d1SSteven Rostedt list = &arg->next; 1782ea4010d1SSteven Rostedt continue; 1783ea4010d1SSteven Rostedt } 1784ea4010d1SSteven Rostedt break; 1785ea4010d1SSteven Rostedt } while (type != EVENT_NONE); 1786ea4010d1SSteven Rostedt 1787ea4010d1SSteven Rostedt if (type != EVENT_NONE) 1788ea4010d1SSteven Rostedt free_token(token); 1789ea4010d1SSteven Rostedt 1790ea4010d1SSteven Rostedt return args; 1791ea4010d1SSteven Rostedt } 1792ea4010d1SSteven Rostedt 1793ea4010d1SSteven Rostedt static int event_read_print(struct event *event) 1794ea4010d1SSteven Rostedt { 1795ea4010d1SSteven Rostedt enum event_type type; 1796ea4010d1SSteven Rostedt char *token; 1797ea4010d1SSteven Rostedt int ret; 1798ea4010d1SSteven Rostedt 1799c4dc775fSSteven Rostedt if (read_expected_item(EVENT_ITEM, "print") < 0) 1800ea4010d1SSteven Rostedt return -1; 1801ea4010d1SSteven Rostedt 1802c4dc775fSSteven Rostedt if (read_expected(EVENT_ITEM, "fmt") < 0) 1803ea4010d1SSteven Rostedt return -1; 1804ea4010d1SSteven Rostedt 1805c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ":") < 0) 1806ea4010d1SSteven Rostedt return -1; 1807ea4010d1SSteven Rostedt 1808ea4010d1SSteven Rostedt if (read_expect_type(EVENT_DQUOTE, &token) < 0) 1809ea4010d1SSteven Rostedt goto fail; 1810ea4010d1SSteven Rostedt 1811924a79afSSteven Rostedt concat: 1812ea4010d1SSteven Rostedt event->print_fmt.format = token; 1813ea4010d1SSteven Rostedt event->print_fmt.args = NULL; 1814ea4010d1SSteven Rostedt 1815ea4010d1SSteven Rostedt /* ok to have no arg */ 1816ea4010d1SSteven Rostedt type = read_token_item(&token); 1817ea4010d1SSteven Rostedt 1818ea4010d1SSteven Rostedt if (type == EVENT_NONE) 1819ea4010d1SSteven Rostedt return 0; 1820ea4010d1SSteven Rostedt 1821924a79afSSteven Rostedt /* Handle concatination of print lines */ 1822924a79afSSteven Rostedt if (type == EVENT_DQUOTE) { 1823924a79afSSteven Rostedt char *cat; 1824924a79afSSteven Rostedt 1825924a79afSSteven Rostedt cat = malloc_or_die(strlen(event->print_fmt.format) + 1826924a79afSSteven Rostedt strlen(token) + 1); 1827924a79afSSteven Rostedt strcpy(cat, event->print_fmt.format); 1828924a79afSSteven Rostedt strcat(cat, token); 1829924a79afSSteven Rostedt free_token(token); 1830924a79afSSteven Rostedt free_token(event->print_fmt.format); 1831924a79afSSteven Rostedt event->print_fmt.format = NULL; 1832924a79afSSteven Rostedt token = cat; 1833924a79afSSteven Rostedt goto concat; 1834924a79afSSteven Rostedt } 1835924a79afSSteven Rostedt 1836c4dc775fSSteven Rostedt if (test_type_token(type, token, EVENT_DELIM, ",")) 1837ea4010d1SSteven Rostedt goto fail; 1838ea4010d1SSteven Rostedt 1839ea4010d1SSteven Rostedt free_token(token); 1840ea4010d1SSteven Rostedt 1841ea4010d1SSteven Rostedt ret = event_read_print_args(event, &event->print_fmt.args); 1842ea4010d1SSteven Rostedt if (ret < 0) 1843ea4010d1SSteven Rostedt return -1; 1844ea4010d1SSteven Rostedt 18450d1da915SSteven Rostedt return ret; 1846ea4010d1SSteven Rostedt 1847ea4010d1SSteven Rostedt fail: 1848ea4010d1SSteven Rostedt free_token(token); 1849ea4010d1SSteven Rostedt return -1; 1850ea4010d1SSteven Rostedt } 1851ea4010d1SSteven Rostedt 1852ea4010d1SSteven Rostedt static struct format_field * 1853ea4010d1SSteven Rostedt find_common_field(struct event *event, const char *name) 1854ea4010d1SSteven Rostedt { 1855ea4010d1SSteven Rostedt struct format_field *format; 1856ea4010d1SSteven Rostedt 1857ea4010d1SSteven Rostedt for (format = event->format.common_fields; 1858ea4010d1SSteven Rostedt format; format = format->next) { 1859ea4010d1SSteven Rostedt if (strcmp(format->name, name) == 0) 1860ea4010d1SSteven Rostedt break; 1861ea4010d1SSteven Rostedt } 1862ea4010d1SSteven Rostedt 1863ea4010d1SSteven Rostedt return format; 1864ea4010d1SSteven Rostedt } 1865ea4010d1SSteven Rostedt 1866ea4010d1SSteven Rostedt static struct format_field * 1867ea4010d1SSteven Rostedt find_field(struct event *event, const char *name) 1868ea4010d1SSteven Rostedt { 1869ea4010d1SSteven Rostedt struct format_field *format; 1870ea4010d1SSteven Rostedt 1871ea4010d1SSteven Rostedt for (format = event->format.fields; 1872ea4010d1SSteven Rostedt format; format = format->next) { 1873ea4010d1SSteven Rostedt if (strcmp(format->name, name) == 0) 1874ea4010d1SSteven Rostedt break; 1875ea4010d1SSteven Rostedt } 1876ea4010d1SSteven Rostedt 1877ea4010d1SSteven Rostedt return format; 1878ea4010d1SSteven Rostedt } 1879ea4010d1SSteven Rostedt 1880ea4010d1SSteven Rostedt static struct format_field * 1881ea4010d1SSteven Rostedt find_any_field(struct event *event, const char *name) 1882ea4010d1SSteven Rostedt { 1883ea4010d1SSteven Rostedt struct format_field *format; 1884ea4010d1SSteven Rostedt 1885ea4010d1SSteven Rostedt format = find_common_field(event, name); 1886ea4010d1SSteven Rostedt if (format) 1887ea4010d1SSteven Rostedt return format; 1888ea4010d1SSteven Rostedt return find_field(event, name); 1889ea4010d1SSteven Rostedt } 1890ea4010d1SSteven Rostedt 189116c632deSTom Zanussi unsigned long long read_size(void *ptr, int size) 1892ea4010d1SSteven Rostedt { 1893ea4010d1SSteven Rostedt switch (size) { 1894ea4010d1SSteven Rostedt case 1: 1895ea4010d1SSteven Rostedt return *(unsigned char *)ptr; 1896ea4010d1SSteven Rostedt case 2: 1897ea4010d1SSteven Rostedt return data2host2(ptr); 1898ea4010d1SSteven Rostedt case 4: 1899ea4010d1SSteven Rostedt return data2host4(ptr); 1900ea4010d1SSteven Rostedt case 8: 1901ea4010d1SSteven Rostedt return data2host8(ptr); 1902ea4010d1SSteven Rostedt default: 1903ea4010d1SSteven Rostedt /* BUG! */ 1904ea4010d1SSteven Rostedt return 0; 1905ea4010d1SSteven Rostedt } 1906ea4010d1SSteven Rostedt } 1907ea4010d1SSteven Rostedt 190846538818SFrederic Weisbecker unsigned long long 190946538818SFrederic Weisbecker raw_field_value(struct event *event, const char *name, void *data) 191046538818SFrederic Weisbecker { 191146538818SFrederic Weisbecker struct format_field *field; 191246538818SFrederic Weisbecker 191346538818SFrederic Weisbecker field = find_any_field(event, name); 191446538818SFrederic Weisbecker if (!field) 191546538818SFrederic Weisbecker return 0ULL; 191646538818SFrederic Weisbecker 191746538818SFrederic Weisbecker return read_size(data + field->offset, field->size); 191846538818SFrederic Weisbecker } 191946538818SFrederic Weisbecker 192046538818SFrederic Weisbecker void *raw_field_ptr(struct event *event, const char *name, void *data) 192146538818SFrederic Weisbecker { 192246538818SFrederic Weisbecker struct format_field *field; 192346538818SFrederic Weisbecker 192446538818SFrederic Weisbecker field = find_any_field(event, name); 192546538818SFrederic Weisbecker if (!field) 192646538818SFrederic Weisbecker return NULL; 192746538818SFrederic Weisbecker 192886d8d296SHitoshi Mitake if (field->flags & FIELD_IS_STRING) { 192986d8d296SHitoshi Mitake int offset; 193086d8d296SHitoshi Mitake 193186d8d296SHitoshi Mitake offset = *(int *)(data + field->offset); 193286d8d296SHitoshi Mitake offset &= 0xffff; 193386d8d296SHitoshi Mitake 193486d8d296SHitoshi Mitake return data + offset; 193586d8d296SHitoshi Mitake } 193686d8d296SHitoshi Mitake 193746538818SFrederic Weisbecker return data + field->offset; 193846538818SFrederic Weisbecker } 193946538818SFrederic Weisbecker 1940ea4010d1SSteven Rostedt static int get_common_info(const char *type, int *offset, int *size) 1941ea4010d1SSteven Rostedt { 1942ea4010d1SSteven Rostedt struct event *event; 1943ea4010d1SSteven Rostedt struct format_field *field; 1944ea4010d1SSteven Rostedt 1945ea4010d1SSteven Rostedt /* 1946ea4010d1SSteven Rostedt * All events should have the same common elements. 1947ea4010d1SSteven Rostedt * Pick any event to find where the type is; 1948ea4010d1SSteven Rostedt */ 1949ea4010d1SSteven Rostedt if (!event_list) 1950ea4010d1SSteven Rostedt die("no event_list!"); 1951ea4010d1SSteven Rostedt 1952ea4010d1SSteven Rostedt event = event_list; 1953ea4010d1SSteven Rostedt field = find_common_field(event, type); 1954ea4010d1SSteven Rostedt if (!field) 1955ea4010d1SSteven Rostedt die("field '%s' not found", type); 1956ea4010d1SSteven Rostedt 1957ea4010d1SSteven Rostedt *offset = field->offset; 1958ea4010d1SSteven Rostedt *size = field->size; 1959ea4010d1SSteven Rostedt 1960ea4010d1SSteven Rostedt return 0; 1961ea4010d1SSteven Rostedt } 1962ea4010d1SSteven Rostedt 1963cda48461SSteven Rostedt static int __parse_common(void *data, int *size, int *offset, 1964c4dc775fSSteven Rostedt const char *name) 1965cda48461SSteven Rostedt { 1966cda48461SSteven Rostedt int ret; 1967cda48461SSteven Rostedt 1968cda48461SSteven Rostedt if (!*size) { 1969cda48461SSteven Rostedt ret = get_common_info(name, offset, size); 1970cda48461SSteven Rostedt if (ret < 0) 1971cda48461SSteven Rostedt return ret; 1972cda48461SSteven Rostedt } 1973cda48461SSteven Rostedt return read_size(data + *offset, *size); 1974cda48461SSteven Rostedt } 1975cda48461SSteven Rostedt 1976ec156764SIngo Molnar int trace_parse_common_type(void *data) 1977ea4010d1SSteven Rostedt { 1978ea4010d1SSteven Rostedt static int type_offset; 1979ea4010d1SSteven Rostedt static int type_size; 1980ea4010d1SSteven Rostedt 1981cda48461SSteven Rostedt return __parse_common(data, &type_size, &type_offset, 1982c4dc775fSSteven Rostedt "common_type"); 1983ea4010d1SSteven Rostedt } 1984ea4010d1SSteven Rostedt 198516c632deSTom Zanussi int trace_parse_common_pid(void *data) 1986ea4010d1SSteven Rostedt { 1987ea4010d1SSteven Rostedt static int pid_offset; 1988ea4010d1SSteven Rostedt static int pid_size; 1989ea4010d1SSteven Rostedt 1990cda48461SSteven Rostedt return __parse_common(data, &pid_size, &pid_offset, 1991c4dc775fSSteven Rostedt "common_pid"); 1992ea4010d1SSteven Rostedt } 1993ea4010d1SSteven Rostedt 1994d1b93772STom Zanussi int parse_common_pc(void *data) 1995cda48461SSteven Rostedt { 1996cda48461SSteven Rostedt static int pc_offset; 1997cda48461SSteven Rostedt static int pc_size; 1998cda48461SSteven Rostedt 1999cda48461SSteven Rostedt return __parse_common(data, &pc_size, &pc_offset, 2000c4dc775fSSteven Rostedt "common_preempt_count"); 2001cda48461SSteven Rostedt } 2002cda48461SSteven Rostedt 2003d1b93772STom Zanussi int parse_common_flags(void *data) 2004cda48461SSteven Rostedt { 2005cda48461SSteven Rostedt static int flags_offset; 2006cda48461SSteven Rostedt static int flags_size; 2007cda48461SSteven Rostedt 2008cda48461SSteven Rostedt return __parse_common(data, &flags_size, &flags_offset, 2009c4dc775fSSteven Rostedt "common_flags"); 2010cda48461SSteven Rostedt } 2011cda48461SSteven Rostedt 2012d1b93772STom Zanussi int parse_common_lock_depth(void *data) 2013cda48461SSteven Rostedt { 2014cda48461SSteven Rostedt static int ld_offset; 2015cda48461SSteven Rostedt static int ld_size; 2016cda48461SSteven Rostedt int ret; 2017cda48461SSteven Rostedt 2018cda48461SSteven Rostedt ret = __parse_common(data, &ld_size, &ld_offset, 2019c4dc775fSSteven Rostedt "common_lock_depth"); 2020cda48461SSteven Rostedt if (ret < 0) 2021cda48461SSteven Rostedt return -1; 2022cda48461SSteven Rostedt 2023cda48461SSteven Rostedt return ret; 2024ea4010d1SSteven Rostedt } 2025ea4010d1SSteven Rostedt 2026ec156764SIngo Molnar struct event *trace_find_event(int id) 2027ea4010d1SSteven Rostedt { 2028ea4010d1SSteven Rostedt struct event *event; 2029ea4010d1SSteven Rostedt 2030ea4010d1SSteven Rostedt for (event = event_list; event; event = event->next) { 2031ea4010d1SSteven Rostedt if (event->id == id) 2032ea4010d1SSteven Rostedt break; 2033ea4010d1SSteven Rostedt } 2034ea4010d1SSteven Rostedt return event; 2035ea4010d1SSteven Rostedt } 2036ea4010d1SSteven Rostedt 203716c632deSTom Zanussi struct event *trace_find_next_event(struct event *event) 203816c632deSTom Zanussi { 203916c632deSTom Zanussi if (!event) 204016c632deSTom Zanussi return event_list; 204116c632deSTom Zanussi 204216c632deSTom Zanussi return event->next; 204316c632deSTom Zanussi } 204416c632deSTom Zanussi 2045ea4010d1SSteven Rostedt static unsigned long long eval_num_arg(void *data, int size, 2046ea4010d1SSteven Rostedt struct event *event, struct print_arg *arg) 2047ea4010d1SSteven Rostedt { 2048ea4010d1SSteven Rostedt unsigned long long val = 0; 2049ea4010d1SSteven Rostedt unsigned long long left, right; 20500959b8d6SSteven Rostedt struct print_arg *larg; 2051ea4010d1SSteven Rostedt 2052ea4010d1SSteven Rostedt switch (arg->type) { 2053ea4010d1SSteven Rostedt case PRINT_NULL: 2054ea4010d1SSteven Rostedt /* ?? */ 2055ea4010d1SSteven Rostedt return 0; 2056ea4010d1SSteven Rostedt case PRINT_ATOM: 2057ea4010d1SSteven Rostedt return strtoull(arg->atom.atom, NULL, 0); 2058ea4010d1SSteven Rostedt case PRINT_FIELD: 2059ea4010d1SSteven Rostedt if (!arg->field.field) { 2060ea4010d1SSteven Rostedt arg->field.field = find_any_field(event, arg->field.name); 2061ea4010d1SSteven Rostedt if (!arg->field.field) 2062ea4010d1SSteven Rostedt die("field %s not found", arg->field.name); 2063ea4010d1SSteven Rostedt } 2064ea4010d1SSteven Rostedt /* must be a number */ 2065ea4010d1SSteven Rostedt val = read_size(data + arg->field.field->offset, 2066ea4010d1SSteven Rostedt arg->field.field->size); 2067ea4010d1SSteven Rostedt break; 2068ea4010d1SSteven Rostedt case PRINT_FLAGS: 2069ea4010d1SSteven Rostedt case PRINT_SYMBOL: 2070ea4010d1SSteven Rostedt break; 2071ea4010d1SSteven Rostedt case PRINT_TYPE: 2072ea4010d1SSteven Rostedt return eval_num_arg(data, size, event, arg->typecast.item); 2073ea4010d1SSteven Rostedt case PRINT_STRING: 2074ea4010d1SSteven Rostedt return 0; 2075ea4010d1SSteven Rostedt break; 2076ea4010d1SSteven Rostedt case PRINT_OP: 20770959b8d6SSteven Rostedt if (strcmp(arg->op.op, "[") == 0) { 20780959b8d6SSteven Rostedt /* 20790959b8d6SSteven Rostedt * Arrays are special, since we don't want 20800959b8d6SSteven Rostedt * to read the arg as is. 20810959b8d6SSteven Rostedt */ 20820959b8d6SSteven Rostedt if (arg->op.left->type != PRINT_FIELD) 20830959b8d6SSteven Rostedt goto default_op; /* oops, all bets off */ 20840959b8d6SSteven Rostedt larg = arg->op.left; 20850959b8d6SSteven Rostedt if (!larg->field.field) { 20860959b8d6SSteven Rostedt larg->field.field = 20870959b8d6SSteven Rostedt find_any_field(event, larg->field.name); 20880959b8d6SSteven Rostedt if (!larg->field.field) 20890959b8d6SSteven Rostedt die("field %s not found", larg->field.name); 20900959b8d6SSteven Rostedt } 20910959b8d6SSteven Rostedt right = eval_num_arg(data, size, event, arg->op.right); 20920959b8d6SSteven Rostedt val = read_size(data + larg->field.field->offset + 20930959b8d6SSteven Rostedt right * long_size, long_size); 20940959b8d6SSteven Rostedt break; 20950959b8d6SSteven Rostedt } 20960959b8d6SSteven Rostedt default_op: 2097ea4010d1SSteven Rostedt left = eval_num_arg(data, size, event, arg->op.left); 2098ea4010d1SSteven Rostedt right = eval_num_arg(data, size, event, arg->op.right); 2099ea4010d1SSteven Rostedt switch (arg->op.op[0]) { 2100ea4010d1SSteven Rostedt case '|': 2101ea4010d1SSteven Rostedt if (arg->op.op[1]) 2102ea4010d1SSteven Rostedt val = left || right; 2103ea4010d1SSteven Rostedt else 2104ea4010d1SSteven Rostedt val = left | right; 2105ea4010d1SSteven Rostedt break; 2106ea4010d1SSteven Rostedt case '&': 2107ea4010d1SSteven Rostedt if (arg->op.op[1]) 2108ea4010d1SSteven Rostedt val = left && right; 2109ea4010d1SSteven Rostedt else 2110ea4010d1SSteven Rostedt val = left & right; 2111ea4010d1SSteven Rostedt break; 2112ea4010d1SSteven Rostedt case '<': 2113ea4010d1SSteven Rostedt switch (arg->op.op[1]) { 2114ea4010d1SSteven Rostedt case 0: 2115ea4010d1SSteven Rostedt val = left < right; 2116ea4010d1SSteven Rostedt break; 2117ea4010d1SSteven Rostedt case '<': 2118ea4010d1SSteven Rostedt val = left << right; 2119ea4010d1SSteven Rostedt break; 2120ea4010d1SSteven Rostedt case '=': 2121ea4010d1SSteven Rostedt val = left <= right; 2122ea4010d1SSteven Rostedt break; 2123ea4010d1SSteven Rostedt default: 2124ea4010d1SSteven Rostedt die("unknown op '%s'", arg->op.op); 2125ea4010d1SSteven Rostedt } 2126ea4010d1SSteven Rostedt break; 2127ea4010d1SSteven Rostedt case '>': 2128ea4010d1SSteven Rostedt switch (arg->op.op[1]) { 2129ea4010d1SSteven Rostedt case 0: 2130ea4010d1SSteven Rostedt val = left > right; 2131ea4010d1SSteven Rostedt break; 2132ea4010d1SSteven Rostedt case '>': 2133ea4010d1SSteven Rostedt val = left >> right; 2134ea4010d1SSteven Rostedt break; 2135ea4010d1SSteven Rostedt case '=': 2136ea4010d1SSteven Rostedt val = left >= right; 2137ea4010d1SSteven Rostedt break; 2138ea4010d1SSteven Rostedt default: 2139ea4010d1SSteven Rostedt die("unknown op '%s'", arg->op.op); 2140ea4010d1SSteven Rostedt } 2141ea4010d1SSteven Rostedt break; 2142ea4010d1SSteven Rostedt case '=': 2143ea4010d1SSteven Rostedt if (arg->op.op[1] != '=') 2144ea4010d1SSteven Rostedt die("unknown op '%s'", arg->op.op); 2145ea4010d1SSteven Rostedt val = left == right; 2146ea4010d1SSteven Rostedt break; 2147afdf1a40SSteven Rostedt case '-': 2148afdf1a40SSteven Rostedt val = left - right; 2149afdf1a40SSteven Rostedt break; 2150afdf1a40SSteven Rostedt case '+': 2151afdf1a40SSteven Rostedt val = left + right; 2152afdf1a40SSteven Rostedt break; 2153ea4010d1SSteven Rostedt default: 2154ea4010d1SSteven Rostedt die("unknown op '%s'", arg->op.op); 2155ea4010d1SSteven Rostedt } 2156ea4010d1SSteven Rostedt break; 2157ea4010d1SSteven Rostedt default: /* not sure what to do there */ 2158ea4010d1SSteven Rostedt return 0; 2159ea4010d1SSteven Rostedt } 2160ea4010d1SSteven Rostedt return val; 2161ea4010d1SSteven Rostedt } 2162ea4010d1SSteven Rostedt 2163ea4010d1SSteven Rostedt struct flag { 2164ea4010d1SSteven Rostedt const char *name; 2165ea4010d1SSteven Rostedt unsigned long long value; 2166ea4010d1SSteven Rostedt }; 2167ea4010d1SSteven Rostedt 2168ea4010d1SSteven Rostedt static const struct flag flags[] = { 2169ea4010d1SSteven Rostedt { "HI_SOFTIRQ", 0 }, 2170ea4010d1SSteven Rostedt { "TIMER_SOFTIRQ", 1 }, 2171ea4010d1SSteven Rostedt { "NET_TX_SOFTIRQ", 2 }, 2172ea4010d1SSteven Rostedt { "NET_RX_SOFTIRQ", 3 }, 2173ea4010d1SSteven Rostedt { "BLOCK_SOFTIRQ", 4 }, 2174b934cdd5STom Zanussi { "BLOCK_IOPOLL_SOFTIRQ", 5 }, 2175b934cdd5STom Zanussi { "TASKLET_SOFTIRQ", 6 }, 2176b934cdd5STom Zanussi { "SCHED_SOFTIRQ", 7 }, 2177b934cdd5STom Zanussi { "HRTIMER_SOFTIRQ", 8 }, 2178b934cdd5STom Zanussi { "RCU_SOFTIRQ", 9 }, 2179ea4010d1SSteven Rostedt 2180ea4010d1SSteven Rostedt { "HRTIMER_NORESTART", 0 }, 2181ea4010d1SSteven Rostedt { "HRTIMER_RESTART", 1 }, 2182ea4010d1SSteven Rostedt }; 2183ea4010d1SSteven Rostedt 218416c632deSTom Zanussi unsigned long long eval_flag(const char *flag) 2185ea4010d1SSteven Rostedt { 2186ea4010d1SSteven Rostedt int i; 2187ea4010d1SSteven Rostedt 2188ea4010d1SSteven Rostedt /* 2189ea4010d1SSteven Rostedt * Some flags in the format files do not get converted. 2190ea4010d1SSteven Rostedt * If the flag is not numeric, see if it is something that 2191ea4010d1SSteven Rostedt * we already know about. 2192ea4010d1SSteven Rostedt */ 2193ea4010d1SSteven Rostedt if (isdigit(flag[0])) 2194ea4010d1SSteven Rostedt return strtoull(flag, NULL, 0); 2195ea4010d1SSteven Rostedt 2196ea4010d1SSteven Rostedt for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++) 2197ea4010d1SSteven Rostedt if (strcmp(flags[i].name, flag) == 0) 2198ea4010d1SSteven Rostedt return flags[i].value; 2199ea4010d1SSteven Rostedt 2200ea4010d1SSteven Rostedt return 0; 2201ea4010d1SSteven Rostedt } 2202ea4010d1SSteven Rostedt 2203ea4010d1SSteven Rostedt static void print_str_arg(void *data, int size, 2204ea4010d1SSteven Rostedt struct event *event, struct print_arg *arg) 2205ea4010d1SSteven Rostedt { 2206ea4010d1SSteven Rostedt struct print_flag_sym *flag; 2207ea4010d1SSteven Rostedt unsigned long long val, fval; 2208ea4010d1SSteven Rostedt char *str; 2209ea4010d1SSteven Rostedt int print; 2210ea4010d1SSteven Rostedt 2211ea4010d1SSteven Rostedt switch (arg->type) { 2212ea4010d1SSteven Rostedt case PRINT_NULL: 2213ea4010d1SSteven Rostedt /* ?? */ 2214ea4010d1SSteven Rostedt return; 2215ea4010d1SSteven Rostedt case PRINT_ATOM: 2216ea4010d1SSteven Rostedt printf("%s", arg->atom.atom); 2217ea4010d1SSteven Rostedt return; 2218ea4010d1SSteven Rostedt case PRINT_FIELD: 2219ea4010d1SSteven Rostedt if (!arg->field.field) { 2220ea4010d1SSteven Rostedt arg->field.field = find_any_field(event, arg->field.name); 2221ea4010d1SSteven Rostedt if (!arg->field.field) 2222ea4010d1SSteven Rostedt die("field %s not found", arg->field.name); 2223ea4010d1SSteven Rostedt } 2224ea4010d1SSteven Rostedt str = malloc_or_die(arg->field.field->size + 1); 2225ea4010d1SSteven Rostedt memcpy(str, data + arg->field.field->offset, 2226ea4010d1SSteven Rostedt arg->field.field->size); 2227ea4010d1SSteven Rostedt str[arg->field.field->size] = 0; 2228d498bc1fSFrederic Weisbecker printf("%s", str); 2229ea4010d1SSteven Rostedt free(str); 2230ea4010d1SSteven Rostedt break; 2231ea4010d1SSteven Rostedt case PRINT_FLAGS: 2232ea4010d1SSteven Rostedt val = eval_num_arg(data, size, event, arg->flags.field); 2233ea4010d1SSteven Rostedt print = 0; 2234ea4010d1SSteven Rostedt for (flag = arg->flags.flags; flag; flag = flag->next) { 2235ea4010d1SSteven Rostedt fval = eval_flag(flag->value); 2236ea4010d1SSteven Rostedt if (!val && !fval) { 2237ea4010d1SSteven Rostedt printf("%s", flag->str); 2238ea4010d1SSteven Rostedt break; 2239ea4010d1SSteven Rostedt } 2240ea4010d1SSteven Rostedt if (fval && (val & fval) == fval) { 2241ea4010d1SSteven Rostedt if (print && arg->flags.delim) 2242ea4010d1SSteven Rostedt printf("%s", arg->flags.delim); 2243ea4010d1SSteven Rostedt printf("%s", flag->str); 2244ea4010d1SSteven Rostedt print = 1; 2245ea4010d1SSteven Rostedt val &= ~fval; 2246ea4010d1SSteven Rostedt } 2247ea4010d1SSteven Rostedt } 2248ea4010d1SSteven Rostedt break; 2249ea4010d1SSteven Rostedt case PRINT_SYMBOL: 2250ea4010d1SSteven Rostedt val = eval_num_arg(data, size, event, arg->symbol.field); 2251ea4010d1SSteven Rostedt for (flag = arg->symbol.symbols; flag; flag = flag->next) { 2252ea4010d1SSteven Rostedt fval = eval_flag(flag->value); 2253ea4010d1SSteven Rostedt if (val == fval) { 2254ea4010d1SSteven Rostedt printf("%s", flag->str); 2255ea4010d1SSteven Rostedt break; 2256ea4010d1SSteven Rostedt } 2257ea4010d1SSteven Rostedt } 2258ea4010d1SSteven Rostedt break; 2259ea4010d1SSteven Rostedt 2260ea4010d1SSteven Rostedt case PRINT_TYPE: 2261ea4010d1SSteven Rostedt break; 2262561f732cSFrederic Weisbecker case PRINT_STRING: { 2263561f732cSFrederic Weisbecker int str_offset; 2264561f732cSFrederic Weisbecker 2265561f732cSFrederic Weisbecker if (arg->string.offset == -1) { 2266561f732cSFrederic Weisbecker struct format_field *f; 2267561f732cSFrederic Weisbecker 2268561f732cSFrederic Weisbecker f = find_any_field(event, arg->string.string); 2269561f732cSFrederic Weisbecker arg->string.offset = f->offset; 2270561f732cSFrederic Weisbecker } 2271561f732cSFrederic Weisbecker str_offset = *(int *)(data + arg->string.offset); 2272561f732cSFrederic Weisbecker str_offset &= 0xffff; 2273561f732cSFrederic Weisbecker printf("%s", ((char *)data) + str_offset); 2274ea4010d1SSteven Rostedt break; 2275561f732cSFrederic Weisbecker } 2276ea4010d1SSteven Rostedt case PRINT_OP: 2277ea4010d1SSteven Rostedt /* 2278ea4010d1SSteven Rostedt * The only op for string should be ? : 2279ea4010d1SSteven Rostedt */ 2280ea4010d1SSteven Rostedt if (arg->op.op[0] != '?') 2281ea4010d1SSteven Rostedt return; 2282ea4010d1SSteven Rostedt val = eval_num_arg(data, size, event, arg->op.left); 2283ea4010d1SSteven Rostedt if (val) 2284ea4010d1SSteven Rostedt print_str_arg(data, size, event, arg->op.right->op.left); 2285ea4010d1SSteven Rostedt else 2286ea4010d1SSteven Rostedt print_str_arg(data, size, event, arg->op.right->op.right); 2287ea4010d1SSteven Rostedt break; 2288ea4010d1SSteven Rostedt default: 2289ea4010d1SSteven Rostedt /* well... */ 2290ea4010d1SSteven Rostedt break; 2291ea4010d1SSteven Rostedt } 2292ea4010d1SSteven Rostedt } 2293ea4010d1SSteven Rostedt 2294ea4010d1SSteven Rostedt static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event *event) 2295ea4010d1SSteven Rostedt { 2296ea4010d1SSteven Rostedt static struct format_field *field, *ip_field; 2297ea4010d1SSteven Rostedt struct print_arg *args, *arg, **next; 2298ea4010d1SSteven Rostedt unsigned long long ip, val; 2299ea4010d1SSteven Rostedt char *ptr; 2300ea4010d1SSteven Rostedt void *bptr; 2301ea4010d1SSteven Rostedt 2302ea4010d1SSteven Rostedt if (!field) { 2303ea4010d1SSteven Rostedt field = find_field(event, "buf"); 2304ea4010d1SSteven Rostedt if (!field) 2305ea4010d1SSteven Rostedt die("can't find buffer field for binary printk"); 2306ea4010d1SSteven Rostedt ip_field = find_field(event, "ip"); 2307ea4010d1SSteven Rostedt if (!ip_field) 2308ea4010d1SSteven Rostedt die("can't find ip field for binary printk"); 2309ea4010d1SSteven Rostedt } 2310ea4010d1SSteven Rostedt 2311ea4010d1SSteven Rostedt ip = read_size(data + ip_field->offset, ip_field->size); 2312ea4010d1SSteven Rostedt 2313ea4010d1SSteven Rostedt /* 2314ea4010d1SSteven Rostedt * The first arg is the IP pointer. 2315ea4010d1SSteven Rostedt */ 2316ea4010d1SSteven Rostedt args = malloc_or_die(sizeof(*args)); 2317ea4010d1SSteven Rostedt arg = args; 2318ea4010d1SSteven Rostedt arg->next = NULL; 2319ea4010d1SSteven Rostedt next = &arg->next; 2320ea4010d1SSteven Rostedt 2321ea4010d1SSteven Rostedt arg->type = PRINT_ATOM; 2322ea4010d1SSteven Rostedt arg->atom.atom = malloc_or_die(32); 2323ea4010d1SSteven Rostedt sprintf(arg->atom.atom, "%lld", ip); 2324ea4010d1SSteven Rostedt 2325ea4010d1SSteven Rostedt /* skip the first "%pf : " */ 2326ea4010d1SSteven Rostedt for (ptr = fmt + 6, bptr = data + field->offset; 2327ea4010d1SSteven Rostedt bptr < data + size && *ptr; ptr++) { 2328ea4010d1SSteven Rostedt int ls = 0; 2329ea4010d1SSteven Rostedt 2330ea4010d1SSteven Rostedt if (*ptr == '%') { 2331ea4010d1SSteven Rostedt process_again: 2332ea4010d1SSteven Rostedt ptr++; 2333ea4010d1SSteven Rostedt switch (*ptr) { 2334ea4010d1SSteven Rostedt case '%': 2335ea4010d1SSteven Rostedt break; 2336ea4010d1SSteven Rostedt case 'l': 2337ea4010d1SSteven Rostedt ls++; 2338ea4010d1SSteven Rostedt goto process_again; 2339ea4010d1SSteven Rostedt case 'L': 2340ea4010d1SSteven Rostedt ls = 2; 2341ea4010d1SSteven Rostedt goto process_again; 2342ea4010d1SSteven Rostedt case '0' ... '9': 2343ea4010d1SSteven Rostedt goto process_again; 2344ea4010d1SSteven Rostedt case 'p': 2345ea4010d1SSteven Rostedt ls = 1; 2346ea4010d1SSteven Rostedt /* fall through */ 2347ea4010d1SSteven Rostedt case 'd': 2348ea4010d1SSteven Rostedt case 'u': 2349ea4010d1SSteven Rostedt case 'x': 2350ea4010d1SSteven Rostedt case 'i': 2351ffa18955SSteven Rostedt /* the pointers are always 4 bytes aligned */ 2352ffa18955SSteven Rostedt bptr = (void *)(((unsigned long)bptr + 3) & 2353ffa18955SSteven Rostedt ~3); 2354ea4010d1SSteven Rostedt switch (ls) { 2355ea4010d1SSteven Rostedt case 0: 2356ea4010d1SSteven Rostedt case 1: 2357ea4010d1SSteven Rostedt ls = long_size; 2358ea4010d1SSteven Rostedt break; 2359ea4010d1SSteven Rostedt case 2: 2360ea4010d1SSteven Rostedt ls = 8; 2361ea4010d1SSteven Rostedt default: 2362ea4010d1SSteven Rostedt break; 2363ea4010d1SSteven Rostedt } 2364ea4010d1SSteven Rostedt val = read_size(bptr, ls); 2365ea4010d1SSteven Rostedt bptr += ls; 2366ea4010d1SSteven Rostedt arg = malloc_or_die(sizeof(*arg)); 2367ea4010d1SSteven Rostedt arg->next = NULL; 2368ea4010d1SSteven Rostedt arg->type = PRINT_ATOM; 2369ea4010d1SSteven Rostedt arg->atom.atom = malloc_or_die(32); 2370ea4010d1SSteven Rostedt sprintf(arg->atom.atom, "%lld", val); 2371ea4010d1SSteven Rostedt *next = arg; 2372ea4010d1SSteven Rostedt next = &arg->next; 2373ea4010d1SSteven Rostedt break; 2374ea4010d1SSteven Rostedt case 's': 2375ea4010d1SSteven Rostedt arg = malloc_or_die(sizeof(*arg)); 2376ea4010d1SSteven Rostedt arg->next = NULL; 2377ea4010d1SSteven Rostedt arg->type = PRINT_STRING; 2378ea4010d1SSteven Rostedt arg->string.string = strdup(bptr); 2379ea4010d1SSteven Rostedt bptr += strlen(bptr) + 1; 2380ea4010d1SSteven Rostedt *next = arg; 2381ea4010d1SSteven Rostedt next = &arg->next; 2382ea4010d1SSteven Rostedt default: 2383ea4010d1SSteven Rostedt break; 2384ea4010d1SSteven Rostedt } 2385ea4010d1SSteven Rostedt } 2386ea4010d1SSteven Rostedt } 2387ea4010d1SSteven Rostedt 2388ea4010d1SSteven Rostedt return args; 2389ea4010d1SSteven Rostedt } 2390ea4010d1SSteven Rostedt 2391ea4010d1SSteven Rostedt static void free_args(struct print_arg *args) 2392ea4010d1SSteven Rostedt { 2393ea4010d1SSteven Rostedt struct print_arg *next; 2394ea4010d1SSteven Rostedt 2395ea4010d1SSteven Rostedt while (args) { 2396ea4010d1SSteven Rostedt next = args->next; 2397ea4010d1SSteven Rostedt 2398ea4010d1SSteven Rostedt if (args->type == PRINT_ATOM) 2399ea4010d1SSteven Rostedt free(args->atom.atom); 2400ea4010d1SSteven Rostedt else 2401ea4010d1SSteven Rostedt free(args->string.string); 2402ea4010d1SSteven Rostedt free(args); 2403ea4010d1SSteven Rostedt args = next; 2404ea4010d1SSteven Rostedt } 2405ea4010d1SSteven Rostedt } 2406ea4010d1SSteven Rostedt 2407ea4010d1SSteven Rostedt static char *get_bprint_format(void *data, int size __unused, struct event *event) 2408ea4010d1SSteven Rostedt { 2409ea4010d1SSteven Rostedt unsigned long long addr; 2410ea4010d1SSteven Rostedt static struct format_field *field; 2411ea4010d1SSteven Rostedt struct printk_map *printk; 2412ea4010d1SSteven Rostedt char *format; 2413ea4010d1SSteven Rostedt char *p; 2414ea4010d1SSteven Rostedt 2415ea4010d1SSteven Rostedt if (!field) { 2416ea4010d1SSteven Rostedt field = find_field(event, "fmt"); 2417ea4010d1SSteven Rostedt if (!field) 2418ea4010d1SSteven Rostedt die("can't find format field for binary printk"); 2419ea4010d1SSteven Rostedt printf("field->offset = %d size=%d\n", field->offset, field->size); 2420ea4010d1SSteven Rostedt } 2421ea4010d1SSteven Rostedt 2422ea4010d1SSteven Rostedt addr = read_size(data + field->offset, field->size); 2423ea4010d1SSteven Rostedt 2424ea4010d1SSteven Rostedt printk = find_printk(addr); 2425ea4010d1SSteven Rostedt if (!printk) { 2426ea4010d1SSteven Rostedt format = malloc_or_die(45); 2427ea4010d1SSteven Rostedt sprintf(format, "%%pf : (NO FORMAT FOUND at %llx)\n", 2428ea4010d1SSteven Rostedt addr); 2429ea4010d1SSteven Rostedt return format; 2430ea4010d1SSteven Rostedt } 2431ea4010d1SSteven Rostedt 2432ea4010d1SSteven Rostedt p = printk->printk; 2433ea4010d1SSteven Rostedt /* Remove any quotes. */ 2434ea4010d1SSteven Rostedt if (*p == '"') 2435ea4010d1SSteven Rostedt p++; 2436ea4010d1SSteven Rostedt format = malloc_or_die(strlen(p) + 10); 2437ea4010d1SSteven Rostedt sprintf(format, "%s : %s", "%pf", p); 2438ea4010d1SSteven Rostedt /* remove ending quotes and new line since we will add one too */ 2439ea4010d1SSteven Rostedt p = format + strlen(format) - 1; 2440ea4010d1SSteven Rostedt if (*p == '"') 2441ea4010d1SSteven Rostedt *p = 0; 2442ea4010d1SSteven Rostedt 2443ea4010d1SSteven Rostedt p -= 2; 2444ea4010d1SSteven Rostedt if (strcmp(p, "\\n") == 0) 2445ea4010d1SSteven Rostedt *p = 0; 2446ea4010d1SSteven Rostedt 2447ea4010d1SSteven Rostedt return format; 2448ea4010d1SSteven Rostedt } 2449ea4010d1SSteven Rostedt 2450ea4010d1SSteven Rostedt static void pretty_print(void *data, int size, struct event *event) 2451ea4010d1SSteven Rostedt { 2452ea4010d1SSteven Rostedt struct print_fmt *print_fmt = &event->print_fmt; 2453ea4010d1SSteven Rostedt struct print_arg *arg = print_fmt->args; 2454ea4010d1SSteven Rostedt struct print_arg *args = NULL; 2455ea4010d1SSteven Rostedt const char *ptr = print_fmt->format; 2456ea4010d1SSteven Rostedt unsigned long long val; 2457ea4010d1SSteven Rostedt struct func_map *func; 2458ea4010d1SSteven Rostedt const char *saveptr; 2459ea4010d1SSteven Rostedt char *bprint_fmt = NULL; 2460ea4010d1SSteven Rostedt char format[32]; 2461ea4010d1SSteven Rostedt int show_func; 2462ea4010d1SSteven Rostedt int len; 2463ea4010d1SSteven Rostedt int ls; 2464ea4010d1SSteven Rostedt 2465ea4010d1SSteven Rostedt if (event->flags & EVENT_FL_ISFUNC) 2466ea4010d1SSteven Rostedt ptr = " %pF <-- %pF"; 2467ea4010d1SSteven Rostedt 2468ea4010d1SSteven Rostedt if (event->flags & EVENT_FL_ISBPRINT) { 2469ea4010d1SSteven Rostedt bprint_fmt = get_bprint_format(data, size, event); 2470ea4010d1SSteven Rostedt args = make_bprint_args(bprint_fmt, data, size, event); 2471ea4010d1SSteven Rostedt arg = args; 2472ea4010d1SSteven Rostedt ptr = bprint_fmt; 2473ea4010d1SSteven Rostedt } 2474ea4010d1SSteven Rostedt 2475ea4010d1SSteven Rostedt for (; *ptr; ptr++) { 2476ea4010d1SSteven Rostedt ls = 0; 247791ff2bc1SSteven Rostedt if (*ptr == '\\') { 247891ff2bc1SSteven Rostedt ptr++; 247991ff2bc1SSteven Rostedt switch (*ptr) { 248091ff2bc1SSteven Rostedt case 'n': 248191ff2bc1SSteven Rostedt printf("\n"); 248291ff2bc1SSteven Rostedt break; 248391ff2bc1SSteven Rostedt case 't': 248491ff2bc1SSteven Rostedt printf("\t"); 248591ff2bc1SSteven Rostedt break; 248691ff2bc1SSteven Rostedt case 'r': 248791ff2bc1SSteven Rostedt printf("\r"); 248891ff2bc1SSteven Rostedt break; 248991ff2bc1SSteven Rostedt case '\\': 249091ff2bc1SSteven Rostedt printf("\\"); 249191ff2bc1SSteven Rostedt break; 249291ff2bc1SSteven Rostedt default: 249391ff2bc1SSteven Rostedt printf("%c", *ptr); 249491ff2bc1SSteven Rostedt break; 249591ff2bc1SSteven Rostedt } 249691ff2bc1SSteven Rostedt 249791ff2bc1SSteven Rostedt } else if (*ptr == '%') { 2498ea4010d1SSteven Rostedt saveptr = ptr; 2499ea4010d1SSteven Rostedt show_func = 0; 2500ea4010d1SSteven Rostedt cont_process: 2501ea4010d1SSteven Rostedt ptr++; 2502ea4010d1SSteven Rostedt switch (*ptr) { 2503ea4010d1SSteven Rostedt case '%': 2504ea4010d1SSteven Rostedt printf("%%"); 2505ea4010d1SSteven Rostedt break; 2506ea4010d1SSteven Rostedt case 'l': 2507ea4010d1SSteven Rostedt ls++; 2508ea4010d1SSteven Rostedt goto cont_process; 2509ea4010d1SSteven Rostedt case 'L': 2510ea4010d1SSteven Rostedt ls = 2; 2511ea4010d1SSteven Rostedt goto cont_process; 2512ea4010d1SSteven Rostedt case 'z': 2513ea4010d1SSteven Rostedt case 'Z': 2514ea4010d1SSteven Rostedt case '0' ... '9': 2515ea4010d1SSteven Rostedt goto cont_process; 2516ea4010d1SSteven Rostedt case 'p': 2517ea4010d1SSteven Rostedt if (long_size == 4) 2518ea4010d1SSteven Rostedt ls = 1; 2519ea4010d1SSteven Rostedt else 2520ea4010d1SSteven Rostedt ls = 2; 2521ea4010d1SSteven Rostedt 2522ea4010d1SSteven Rostedt if (*(ptr+1) == 'F' || 2523ea4010d1SSteven Rostedt *(ptr+1) == 'f') { 2524ea4010d1SSteven Rostedt ptr++; 2525ea4010d1SSteven Rostedt show_func = *ptr; 2526ea4010d1SSteven Rostedt } 2527ea4010d1SSteven Rostedt 2528ea4010d1SSteven Rostedt /* fall through */ 2529ea4010d1SSteven Rostedt case 'd': 2530ea4010d1SSteven Rostedt case 'i': 2531ea4010d1SSteven Rostedt case 'x': 2532ea4010d1SSteven Rostedt case 'X': 2533ea4010d1SSteven Rostedt case 'u': 2534ea4010d1SSteven Rostedt if (!arg) 2535ea4010d1SSteven Rostedt die("no argument match"); 2536ea4010d1SSteven Rostedt 2537ea4010d1SSteven Rostedt len = ((unsigned long)ptr + 1) - 2538ea4010d1SSteven Rostedt (unsigned long)saveptr; 2539ea4010d1SSteven Rostedt 2540ea4010d1SSteven Rostedt /* should never happen */ 2541ea4010d1SSteven Rostedt if (len > 32) 2542ea4010d1SSteven Rostedt die("bad format!"); 2543ea4010d1SSteven Rostedt 2544ea4010d1SSteven Rostedt memcpy(format, saveptr, len); 2545ea4010d1SSteven Rostedt format[len] = 0; 2546ea4010d1SSteven Rostedt 2547ea4010d1SSteven Rostedt val = eval_num_arg(data, size, event, arg); 2548ea4010d1SSteven Rostedt arg = arg->next; 2549ea4010d1SSteven Rostedt 2550ea4010d1SSteven Rostedt if (show_func) { 2551ea4010d1SSteven Rostedt func = find_func(val); 2552ea4010d1SSteven Rostedt if (func) { 2553ea4010d1SSteven Rostedt printf("%s", func->func); 2554ea4010d1SSteven Rostedt if (show_func == 'F') 2555ea4010d1SSteven Rostedt printf("+0x%llx", 2556ea4010d1SSteven Rostedt val - func->addr); 2557ea4010d1SSteven Rostedt break; 2558ea4010d1SSteven Rostedt } 2559ea4010d1SSteven Rostedt } 2560ea4010d1SSteven Rostedt switch (ls) { 2561ea4010d1SSteven Rostedt case 0: 2562ea4010d1SSteven Rostedt printf(format, (int)val); 2563ea4010d1SSteven Rostedt break; 2564ea4010d1SSteven Rostedt case 1: 2565ea4010d1SSteven Rostedt printf(format, (long)val); 2566ea4010d1SSteven Rostedt break; 2567ea4010d1SSteven Rostedt case 2: 2568ea4010d1SSteven Rostedt printf(format, (long long)val); 2569ea4010d1SSteven Rostedt break; 2570ea4010d1SSteven Rostedt default: 2571ea4010d1SSteven Rostedt die("bad count (%d)", ls); 2572ea4010d1SSteven Rostedt } 2573ea4010d1SSteven Rostedt break; 2574ea4010d1SSteven Rostedt case 's': 2575ea4010d1SSteven Rostedt if (!arg) 2576ea4010d1SSteven Rostedt die("no matching argument"); 2577ea4010d1SSteven Rostedt 2578ea4010d1SSteven Rostedt print_str_arg(data, size, event, arg); 2579ea4010d1SSteven Rostedt arg = arg->next; 2580ea4010d1SSteven Rostedt break; 2581ea4010d1SSteven Rostedt default: 2582ea4010d1SSteven Rostedt printf(">%c<", *ptr); 2583ea4010d1SSteven Rostedt 2584ea4010d1SSteven Rostedt } 2585ea4010d1SSteven Rostedt } else 2586ea4010d1SSteven Rostedt printf("%c", *ptr); 2587ea4010d1SSteven Rostedt } 2588ea4010d1SSteven Rostedt 2589ea4010d1SSteven Rostedt if (args) { 2590ea4010d1SSteven Rostedt free_args(args); 2591ea4010d1SSteven Rostedt free(bprint_fmt); 2592ea4010d1SSteven Rostedt } 2593ea4010d1SSteven Rostedt } 2594ea4010d1SSteven Rostedt 2595ea4010d1SSteven Rostedt static inline int log10_cpu(int nb) 2596ea4010d1SSteven Rostedt { 2597ea4010d1SSteven Rostedt if (nb / 100) 2598ea4010d1SSteven Rostedt return 3; 2599ea4010d1SSteven Rostedt if (nb / 10) 2600ea4010d1SSteven Rostedt return 2; 2601ea4010d1SSteven Rostedt return 1; 2602ea4010d1SSteven Rostedt } 2603ea4010d1SSteven Rostedt 2604cda48461SSteven Rostedt static void print_lat_fmt(void *data, int size __unused) 2605cda48461SSteven Rostedt { 2606cda48461SSteven Rostedt unsigned int lat_flags; 2607cda48461SSteven Rostedt unsigned int pc; 2608cda48461SSteven Rostedt int lock_depth; 2609cda48461SSteven Rostedt int hardirq; 2610cda48461SSteven Rostedt int softirq; 2611cda48461SSteven Rostedt 2612cda48461SSteven Rostedt lat_flags = parse_common_flags(data); 2613cda48461SSteven Rostedt pc = parse_common_pc(data); 2614cda48461SSteven Rostedt lock_depth = parse_common_lock_depth(data); 2615cda48461SSteven Rostedt 2616cda48461SSteven Rostedt hardirq = lat_flags & TRACE_FLAG_HARDIRQ; 2617cda48461SSteven Rostedt softirq = lat_flags & TRACE_FLAG_SOFTIRQ; 2618cda48461SSteven Rostedt 2619cda48461SSteven Rostedt printf("%c%c%c", 2620cda48461SSteven Rostedt (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' : 2621cda48461SSteven Rostedt (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ? 2622cda48461SSteven Rostedt 'X' : '.', 2623cda48461SSteven Rostedt (lat_flags & TRACE_FLAG_NEED_RESCHED) ? 2624cda48461SSteven Rostedt 'N' : '.', 2625cda48461SSteven Rostedt (hardirq && softirq) ? 'H' : 2626cda48461SSteven Rostedt hardirq ? 'h' : softirq ? 's' : '.'); 2627cda48461SSteven Rostedt 2628cda48461SSteven Rostedt if (pc) 2629cda48461SSteven Rostedt printf("%x", pc); 2630cda48461SSteven Rostedt else 2631cda48461SSteven Rostedt printf("."); 2632cda48461SSteven Rostedt 2633cda48461SSteven Rostedt if (lock_depth < 0) 2634cda48461SSteven Rostedt printf("."); 2635cda48461SSteven Rostedt else 2636cda48461SSteven Rostedt printf("%d", lock_depth); 2637cda48461SSteven Rostedt } 2638cda48461SSteven Rostedt 2639ea4010d1SSteven Rostedt /* taken from Linux, written by Frederic Weisbecker */ 2640ea4010d1SSteven Rostedt static void print_graph_cpu(int cpu) 2641ea4010d1SSteven Rostedt { 2642ea4010d1SSteven Rostedt int i; 2643ea4010d1SSteven Rostedt int log10_this = log10_cpu(cpu); 2644ea4010d1SSteven Rostedt int log10_all = log10_cpu(cpus); 2645ea4010d1SSteven Rostedt 2646ea4010d1SSteven Rostedt 2647ea4010d1SSteven Rostedt /* 2648ea4010d1SSteven Rostedt * Start with a space character - to make it stand out 2649ea4010d1SSteven Rostedt * to the right a bit when trace output is pasted into 2650ea4010d1SSteven Rostedt * email: 2651ea4010d1SSteven Rostedt */ 2652ea4010d1SSteven Rostedt printf(" "); 2653ea4010d1SSteven Rostedt 2654ea4010d1SSteven Rostedt /* 2655ea4010d1SSteven Rostedt * Tricky - we space the CPU field according to the max 2656ea4010d1SSteven Rostedt * number of online CPUs. On a 2-cpu system it would take 2657ea4010d1SSteven Rostedt * a maximum of 1 digit - on a 128 cpu system it would 2658ea4010d1SSteven Rostedt * take up to 3 digits: 2659ea4010d1SSteven Rostedt */ 2660ea4010d1SSteven Rostedt for (i = 0; i < log10_all - log10_this; i++) 2661ea4010d1SSteven Rostedt printf(" "); 2662ea4010d1SSteven Rostedt 2663ea4010d1SSteven Rostedt printf("%d) ", cpu); 2664ea4010d1SSteven Rostedt } 2665ea4010d1SSteven Rostedt 2666ea4010d1SSteven Rostedt #define TRACE_GRAPH_PROCINFO_LENGTH 14 2667ea4010d1SSteven Rostedt #define TRACE_GRAPH_INDENT 2 2668ea4010d1SSteven Rostedt 2669ea4010d1SSteven Rostedt static void print_graph_proc(int pid, const char *comm) 2670ea4010d1SSteven Rostedt { 2671ea4010d1SSteven Rostedt /* sign + log10(MAX_INT) + '\0' */ 2672ea4010d1SSteven Rostedt char pid_str[11]; 2673ea4010d1SSteven Rostedt int spaces = 0; 2674ea4010d1SSteven Rostedt int len; 2675ea4010d1SSteven Rostedt int i; 2676ea4010d1SSteven Rostedt 2677ea4010d1SSteven Rostedt sprintf(pid_str, "%d", pid); 2678ea4010d1SSteven Rostedt 2679ea4010d1SSteven Rostedt /* 1 stands for the "-" character */ 2680ea4010d1SSteven Rostedt len = strlen(comm) + strlen(pid_str) + 1; 2681ea4010d1SSteven Rostedt 2682ea4010d1SSteven Rostedt if (len < TRACE_GRAPH_PROCINFO_LENGTH) 2683ea4010d1SSteven Rostedt spaces = TRACE_GRAPH_PROCINFO_LENGTH - len; 2684ea4010d1SSteven Rostedt 2685ea4010d1SSteven Rostedt /* First spaces to align center */ 2686ea4010d1SSteven Rostedt for (i = 0; i < spaces / 2; i++) 2687ea4010d1SSteven Rostedt printf(" "); 2688ea4010d1SSteven Rostedt 2689ea4010d1SSteven Rostedt printf("%s-%s", comm, pid_str); 2690ea4010d1SSteven Rostedt 2691ea4010d1SSteven Rostedt /* Last spaces to align center */ 2692ea4010d1SSteven Rostedt for (i = 0; i < spaces - (spaces / 2); i++) 2693ea4010d1SSteven Rostedt printf(" "); 2694ea4010d1SSteven Rostedt } 2695ea4010d1SSteven Rostedt 2696ea4010d1SSteven Rostedt static struct record * 2697ea4010d1SSteven Rostedt get_return_for_leaf(int cpu, int cur_pid, unsigned long long cur_func, 2698ea4010d1SSteven Rostedt struct record *next) 2699ea4010d1SSteven Rostedt { 2700ea4010d1SSteven Rostedt struct format_field *field; 2701ea4010d1SSteven Rostedt struct event *event; 2702ea4010d1SSteven Rostedt unsigned long val; 2703ea4010d1SSteven Rostedt int type; 2704ea4010d1SSteven Rostedt int pid; 2705ea4010d1SSteven Rostedt 2706ec156764SIngo Molnar type = trace_parse_common_type(next->data); 2707ec156764SIngo Molnar event = trace_find_event(type); 2708ea4010d1SSteven Rostedt if (!event) 2709ea4010d1SSteven Rostedt return NULL; 2710ea4010d1SSteven Rostedt 2711ea4010d1SSteven Rostedt if (!(event->flags & EVENT_FL_ISFUNCRET)) 2712ea4010d1SSteven Rostedt return NULL; 2713ea4010d1SSteven Rostedt 271416c632deSTom Zanussi pid = trace_parse_common_pid(next->data); 2715ea4010d1SSteven Rostedt field = find_field(event, "func"); 2716ea4010d1SSteven Rostedt if (!field) 2717ea4010d1SSteven Rostedt die("function return does not have field func"); 2718ea4010d1SSteven Rostedt 2719ea4010d1SSteven Rostedt val = read_size(next->data + field->offset, field->size); 2720ea4010d1SSteven Rostedt 2721ea4010d1SSteven Rostedt if (cur_pid != pid || cur_func != val) 2722ea4010d1SSteven Rostedt return NULL; 2723ea4010d1SSteven Rostedt 2724ea4010d1SSteven Rostedt /* this is a leaf, now advance the iterator */ 2725ea4010d1SSteven Rostedt return trace_read_data(cpu); 2726ea4010d1SSteven Rostedt } 2727ea4010d1SSteven Rostedt 2728ea4010d1SSteven Rostedt /* Signal a overhead of time execution to the output */ 2729ea4010d1SSteven Rostedt static void print_graph_overhead(unsigned long long duration) 2730ea4010d1SSteven Rostedt { 2731ea4010d1SSteven Rostedt /* Non nested entry or return */ 2732ea4010d1SSteven Rostedt if (duration == ~0ULL) 2733ea4010d1SSteven Rostedt return (void)printf(" "); 2734ea4010d1SSteven Rostedt 2735ea4010d1SSteven Rostedt /* Duration exceeded 100 msecs */ 2736ea4010d1SSteven Rostedt if (duration > 100000ULL) 2737ea4010d1SSteven Rostedt return (void)printf("! "); 2738ea4010d1SSteven Rostedt 2739ea4010d1SSteven Rostedt /* Duration exceeded 10 msecs */ 2740ea4010d1SSteven Rostedt if (duration > 10000ULL) 2741ea4010d1SSteven Rostedt return (void)printf("+ "); 2742ea4010d1SSteven Rostedt 2743ea4010d1SSteven Rostedt printf(" "); 2744ea4010d1SSteven Rostedt } 2745ea4010d1SSteven Rostedt 2746ea4010d1SSteven Rostedt static void print_graph_duration(unsigned long long duration) 2747ea4010d1SSteven Rostedt { 2748ea4010d1SSteven Rostedt unsigned long usecs = duration / 1000; 2749ea4010d1SSteven Rostedt unsigned long nsecs_rem = duration % 1000; 2750ea4010d1SSteven Rostedt /* log10(ULONG_MAX) + '\0' */ 2751ea4010d1SSteven Rostedt char msecs_str[21]; 2752ea4010d1SSteven Rostedt char nsecs_str[5]; 2753ea4010d1SSteven Rostedt int len; 2754ea4010d1SSteven Rostedt int i; 2755ea4010d1SSteven Rostedt 2756ea4010d1SSteven Rostedt sprintf(msecs_str, "%lu", usecs); 2757ea4010d1SSteven Rostedt 2758ea4010d1SSteven Rostedt /* Print msecs */ 2759ea4010d1SSteven Rostedt len = printf("%lu", usecs); 2760ea4010d1SSteven Rostedt 2761ea4010d1SSteven Rostedt /* Print nsecs (we don't want to exceed 7 numbers) */ 2762ea4010d1SSteven Rostedt if (len < 7) { 2763ea4010d1SSteven Rostedt snprintf(nsecs_str, 8 - len, "%03lu", nsecs_rem); 2764ea4010d1SSteven Rostedt len += printf(".%s", nsecs_str); 2765ea4010d1SSteven Rostedt } 2766ea4010d1SSteven Rostedt 2767ea4010d1SSteven Rostedt printf(" us "); 2768ea4010d1SSteven Rostedt 2769ea4010d1SSteven Rostedt /* Print remaining spaces to fit the row's width */ 2770ea4010d1SSteven Rostedt for (i = len; i < 7; i++) 2771ea4010d1SSteven Rostedt printf(" "); 2772ea4010d1SSteven Rostedt 2773ea4010d1SSteven Rostedt printf("| "); 2774ea4010d1SSteven Rostedt } 2775ea4010d1SSteven Rostedt 2776ea4010d1SSteven Rostedt static void 2777ea4010d1SSteven Rostedt print_graph_entry_leaf(struct event *event, void *data, struct record *ret_rec) 2778ea4010d1SSteven Rostedt { 2779ea4010d1SSteven Rostedt unsigned long long rettime, calltime; 2780ea4010d1SSteven Rostedt unsigned long long duration, depth; 2781ea4010d1SSteven Rostedt unsigned long long val; 2782ea4010d1SSteven Rostedt struct format_field *field; 2783ea4010d1SSteven Rostedt struct func_map *func; 2784ea4010d1SSteven Rostedt struct event *ret_event; 2785ea4010d1SSteven Rostedt int type; 2786ea4010d1SSteven Rostedt int i; 2787ea4010d1SSteven Rostedt 2788ec156764SIngo Molnar type = trace_parse_common_type(ret_rec->data); 2789ec156764SIngo Molnar ret_event = trace_find_event(type); 2790ea4010d1SSteven Rostedt 2791ea4010d1SSteven Rostedt field = find_field(ret_event, "rettime"); 2792ea4010d1SSteven Rostedt if (!field) 2793ea4010d1SSteven Rostedt die("can't find rettime in return graph"); 2794ea4010d1SSteven Rostedt rettime = read_size(ret_rec->data + field->offset, field->size); 2795ea4010d1SSteven Rostedt 2796ea4010d1SSteven Rostedt field = find_field(ret_event, "calltime"); 2797ea4010d1SSteven Rostedt if (!field) 2798ea4010d1SSteven Rostedt die("can't find rettime in return graph"); 2799ea4010d1SSteven Rostedt calltime = read_size(ret_rec->data + field->offset, field->size); 2800ea4010d1SSteven Rostedt 2801ea4010d1SSteven Rostedt duration = rettime - calltime; 2802ea4010d1SSteven Rostedt 2803ea4010d1SSteven Rostedt /* Overhead */ 2804ea4010d1SSteven Rostedt print_graph_overhead(duration); 2805ea4010d1SSteven Rostedt 2806ea4010d1SSteven Rostedt /* Duration */ 2807ea4010d1SSteven Rostedt print_graph_duration(duration); 2808ea4010d1SSteven Rostedt 2809ea4010d1SSteven Rostedt field = find_field(event, "depth"); 2810ea4010d1SSteven Rostedt if (!field) 2811ea4010d1SSteven Rostedt die("can't find depth in entry graph"); 2812ea4010d1SSteven Rostedt depth = read_size(data + field->offset, field->size); 2813ea4010d1SSteven Rostedt 2814ea4010d1SSteven Rostedt /* Function */ 2815ea4010d1SSteven Rostedt for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++) 2816ea4010d1SSteven Rostedt printf(" "); 2817ea4010d1SSteven Rostedt 2818ea4010d1SSteven Rostedt field = find_field(event, "func"); 2819ea4010d1SSteven Rostedt if (!field) 2820ea4010d1SSteven Rostedt die("can't find func in entry graph"); 2821ea4010d1SSteven Rostedt val = read_size(data + field->offset, field->size); 2822ea4010d1SSteven Rostedt func = find_func(val); 2823ea4010d1SSteven Rostedt 2824ea4010d1SSteven Rostedt if (func) 2825ea4010d1SSteven Rostedt printf("%s();", func->func); 2826ea4010d1SSteven Rostedt else 2827ea4010d1SSteven Rostedt printf("%llx();", val); 2828ea4010d1SSteven Rostedt } 2829ea4010d1SSteven Rostedt 2830ea4010d1SSteven Rostedt static void print_graph_nested(struct event *event, void *data) 2831ea4010d1SSteven Rostedt { 2832ea4010d1SSteven Rostedt struct format_field *field; 2833ea4010d1SSteven Rostedt unsigned long long depth; 2834ea4010d1SSteven Rostedt unsigned long long val; 2835ea4010d1SSteven Rostedt struct func_map *func; 2836ea4010d1SSteven Rostedt int i; 2837ea4010d1SSteven Rostedt 2838ea4010d1SSteven Rostedt /* No overhead */ 2839ea4010d1SSteven Rostedt print_graph_overhead(-1); 2840ea4010d1SSteven Rostedt 2841ea4010d1SSteven Rostedt /* No time */ 2842ea4010d1SSteven Rostedt printf(" | "); 2843ea4010d1SSteven Rostedt 2844ea4010d1SSteven Rostedt field = find_field(event, "depth"); 2845ea4010d1SSteven Rostedt if (!field) 2846ea4010d1SSteven Rostedt die("can't find depth in entry graph"); 2847ea4010d1SSteven Rostedt depth = read_size(data + field->offset, field->size); 2848ea4010d1SSteven Rostedt 2849ea4010d1SSteven Rostedt /* Function */ 2850ea4010d1SSteven Rostedt for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++) 2851ea4010d1SSteven Rostedt printf(" "); 2852ea4010d1SSteven Rostedt 2853ea4010d1SSteven Rostedt field = find_field(event, "func"); 2854ea4010d1SSteven Rostedt if (!field) 2855ea4010d1SSteven Rostedt die("can't find func in entry graph"); 2856ea4010d1SSteven Rostedt val = read_size(data + field->offset, field->size); 2857ea4010d1SSteven Rostedt func = find_func(val); 2858ea4010d1SSteven Rostedt 2859ea4010d1SSteven Rostedt if (func) 2860ea4010d1SSteven Rostedt printf("%s() {", func->func); 2861ea4010d1SSteven Rostedt else 2862ea4010d1SSteven Rostedt printf("%llx() {", val); 2863ea4010d1SSteven Rostedt } 2864ea4010d1SSteven Rostedt 2865ea4010d1SSteven Rostedt static void 2866ea4010d1SSteven Rostedt pretty_print_func_ent(void *data, int size, struct event *event, 2867ea4010d1SSteven Rostedt int cpu, int pid, const char *comm, 2868ea4010d1SSteven Rostedt unsigned long secs, unsigned long usecs) 2869ea4010d1SSteven Rostedt { 2870ea4010d1SSteven Rostedt struct format_field *field; 2871ea4010d1SSteven Rostedt struct record *rec; 2872ea4010d1SSteven Rostedt void *copy_data; 2873ea4010d1SSteven Rostedt unsigned long val; 2874ea4010d1SSteven Rostedt 2875ea4010d1SSteven Rostedt printf("%5lu.%06lu | ", secs, usecs); 2876ea4010d1SSteven Rostedt 2877ea4010d1SSteven Rostedt print_graph_cpu(cpu); 2878ea4010d1SSteven Rostedt print_graph_proc(pid, comm); 2879ea4010d1SSteven Rostedt 2880ea4010d1SSteven Rostedt printf(" | "); 2881ea4010d1SSteven Rostedt 2882cda48461SSteven Rostedt if (latency_format) { 2883cda48461SSteven Rostedt print_lat_fmt(data, size); 2884cda48461SSteven Rostedt printf(" | "); 2885cda48461SSteven Rostedt } 2886cda48461SSteven Rostedt 2887ea4010d1SSteven Rostedt field = find_field(event, "func"); 2888ea4010d1SSteven Rostedt if (!field) 2889ea4010d1SSteven Rostedt die("function entry does not have func field"); 2890ea4010d1SSteven Rostedt 2891ea4010d1SSteven Rostedt val = read_size(data + field->offset, field->size); 2892ea4010d1SSteven Rostedt 2893ea4010d1SSteven Rostedt /* 2894ea4010d1SSteven Rostedt * peek_data may unmap the data pointer. Copy it first. 2895ea4010d1SSteven Rostedt */ 2896ea4010d1SSteven Rostedt copy_data = malloc_or_die(size); 2897ea4010d1SSteven Rostedt memcpy(copy_data, data, size); 2898ea4010d1SSteven Rostedt data = copy_data; 2899ea4010d1SSteven Rostedt 2900ea4010d1SSteven Rostedt rec = trace_peek_data(cpu); 2901ea4010d1SSteven Rostedt if (rec) { 2902ea4010d1SSteven Rostedt rec = get_return_for_leaf(cpu, pid, val, rec); 2903ea4010d1SSteven Rostedt if (rec) { 2904ea4010d1SSteven Rostedt print_graph_entry_leaf(event, data, rec); 2905ea4010d1SSteven Rostedt goto out_free; 2906ea4010d1SSteven Rostedt } 2907ea4010d1SSteven Rostedt } 2908ea4010d1SSteven Rostedt print_graph_nested(event, data); 2909ea4010d1SSteven Rostedt out_free: 2910ea4010d1SSteven Rostedt free(data); 2911ea4010d1SSteven Rostedt } 2912ea4010d1SSteven Rostedt 2913ea4010d1SSteven Rostedt static void 2914ea4010d1SSteven Rostedt pretty_print_func_ret(void *data, int size __unused, struct event *event, 2915ea4010d1SSteven Rostedt int cpu, int pid, const char *comm, 2916ea4010d1SSteven Rostedt unsigned long secs, unsigned long usecs) 2917ea4010d1SSteven Rostedt { 2918ea4010d1SSteven Rostedt unsigned long long rettime, calltime; 2919ea4010d1SSteven Rostedt unsigned long long duration, depth; 2920ea4010d1SSteven Rostedt struct format_field *field; 2921ea4010d1SSteven Rostedt int i; 2922ea4010d1SSteven Rostedt 2923ea4010d1SSteven Rostedt printf("%5lu.%06lu | ", secs, usecs); 2924ea4010d1SSteven Rostedt 2925ea4010d1SSteven Rostedt print_graph_cpu(cpu); 2926ea4010d1SSteven Rostedt print_graph_proc(pid, comm); 2927ea4010d1SSteven Rostedt 2928ea4010d1SSteven Rostedt printf(" | "); 2929ea4010d1SSteven Rostedt 2930cda48461SSteven Rostedt if (latency_format) { 2931cda48461SSteven Rostedt print_lat_fmt(data, size); 2932cda48461SSteven Rostedt printf(" | "); 2933cda48461SSteven Rostedt } 2934cda48461SSteven Rostedt 2935ea4010d1SSteven Rostedt field = find_field(event, "rettime"); 2936ea4010d1SSteven Rostedt if (!field) 2937ea4010d1SSteven Rostedt die("can't find rettime in return graph"); 2938ea4010d1SSteven Rostedt rettime = read_size(data + field->offset, field->size); 2939ea4010d1SSteven Rostedt 2940ea4010d1SSteven Rostedt field = find_field(event, "calltime"); 2941ea4010d1SSteven Rostedt if (!field) 2942ea4010d1SSteven Rostedt die("can't find calltime in return graph"); 2943ea4010d1SSteven Rostedt calltime = read_size(data + field->offset, field->size); 2944ea4010d1SSteven Rostedt 2945ea4010d1SSteven Rostedt duration = rettime - calltime; 2946ea4010d1SSteven Rostedt 2947ea4010d1SSteven Rostedt /* Overhead */ 2948ea4010d1SSteven Rostedt print_graph_overhead(duration); 2949ea4010d1SSteven Rostedt 2950ea4010d1SSteven Rostedt /* Duration */ 2951ea4010d1SSteven Rostedt print_graph_duration(duration); 2952ea4010d1SSteven Rostedt 2953ea4010d1SSteven Rostedt field = find_field(event, "depth"); 2954ea4010d1SSteven Rostedt if (!field) 2955ea4010d1SSteven Rostedt die("can't find depth in entry graph"); 2956ea4010d1SSteven Rostedt depth = read_size(data + field->offset, field->size); 2957ea4010d1SSteven Rostedt 2958ea4010d1SSteven Rostedt /* Function */ 2959ea4010d1SSteven Rostedt for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++) 2960ea4010d1SSteven Rostedt printf(" "); 2961ea4010d1SSteven Rostedt 2962ea4010d1SSteven Rostedt printf("}"); 2963ea4010d1SSteven Rostedt } 2964ea4010d1SSteven Rostedt 2965ea4010d1SSteven Rostedt static void 2966ea4010d1SSteven Rostedt pretty_print_func_graph(void *data, int size, struct event *event, 2967ea4010d1SSteven Rostedt int cpu, int pid, const char *comm, 2968ea4010d1SSteven Rostedt unsigned long secs, unsigned long usecs) 2969ea4010d1SSteven Rostedt { 2970ea4010d1SSteven Rostedt if (event->flags & EVENT_FL_ISFUNCENT) 2971ea4010d1SSteven Rostedt pretty_print_func_ent(data, size, event, 2972ea4010d1SSteven Rostedt cpu, pid, comm, secs, usecs); 2973ea4010d1SSteven Rostedt else if (event->flags & EVENT_FL_ISFUNCRET) 2974ea4010d1SSteven Rostedt pretty_print_func_ret(data, size, event, 2975ea4010d1SSteven Rostedt cpu, pid, comm, secs, usecs); 2976ea4010d1SSteven Rostedt printf("\n"); 2977ea4010d1SSteven Rostedt } 2978ea4010d1SSteven Rostedt 2979ea4010d1SSteven Rostedt void print_event(int cpu, void *data, int size, unsigned long long nsecs, 2980ea4010d1SSteven Rostedt char *comm) 2981ea4010d1SSteven Rostedt { 2982ea4010d1SSteven Rostedt struct event *event; 2983ea4010d1SSteven Rostedt unsigned long secs; 2984ea4010d1SSteven Rostedt unsigned long usecs; 2985ea4010d1SSteven Rostedt int type; 2986ea4010d1SSteven Rostedt int pid; 2987ea4010d1SSteven Rostedt 2988ea4010d1SSteven Rostedt secs = nsecs / NSECS_PER_SEC; 2989ea4010d1SSteven Rostedt nsecs -= secs * NSECS_PER_SEC; 2990ea4010d1SSteven Rostedt usecs = nsecs / NSECS_PER_USEC; 2991ea4010d1SSteven Rostedt 2992ec156764SIngo Molnar type = trace_parse_common_type(data); 2993ea4010d1SSteven Rostedt 2994ec156764SIngo Molnar event = trace_find_event(type); 2995ea57c4f5SIngo Molnar if (!event) { 299607a4bdddSSteven Rostedt warning("ug! no event found for type %d", type); 2997ea57c4f5SIngo Molnar return; 2998ea57c4f5SIngo Molnar } 2999ea4010d1SSteven Rostedt 300016c632deSTom Zanussi pid = trace_parse_common_pid(data); 3001ea4010d1SSteven Rostedt 3002ea4010d1SSteven Rostedt if (event->flags & (EVENT_FL_ISFUNCENT | EVENT_FL_ISFUNCRET)) 3003ea4010d1SSteven Rostedt return pretty_print_func_graph(data, size, event, cpu, 3004ea4010d1SSteven Rostedt pid, comm, secs, usecs); 3005ea4010d1SSteven Rostedt 3006cda48461SSteven Rostedt if (latency_format) { 3007cda48461SSteven Rostedt printf("%8.8s-%-5d %3d", 3008cda48461SSteven Rostedt comm, pid, cpu); 3009cda48461SSteven Rostedt print_lat_fmt(data, size); 3010cda48461SSteven Rostedt } else 3011cda48461SSteven Rostedt printf("%16s-%-5d [%03d]", comm, pid, cpu); 3012cda48461SSteven Rostedt 3013cda48461SSteven Rostedt printf(" %5lu.%06lu: %s: ", secs, usecs, event->name); 3014ea4010d1SSteven Rostedt 301507a4bdddSSteven Rostedt if (event->flags & EVENT_FL_FAILED) { 301607a4bdddSSteven Rostedt printf("EVENT '%s' FAILED TO PARSE\n", 301707a4bdddSSteven Rostedt event->name); 301807a4bdddSSteven Rostedt return; 301907a4bdddSSteven Rostedt } 302007a4bdddSSteven Rostedt 3021ea4010d1SSteven Rostedt pretty_print(data, size, event); 3022ea4010d1SSteven Rostedt printf("\n"); 3023ea4010d1SSteven Rostedt } 3024ea4010d1SSteven Rostedt 3025ea4010d1SSteven Rostedt static void print_fields(struct print_flag_sym *field) 3026ea4010d1SSteven Rostedt { 3027ea4010d1SSteven Rostedt printf("{ %s, %s }", field->value, field->str); 3028ea4010d1SSteven Rostedt if (field->next) { 3029ea4010d1SSteven Rostedt printf(", "); 3030ea4010d1SSteven Rostedt print_fields(field->next); 3031ea4010d1SSteven Rostedt } 3032ea4010d1SSteven Rostedt } 3033ea4010d1SSteven Rostedt 3034ea4010d1SSteven Rostedt static void print_args(struct print_arg *args) 3035ea4010d1SSteven Rostedt { 3036ea4010d1SSteven Rostedt int print_paren = 1; 3037ea4010d1SSteven Rostedt 3038ea4010d1SSteven Rostedt switch (args->type) { 3039ea4010d1SSteven Rostedt case PRINT_NULL: 3040ea4010d1SSteven Rostedt printf("null"); 3041ea4010d1SSteven Rostedt break; 3042ea4010d1SSteven Rostedt case PRINT_ATOM: 3043ea4010d1SSteven Rostedt printf("%s", args->atom.atom); 3044ea4010d1SSteven Rostedt break; 3045ea4010d1SSteven Rostedt case PRINT_FIELD: 3046ea4010d1SSteven Rostedt printf("REC->%s", args->field.name); 3047ea4010d1SSteven Rostedt break; 3048ea4010d1SSteven Rostedt case PRINT_FLAGS: 3049ea4010d1SSteven Rostedt printf("__print_flags("); 3050ea4010d1SSteven Rostedt print_args(args->flags.field); 3051ea4010d1SSteven Rostedt printf(", %s, ", args->flags.delim); 3052ea4010d1SSteven Rostedt print_fields(args->flags.flags); 3053ea4010d1SSteven Rostedt printf(")"); 3054ea4010d1SSteven Rostedt break; 3055ea4010d1SSteven Rostedt case PRINT_SYMBOL: 3056ea4010d1SSteven Rostedt printf("__print_symbolic("); 3057ea4010d1SSteven Rostedt print_args(args->symbol.field); 3058ea4010d1SSteven Rostedt printf(", "); 3059ea4010d1SSteven Rostedt print_fields(args->symbol.symbols); 3060ea4010d1SSteven Rostedt printf(")"); 3061ea4010d1SSteven Rostedt break; 3062ea4010d1SSteven Rostedt case PRINT_STRING: 3063ea4010d1SSteven Rostedt printf("__get_str(%s)", args->string.string); 3064ea4010d1SSteven Rostedt break; 3065ea4010d1SSteven Rostedt case PRINT_TYPE: 3066ea4010d1SSteven Rostedt printf("(%s)", args->typecast.type); 3067ea4010d1SSteven Rostedt print_args(args->typecast.item); 3068ea4010d1SSteven Rostedt break; 3069ea4010d1SSteven Rostedt case PRINT_OP: 3070ea4010d1SSteven Rostedt if (strcmp(args->op.op, ":") == 0) 3071ea4010d1SSteven Rostedt print_paren = 0; 3072ea4010d1SSteven Rostedt if (print_paren) 3073ea4010d1SSteven Rostedt printf("("); 3074ea4010d1SSteven Rostedt print_args(args->op.left); 3075ea4010d1SSteven Rostedt printf(" %s ", args->op.op); 3076ea4010d1SSteven Rostedt print_args(args->op.right); 3077ea4010d1SSteven Rostedt if (print_paren) 3078ea4010d1SSteven Rostedt printf(")"); 3079ea4010d1SSteven Rostedt break; 3080ea4010d1SSteven Rostedt default: 3081ea4010d1SSteven Rostedt /* we should warn... */ 3082ea4010d1SSteven Rostedt return; 3083ea4010d1SSteven Rostedt } 3084ea4010d1SSteven Rostedt if (args->next) { 3085ea4010d1SSteven Rostedt printf("\n"); 3086ea4010d1SSteven Rostedt print_args(args->next); 3087ea4010d1SSteven Rostedt } 3088ea4010d1SSteven Rostedt } 3089ea4010d1SSteven Rostedt 3090c4dc775fSSteven Rostedt static void parse_header_field(const char *field, 3091ea4010d1SSteven Rostedt int *offset, int *size) 3092ea4010d1SSteven Rostedt { 3093ea4010d1SSteven Rostedt char *token; 309413999e59SSteven Rostedt int type; 3095ea4010d1SSteven Rostedt 3096c4dc775fSSteven Rostedt if (read_expected(EVENT_ITEM, "field") < 0) 3097ea4010d1SSteven Rostedt return; 3098c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ":") < 0) 3099ea4010d1SSteven Rostedt return; 310013999e59SSteven Rostedt 3101ea4010d1SSteven Rostedt /* type */ 3102ea4010d1SSteven Rostedt if (read_expect_type(EVENT_ITEM, &token) < 0) 310313999e59SSteven Rostedt goto fail; 3104ea4010d1SSteven Rostedt free_token(token); 3105ea4010d1SSteven Rostedt 310613999e59SSteven Rostedt if (read_expected(EVENT_ITEM, field) < 0) 3107ea4010d1SSteven Rostedt return; 3108c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ";") < 0) 3109ea4010d1SSteven Rostedt return; 3110c4dc775fSSteven Rostedt if (read_expected(EVENT_ITEM, "offset") < 0) 3111ea4010d1SSteven Rostedt return; 3112c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ":") < 0) 3113ea4010d1SSteven Rostedt return; 3114ea4010d1SSteven Rostedt if (read_expect_type(EVENT_ITEM, &token) < 0) 311513999e59SSteven Rostedt goto fail; 3116ea4010d1SSteven Rostedt *offset = atoi(token); 3117ea4010d1SSteven Rostedt free_token(token); 3118c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ";") < 0) 3119ea4010d1SSteven Rostedt return; 3120c4dc775fSSteven Rostedt if (read_expected(EVENT_ITEM, "size") < 0) 3121ea4010d1SSteven Rostedt return; 3122c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ":") < 0) 3123ea4010d1SSteven Rostedt return; 3124ea4010d1SSteven Rostedt if (read_expect_type(EVENT_ITEM, &token) < 0) 312513999e59SSteven Rostedt goto fail; 3126ea4010d1SSteven Rostedt *size = atoi(token); 3127ea4010d1SSteven Rostedt free_token(token); 3128c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ";") < 0) 3129ea4010d1SSteven Rostedt return; 313013999e59SSteven Rostedt type = read_token(&token); 313113999e59SSteven Rostedt if (type != EVENT_NEWLINE) { 313213999e59SSteven Rostedt /* newer versions of the kernel have a "signed" type */ 313313999e59SSteven Rostedt if (type != EVENT_ITEM) 313413999e59SSteven Rostedt goto fail; 313513999e59SSteven Rostedt 3136c4dc775fSSteven Rostedt if (strcmp(token, "signed") != 0) 313713999e59SSteven Rostedt goto fail; 313813999e59SSteven Rostedt 313913999e59SSteven Rostedt free_token(token); 314013999e59SSteven Rostedt 3141c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ":") < 0) 314226a50744STom Zanussi return; 314313999e59SSteven Rostedt 314413999e59SSteven Rostedt if (read_expect_type(EVENT_ITEM, &token)) 314513999e59SSteven Rostedt goto fail; 314613999e59SSteven Rostedt 314726a50744STom Zanussi free_token(token); 3148c4dc775fSSteven Rostedt if (read_expected(EVENT_OP, ";") < 0) 314926a50744STom Zanussi return; 315013999e59SSteven Rostedt 315113999e59SSteven Rostedt if (read_expect_type(EVENT_NEWLINE, &token)) 315213999e59SSteven Rostedt goto fail; 315313999e59SSteven Rostedt } 315413999e59SSteven Rostedt fail: 3155ea4010d1SSteven Rostedt free_token(token); 3156ea4010d1SSteven Rostedt } 3157ea4010d1SSteven Rostedt 3158ea4010d1SSteven Rostedt int parse_header_page(char *buf, unsigned long size) 3159ea4010d1SSteven Rostedt { 3160ea4010d1SSteven Rostedt init_input_buf(buf, size); 3161ea4010d1SSteven Rostedt 3162c4dc775fSSteven Rostedt parse_header_field("timestamp", &header_page_ts_offset, 3163ea4010d1SSteven Rostedt &header_page_ts_size); 3164c4dc775fSSteven Rostedt parse_header_field("commit", &header_page_size_offset, 3165ea4010d1SSteven Rostedt &header_page_size_size); 3166c4dc775fSSteven Rostedt parse_header_field("data", &header_page_data_offset, 3167ea4010d1SSteven Rostedt &header_page_data_size); 3168ea4010d1SSteven Rostedt 3169ea4010d1SSteven Rostedt return 0; 3170ea4010d1SSteven Rostedt } 3171ea4010d1SSteven Rostedt 3172ea4010d1SSteven Rostedt int parse_ftrace_file(char *buf, unsigned long size) 3173ea4010d1SSteven Rostedt { 3174ea4010d1SSteven Rostedt struct format_field *field; 3175ea4010d1SSteven Rostedt struct print_arg *arg, **list; 3176ea4010d1SSteven Rostedt struct event *event; 3177ea4010d1SSteven Rostedt int ret; 3178ea4010d1SSteven Rostedt 3179ea4010d1SSteven Rostedt init_input_buf(buf, size); 3180ea4010d1SSteven Rostedt 3181ea4010d1SSteven Rostedt event = alloc_event(); 3182ea4010d1SSteven Rostedt if (!event) 3183ea4010d1SSteven Rostedt return -ENOMEM; 3184ea4010d1SSteven Rostedt 3185ea4010d1SSteven Rostedt event->flags |= EVENT_FL_ISFTRACE; 3186ea4010d1SSteven Rostedt 3187ea4010d1SSteven Rostedt event->name = event_read_name(); 3188ea4010d1SSteven Rostedt if (!event->name) 3189ea4010d1SSteven Rostedt die("failed to read ftrace event name"); 3190ea4010d1SSteven Rostedt 3191ea4010d1SSteven Rostedt if (strcmp(event->name, "function") == 0) 3192ea4010d1SSteven Rostedt event->flags |= EVENT_FL_ISFUNC; 3193ea4010d1SSteven Rostedt 3194ea4010d1SSteven Rostedt else if (strcmp(event->name, "funcgraph_entry") == 0) 3195ea4010d1SSteven Rostedt event->flags |= EVENT_FL_ISFUNCENT; 3196ea4010d1SSteven Rostedt 3197ea4010d1SSteven Rostedt else if (strcmp(event->name, "funcgraph_exit") == 0) 3198ea4010d1SSteven Rostedt event->flags |= EVENT_FL_ISFUNCRET; 3199ea4010d1SSteven Rostedt 3200ea4010d1SSteven Rostedt else if (strcmp(event->name, "bprint") == 0) 3201ea4010d1SSteven Rostedt event->flags |= EVENT_FL_ISBPRINT; 3202ea4010d1SSteven Rostedt 3203ea4010d1SSteven Rostedt event->id = event_read_id(); 3204ea4010d1SSteven Rostedt if (event->id < 0) 3205ea4010d1SSteven Rostedt die("failed to read ftrace event id"); 3206ea4010d1SSteven Rostedt 3207ea4010d1SSteven Rostedt add_event(event); 3208ea4010d1SSteven Rostedt 3209ea4010d1SSteven Rostedt ret = event_read_format(event); 3210ea4010d1SSteven Rostedt if (ret < 0) 3211ea4010d1SSteven Rostedt die("failed to read ftrace event format"); 3212ea4010d1SSteven Rostedt 3213ea4010d1SSteven Rostedt ret = event_read_print(event); 3214ea4010d1SSteven Rostedt if (ret < 0) 3215ea4010d1SSteven Rostedt die("failed to read ftrace event print fmt"); 3216ea4010d1SSteven Rostedt 32170d1da915SSteven Rostedt /* New ftrace handles args */ 32180d1da915SSteven Rostedt if (ret > 0) 32190d1da915SSteven Rostedt return 0; 3220ea4010d1SSteven Rostedt /* 3221ea4010d1SSteven Rostedt * The arguments for ftrace files are parsed by the fields. 3222ea4010d1SSteven Rostedt * Set up the fields as their arguments. 3223ea4010d1SSteven Rostedt */ 3224ea4010d1SSteven Rostedt list = &event->print_fmt.args; 3225ea4010d1SSteven Rostedt for (field = event->format.fields; field; field = field->next) { 3226ea4010d1SSteven Rostedt arg = malloc_or_die(sizeof(*arg)); 3227ea4010d1SSteven Rostedt memset(arg, 0, sizeof(*arg)); 3228ea4010d1SSteven Rostedt *list = arg; 3229ea4010d1SSteven Rostedt list = &arg->next; 3230ea4010d1SSteven Rostedt arg->type = PRINT_FIELD; 3231ea4010d1SSteven Rostedt arg->field.name = field->name; 3232ea4010d1SSteven Rostedt arg->field.field = field; 3233ea4010d1SSteven Rostedt } 3234ea4010d1SSteven Rostedt return 0; 3235ea4010d1SSteven Rostedt } 3236ea4010d1SSteven Rostedt 323727746018STom Zanussi int parse_event_file(char *buf, unsigned long size, char *sys) 3238ea4010d1SSteven Rostedt { 3239ea4010d1SSteven Rostedt struct event *event; 3240ea4010d1SSteven Rostedt int ret; 3241ea4010d1SSteven Rostedt 3242ea4010d1SSteven Rostedt init_input_buf(buf, size); 3243ea4010d1SSteven Rostedt 3244ea4010d1SSteven Rostedt event = alloc_event(); 3245ea4010d1SSteven Rostedt if (!event) 3246ea4010d1SSteven Rostedt return -ENOMEM; 3247ea4010d1SSteven Rostedt 3248ea4010d1SSteven Rostedt event->name = event_read_name(); 3249ea4010d1SSteven Rostedt if (!event->name) 3250ea4010d1SSteven Rostedt die("failed to read event name"); 3251ea4010d1SSteven Rostedt 3252ea4010d1SSteven Rostedt event->id = event_read_id(); 3253ea4010d1SSteven Rostedt if (event->id < 0) 3254ea4010d1SSteven Rostedt die("failed to read event id"); 3255ea4010d1SSteven Rostedt 3256ea4010d1SSteven Rostedt ret = event_read_format(event); 325707a4bdddSSteven Rostedt if (ret < 0) { 325807a4bdddSSteven Rostedt warning("failed to read event format for %s", event->name); 325907a4bdddSSteven Rostedt goto event_failed; 326007a4bdddSSteven Rostedt } 3261ea4010d1SSteven Rostedt 3262ea4010d1SSteven Rostedt ret = event_read_print(event); 326307a4bdddSSteven Rostedt if (ret < 0) { 326407a4bdddSSteven Rostedt warning("failed to read event print fmt for %s", event->name); 326507a4bdddSSteven Rostedt goto event_failed; 326607a4bdddSSteven Rostedt } 3267ea4010d1SSteven Rostedt 326827746018STom Zanussi event->system = strdup(sys); 326927746018STom Zanussi 3270ea4010d1SSteven Rostedt #define PRINT_ARGS 0 3271ea4010d1SSteven Rostedt if (PRINT_ARGS && event->print_fmt.args) 3272ea4010d1SSteven Rostedt print_args(event->print_fmt.args); 3273ea4010d1SSteven Rostedt 3274ea4010d1SSteven Rostedt add_event(event); 3275ea4010d1SSteven Rostedt return 0; 327607a4bdddSSteven Rostedt 327707a4bdddSSteven Rostedt event_failed: 327807a4bdddSSteven Rostedt event->flags |= EVENT_FL_FAILED; 327907a4bdddSSteven Rostedt /* still add it even if it failed */ 328007a4bdddSSteven Rostedt add_event(event); 328107a4bdddSSteven Rostedt return -1; 3282ea4010d1SSteven Rostedt } 3283ea4010d1SSteven Rostedt 3284ea4010d1SSteven Rostedt void parse_set_info(int nr_cpus, int long_sz) 3285ea4010d1SSteven Rostedt { 3286ea4010d1SSteven Rostedt cpus = nr_cpus; 3287ea4010d1SSteven Rostedt long_size = long_sz; 3288ea4010d1SSteven Rostedt } 32897397d80dSTom Zanussi 32907397d80dSTom Zanussi int common_pc(struct scripting_context *context) 32917397d80dSTom Zanussi { 32927397d80dSTom Zanussi return parse_common_pc(context->event_data); 32937397d80dSTom Zanussi } 32947397d80dSTom Zanussi 32957397d80dSTom Zanussi int common_flags(struct scripting_context *context) 32967397d80dSTom Zanussi { 32977397d80dSTom Zanussi return parse_common_flags(context->event_data); 32987397d80dSTom Zanussi } 32997397d80dSTom Zanussi 33007397d80dSTom Zanussi int common_lock_depth(struct scripting_context *context) 33017397d80dSTom Zanussi { 33027397d80dSTom Zanussi return parse_common_lock_depth(context->event_data); 33037397d80dSTom Zanussi } 3304