From b22da3d8526a935aa31e086e63f60ff3246cb61c Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Sat, 09 Dec 2023 07:24:11 +0000 Subject: [PATCH] add stmac read mac form eeprom --- kernel/tools/lib/traceevent/event-parse.c | 3845 +++++++++++++++++++++++++++++++++++------------------------ 1 files changed, 2,278 insertions(+), 1,567 deletions(-) diff --git a/kernel/tools/lib/traceevent/event-parse.c b/kernel/tools/lib/traceevent/event-parse.c index c0fcc8a..fe58843 100644 --- a/kernel/tools/lib/traceevent/event-parse.c +++ b/kernel/tools/lib/traceevent/event-parse.c @@ -18,12 +18,14 @@ #include <errno.h> #include <stdint.h> #include <limits.h> -#include <linux/string.h> #include <linux/time64.h> #include <netinet/in.h> #include "event-parse.h" + +#include "event-parse-local.h" #include "event-utils.h" +#include "trace-seq.h" static const char *input_buf; static unsigned long long input_buf_ptr; @@ -52,19 +54,26 @@ warning(fmt, ##__VA_ARGS__); \ } while (0) -static void init_input_buf(const char *buf, unsigned long long size) +/** + * init_input_buf - init buffer for parsing + * @buf: buffer to parse + * @size: the size of the buffer + * + * Initializes the internal buffer that tep_read_token() will parse. + */ +__hidden void init_input_buf(const char *buf, unsigned long long size) { input_buf = buf; input_buf_siz = size; input_buf_ptr = 0; } -const char *tep_get_input_buf(void) +__hidden const char *get_input_buf(void) { return input_buf; } -unsigned long long tep_get_input_buf_ptr(void) +__hidden unsigned long long get_input_buf_ptr(void) { return input_buf_ptr; } @@ -94,22 +103,9 @@ static unsigned long long process_defined_func(struct trace_seq *s, void *data, int size, - struct event_format *event, struct print_arg *arg); + struct tep_event *event, struct tep_print_arg *arg); static void free_func_handle(struct tep_function_handler *func); - -/** - * tep_buffer_init - init buffer for parsing - * @buf: buffer to parse - * @size: the size of the buffer - * - * For use with tep_read_token(), this initializes the internal - * buffer that tep_read_token() will parse. - */ -void tep_buffer_init(const char *buf, unsigned long long size) -{ - init_input_buf(buf, size); -} void breakpoint(void) { @@ -117,25 +113,44 @@ x++; } -struct print_arg *alloc_arg(void) +static struct tep_print_arg *alloc_arg(void) { - return calloc(1, sizeof(struct print_arg)); + return calloc(1, sizeof(struct tep_print_arg)); } -struct cmdline { +struct tep_cmdline { char *comm; int pid; }; static int cmdline_cmp(const void *a, const void *b) { - const struct cmdline *ca = a; - const struct cmdline *cb = b; + const struct tep_cmdline *ca = a; + const struct tep_cmdline *cb = b; if (ca->pid < cb->pid) return -1; if (ca->pid > cb->pid) return 1; + + return 0; +} + +/* Looking for where to place the key */ +static int cmdline_slot_cmp(const void *a, const void *b) +{ + const struct tep_cmdline *ca = a; + const struct tep_cmdline *cb = b; + const struct tep_cmdline *cb1 = cb + 1; + + if (ca->pid < cb->pid) + return -1; + + if (ca->pid > cb->pid) { + if (ca->pid <= cb1->pid) + return 0; + return 1; + } return 0; } @@ -146,14 +161,14 @@ int pid; }; -static int cmdline_init(struct tep_handle *pevent) +static int cmdline_init(struct tep_handle *tep) { - struct cmdline_list *cmdlist = pevent->cmdlist; + struct cmdline_list *cmdlist = tep->cmdlist; struct cmdline_list *item; - struct cmdline *cmdlines; + struct tep_cmdline *cmdlines; int i; - cmdlines = malloc(sizeof(*cmdlines) * pevent->cmdline_count); + cmdlines = malloc(sizeof(*cmdlines) * tep->cmdline_count); if (!cmdlines) return -1; @@ -167,29 +182,29 @@ free(item); } - qsort(cmdlines, pevent->cmdline_count, sizeof(*cmdlines), cmdline_cmp); + qsort(cmdlines, tep->cmdline_count, sizeof(*cmdlines), cmdline_cmp); - pevent->cmdlines = cmdlines; - pevent->cmdlist = NULL; + tep->cmdlines = cmdlines; + tep->cmdlist = NULL; return 0; } -static const char *find_cmdline(struct tep_handle *pevent, int pid) +static const char *find_cmdline(struct tep_handle *tep, int pid) { - const struct cmdline *comm; - struct cmdline key; + const struct tep_cmdline *comm; + struct tep_cmdline key; if (!pid) return "<idle>"; - if (!pevent->cmdlines && cmdline_init(pevent)) + if (!tep->cmdlines && cmdline_init(tep)) return "<not enough memory for cmdlines!>"; key.pid = pid; - comm = bsearch(&key, pevent->cmdlines, pevent->cmdline_count, - sizeof(*pevent->cmdlines), cmdline_cmp); + comm = bsearch(&key, tep->cmdlines, tep->cmdline_count, + sizeof(*tep->cmdlines), cmdline_cmp); if (comm) return comm->comm; @@ -197,32 +212,32 @@ } /** - * tep_pid_is_registered - return if a pid has a cmdline registered - * @pevent: handle for the pevent + * tep_is_pid_registered - return if a pid has a cmdline registered + * @tep: a handle to the trace event parser context * @pid: The pid to check if it has a cmdline registered with. * - * Returns 1 if the pid has a cmdline mapped to it - * 0 otherwise. + * Returns true if the pid has a cmdline mapped to it + * false otherwise. */ -int tep_pid_is_registered(struct tep_handle *pevent, int pid) +bool tep_is_pid_registered(struct tep_handle *tep, int pid) { - const struct cmdline *comm; - struct cmdline key; + const struct tep_cmdline *comm; + struct tep_cmdline key; if (!pid) - return 1; + return true; - if (!pevent->cmdlines && cmdline_init(pevent)) - return 0; + if (!tep->cmdlines && cmdline_init(tep)) + return false; key.pid = pid; - comm = bsearch(&key, pevent->cmdlines, pevent->cmdline_count, - sizeof(*pevent->cmdlines), cmdline_cmp); + comm = bsearch(&key, tep->cmdlines, tep->cmdline_count, + sizeof(*tep->cmdlines), cmdline_cmp); if (comm) - return 1; - return 0; + return true; + return false; } /* @@ -230,11 +245,14 @@ * we must add this pid. This is much slower than when cmdlines * are added before the array is initialized. */ -static int add_new_comm(struct tep_handle *pevent, const char *comm, int pid) +static int add_new_comm(struct tep_handle *tep, + const char *comm, int pid, bool override) { - struct cmdline *cmdlines = pevent->cmdlines; - const struct cmdline *cmdline; - struct cmdline key; + struct tep_cmdline *cmdlines = tep->cmdlines; + struct tep_cmdline *cmdline; + struct tep_cmdline key; + char *new_comm; + int cnt; if (!pid) return 0; @@ -242,51 +260,77 @@ /* avoid duplicates */ key.pid = pid; - cmdline = bsearch(&key, pevent->cmdlines, pevent->cmdline_count, - sizeof(*pevent->cmdlines), cmdline_cmp); + cmdline = bsearch(&key, tep->cmdlines, tep->cmdline_count, + sizeof(*tep->cmdlines), cmdline_cmp); if (cmdline) { - errno = EEXIST; - return -1; + if (!override) { + errno = EEXIST; + return -1; + } + new_comm = strdup(comm); + if (!new_comm) { + errno = ENOMEM; + return -1; + } + free(cmdline->comm); + cmdline->comm = new_comm; + + return 0; } - cmdlines = realloc(cmdlines, sizeof(*cmdlines) * (pevent->cmdline_count + 1)); + cmdlines = realloc(cmdlines, sizeof(*cmdlines) * (tep->cmdline_count + 1)); if (!cmdlines) { errno = ENOMEM; return -1; } - pevent->cmdlines = cmdlines; + tep->cmdlines = cmdlines; - cmdlines[pevent->cmdline_count].comm = strdup(comm); - if (!cmdlines[pevent->cmdline_count].comm) { + key.comm = strdup(comm); + if (!key.comm) { errno = ENOMEM; return -1; } - cmdlines[pevent->cmdline_count].pid = pid; - - if (cmdlines[pevent->cmdline_count].comm) - pevent->cmdline_count++; + if (!tep->cmdline_count) { + /* no entries yet */ + tep->cmdlines[0] = key; + tep->cmdline_count++; + return 0; + } - qsort(cmdlines, pevent->cmdline_count, sizeof(*cmdlines), cmdline_cmp); + /* Now find where we want to store the new cmdline */ + cmdline = bsearch(&key, tep->cmdlines, tep->cmdline_count - 1, + sizeof(*tep->cmdlines), cmdline_slot_cmp); + + cnt = tep->cmdline_count; + if (cmdline) { + /* cmdline points to the one before the spot we want */ + cmdline++; + cnt -= cmdline - tep->cmdlines; + + } else { + /* The new entry is either before or after the list */ + if (key.pid > tep->cmdlines[tep->cmdline_count - 1].pid) { + tep->cmdlines[tep->cmdline_count++] = key; + return 0; + } + cmdline = &tep->cmdlines[0]; + } + memmove(cmdline + 1, cmdline, (cnt * sizeof(*cmdline))); + *cmdline = key; + + tep->cmdline_count++; return 0; } -/** - * tep_register_comm - register a pid / comm mapping - * @pevent: handle for the pevent - * @comm: the command line to register - * @pid: the pid to map the command line to - * - * This adds a mapping to search for command line names with - * a given pid. The comm is duplicated. - */ -int tep_register_comm(struct tep_handle *pevent, const char *comm, int pid) +static int _tep_register_comm(struct tep_handle *tep, + const char *comm, int pid, bool override) { struct cmdline_list *item; - if (pevent->cmdlines) - return add_new_comm(pevent, comm, pid); + if (tep->cmdlines) + return add_new_comm(tep, comm, pid, override); item = malloc(sizeof(*item)); if (!item) @@ -301,22 +345,46 @@ return -1; } item->pid = pid; - item->next = pevent->cmdlist; + item->next = tep->cmdlist; - pevent->cmdlist = item; - pevent->cmdline_count++; + tep->cmdlist = item; + tep->cmdline_count++; return 0; } -int tep_register_trace_clock(struct tep_handle *pevent, const char *trace_clock) +/** + * tep_register_comm - register a pid / comm mapping + * @tep: a handle to the trace event parser context + * @comm: the command line to register + * @pid: the pid to map the command line to + * + * This adds a mapping to search for command line names with + * a given pid. The comm is duplicated. If a command with the same pid + * already exist, -1 is returned and errno is set to EEXIST + */ +int tep_register_comm(struct tep_handle *tep, const char *comm, int pid) { - pevent->trace_clock = strdup(trace_clock); - if (!pevent->trace_clock) { + return _tep_register_comm(tep, comm, pid, false); +} + +/** + * tep_override_comm - register a pid / comm mapping + * @tep: a handle to the trace event parser context + * @comm: the command line to register + * @pid: the pid to map the command line to + * + * This adds a mapping to search for command line names with + * a given pid. The comm is duplicated. If a command with the same pid + * already exist, the command string is udapted with the new one + */ +int tep_override_comm(struct tep_handle *tep, const char *comm, int pid) +{ + if (!tep->cmdlines && cmdline_init(tep)) { errno = ENOMEM; return -1; } - return 0; + return _tep_register_comm(tep, comm, pid, true); } struct func_map { @@ -366,18 +434,18 @@ return 1; } -static int func_map_init(struct tep_handle *pevent) +static int func_map_init(struct tep_handle *tep) { struct func_list *funclist; struct func_list *item; struct func_map *func_map; int i; - func_map = malloc(sizeof(*func_map) * (pevent->func_count + 1)); + func_map = malloc(sizeof(*func_map) * (tep->func_count + 1)); if (!func_map) return -1; - funclist = pevent->funclist; + funclist = tep->funclist; i = 0; while (funclist) { @@ -390,34 +458,34 @@ free(item); } - qsort(func_map, pevent->func_count, sizeof(*func_map), func_cmp); + qsort(func_map, tep->func_count, sizeof(*func_map), func_cmp); /* * Add a special record at the end. */ - func_map[pevent->func_count].func = NULL; - func_map[pevent->func_count].addr = 0; - func_map[pevent->func_count].mod = NULL; + func_map[tep->func_count].func = NULL; + func_map[tep->func_count].addr = 0; + func_map[tep->func_count].mod = NULL; - pevent->func_map = func_map; - pevent->funclist = NULL; + tep->func_map = func_map; + tep->funclist = NULL; return 0; } static struct func_map * -__find_func(struct tep_handle *pevent, unsigned long long addr) +__find_func(struct tep_handle *tep, unsigned long long addr) { struct func_map *func; struct func_map key; - if (!pevent->func_map) - func_map_init(pevent); + if (!tep->func_map) + func_map_init(tep); key.addr = addr; - func = bsearch(&key, pevent->func_map, pevent->func_count, - sizeof(*pevent->func_map), func_bcmp); + func = bsearch(&key, tep->func_map, tep->func_count, + sizeof(*tep->func_map), func_bcmp); return func; } @@ -430,15 +498,14 @@ /** * tep_set_function_resolver - set an alternative function resolver - * @pevent: handle for the pevent + * @tep: a handle to the trace event parser context * @resolver: function to be used * @priv: resolver function private state. * * Some tools may have already a way to resolve kernel functions, allow them to - * keep using it instead of duplicating all the entries inside - * pevent->funclist. + * keep using it instead of duplicating all the entries inside tep->funclist. */ -int tep_set_function_resolver(struct tep_handle *pevent, +int tep_set_function_resolver(struct tep_handle *tep, tep_func_resolver_t *func, void *priv) { struct func_resolver *resolver = malloc(sizeof(*resolver)); @@ -449,38 +516,38 @@ resolver->func = func; resolver->priv = priv; - free(pevent->func_resolver); - pevent->func_resolver = resolver; + free(tep->func_resolver); + tep->func_resolver = resolver; return 0; } /** * tep_reset_function_resolver - reset alternative function resolver - * @pevent: handle for the pevent + * @tep: a handle to the trace event parser context * * Stop using whatever alternative resolver was set, use the default * one instead. */ -void tep_reset_function_resolver(struct tep_handle *pevent) +void tep_reset_function_resolver(struct tep_handle *tep) { - free(pevent->func_resolver); - pevent->func_resolver = NULL; + free(tep->func_resolver); + tep->func_resolver = NULL; } static struct func_map * -find_func(struct tep_handle *pevent, unsigned long long addr) +find_func(struct tep_handle *tep, unsigned long long addr) { struct func_map *map; - if (!pevent->func_resolver) - return __find_func(pevent, addr); + if (!tep->func_resolver) + return __find_func(tep, addr); - map = &pevent->func_resolver->map; + map = &tep->func_resolver->map; map->mod = NULL; map->addr = addr; - map->func = pevent->func_resolver->func(pevent->func_resolver->priv, - &map->addr, &map->mod); + map->func = tep->func_resolver->func(tep->func_resolver->priv, + &map->addr, &map->mod); if (map->func == NULL) return NULL; @@ -489,18 +556,18 @@ /** * tep_find_function - find a function by a given address - * @pevent: handle for the pevent + * @tep: a handle to the trace event parser context * @addr: the address to find the function with * * Returns a pointer to the function stored that has the given * address. Note, the address does not have to be exact, it * will select the function that would contain the address. */ -const char *tep_find_function(struct tep_handle *pevent, unsigned long long addr) +const char *tep_find_function(struct tep_handle *tep, unsigned long long addr) { struct func_map *map; - map = find_func(pevent, addr); + map = find_func(tep, addr); if (!map) return NULL; @@ -509,7 +576,7 @@ /** * tep_find_function_address - find a function address by a given address - * @pevent: handle for the pevent + * @tep: a handle to the trace event parser context * @addr: the address to find the function with * * Returns the address the function starts at. This can be used in @@ -517,11 +584,11 @@ * name and the function offset. */ unsigned long long -tep_find_function_address(struct tep_handle *pevent, unsigned long long addr) +tep_find_function_address(struct tep_handle *tep, unsigned long long addr) { struct func_map *map; - map = find_func(pevent, addr); + map = find_func(tep, addr); if (!map) return 0; @@ -530,7 +597,7 @@ /** * tep_register_function - register a function with a given address - * @pevent: handle for the pevent + * @tep: a handle to the trace event parser context * @function: the function name to register * @addr: the address the function starts at * @mod: the kernel module the function may be in (NULL for none) @@ -538,7 +605,7 @@ * This registers a function name with an address and module. * The @func passed in is duplicated. */ -int tep_register_function(struct tep_handle *pevent, char *func, +int tep_register_function(struct tep_handle *tep, char *func, unsigned long long addr, char *mod) { struct func_list *item = malloc(sizeof(*item)); @@ -546,7 +613,7 @@ if (!item) return -1; - item->next = pevent->funclist; + item->next = tep->funclist; item->func = strdup(func); if (!item->func) goto out_free; @@ -559,8 +626,8 @@ item->mod = NULL; item->addr = addr; - pevent->funclist = item; - pevent->func_count++; + tep->funclist = item; + tep->func_count++; return 0; @@ -575,23 +642,23 @@ /** * tep_print_funcs - print out the stored functions - * @pevent: handle for the pevent + * @tep: a handle to the trace event parser context * * This prints out the stored functions. */ -void tep_print_funcs(struct tep_handle *pevent) +void tep_print_funcs(struct tep_handle *tep) { int i; - if (!pevent->func_map) - func_map_init(pevent); + if (!tep->func_map) + func_map_init(tep); - for (i = 0; i < (int)pevent->func_count; i++) { + for (i = 0; i < (int)tep->func_count; i++) { printf("%016llx %s", - pevent->func_map[i].addr, - pevent->func_map[i].func); - if (pevent->func_map[i].mod) - printf(" [%s]\n", pevent->func_map[i].mod); + tep->func_map[i].addr, + tep->func_map[i].func); + if (tep->func_map[i].mod) + printf(" [%s]\n", tep->func_map[i].mod); else printf("\n"); } @@ -621,18 +688,18 @@ return 0; } -static int printk_map_init(struct tep_handle *pevent) +static int printk_map_init(struct tep_handle *tep) { struct printk_list *printklist; struct printk_list *item; struct printk_map *printk_map; int i; - printk_map = malloc(sizeof(*printk_map) * (pevent->printk_count + 1)); + printk_map = malloc(sizeof(*printk_map) * (tep->printk_count + 1)); if (!printk_map) return -1; - printklist = pevent->printklist; + printklist = tep->printklist; i = 0; while (printklist) { @@ -644,41 +711,41 @@ free(item); } - qsort(printk_map, pevent->printk_count, sizeof(*printk_map), printk_cmp); + qsort(printk_map, tep->printk_count, sizeof(*printk_map), printk_cmp); - pevent->printk_map = printk_map; - pevent->printklist = NULL; + tep->printk_map = printk_map; + tep->printklist = NULL; return 0; } static struct printk_map * -find_printk(struct tep_handle *pevent, unsigned long long addr) +find_printk(struct tep_handle *tep, unsigned long long addr) { struct printk_map *printk; struct printk_map key; - if (!pevent->printk_map && printk_map_init(pevent)) + if (!tep->printk_map && printk_map_init(tep)) return NULL; key.addr = addr; - printk = bsearch(&key, pevent->printk_map, pevent->printk_count, - sizeof(*pevent->printk_map), printk_cmp); + printk = bsearch(&key, tep->printk_map, tep->printk_count, + sizeof(*tep->printk_map), printk_cmp); return printk; } /** * tep_register_print_string - register a string by its address - * @pevent: handle for the pevent + * @tep: a handle to the trace event parser context * @fmt: the string format to register * @addr: the address the string was located at * * This registers a string by the address it was stored in the kernel. * The @fmt passed in is duplicated. */ -int tep_register_print_string(struct tep_handle *pevent, const char *fmt, +int tep_register_print_string(struct tep_handle *tep, const char *fmt, unsigned long long addr) { struct printk_list *item = malloc(sizeof(*item)); @@ -687,7 +754,7 @@ if (!item) return -1; - item->next = pevent->printklist; + item->next = tep->printklist; item->addr = addr; /* Strip off quotes and '\n' from the end */ @@ -705,8 +772,8 @@ if (strcmp(p, "\\n") == 0) *p = 0; - pevent->printklist = item; - pevent->printk_count++; + tep->printklist = item; + tep->printk_count++; return 0; @@ -718,70 +785,70 @@ /** * tep_print_printk - print out the stored strings - * @pevent: handle for the pevent + * @tep: a handle to the trace event parser context * * This prints the string formats that were stored. */ -void tep_print_printk(struct tep_handle *pevent) +void tep_print_printk(struct tep_handle *tep) { int i; - if (!pevent->printk_map) - printk_map_init(pevent); + if (!tep->printk_map) + printk_map_init(tep); - for (i = 0; i < (int)pevent->printk_count; i++) { + for (i = 0; i < (int)tep->printk_count; i++) { printf("%016llx %s\n", - pevent->printk_map[i].addr, - pevent->printk_map[i].printk); + tep->printk_map[i].addr, + tep->printk_map[i].printk); } } -static struct event_format *alloc_event(void) +static struct tep_event *alloc_event(void) { - return calloc(1, sizeof(struct event_format)); + return calloc(1, sizeof(struct tep_event)); } -static int add_event(struct tep_handle *pevent, struct event_format *event) +static int add_event(struct tep_handle *tep, struct tep_event *event) { int i; - struct event_format **events = realloc(pevent->events, sizeof(event) * - (pevent->nr_events + 1)); + struct tep_event **events = realloc(tep->events, sizeof(event) * + (tep->nr_events + 1)); if (!events) return -1; - pevent->events = events; + tep->events = events; - for (i = 0; i < pevent->nr_events; i++) { - if (pevent->events[i]->id > event->id) + for (i = 0; i < tep->nr_events; i++) { + if (tep->events[i]->id > event->id) break; } - if (i < pevent->nr_events) - memmove(&pevent->events[i + 1], - &pevent->events[i], - sizeof(event) * (pevent->nr_events - i)); + if (i < tep->nr_events) + memmove(&tep->events[i + 1], + &tep->events[i], + sizeof(event) * (tep->nr_events - i)); - pevent->events[i] = event; - pevent->nr_events++; + tep->events[i] = event; + tep->nr_events++; - event->pevent = pevent; + event->tep = tep; return 0; } -static int event_item_type(enum event_type type) +static int event_item_type(enum tep_event_type type) { switch (type) { - case EVENT_ITEM ... EVENT_SQUOTE: + case TEP_EVENT_ITEM ... TEP_EVENT_SQUOTE: return 1; - case EVENT_ERROR ... EVENT_DELIM: + case TEP_EVENT_ERROR ... TEP_EVENT_DELIM: default: return 0; } } -static void free_flag_sym(struct print_flag_sym *fsym) +static void free_flag_sym(struct tep_print_flag_sym *fsym) { - struct print_flag_sym *next; + struct tep_print_flag_sym *next; while (fsym) { next = fsym->next; @@ -792,60 +859,60 @@ } } -static void free_arg(struct print_arg *arg) +static void free_arg(struct tep_print_arg *arg) { - struct print_arg *farg; + struct tep_print_arg *farg; if (!arg) return; switch (arg->type) { - case PRINT_ATOM: + case TEP_PRINT_ATOM: free(arg->atom.atom); break; - case PRINT_FIELD: + case TEP_PRINT_FIELD: free(arg->field.name); break; - case PRINT_FLAGS: + case TEP_PRINT_FLAGS: free_arg(arg->flags.field); free(arg->flags.delim); free_flag_sym(arg->flags.flags); break; - case PRINT_SYMBOL: + case TEP_PRINT_SYMBOL: free_arg(arg->symbol.field); free_flag_sym(arg->symbol.symbols); break; - case PRINT_HEX: - case PRINT_HEX_STR: + case TEP_PRINT_HEX: + case TEP_PRINT_HEX_STR: free_arg(arg->hex.field); free_arg(arg->hex.size); break; - case PRINT_INT_ARRAY: + case TEP_PRINT_INT_ARRAY: free_arg(arg->int_array.field); free_arg(arg->int_array.count); free_arg(arg->int_array.el_size); break; - case PRINT_TYPE: + case TEP_PRINT_TYPE: free(arg->typecast.type); free_arg(arg->typecast.item); break; - case PRINT_STRING: - case PRINT_BSTRING: + case TEP_PRINT_STRING: + case TEP_PRINT_BSTRING: free(arg->string.string); break; - case PRINT_BITMASK: + case TEP_PRINT_BITMASK: free(arg->bitmask.bitmask); break; - case PRINT_DYNAMIC_ARRAY: - case PRINT_DYNAMIC_ARRAY_LEN: + case TEP_PRINT_DYNAMIC_ARRAY: + case TEP_PRINT_DYNAMIC_ARRAY_LEN: free(arg->dynarray.index); break; - case PRINT_OP: + case TEP_PRINT_OP: free(arg->op.op); free_arg(arg->op.left); free_arg(arg->op.right); break; - case PRINT_FUNC: + case TEP_PRINT_FUNC: while (arg->func.args) { farg = arg->func.args; arg->func.args = farg->next; @@ -853,7 +920,7 @@ } break; - case PRINT_NULL: + case TEP_PRINT_NULL: default: break; } @@ -861,24 +928,24 @@ free(arg); } -static enum event_type get_type(int ch) +static enum tep_event_type get_type(int ch) { if (ch == '\n') - return EVENT_NEWLINE; + return TEP_EVENT_NEWLINE; if (isspace(ch)) - return EVENT_SPACE; + return TEP_EVENT_SPACE; if (isalnum(ch) || ch == '_') - return EVENT_ITEM; + return TEP_EVENT_ITEM; if (ch == '\'') - return EVENT_SQUOTE; + return TEP_EVENT_SQUOTE; if (ch == '"') - return EVENT_DQUOTE; + return TEP_EVENT_DQUOTE; if (!isprint(ch)) - return EVENT_NONE; + return TEP_EVENT_NONE; if (ch == '(' || ch == ')' || ch == ',') - return EVENT_DELIM; + return TEP_EVENT_DELIM; - return EVENT_OP; + return TEP_EVENT_OP; } static int __read_char(void) @@ -889,22 +956,17 @@ return input_buf[input_buf_ptr++]; } -static int __peek_char(void) +/** + * peek_char - peek at the next character that will be read + * + * Returns the next character read, or -1 if end of buffer. + */ +__hidden int peek_char(void) { if (input_buf_ptr >= input_buf_siz) return -1; return input_buf[input_buf_ptr]; -} - -/** - * tep_peek_char - peek at the next character that will be read - * - * Returns the next character read, or -1 if end of buffer. - */ -int tep_peek_char(void) -{ - return __peek_char(); } static int extend_token(char **tok, char *buf, int size) @@ -926,41 +988,41 @@ return 0; } -static enum event_type force_token(const char *str, char **tok); +static enum tep_event_type force_token(const char *str, char **tok); -static enum event_type __read_token(char **tok) +static enum tep_event_type __read_token(char **tok) { char buf[BUFSIZ]; int ch, last_ch, quote_ch, next_ch; int i = 0; int tok_size = 0; - enum event_type type; + enum tep_event_type type; *tok = NULL; ch = __read_char(); if (ch < 0) - return EVENT_NONE; + return TEP_EVENT_NONE; type = get_type(ch); - if (type == EVENT_NONE) + if (type == TEP_EVENT_NONE) return type; buf[i++] = ch; switch (type) { - case EVENT_NEWLINE: - case EVENT_DELIM: + case TEP_EVENT_NEWLINE: + case TEP_EVENT_DELIM: if (asprintf(tok, "%c", ch) < 0) - return EVENT_ERROR; + return TEP_EVENT_ERROR; return type; - case EVENT_OP: + case TEP_EVENT_OP: switch (ch) { case '-': - next_ch = __peek_char(); + next_ch = peek_char(); if (next_ch == '>') { buf[i++] = __read_char(); break; @@ -972,7 +1034,7 @@ case '>': case '<': last_ch = ch; - ch = __peek_char(); + ch = peek_char(); if (ch != last_ch) goto test_equal; buf[i++] = __read_char(); @@ -995,13 +1057,13 @@ return type; test_equal: - ch = __peek_char(); + ch = peek_char(); if (ch == '=') buf[i++] = __read_char(); goto out; - case EVENT_DQUOTE: - case EVENT_SQUOTE: + case TEP_EVENT_DQUOTE: + case TEP_EVENT_SQUOTE: /* don't keep quotes */ i--; quote_ch = ch; @@ -1013,7 +1075,7 @@ tok_size += BUFSIZ; if (extend_token(tok, buf, tok_size) < 0) - return EVENT_NONE; + return TEP_EVENT_NONE; i = 0; } last_ch = ch; @@ -1030,7 +1092,7 @@ * For strings (double quotes) check the next token. * If it is another string, concatinate the two. */ - if (type == EVENT_DQUOTE) { + if (type == TEP_EVENT_DQUOTE) { unsigned long long save_input_buf_ptr = input_buf_ptr; do { @@ -1043,19 +1105,19 @@ goto out; - case EVENT_ERROR ... EVENT_SPACE: - case EVENT_ITEM: + case TEP_EVENT_ERROR ... TEP_EVENT_SPACE: + case TEP_EVENT_ITEM: default: break; } - while (get_type(__peek_char()) == type) { + while (get_type(peek_char()) == type) { if (i == (BUFSIZ - 1)) { buf[i] = 0; tok_size += BUFSIZ; if (extend_token(tok, buf, tok_size) < 0) - return EVENT_NONE; + return TEP_EVENT_NONE; i = 0; } ch = __read_char(); @@ -1065,9 +1127,9 @@ out: buf[i] = 0; if (extend_token(tok, buf, tok_size + i + 1) < 0) - return EVENT_NONE; + return TEP_EVENT_NONE; - if (type == EVENT_ITEM) { + if (type == TEP_EVENT_ITEM) { /* * Older versions of the kernel has a bug that * creates invalid symbols and will break the mac80211 @@ -1094,12 +1156,12 @@ return type; } -static enum event_type force_token(const char *str, char **tok) +static enum tep_event_type force_token(const char *str, char **tok) { const char *save_input_buf; unsigned long long save_input_buf_ptr; unsigned long long save_input_buf_siz; - enum event_type type; + enum tep_event_type type; /* save off the current input pointers */ save_input_buf = input_buf; @@ -1118,31 +1180,18 @@ return type; } -static void free_token(char *tok) +/** + * free_token - free a token returned by tep_read_token + * @token: the token to free + */ +__hidden void free_token(char *tok) { if (tok) free(tok); } -static enum event_type read_token(char **tok) -{ - enum event_type type; - - for (;;) { - type = __read_token(tok); - if (type != EVENT_SPACE) - return type; - - free_token(*tok); - } - - /* not reached */ - *tok = NULL; - return EVENT_NONE; -} - /** - * tep_read_token - access to utilites to use the pevent parser + * read_token - access to utilities to use the tep parser * @tok: The token to return * * This will parse tokens from the string given by @@ -1150,28 +1199,31 @@ * * Returns the token type. */ -enum event_type tep_read_token(char **tok) +__hidden enum tep_event_type read_token(char **tok) { - return read_token(tok); -} - -/** - * tep_free_token - free a token returned by tep_read_token - * @token: the token to free - */ -void tep_free_token(char *token) -{ - free_token(token); -} - -/* no newline */ -static enum event_type read_token_item(char **tok) -{ - enum event_type type; + enum tep_event_type type; for (;;) { type = __read_token(tok); - if (type != EVENT_SPACE && type != EVENT_NEWLINE) + if (type != TEP_EVENT_SPACE) + return type; + + free_token(*tok); + } + + /* not reached */ + *tok = NULL; + return TEP_EVENT_NONE; +} + +/* no newline */ +static enum tep_event_type read_token_item(char **tok) +{ + enum tep_event_type type; + + for (;;) { + type = __read_token(tok); + if (type != TEP_EVENT_SPACE && type != TEP_EVENT_NEWLINE) return type; free_token(*tok); *tok = NULL; @@ -1179,10 +1231,10 @@ /* not reached */ *tok = NULL; - return EVENT_NONE; + return TEP_EVENT_NONE; } -static int test_type(enum event_type type, enum event_type expect) +static int test_type(enum tep_event_type type, enum tep_event_type expect) { if (type != expect) { do_warning("Error: expected type %d but read %d", @@ -1192,8 +1244,8 @@ return 0; } -static int test_type_token(enum event_type type, const char *token, - enum event_type expect, const char *expect_tok) +static int test_type_token(enum tep_event_type type, const char *token, + enum tep_event_type expect, const char *expect_tok) { if (type != expect) { do_warning("Error: expected type %d but read %d", @@ -1209,9 +1261,9 @@ return 0; } -static int __read_expect_type(enum event_type expect, char **tok, int newline_ok) +static int __read_expect_type(enum tep_event_type expect, char **tok, int newline_ok) { - enum event_type type; + enum tep_event_type type; if (newline_ok) type = read_token(tok); @@ -1220,15 +1272,15 @@ return test_type(type, expect); } -static int read_expect_type(enum event_type expect, char **tok) +static int read_expect_type(enum tep_event_type expect, char **tok) { return __read_expect_type(expect, tok, 1); } -static int __read_expected(enum event_type expect, const char *str, +static int __read_expected(enum tep_event_type expect, const char *str, int newline_ok) { - enum event_type type; + enum tep_event_type type; char *token; int ret; @@ -1244,12 +1296,12 @@ return ret; } -static int read_expected(enum event_type expect, const char *str) +static int read_expected(enum tep_event_type expect, const char *str) { return __read_expected(expect, str, 1); } -static int read_expected_item(enum event_type expect, const char *str) +static int read_expected_item(enum tep_event_type expect, const char *str) { return __read_expected(expect, str, 0); } @@ -1258,13 +1310,13 @@ { char *token; - if (read_expected(EVENT_ITEM, "name") < 0) + if (read_expected(TEP_EVENT_ITEM, "name") < 0) return NULL; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) return NULL; - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto fail; return token; @@ -1279,13 +1331,13 @@ char *token; int id; - if (read_expected_item(EVENT_ITEM, "ID") < 0) + if (read_expected_item(TEP_EVENT_ITEM, "ID") < 0) return -1; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) return -1; - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto fail; id = strtoul(token, NULL, 0); @@ -1297,9 +1349,9 @@ return -1; } -static int field_is_string(struct format_field *field) +static int field_is_string(struct tep_format_field *field) { - if ((field->flags & FIELD_IS_ARRAY) && + if ((field->flags & TEP_FIELD_IS_ARRAY) && (strstr(field->type, "char") || strstr(field->type, "u8") || strstr(field->type, "s8"))) return 1; @@ -1307,7 +1359,7 @@ return 0; } -static int field_is_dynamic(struct format_field *field) +static int field_is_dynamic(struct tep_format_field *field) { if (strncmp(field->type, "__data_loc", 10) == 0) return 1; @@ -1315,7 +1367,7 @@ return 0; } -static int field_is_long(struct format_field *field) +static int field_is_long(struct tep_format_field *field) { /* includes long long */ if (strstr(field->type, "long")) @@ -1326,7 +1378,7 @@ static unsigned int type_size(const char *name) { - /* This covers all FIELD_IS_STRING types. */ + /* This covers all TEP_FIELD_IS_STRING types. */ static struct { const char *type; unsigned int size; @@ -1352,26 +1404,41 @@ return 0; } -static int event_read_fields(struct event_format *event, struct format_field **fields) +static int append(char **buf, const char *delim, const char *str) { - struct format_field *field = NULL; - enum event_type type; + char *new_buf; + + new_buf = realloc(*buf, strlen(*buf) + strlen(delim) + strlen(str) + 1); + if (!new_buf) + return -1; + strcat(new_buf, delim); + strcat(new_buf, str); + *buf = new_buf; + return 0; +} + +static int event_read_fields(struct tep_event *event, struct tep_format_field **fields) +{ + struct tep_format_field *field = NULL; + enum tep_event_type type; char *token; char *last_token; + char *delim = " "; int count = 0; + int ret; do { unsigned int size_dynamic = 0; type = read_token(&token); - if (type == EVENT_NEWLINE) { + if (type == TEP_EVENT_NEWLINE) { free_token(token); return count; } count++; - if (test_type_token(type, token, EVENT_ITEM, "field")) + if (test_type_token(type, token, TEP_EVENT_ITEM, "field")) goto fail; free_token(token); @@ -1380,17 +1447,17 @@ * The ftrace fields may still use the "special" name. * Just ignore it. */ - if (event->flags & EVENT_FL_ISFTRACE && - type == EVENT_ITEM && strcmp(token, "special") == 0) { + if (event->flags & TEP_EVENT_FL_ISFTRACE && + type == TEP_EVENT_ITEM && strcmp(token, "special") == 0) { free_token(token); type = read_token(&token); } - if (test_type_token(type, token, EVENT_OP, ":") < 0) + if (test_type_token(type, token, TEP_EVENT_OP, ":") < 0) goto fail; free_token(token); - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto fail; last_token = token; @@ -1404,37 +1471,64 @@ /* read the rest of the type */ for (;;) { type = read_token(&token); - if (type == EVENT_ITEM || - (type == EVENT_OP && strcmp(token, "*") == 0) || + if (type == TEP_EVENT_ITEM || + (type == TEP_EVENT_OP && strcmp(token, "*") == 0) || /* * Some of the ftrace fields are broken and have * an illegal "." in them. */ - (event->flags & EVENT_FL_ISFTRACE && - type == EVENT_OP && strcmp(token, ".") == 0)) { + (event->flags & TEP_EVENT_FL_ISFTRACE && + type == TEP_EVENT_OP && strcmp(token, ".") == 0)) { if (strcmp(token, "*") == 0) - field->flags |= FIELD_IS_POINTER; + field->flags |= TEP_FIELD_IS_POINTER; if (field->type) { - char *new_type; - new_type = realloc(field->type, - strlen(field->type) + - strlen(last_token) + 2); - if (!new_type) { - free(last_token); - goto fail; - } - field->type = new_type; - strcat(field->type, " "); - strcat(field->type, last_token); + ret = append(&field->type, delim, last_token); free(last_token); + if (ret < 0) + goto fail; } else field->type = last_token; last_token = token; + delim = " "; continue; } + /* Handle __attribute__((user)) */ + if ((type == TEP_EVENT_DELIM) && + strcmp("__attribute__", last_token) == 0 && + token[0] == '(') { + int depth = 1; + int ret; + + ret = append(&field->type, " ", last_token); + ret |= append(&field->type, "", "("); + if (ret < 0) + goto fail; + + delim = " "; + while ((type = read_token(&token)) != TEP_EVENT_NONE) { + if (type == TEP_EVENT_DELIM) { + if (token[0] == '(') + depth++; + else if (token[0] == ')') + depth--; + if (!depth) + break; + ret = append(&field->type, "", token); + delim = ""; + } else { + ret = append(&field->type, delim, token); + delim = " "; + } + if (ret < 0) + goto fail; + free(last_token); + last_token = token; + } + continue; + } break; } @@ -1444,48 +1538,44 @@ } field->name = field->alias = last_token; - if (test_type(type, EVENT_OP)) + if (test_type(type, TEP_EVENT_OP)) goto fail; if (strcmp(token, "[") == 0) { - enum event_type last_type = type; + enum tep_event_type last_type = type; char *brackets = token; - char *new_brackets; - int len; - field->flags |= FIELD_IS_ARRAY; + field->flags |= TEP_FIELD_IS_ARRAY; type = read_token(&token); - if (type == EVENT_ITEM) + if (type == TEP_EVENT_ITEM) field->arraylen = strtoul(token, NULL, 0); else field->arraylen = 0; while (strcmp(token, "]") != 0) { - if (last_type == EVENT_ITEM && - type == EVENT_ITEM) - len = 2; + const char *delim; + + if (last_type == TEP_EVENT_ITEM && + type == TEP_EVENT_ITEM) + delim = " "; else - len = 1; + delim = ""; + last_type = type; - new_brackets = realloc(brackets, - strlen(brackets) + - strlen(token) + len); - if (!new_brackets) { + ret = append(&brackets, delim, token); + if (ret < 0) { free(brackets); goto fail; } - brackets = new_brackets; - if (len == 2) - strcat(brackets, " "); - strcat(brackets, token); /* We only care about the last token */ field->arraylen = strtoul(token, NULL, 0); free_token(token); type = read_token(&token); - if (type == EVENT_NONE) { + if (type == TEP_EVENT_NONE) { + free(brackets); do_warning_event(event, "failed to find token"); goto fail; } @@ -1493,13 +1583,11 @@ free_token(token); - new_brackets = realloc(brackets, strlen(brackets) + 2); - if (!new_brackets) { + ret = append(&brackets, "", "]"); + if (ret < 0) { free(brackets); goto fail; } - brackets = new_brackets; - strcat(brackets, "]"); /* add brackets to type */ @@ -1508,115 +1596,104 @@ * If the next token is not an OP, then it is of * the format: type [] item; */ - if (type == EVENT_ITEM) { - char *new_type; - new_type = realloc(field->type, - strlen(field->type) + - strlen(field->name) + - strlen(brackets) + 2); - if (!new_type) { + if (type == TEP_EVENT_ITEM) { + ret = append(&field->type, " ", field->name); + if (ret < 0) { free(brackets); goto fail; } - field->type = new_type; - strcat(field->type, " "); - strcat(field->type, field->name); + ret = append(&field->type, "", brackets); + size_dynamic = type_size(field->name); free_token(field->name); - strcat(field->type, brackets); field->name = field->alias = token; type = read_token(&token); } else { - char *new_type; - new_type = realloc(field->type, - strlen(field->type) + - strlen(brackets) + 1); - if (!new_type) { + ret = append(&field->type, "", brackets); + if (ret < 0) { free(brackets); goto fail; } - field->type = new_type; - strcat(field->type, brackets); } free(brackets); } if (field_is_string(field)) - field->flags |= FIELD_IS_STRING; + field->flags |= TEP_FIELD_IS_STRING; if (field_is_dynamic(field)) - field->flags |= FIELD_IS_DYNAMIC; + field->flags |= TEP_FIELD_IS_DYNAMIC; if (field_is_long(field)) - field->flags |= FIELD_IS_LONG; + field->flags |= TEP_FIELD_IS_LONG; - if (test_type_token(type, token, EVENT_OP, ";")) + if (test_type_token(type, token, TEP_EVENT_OP, ";")) goto fail; free_token(token); - if (read_expected(EVENT_ITEM, "offset") < 0) + if (read_expected(TEP_EVENT_ITEM, "offset") < 0) goto fail_expect; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) goto fail_expect; - if (read_expect_type(EVENT_ITEM, &token)) + if (read_expect_type(TEP_EVENT_ITEM, &token)) goto fail; field->offset = strtoul(token, NULL, 0); free_token(token); - if (read_expected(EVENT_OP, ";") < 0) + if (read_expected(TEP_EVENT_OP, ";") < 0) goto fail_expect; - if (read_expected(EVENT_ITEM, "size") < 0) + if (read_expected(TEP_EVENT_ITEM, "size") < 0) goto fail_expect; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) goto fail_expect; - if (read_expect_type(EVENT_ITEM, &token)) + if (read_expect_type(TEP_EVENT_ITEM, &token)) goto fail; field->size = strtoul(token, NULL, 0); free_token(token); - if (read_expected(EVENT_OP, ";") < 0) + if (read_expected(TEP_EVENT_OP, ";") < 0) goto fail_expect; type = read_token(&token); - if (type != EVENT_NEWLINE) { + if (type != TEP_EVENT_NEWLINE) { /* newer versions of the kernel have a "signed" type */ - if (test_type_token(type, token, EVENT_ITEM, "signed")) + if (test_type_token(type, token, TEP_EVENT_ITEM, "signed")) goto fail; free_token(token); - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) goto fail_expect; - if (read_expect_type(EVENT_ITEM, &token)) + if (read_expect_type(TEP_EVENT_ITEM, &token)) goto fail; if (strtoul(token, NULL, 0)) - field->flags |= FIELD_IS_SIGNED; + field->flags |= TEP_FIELD_IS_SIGNED; free_token(token); - if (read_expected(EVENT_OP, ";") < 0) + if (read_expected(TEP_EVENT_OP, ";") < 0) goto fail_expect; - if (read_expect_type(EVENT_NEWLINE, &token)) + if (read_expect_type(TEP_EVENT_NEWLINE, &token)) goto fail; } free_token(token); - if (field->flags & FIELD_IS_ARRAY) { + if (field->flags & TEP_FIELD_IS_ARRAY) { if (field->arraylen) field->elementsize = field->size / field->arraylen; - else if (field->flags & FIELD_IS_DYNAMIC) + else if (field->flags & TEP_FIELD_IS_DYNAMIC) field->elementsize = size_dynamic; - else if (field->flags & FIELD_IS_STRING) + else if (field->flags & TEP_FIELD_IS_STRING) field->elementsize = 1; - else if (field->flags & FIELD_IS_LONG) - field->elementsize = event->pevent ? - event->pevent->long_size : + else if (field->flags & TEP_FIELD_IS_LONG) + field->elementsize = event->tep ? + event->tep->long_size : sizeof(long); } else field->elementsize = field->size; @@ -1639,18 +1716,18 @@ return -1; } -static int event_read_format(struct event_format *event) +static int event_read_format(struct tep_event *event) { char *token; int ret; - if (read_expected_item(EVENT_ITEM, "format") < 0) + if (read_expected_item(TEP_EVENT_ITEM, "format") < 0) return -1; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) return -1; - if (read_expect_type(EVENT_NEWLINE, &token)) + if (read_expect_type(TEP_EVENT_NEWLINE, &token)) goto fail; free_token(token); @@ -1671,14 +1748,14 @@ return -1; } -static enum event_type -process_arg_token(struct event_format *event, struct print_arg *arg, - char **tok, enum event_type type); +static enum tep_event_type +process_arg_token(struct tep_event *event, struct tep_print_arg *arg, + char **tok, enum tep_event_type type); -static enum event_type -process_arg(struct event_format *event, struct print_arg *arg, char **tok) +static enum tep_event_type +process_arg(struct tep_event *event, struct tep_print_arg *arg, char **tok) { - enum event_type type; + enum tep_event_type type; char *token; type = read_token(&token); @@ -1687,32 +1764,32 @@ return process_arg_token(event, arg, tok, type); } -static enum event_type -process_op(struct event_format *event, struct print_arg *arg, char **tok); +static enum tep_event_type +process_op(struct tep_event *event, struct tep_print_arg *arg, char **tok); /* * For __print_symbolic() and __print_flags, we need to completely * evaluate the first argument, which defines what to print next. */ -static enum event_type -process_field_arg(struct event_format *event, struct print_arg *arg, char **tok) +static enum tep_event_type +process_field_arg(struct tep_event *event, struct tep_print_arg *arg, char **tok) { - enum event_type type; + enum tep_event_type type; type = process_arg(event, arg, tok); - while (type == EVENT_OP) { + while (type == TEP_EVENT_OP) { type = process_op(event, arg, tok); } return type; } -static enum event_type -process_cond(struct event_format *event, struct print_arg *top, char **tok) +static enum tep_event_type +process_cond(struct tep_event *event, struct tep_print_arg *top, char **tok) { - struct print_arg *arg, *left, *right; - enum event_type type; + struct tep_print_arg *arg, *left, *right; + enum tep_event_type type; char *token = NULL; arg = alloc_arg(); @@ -1727,7 +1804,7 @@ goto out_free; } - arg->type = PRINT_OP; + arg->type = TEP_PRINT_OP; arg->op.left = left; arg->op.right = right; @@ -1735,16 +1812,16 @@ type = process_arg(event, left, &token); again: - if (type == EVENT_ERROR) + if (type == TEP_EVENT_ERROR) goto out_free; /* Handle other operations in the arguments */ - if (type == EVENT_OP && strcmp(token, ":") != 0) { + if (type == TEP_EVENT_OP && strcmp(token, ":") != 0) { type = process_op(event, left, &token); goto again; } - if (test_type_token(type, token, EVENT_OP, ":")) + if (test_type_token(type, token, TEP_EVENT_OP, ":")) goto out_free; arg->op.op = token; @@ -1761,14 +1838,14 @@ top->op.right = NULL; free_token(token); free_arg(arg); - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type -process_array(struct event_format *event, struct print_arg *top, char **tok) +static enum tep_event_type +process_array(struct tep_event *event, struct tep_print_arg *top, char **tok) { - struct print_arg *arg; - enum event_type type; + struct tep_print_arg *arg; + enum tep_event_type type; char *token = NULL; arg = alloc_arg(); @@ -1776,12 +1853,12 @@ do_warning_event(event, "%s: not enough memory!", __func__); /* '*tok' is set to top->op.op. No need to free. */ *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } *tok = NULL; type = process_arg(event, arg, &token); - if (test_type_token(type, token, EVENT_OP, "]")) + if (test_type_token(type, token, TEP_EVENT_OP, "]")) goto out_free; top->op.right = arg; @@ -1795,7 +1872,7 @@ out_free: free_token(token); free_arg(arg); - return EVENT_ERROR; + return TEP_EVENT_ERROR; } static int get_op_prio(char *op) @@ -1853,11 +1930,11 @@ } } -static int set_op_prio(struct print_arg *arg) +static int set_op_prio(struct tep_print_arg *arg) { /* single ops are the greatest */ - if (!arg->op.left || arg->op.left->type == PRINT_NULL) + if (!arg->op.left || arg->op.left->type == TEP_PRINT_NULL) arg->op.prio = 0; else arg->op.prio = get_op_prio(arg->op.op); @@ -1866,17 +1943,17 @@ } /* Note, *tok does not get freed, but will most likely be saved */ -static enum event_type -process_op(struct event_format *event, struct print_arg *arg, char **tok) +static enum tep_event_type +process_op(struct tep_event *event, struct tep_print_arg *arg, char **tok) { - struct print_arg *left, *right = NULL; - enum event_type type; + struct tep_print_arg *left, *right = NULL; + enum tep_event_type type; char *token; /* the op is passed in via tok */ token = *tok; - if (arg->type == PRINT_OP && !arg->op.left) { + if (arg->type == TEP_PRINT_OP && !arg->op.left) { /* handle single op */ if (token[1]) { do_warning_event(event, "bad op token %s", token); @@ -1899,7 +1976,7 @@ if (!left) goto out_warn_free; - left->type = PRINT_NULL; + left->type = TEP_PRINT_NULL; arg->op.left = left; right = alloc_arg(); @@ -1921,7 +1998,7 @@ /* copy the top arg to the left */ *left = *arg; - arg->type = PRINT_OP; + arg->type = TEP_PRINT_OP; arg->op.op = token; arg->op.left = left; arg->op.prio = 0; @@ -1955,13 +2032,13 @@ /* copy the top arg to the left */ *left = *arg; - arg->type = PRINT_OP; + arg->type = TEP_PRINT_OP; arg->op.op = token; arg->op.left = left; arg->op.right = NULL; if (set_op_prio(arg) == -1) { - event->flags |= EVENT_FL_FAILED; + event->flags |= TEP_EVENT_FL_FAILED; /* arg->op.op (= token) will be freed at out_free */ arg->op.op = NULL; goto out_free; @@ -1972,20 +2049,17 @@ /* could just be a type pointer */ if ((strcmp(arg->op.op, "*") == 0) && - type == EVENT_DELIM && (strcmp(token, ")") == 0)) { - char *new_atom; + type == TEP_EVENT_DELIM && (strcmp(token, ")") == 0)) { + int ret; - if (left->type != PRINT_ATOM) { + if (left->type != TEP_PRINT_ATOM) { do_warning_event(event, "bad pointer type"); goto out_free; } - new_atom = realloc(left->atom.atom, - strlen(left->atom.atom) + 3); - if (!new_atom) + ret = append(&left->atom.atom, " ", "*"); + if (ret < 0) goto out_warn_free; - left->atom.atom = new_atom; - strcat(left->atom.atom, " *"); free(arg->op.op); *arg = *left; free(left); @@ -1998,16 +2072,16 @@ goto out_warn_free; type = process_arg_token(event, right, tok, type); - if (type == EVENT_ERROR) { + if (type == TEP_EVENT_ERROR) { free_arg(right); /* token was freed in process_arg_token() via *tok */ token = NULL; goto out_free; } - if (right->type == PRINT_OP && + if (right->type == TEP_PRINT_OP && get_op_prio(arg->op.op) < get_op_prio(right->op.op)) { - struct print_arg tmp; + struct tep_print_arg tmp; /* rotate ops according to the priority */ arg->op.right = right->op.left; @@ -2029,7 +2103,7 @@ *left = *arg; - arg->type = PRINT_OP; + arg->type = TEP_PRINT_OP; arg->op.op = token; arg->op.left = left; @@ -2040,12 +2114,12 @@ } else { do_warning_event(event, "unknown op '%s'", token); - event->flags |= EVENT_FL_FAILED; + event->flags |= TEP_EVENT_FL_FAILED; /* the arg is now the left side */ goto out_free; } - if (type == EVENT_OP && strcmp(*tok, ":") != 0) { + if (type == TEP_EVENT_OP && strcmp(*tok, ":") != 0) { int prio; /* higher prios need to be closer to the root */ @@ -2064,34 +2138,34 @@ out_free: free_token(token); *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type -process_entry(struct event_format *event __maybe_unused, struct print_arg *arg, +static enum tep_event_type +process_entry(struct tep_event *event __maybe_unused, struct tep_print_arg *arg, char **tok) { - enum event_type type; + enum tep_event_type type; char *field; char *token; - if (read_expected(EVENT_OP, "->") < 0) + if (read_expected(TEP_EVENT_OP, "->") < 0) goto out_err; - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto out_free; field = token; - arg->type = PRINT_FIELD; + arg->type = TEP_PRINT_FIELD; arg->field.name = field; if (is_flag_field) { arg->field.field = tep_find_any_field(event, arg->field.name); - arg->field.field->flags |= FIELD_IS_FLAG; + arg->field.field->flags |= TEP_FIELD_IS_FLAG; is_flag_field = 0; } else if (is_symbolic_field) { arg->field.field = tep_find_any_field(event, arg->field.name); - arg->field.field->flags |= FIELD_IS_SYMBOLIC; + arg->field.field->flags |= TEP_FIELD_IS_SYMBOLIC; is_symbolic_field = 0; } @@ -2104,14 +2178,14 @@ free_token(token); out_err: *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static int alloc_and_process_delim(struct event_format *event, char *next_token, - struct print_arg **print_arg) +static int alloc_and_process_delim(struct tep_event *event, char *next_token, + struct tep_print_arg **print_arg) { - struct print_arg *field; - enum event_type type; + struct tep_print_arg *field; + enum tep_event_type type; char *token; int ret = 0; @@ -2124,7 +2198,7 @@ type = process_arg(event, field, &token); - if (test_type_token(type, token, EVENT_DELIM, next_token)) { + if (test_type_token(type, token, TEP_EVENT_DELIM, next_token)) { errno = EINVAL; ret = -1; free_arg(field); @@ -2139,7 +2213,7 @@ return ret; } -static char *arg_eval (struct print_arg *arg); +static char *arg_eval (struct tep_print_arg *arg); static unsigned long long eval_type_str(unsigned long long val, const char *type, int pointer) @@ -2236,9 +2310,9 @@ * Try to figure out the type. */ static unsigned long long -eval_type(unsigned long long val, struct print_arg *arg, int pointer) +eval_type(unsigned long long val, struct tep_print_arg *arg, int pointer) { - if (arg->type != PRINT_TYPE) { + if (arg->type != TEP_PRINT_TYPE) { do_warning("expected type argument"); return 0; } @@ -2246,22 +2320,22 @@ return eval_type_str(val, arg->typecast.type, pointer); } -static int arg_num_eval(struct print_arg *arg, long long *val) +static int arg_num_eval(struct tep_print_arg *arg, long long *val) { long long left, right; int ret = 1; switch (arg->type) { - case PRINT_ATOM: + case TEP_PRINT_ATOM: *val = strtoll(arg->atom.atom, NULL, 0); break; - case PRINT_TYPE: + case TEP_PRINT_TYPE: ret = arg_num_eval(arg->typecast.item, val); if (!ret) break; *val = eval_type(*val, arg, 0); break; - case PRINT_OP: + case TEP_PRINT_OP: switch (arg->op.op[0]) { case '|': ret = arg_num_eval(arg->op.left, &left); @@ -2364,7 +2438,7 @@ break; case '-': /* check for negative */ - if (arg->op.left->type == PRINT_NULL) + if (arg->op.left->type == TEP_PRINT_NULL) left = 0; else ret = arg_num_eval(arg->op.left, &left); @@ -2376,7 +2450,7 @@ *val = left - right; break; case '+': - if (arg->op.left->type == PRINT_NULL) + if (arg->op.left->type == TEP_PRINT_NULL) left = 0; else ret = arg_num_eval(arg->op.left, &left); @@ -2399,11 +2473,11 @@ } break; - case PRINT_NULL: - case PRINT_FIELD ... PRINT_SYMBOL: - case PRINT_STRING: - case PRINT_BSTRING: - case PRINT_BITMASK: + case TEP_PRINT_NULL: + case TEP_PRINT_FIELD ... TEP_PRINT_SYMBOL: + case TEP_PRINT_STRING: + case TEP_PRINT_BSTRING: + case TEP_PRINT_BITMASK: default: do_warning("invalid eval type %d", arg->type); ret = 0; @@ -2412,27 +2486,27 @@ return ret; } -static char *arg_eval (struct print_arg *arg) +static char *arg_eval (struct tep_print_arg *arg) { long long val; static char buf[24]; switch (arg->type) { - case PRINT_ATOM: + case TEP_PRINT_ATOM: return arg->atom.atom; - case PRINT_TYPE: + case TEP_PRINT_TYPE: return arg_eval(arg->typecast.item); - case PRINT_OP: + case TEP_PRINT_OP: if (!arg_num_eval(arg, &val)) break; sprintf(buf, "%lld", val); return buf; - case PRINT_NULL: - case PRINT_FIELD ... PRINT_SYMBOL: - case PRINT_STRING: - case PRINT_BSTRING: - case PRINT_BITMASK: + case TEP_PRINT_NULL: + case TEP_PRINT_FIELD ... TEP_PRINT_SYMBOL: + case TEP_PRINT_STRING: + case TEP_PRINT_BSTRING: + case TEP_PRINT_BITMASK: default: do_warning("invalid eval type %d", arg->type); break; @@ -2441,19 +2515,19 @@ return NULL; } -static enum event_type -process_fields(struct event_format *event, struct print_flag_sym **list, char **tok) +static enum tep_event_type +process_fields(struct tep_event *event, struct tep_print_flag_sym **list, char **tok) { - enum event_type type; - struct print_arg *arg = NULL; - struct print_flag_sym *field; + enum tep_event_type type; + struct tep_print_arg *arg = NULL; + struct tep_print_flag_sym *field; char *token = *tok; char *value; do { free_token(token); type = read_token_item(&token); - if (test_type_token(type, token, EVENT_OP, "{")) + if (test_type_token(type, token, TEP_EVENT_OP, "{")) break; arg = alloc_arg(); @@ -2463,13 +2537,13 @@ free_token(token); type = process_arg(event, arg, &token); - if (type == EVENT_OP) + if (type == TEP_EVENT_OP) type = process_op(event, arg, &token); - if (type == EVENT_ERROR) + if (type == TEP_EVENT_ERROR) goto out_free; - if (test_type_token(type, token, EVENT_DELIM, ",")) + if (test_type_token(type, token, TEP_EVENT_DELIM, ",")) goto out_free; field = calloc(1, sizeof(*field)); @@ -2490,7 +2564,7 @@ free_token(token); type = process_arg(event, arg, &token); - if (test_type_token(type, token, EVENT_OP, "}")) + if (test_type_token(type, token, TEP_EVENT_OP, "}")) goto out_free_field; value = arg_eval(arg); @@ -2507,7 +2581,7 @@ free_token(token); type = read_token_item(&token); - } while (type == EVENT_DELIM && strcmp(token, ",") == 0); + } while (type == TEP_EVENT_DELIM && strcmp(token, ",") == 0); *tok = token; return type; @@ -2519,18 +2593,18 @@ free_token(token); *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type -process_flags(struct event_format *event, struct print_arg *arg, char **tok) +static enum tep_event_type +process_flags(struct tep_event *event, struct tep_print_arg *arg, char **tok) { - struct print_arg *field; - enum event_type type; + struct tep_print_arg *field; + enum tep_event_type type; char *token = NULL; memset(arg, 0, sizeof(*arg)); - arg->type = PRINT_FLAGS; + arg->type = TEP_PRINT_FLAGS; field = alloc_arg(); if (!field) { @@ -2541,10 +2615,10 @@ type = process_field_arg(event, field, &token); /* Handle operations in the first argument */ - while (type == EVENT_OP) + while (type == TEP_EVENT_OP) type = process_op(event, field, &token); - if (test_type_token(type, token, EVENT_DELIM, ",")) + if (test_type_token(type, token, TEP_EVENT_DELIM, ",")) goto out_free_field; free_token(token); @@ -2556,11 +2630,11 @@ type = read_token_item(&token); } - if (test_type_token(type, token, EVENT_DELIM, ",")) + if (test_type_token(type, token, TEP_EVENT_DELIM, ",")) goto out_free; type = process_fields(event, &arg->flags.flags, &token); - if (test_type_token(type, token, EVENT_DELIM, ")")) + if (test_type_token(type, token, TEP_EVENT_DELIM, ")")) goto out_free; free_token(token); @@ -2572,18 +2646,18 @@ out_free: free_token(token); *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type -process_symbols(struct event_format *event, struct print_arg *arg, char **tok) +static enum tep_event_type +process_symbols(struct tep_event *event, struct tep_print_arg *arg, char **tok) { - struct print_arg *field; - enum event_type type; + struct tep_print_arg *field; + enum tep_event_type type; char *token = NULL; memset(arg, 0, sizeof(*arg)); - arg->type = PRINT_SYMBOL; + arg->type = TEP_PRINT_SYMBOL; field = alloc_arg(); if (!field) { @@ -2593,13 +2667,13 @@ type = process_field_arg(event, field, &token); - if (test_type_token(type, token, EVENT_DELIM, ",")) + if (test_type_token(type, token, TEP_EVENT_DELIM, ",")) goto out_free_field; arg->symbol.field = field; type = process_fields(event, &arg->symbol.symbols, &token); - if (test_type_token(type, token, EVENT_DELIM, ")")) + if (test_type_token(type, token, TEP_EVENT_DELIM, ")")) goto out_free; free_token(token); @@ -2611,12 +2685,12 @@ out_free: free_token(token); *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type -process_hex_common(struct event_format *event, struct print_arg *arg, - char **tok, enum print_arg_type type) +static enum tep_event_type +process_hex_common(struct tep_event *event, struct tep_print_arg *arg, + char **tok, enum tep_print_arg_type type) { memset(arg, 0, sizeof(*arg)); arg->type = type; @@ -2634,27 +2708,27 @@ arg->hex.field = NULL; out: *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type -process_hex(struct event_format *event, struct print_arg *arg, char **tok) +static enum tep_event_type +process_hex(struct tep_event *event, struct tep_print_arg *arg, char **tok) { - return process_hex_common(event, arg, tok, PRINT_HEX); + return process_hex_common(event, arg, tok, TEP_PRINT_HEX); } -static enum event_type -process_hex_str(struct event_format *event, struct print_arg *arg, +static enum tep_event_type +process_hex_str(struct tep_event *event, struct tep_print_arg *arg, char **tok) { - return process_hex_common(event, arg, tok, PRINT_HEX_STR); + return process_hex_common(event, arg, tok, TEP_PRINT_HEX_STR); } -static enum event_type -process_int_array(struct event_format *event, struct print_arg *arg, char **tok) +static enum tep_event_type +process_int_array(struct tep_event *event, struct tep_print_arg *arg, char **tok) { memset(arg, 0, sizeof(*arg)); - arg->type = PRINT_INT_ARRAY; + arg->type = TEP_PRINT_INT_ARRAY; if (alloc_and_process_delim(event, ",", &arg->int_array.field)) goto out; @@ -2675,18 +2749,18 @@ arg->int_array.field = NULL; out: *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type -process_dynamic_array(struct event_format *event, struct print_arg *arg, char **tok) +static enum tep_event_type +process_dynamic_array(struct tep_event *event, struct tep_print_arg *arg, char **tok) { - struct format_field *field; - enum event_type type; + struct tep_format_field *field; + enum tep_event_type type; char *token; memset(arg, 0, sizeof(*arg)); - arg->type = PRINT_DYNAMIC_ARRAY; + arg->type = TEP_PRINT_DYNAMIC_ARRAY; /* * The item within the parenthesis is another field that holds @@ -2694,7 +2768,7 @@ */ type = read_token(&token); *tok = token; - if (type != EVENT_ITEM) + if (type != TEP_EVENT_ITEM) goto out_free; /* Find the field */ @@ -2706,13 +2780,13 @@ arg->dynarray.field = field; arg->dynarray.index = 0; - if (read_expected(EVENT_DELIM, ")") < 0) + if (read_expected(TEP_EVENT_DELIM, ")") < 0) goto out_free; free_token(token); type = read_token_item(&token); *tok = token; - if (type != EVENT_OP || strcmp(token, "[") != 0) + if (type != TEP_EVENT_OP || strcmp(token, "[") != 0) return type; free_token(token); @@ -2720,14 +2794,14 @@ if (!arg) { do_warning_event(event, "%s: not enough memory!", __func__); *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } type = process_arg(event, arg, &token); - if (type == EVENT_ERROR) + if (type == TEP_EVENT_ERROR) goto out_free_arg; - if (!test_type_token(type, token, EVENT_OP, "]")) + if (!test_type_token(type, token, TEP_EVENT_OP, "]")) goto out_free_arg; free_token(token); @@ -2739,21 +2813,21 @@ out_free: free_token(token); *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type -process_dynamic_array_len(struct event_format *event, struct print_arg *arg, +static enum tep_event_type +process_dynamic_array_len(struct tep_event *event, struct tep_print_arg *arg, char **tok) { - struct format_field *field; - enum event_type type; + struct tep_format_field *field; + enum tep_event_type type; char *token; - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto out_free; - arg->type = PRINT_DYNAMIC_ARRAY_LEN; + arg->type = TEP_PRINT_DYNAMIC_ARRAY_LEN; /* Find the field */ field = tep_find_field(event, token); @@ -2763,7 +2837,7 @@ arg->dynarray.field = field; arg->dynarray.index = 0; - if (read_expected(EVENT_DELIM, ")") < 0) + if (read_expected(TEP_EVENT_DELIM, ")") < 0) goto out_err; free_token(token); @@ -2776,28 +2850,28 @@ free_token(token); out_err: *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type -process_paren(struct event_format *event, struct print_arg *arg, char **tok) +static enum tep_event_type +process_paren(struct tep_event *event, struct tep_print_arg *arg, char **tok) { - struct print_arg *item_arg; - enum event_type type; + struct tep_print_arg *item_arg; + enum tep_event_type type; char *token; type = process_arg(event, arg, &token); - if (type == EVENT_ERROR) + if (type == TEP_EVENT_ERROR) goto out_free; - if (type == EVENT_OP) + if (type == TEP_EVENT_OP) type = process_op(event, arg, &token); - if (type == EVENT_ERROR) + if (type == TEP_EVENT_ERROR) goto out_free; - if (test_type_token(type, token, EVENT_DELIM, ")")) + if (test_type_token(type, token, TEP_EVENT_DELIM, ")")) goto out_free; free_token(token); @@ -2808,13 +2882,13 @@ * this was a typecast. */ if (event_item_type(type) || - (type == EVENT_DELIM && strcmp(token, "(") == 0)) { + (type == TEP_EVENT_DELIM && strcmp(token, "(") == 0)) { /* make this a typecast and contine */ /* prevous must be an atom */ - if (arg->type != PRINT_ATOM) { - do_warning_event(event, "previous needed to be PRINT_ATOM"); + if (arg->type != TEP_PRINT_ATOM) { + do_warning_event(event, "previous needed to be TEP_PRINT_ATOM"); goto out_free; } @@ -2825,7 +2899,7 @@ goto out_free; } - arg->type = PRINT_TYPE; + arg->type = TEP_PRINT_TYPE; arg->typecast.type = arg->atom.atom; arg->typecast.item = item_arg; type = process_arg_token(event, item_arg, &token, type); @@ -2838,25 +2912,25 @@ out_free: free_token(token); *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type -process_str(struct event_format *event __maybe_unused, struct print_arg *arg, +static enum tep_event_type +process_str(struct tep_event *event __maybe_unused, struct tep_print_arg *arg, char **tok) { - enum event_type type; + enum tep_event_type type; char *token; - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto out_free; - arg->type = PRINT_STRING; + arg->type = TEP_PRINT_STRING; arg->string.string = token; arg->string.offset = -1; - if (read_expected(EVENT_DELIM, ")") < 0) + if (read_expected(TEP_EVENT_DELIM, ")") < 0) goto out_err; type = read_token(&token); @@ -2868,24 +2942,24 @@ free_token(token); out_err: *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type -process_bitmask(struct event_format *event __maybe_unused, struct print_arg *arg, - char **tok) +static enum tep_event_type +process_bitmask(struct tep_event *event __maybe_unused, struct tep_print_arg *arg, + char **tok) { - enum event_type type; + enum tep_event_type type; char *token; - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto out_free; - arg->type = PRINT_BITMASK; + arg->type = TEP_PRINT_BITMASK; arg->bitmask.bitmask = token; arg->bitmask.offset = -1; - if (read_expected(EVENT_DELIM, ")") < 0) + if (read_expected(TEP_EVENT_DELIM, ")") < 0) goto out_err; type = read_token(&token); @@ -2897,18 +2971,18 @@ free_token(token); out_err: *tok = NULL; - return EVENT_ERROR; + return TEP_EVENT_ERROR; } static struct tep_function_handler * -find_func_handler(struct tep_handle *pevent, char *func_name) +find_func_handler(struct tep_handle *tep, char *func_name) { struct tep_function_handler *func; - if (!pevent) + if (!tep) return NULL; - for (func = pevent->func_handlers; func; func = func->next) { + for (func = tep->func_handlers; func; func = func->next) { if (strcmp(func->name, func_name) == 0) break; } @@ -2916,12 +2990,12 @@ return func; } -static void remove_func_handler(struct tep_handle *pevent, char *func_name) +static void remove_func_handler(struct tep_handle *tep, char *func_name) { struct tep_function_handler *func; struct tep_function_handler **next; - next = &pevent->func_handlers; + next = &tep->func_handlers; while ((func = *next)) { if (strcmp(func->name, func_name) == 0) { *next = func->next; @@ -2932,17 +3006,17 @@ } } -static enum event_type -process_func_handler(struct event_format *event, struct tep_function_handler *func, - struct print_arg *arg, char **tok) +static enum tep_event_type +process_func_handler(struct tep_event *event, struct tep_function_handler *func, + struct tep_print_arg *arg, char **tok) { - struct print_arg **next_arg; - struct print_arg *farg; - enum event_type type; + struct tep_print_arg **next_arg; + struct tep_print_arg *farg; + enum tep_event_type type; char *token; int i; - arg->type = PRINT_FUNC; + arg->type = TEP_PRINT_FUNC; arg->func.func = func; *tok = NULL; @@ -2953,12 +3027,12 @@ if (!farg) { do_warning_event(event, "%s: not enough memory!", __func__); - return EVENT_ERROR; + return TEP_EVENT_ERROR; } type = process_arg(event, farg, &token); if (i < (func->nr_args - 1)) { - if (type != EVENT_DELIM || strcmp(token, ",") != 0) { + if (type != TEP_EVENT_DELIM || strcmp(token, ",") != 0) { do_warning_event(event, "Error: function '%s()' expects %d arguments but event %s only uses %d", func->name, func->nr_args, @@ -2966,7 +3040,7 @@ goto err; } } else { - if (type != EVENT_DELIM || strcmp(token, ")") != 0) { + if (type != TEP_EVENT_DELIM || strcmp(token, ")") != 0) { do_warning_event(event, "Error: function '%s()' only expects %d arguments but event %s has more", func->name, func->nr_args, event->name); @@ -2987,11 +3061,42 @@ err: free_arg(farg); free_token(token); - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type -process_function(struct event_format *event, struct print_arg *arg, +static enum tep_event_type +process_builtin_expect(struct tep_event *event, struct tep_print_arg *arg, char **tok) +{ + enum tep_event_type type; + char *token = NULL; + + /* Handle __builtin_expect( cond, #) */ + type = process_arg(event, arg, &token); + + if (type != TEP_EVENT_DELIM || token[0] != ',') + goto out_free; + + free_token(token); + + /* We don't care what the second parameter is of the __builtin_expect() */ + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) + goto out_free; + + if (read_expected(TEP_EVENT_DELIM, ")") < 0) + goto out_free; + + free_token(token); + type = read_token_item(tok); + return type; + +out_free: + free_token(token); + *tok = NULL; + return TEP_EVENT_ERROR; +} + +static enum tep_event_type +process_function(struct tep_event *event, struct tep_print_arg *arg, char *token, char **tok) { struct tep_function_handler *func; @@ -3034,8 +3139,12 @@ free_token(token); return process_dynamic_array_len(event, arg, tok); } + if (strcmp(token, "__builtin_expect") == 0) { + free_token(token); + return process_builtin_expect(event, arg, tok); + } - func = find_func_handler(event->pevent, token); + func = find_func_handler(event->tep, token); if (func) { free_token(token); return process_func_handler(event, func, arg, tok); @@ -3043,12 +3152,12 @@ do_warning_event(event, "function %s not defined", token); free_token(token); - return EVENT_ERROR; + return TEP_EVENT_ERROR; } -static enum event_type -process_arg_token(struct event_format *event, struct print_arg *arg, - char **tok, enum event_type type) +static enum tep_event_type +process_arg_token(struct tep_event *event, struct tep_print_arg *arg, + char **tok, enum tep_event_type type) { char *token; char *atom; @@ -3056,7 +3165,7 @@ token = *tok; switch (type) { - case EVENT_ITEM: + case TEP_EVENT_ITEM: if (strcmp(token, "REC") == 0) { free_token(token); type = process_entry(event, arg, &token); @@ -3070,7 +3179,7 @@ * If the next token is a parenthesis, then this * is a function. */ - if (type == EVENT_DELIM && strcmp(token, "(") == 0) { + if (type == TEP_EVENT_DELIM && strcmp(token, "(") == 0) { free_token(token); token = NULL; /* this will free atom. */ @@ -3078,72 +3187,69 @@ break; } /* atoms can be more than one token long */ - while (type == EVENT_ITEM) { - char *new_atom; - new_atom = realloc(atom, - strlen(atom) + strlen(token) + 2); - if (!new_atom) { + while (type == TEP_EVENT_ITEM) { + int ret; + + ret = append(&atom, " ", token); + if (ret < 0) { free(atom); *tok = NULL; free_token(token); - return EVENT_ERROR; + return TEP_EVENT_ERROR; } - atom = new_atom; - strcat(atom, " "); - strcat(atom, token); free_token(token); type = read_token_item(&token); } - arg->type = PRINT_ATOM; + arg->type = TEP_PRINT_ATOM; arg->atom.atom = atom; break; - case EVENT_DQUOTE: - case EVENT_SQUOTE: - arg->type = PRINT_ATOM; + case TEP_EVENT_DQUOTE: + case TEP_EVENT_SQUOTE: + arg->type = TEP_PRINT_ATOM; arg->atom.atom = token; type = read_token_item(&token); break; - case EVENT_DELIM: + case TEP_EVENT_DELIM: if (strcmp(token, "(") == 0) { free_token(token); type = process_paren(event, arg, &token); break; } - case EVENT_OP: + case TEP_EVENT_OP: /* handle single ops */ - arg->type = PRINT_OP; + arg->type = TEP_PRINT_OP; arg->op.op = token; arg->op.left = NULL; type = process_op(event, arg, &token); /* On error, the op is freed */ - if (type == EVENT_ERROR) + if (type == TEP_EVENT_ERROR) arg->op.op = NULL; /* return error type if errored */ break; - case EVENT_ERROR ... EVENT_NEWLINE: + case TEP_EVENT_ERROR ... TEP_EVENT_NEWLINE: default: do_warning_event(event, "unexpected type %d", type); - return EVENT_ERROR; + return TEP_EVENT_ERROR; } *tok = token; return type; } -static int event_read_print_args(struct event_format *event, struct print_arg **list) +static int event_read_print_args(struct tep_event *event, struct tep_print_arg **list) { - enum event_type type = EVENT_ERROR; - struct print_arg *arg; + enum tep_event_type type = TEP_EVENT_ERROR; + struct tep_print_arg *arg; char *token; int args = 0; do { - if (type == EVENT_NEWLINE) { + if (type == TEP_EVENT_NEWLINE) { type = read_token_item(&token); continue; } @@ -3157,7 +3263,7 @@ type = process_arg(event, arg, &token); - if (type == EVENT_ERROR) { + if (type == TEP_EVENT_ERROR) { free_token(token); free_arg(arg); return -1; @@ -3166,10 +3272,10 @@ *list = arg; args++; - if (type == EVENT_OP) { + if (type == TEP_EVENT_OP) { type = process_op(event, arg, &token); free_token(token); - if (type == EVENT_ERROR) { + if (type == TEP_EVENT_ERROR) { *list = NULL; free_arg(arg); return -1; @@ -3178,37 +3284,37 @@ continue; } - if (type == EVENT_DELIM && strcmp(token, ",") == 0) { + if (type == TEP_EVENT_DELIM && strcmp(token, ",") == 0) { free_token(token); *list = arg; list = &arg->next; continue; } break; - } while (type != EVENT_NONE); + } while (type != TEP_EVENT_NONE); - if (type != EVENT_NONE && type != EVENT_ERROR) + if (type != TEP_EVENT_NONE && type != TEP_EVENT_ERROR) free_token(token); return args; } -static int event_read_print(struct event_format *event) +static int event_read_print(struct tep_event *event) { - enum event_type type; + enum tep_event_type type; char *token; int ret; - if (read_expected_item(EVENT_ITEM, "print") < 0) + if (read_expected_item(TEP_EVENT_ITEM, "print") < 0) return -1; - if (read_expected(EVENT_ITEM, "fmt") < 0) + if (read_expected(TEP_EVENT_ITEM, "fmt") < 0) return -1; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) return -1; - if (read_expect_type(EVENT_DQUOTE, &token) < 0) + if (read_expect_type(TEP_EVENT_DQUOTE, &token) < 0) goto fail; concat: @@ -3218,11 +3324,11 @@ /* ok to have no arg */ type = read_token_item(&token); - if (type == EVENT_NONE) + if (type == TEP_EVENT_NONE) return 0; /* Handle concatenation of print lines */ - if (type == EVENT_DQUOTE) { + if (type == TEP_EVENT_DQUOTE) { char *cat; if (asprintf(&cat, "%s%s", event->print_fmt.format, token) < 0) @@ -3234,7 +3340,7 @@ goto concat; } - if (test_type_token(type, token, EVENT_DELIM, ",")) + if (test_type_token(type, token, TEP_EVENT_DELIM, ",")) goto fail; free_token(token); @@ -3256,12 +3362,12 @@ * @name: the name of the common field to return * * Returns a common field from the event by the given @name. - * This only searchs the common fields and not all field. + * This only searches the common fields and not all field. */ -struct format_field * -tep_find_common_field(struct event_format *event, const char *name) +struct tep_format_field * +tep_find_common_field(struct tep_event *event, const char *name) { - struct format_field *format; + struct tep_format_field *format; for (format = event->format.common_fields; format; format = format->next) { @@ -3280,10 +3386,10 @@ * Returns a non-common field by the given @name. * This does not search common fields. */ -struct format_field * -tep_find_field(struct event_format *event, const char *name) +struct tep_format_field * +tep_find_field(struct tep_event *event, const char *name) { - struct format_field *format; + struct tep_format_field *format; for (format = event->format.fields; format; format = format->next) { @@ -3300,13 +3406,13 @@ * @name: the name of the field * * Returns a field by the given @name. - * This searchs the common field names first, then + * This searches the common field names first, then * the non-common ones if a common one was not found. */ -struct format_field * -tep_find_any_field(struct event_format *event, const char *name) +struct tep_format_field * +tep_find_any_field(struct tep_event *event, const char *name) { - struct format_field *format; + struct tep_format_field *format; format = tep_find_common_field(event, name); if (format) @@ -3316,25 +3422,28 @@ /** * tep_read_number - read a number from data - * @pevent: handle for the pevent + * @tep: a handle to the trace event parser context * @ptr: the raw data * @size: the size of the data that holds the number * * Returns the number (converted to host) from the * raw data. */ -unsigned long long tep_read_number(struct tep_handle *pevent, +unsigned long long tep_read_number(struct tep_handle *tep, const void *ptr, int size) { + unsigned long long val; + switch (size) { case 1: return *(unsigned char *)ptr; case 2: - return data2host2(pevent, ptr); + return data2host2(tep, *(unsigned short *)ptr); case 4: - return data2host4(pevent, ptr); + return data2host4(tep, *(unsigned int *)ptr); case 8: - return data2host8(pevent, ptr); + memcpy(&val, (ptr), sizeof(unsigned long long)); + return data2host8(tep, val); default: /* BUG! */ return 0; @@ -3352,7 +3461,7 @@ * * Returns 0 on success, -1 otherwise. */ -int tep_read_number_field(struct format_field *field, const void *data, +int tep_read_number_field(struct tep_format_field *field, const void *data, unsigned long long *value) { if (!field) @@ -3362,7 +3471,7 @@ case 2: case 4: case 8: - *value = tep_read_number(field->event->pevent, + *value = tep_read_number(field->event->tep, data + field->offset, field->size); return 0; default: @@ -3370,22 +3479,22 @@ } } -static int get_common_info(struct tep_handle *pevent, +static int get_common_info(struct tep_handle *tep, const char *type, int *offset, int *size) { - struct event_format *event; - struct format_field *field; + struct tep_event *event; + struct tep_format_field *field; /* * All events should have the same common elements. * Pick any event to find where the type is; */ - if (!pevent->events) { + if (!tep->events) { do_warning("no event_list!"); return -1; } - event = pevent->events[0]; + event = tep->events[0]; field = tep_find_common_field(event, type); if (!field) return -1; @@ -3396,58 +3505,58 @@ return 0; } -static int __parse_common(struct tep_handle *pevent, void *data, +static int __parse_common(struct tep_handle *tep, void *data, int *size, int *offset, const char *name) { int ret; if (!*size) { - ret = get_common_info(pevent, name, offset, size); + ret = get_common_info(tep, name, offset, size); if (ret < 0) return ret; } - return tep_read_number(pevent, data + *offset, *size); + return tep_read_number(tep, data + *offset, *size); } -static int trace_parse_common_type(struct tep_handle *pevent, void *data) +static int trace_parse_common_type(struct tep_handle *tep, void *data) { - return __parse_common(pevent, data, - &pevent->type_size, &pevent->type_offset, + return __parse_common(tep, data, + &tep->type_size, &tep->type_offset, "common_type"); } -static int parse_common_pid(struct tep_handle *pevent, void *data) +static int parse_common_pid(struct tep_handle *tep, void *data) { - return __parse_common(pevent, data, - &pevent->pid_size, &pevent->pid_offset, + return __parse_common(tep, data, + &tep->pid_size, &tep->pid_offset, "common_pid"); } -static int parse_common_pc(struct tep_handle *pevent, void *data) +static int parse_common_pc(struct tep_handle *tep, void *data) { - return __parse_common(pevent, data, - &pevent->pc_size, &pevent->pc_offset, + return __parse_common(tep, data, + &tep->pc_size, &tep->pc_offset, "common_preempt_count"); } -static int parse_common_flags(struct tep_handle *pevent, void *data) +static int parse_common_flags(struct tep_handle *tep, void *data) { - return __parse_common(pevent, data, - &pevent->flags_size, &pevent->flags_offset, + return __parse_common(tep, data, + &tep->flags_size, &tep->flags_offset, "common_flags"); } -static int parse_common_lock_depth(struct tep_handle *pevent, void *data) +static int parse_common_lock_depth(struct tep_handle *tep, void *data) { - return __parse_common(pevent, data, - &pevent->ld_size, &pevent->ld_offset, + return __parse_common(tep, data, + &tep->ld_size, &tep->ld_offset, "common_lock_depth"); } -static int parse_common_migrate_disable(struct tep_handle *pevent, void *data) +static int parse_common_migrate_disable(struct tep_handle *tep, void *data) { - return __parse_common(pevent, data, - &pevent->ld_size, &pevent->ld_offset, + return __parse_common(tep, data, + &tep->ld_size, &tep->ld_offset, "common_migrate_disable"); } @@ -3455,28 +3564,28 @@ /** * tep_find_event - find an event by given id - * @pevent: a handle to the pevent + * @tep: a handle to the trace event parser context * @id: the id of the event * * Returns an event that has a given @id. */ -struct event_format *tep_find_event(struct tep_handle *pevent, int id) +struct tep_event *tep_find_event(struct tep_handle *tep, int id) { - struct event_format **eventptr; - struct event_format key; - struct event_format *pkey = &key; + struct tep_event **eventptr; + struct tep_event key; + struct tep_event *pkey = &key; /* Check cache first */ - if (pevent->last_event && pevent->last_event->id == id) - return pevent->last_event; + if (tep->last_event && tep->last_event->id == id) + return tep->last_event; key.id = id; - eventptr = bsearch(&pkey, pevent->events, pevent->nr_events, - sizeof(*pevent->events), events_id_cmp); + eventptr = bsearch(&pkey, tep->events, tep->nr_events, + sizeof(*tep->events), events_id_cmp); if (eventptr) { - pevent->last_event = *eventptr; + tep->last_event = *eventptr; return *eventptr; } @@ -3485,27 +3594,27 @@ /** * tep_find_event_by_name - find an event by given name - * @pevent: a handle to the pevent + * @tep: a handle to the trace event parser context * @sys: the system name to search for * @name: the name of the event to search for * * This returns an event with a given @name and under the system * @sys. If @sys is NULL the first event with @name is returned. */ -struct event_format * -tep_find_event_by_name(struct tep_handle *pevent, +struct tep_event * +tep_find_event_by_name(struct tep_handle *tep, const char *sys, const char *name) { - struct event_format *event; + struct tep_event *event = NULL; int i; - if (pevent->last_event && - strcmp(pevent->last_event->name, name) == 0 && - (!sys || strcmp(pevent->last_event->system, sys) == 0)) - return pevent->last_event; + if (tep->last_event && + strcmp(tep->last_event->name, name) == 0 && + (!sys || strcmp(tep->last_event->system, sys) == 0)) + return tep->last_event; - for (i = 0; i < pevent->nr_events; i++) { - event = pevent->events[i]; + for (i = 0; i < tep->nr_events; i++) { + event = tep->events[i]; if (strcmp(event->name, name) == 0) { if (!sys) break; @@ -3513,31 +3622,31 @@ break; } } - if (i == pevent->nr_events) + if (i == tep->nr_events) event = NULL; - pevent->last_event = event; + tep->last_event = event; return event; } static unsigned long long -eval_num_arg(void *data, int size, struct event_format *event, struct print_arg *arg) +eval_num_arg(void *data, int size, struct tep_event *event, struct tep_print_arg *arg) { - struct tep_handle *pevent = event->pevent; + struct tep_handle *tep = event->tep; unsigned long long val = 0; unsigned long long left, right; - struct print_arg *typearg = NULL; - struct print_arg *larg; + struct tep_print_arg *typearg = NULL; + struct tep_print_arg *larg; unsigned long offset; unsigned int field_size; switch (arg->type) { - case PRINT_NULL: + case TEP_PRINT_NULL: /* ?? */ return 0; - case PRINT_ATOM: + case TEP_PRINT_ATOM: return strtoull(arg->atom.atom, NULL, 0); - case PRINT_FIELD: + case TEP_PRINT_FIELD: if (!arg->field.field) { arg->field.field = tep_find_any_field(event, arg->field.name); if (!arg->field.field) @@ -3545,30 +3654,30 @@ } /* must be a number */ - val = tep_read_number(pevent, data + arg->field.field->offset, + val = tep_read_number(tep, data + arg->field.field->offset, arg->field.field->size); break; - case PRINT_FLAGS: - case PRINT_SYMBOL: - case PRINT_INT_ARRAY: - case PRINT_HEX: - case PRINT_HEX_STR: + case TEP_PRINT_FLAGS: + case TEP_PRINT_SYMBOL: + case TEP_PRINT_INT_ARRAY: + case TEP_PRINT_HEX: + case TEP_PRINT_HEX_STR: break; - case PRINT_TYPE: + case TEP_PRINT_TYPE: val = eval_num_arg(data, size, event, arg->typecast.item); return eval_type(val, arg, 0); - case PRINT_STRING: - case PRINT_BSTRING: - case PRINT_BITMASK: + case TEP_PRINT_STRING: + case TEP_PRINT_BSTRING: + case TEP_PRINT_BITMASK: return 0; - case PRINT_FUNC: { + case TEP_PRINT_FUNC: { struct trace_seq s; trace_seq_init(&s); val = process_defined_func(&s, data, size, event, arg); trace_seq_destroy(&s); return val; } - case PRINT_OP: + case TEP_PRINT_OP: if (strcmp(arg->op.op, "[") == 0) { /* * Arrays are special, since we don't want @@ -3578,18 +3687,18 @@ /* handle typecasts */ larg = arg->op.left; - while (larg->type == PRINT_TYPE) { + while (larg->type == TEP_PRINT_TYPE) { if (!typearg) typearg = larg; larg = larg->typecast.item; } /* Default to long size */ - field_size = pevent->long_size; + field_size = tep->long_size; switch (larg->type) { - case PRINT_DYNAMIC_ARRAY: - offset = tep_read_number(pevent, + case TEP_PRINT_DYNAMIC_ARRAY: + offset = tep_read_number(tep, data + larg->dynarray.field->offset, larg->dynarray.field->size); if (larg->dynarray.field->elementsize) @@ -3602,7 +3711,7 @@ offset &= 0xffff; offset += right; break; - case PRINT_FIELD: + case TEP_PRINT_FIELD: if (!larg->field.field) { larg->field.field = tep_find_any_field(event, larg->field.name); @@ -3618,7 +3727,7 @@ default: goto default_op; /* oops, all bets off */ } - val = tep_read_number(pevent, + val = tep_read_number(tep, data + offset, field_size); if (typearg) val = eval_type(val, typearg, 1); @@ -3718,8 +3827,8 @@ goto out_warning_op; } break; - case PRINT_DYNAMIC_ARRAY_LEN: - offset = tep_read_number(pevent, + case TEP_PRINT_DYNAMIC_ARRAY_LEN: + offset = tep_read_number(tep, data + arg->dynarray.field->offset, arg->dynarray.field->size); /* @@ -3729,9 +3838,9 @@ */ val = (unsigned long long)(offset >> 16); break; - case PRINT_DYNAMIC_ARRAY: + case TEP_PRINT_DYNAMIC_ARRAY: /* Without [], we pass the address to the dynamic data */ - offset = tep_read_number(pevent, + offset = tep_read_number(tep, data + arg->dynarray.field->offset, arg->dynarray.field->size); /* @@ -3806,7 +3915,7 @@ trace_seq_printf(s, format, str); } -static void print_bitmask_to_seq(struct tep_handle *pevent, +static void print_bitmask_to_seq(struct tep_handle *tep, struct trace_seq *s, const char *format, int len_arg, const void *data, int size) { @@ -3836,9 +3945,9 @@ /* * data points to a bit mask of size bytes. * In the kernel, this is an array of long words, thus - * endianess is very important. + * endianness is very important. */ - if (pevent->file_bigendian) + if (tep->file_bigendian) index = size - (len + 1); else index = len; @@ -3861,12 +3970,12 @@ } static void print_str_arg(struct trace_seq *s, void *data, int size, - struct event_format *event, const char *format, - int len_arg, struct print_arg *arg) + struct tep_event *event, const char *format, + int len_arg, struct tep_print_arg *arg) { - struct tep_handle *pevent = event->pevent; - struct print_flag_sym *flag; - struct format_field *field; + struct tep_handle *tep = event->tep; + struct tep_print_flag_sym *flag; + struct tep_format_field *field; struct printk_map *printk; long long val, fval; unsigned long long addr; @@ -3876,13 +3985,13 @@ int i, len; switch (arg->type) { - case PRINT_NULL: + case TEP_PRINT_NULL: /* ?? */ return; - case PRINT_ATOM: + case TEP_PRINT_ATOM: print_str_to_seq(s, format, len_arg, arg->atom.atom); return; - case PRINT_FIELD: + case TEP_PRINT_FIELD: field = arg->field.field; if (!field) { field = tep_find_any_field(event, arg->field.name); @@ -3900,8 +4009,8 @@ * and the size is the same as long_size, assume that it * is a pointer. */ - if (!(field->flags & FIELD_IS_ARRAY) && - field->size == pevent->long_size) { + if (!(field->flags & TEP_FIELD_IS_ARRAY) && + field->size == tep->long_size) { /* Handle heterogeneous recording and processing * architectures @@ -3916,12 +4025,12 @@ * on 32-bit devices: * In this case, 64 bits must be read. */ - addr = (pevent->long_size == 8) ? + addr = (tep->long_size == 8) ? *(unsigned long long *)(data + field->offset) : (unsigned long long)*(unsigned int *)(data + field->offset); /* Check if it matches a print format */ - printk = find_printk(pevent, addr); + printk = find_printk(tep, addr); if (printk) trace_seq_puts(s, printk->printk); else @@ -3939,7 +4048,7 @@ print_str_to_seq(s, format, len_arg, str); free(str); break; - case PRINT_FLAGS: + case TEP_PRINT_FLAGS: val = eval_num_arg(data, size, event, arg->flags.field); print = 0; for (flag = arg->flags.flags; flag; flag = flag->next) { @@ -3962,7 +4071,7 @@ trace_seq_printf(s, "0x%llx", val); } break; - case PRINT_SYMBOL: + case TEP_PRINT_SYMBOL: val = eval_num_arg(data, size, event, arg->symbol.field); for (flag = arg->symbol.symbols; flag; flag = flag->next) { fval = eval_flag(flag->value); @@ -3974,11 +4083,11 @@ if (!flag) trace_seq_printf(s, "0x%llx", val); break; - case PRINT_HEX: - case PRINT_HEX_STR: - if (arg->hex.field->type == PRINT_DYNAMIC_ARRAY) { + case TEP_PRINT_HEX: + case TEP_PRINT_HEX_STR: + if (arg->hex.field->type == TEP_PRINT_DYNAMIC_ARRAY) { unsigned long offset; - offset = tep_read_number(pevent, + offset = tep_read_number(tep, data + arg->hex.field->dynarray.field->offset, arg->hex.field->dynarray.field->size); hex = data + (offset & 0xffff); @@ -3995,21 +4104,21 @@ } len = eval_num_arg(data, size, event, arg->hex.size); for (i = 0; i < len; i++) { - if (i && arg->type == PRINT_HEX) + if (i && arg->type == TEP_PRINT_HEX) trace_seq_putc(s, ' '); trace_seq_printf(s, "%02x", hex[i]); } break; - case PRINT_INT_ARRAY: { + case TEP_PRINT_INT_ARRAY: { void *num; int el_size; - if (arg->int_array.field->type == PRINT_DYNAMIC_ARRAY) { + if (arg->int_array.field->type == TEP_PRINT_DYNAMIC_ARRAY) { unsigned long offset; - struct format_field *field = + struct tep_format_field *field = arg->int_array.field->dynarray.field; - offset = tep_read_number(pevent, + offset = tep_read_number(tep, data + field->offset, field->size); num = data + (offset & 0xffff); @@ -4049,43 +4158,43 @@ } break; } - case PRINT_TYPE: + case TEP_PRINT_TYPE: break; - case PRINT_STRING: { + case TEP_PRINT_STRING: { int str_offset; if (arg->string.offset == -1) { - struct format_field *f; + struct tep_format_field *f; f = tep_find_any_field(event, arg->string.string); arg->string.offset = f->offset; } - str_offset = data2host4(pevent, data + arg->string.offset); + str_offset = data2host4(tep, *(unsigned int *)(data + arg->string.offset)); str_offset &= 0xffff; print_str_to_seq(s, format, len_arg, ((char *)data) + str_offset); break; } - case PRINT_BSTRING: + case TEP_PRINT_BSTRING: print_str_to_seq(s, format, len_arg, arg->string.string); break; - case PRINT_BITMASK: { + case TEP_PRINT_BITMASK: { int bitmask_offset; int bitmask_size; if (arg->bitmask.offset == -1) { - struct format_field *f; + struct tep_format_field *f; f = tep_find_any_field(event, arg->bitmask.bitmask); arg->bitmask.offset = f->offset; } - bitmask_offset = data2host4(pevent, data + arg->bitmask.offset); + bitmask_offset = data2host4(tep, *(unsigned int *)(data + arg->bitmask.offset)); bitmask_size = bitmask_offset >> 16; bitmask_offset &= 0xffff; - print_bitmask_to_seq(pevent, s, format, len_arg, + print_bitmask_to_seq(tep, s, format, len_arg, data + bitmask_offset, bitmask_size); break; } - case PRINT_OP: + case TEP_PRINT_OP: /* * The only op for string should be ? : */ @@ -4099,7 +4208,7 @@ print_str_arg(s, data, size, event, format, len_arg, arg->op.right->op.right); break; - case PRINT_FUNC: + case TEP_PRINT_FUNC: process_defined_func(s, data, size, event, arg); break; default: @@ -4116,13 +4225,13 @@ static unsigned long long process_defined_func(struct trace_seq *s, void *data, int size, - struct event_format *event, struct print_arg *arg) + struct tep_event *event, struct tep_print_arg *arg) { struct tep_function_handler *func_handle = arg->func.func; struct func_params *param; unsigned long long *args; unsigned long long ret; - struct print_arg *farg; + struct tep_print_arg *farg; struct trace_seq str; struct save_str { struct save_str *next; @@ -4199,9 +4308,9 @@ return ret; } -static void free_args(struct print_arg *args) +static void free_args(struct tep_print_arg *args) { - struct print_arg *next; + struct tep_print_arg *next; while (args) { next = args->next; @@ -4211,18 +4320,18 @@ } } -static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event_format *event) +static struct tep_print_arg *make_bprint_args(char *fmt, void *data, int size, struct tep_event *event) { - struct tep_handle *pevent = event->pevent; - struct format_field *field, *ip_field; - struct print_arg *args, *arg, **next; + struct tep_handle *tep = event->tep; + struct tep_format_field *field, *ip_field; + struct tep_print_arg *args, *arg, **next; unsigned long long ip, val; char *ptr; void *bptr; - int vsize; + int vsize = 0; - field = pevent->bprint_buf_field; - ip_field = pevent->bprint_ip_field; + field = tep->bprint_buf_field; + ip_field = tep->bprint_ip_field; if (!field) { field = tep_find_field(event, "buf"); @@ -4235,11 +4344,11 @@ do_warning_event(event, "can't find ip field for binary printk"); return NULL; } - pevent->bprint_buf_field = field; - pevent->bprint_ip_field = ip_field; + tep->bprint_buf_field = field; + tep->bprint_ip_field = ip_field; } - ip = tep_read_number(pevent, data + ip_field->offset, ip_field->size); + ip = tep_read_number(tep, data + ip_field->offset, ip_field->size); /* * The first arg is the IP pointer. @@ -4254,7 +4363,7 @@ arg->next = NULL; next = &arg->next; - arg->type = PRINT_ATOM; + arg->type = TEP_PRINT_ATOM; if (asprintf(&arg->atom.atom, "%lld", ip) < 0) goto out_free; @@ -4292,9 +4401,20 @@ switch (*ptr) { case 's': case 'S': + case 'x': + break; case 'f': case 'F': - break; + /* + * Pre-5.5 kernels use %pf and + * %pF for printing symbols + * while kernels since 5.5 use + * %pfw for fwnodes. So check + * %p[fF] isn't followed by 'w'. + */ + if (ptr[1] != 'w') + break; + /* fall through */ default: /* * Older kernels do not process @@ -4309,14 +4429,16 @@ /* fall through */ case 'd': case 'u': - case 'x': case 'i': + case 'x': + case 'X': + case 'o': switch (ls) { case 0: vsize = 4; break; case 1: - vsize = pevent->long_size; + vsize = tep->long_size; break; case 2: vsize = 8; @@ -4333,7 +4455,7 @@ /* the pointers are always 4 bytes aligned */ bptr = (void *)(((unsigned long)bptr + 3) & ~3); - val = tep_read_number(pevent, bptr, vsize); + val = tep_read_number(tep, bptr, vsize); bptr += vsize; arg = alloc_arg(); if (!arg) { @@ -4342,7 +4464,7 @@ goto out_free; } arg->next = NULL; - arg->type = PRINT_ATOM; + arg->type = TEP_PRINT_ATOM; if (asprintf(&arg->atom.atom, "%lld", val) < 0) { free(arg); goto out_free; @@ -4366,7 +4488,7 @@ goto out_free; } arg->next = NULL; - arg->type = PRINT_BSTRING; + arg->type = TEP_PRINT_BSTRING; arg->string.string = strdup(bptr); if (!arg->string.string) goto out_free; @@ -4388,15 +4510,15 @@ static char * get_bprint_format(void *data, int size __maybe_unused, - struct event_format *event) + struct tep_event *event) { - struct tep_handle *pevent = event->pevent; + struct tep_handle *tep = event->tep; unsigned long long addr; - struct format_field *field; + struct tep_format_field *field; struct printk_map *printk; char *format; - field = pevent->bprint_fmt_field; + field = tep->bprint_fmt_field; if (!field) { field = tep_find_field(event, "fmt"); @@ -4404,61 +4526,111 @@ do_warning_event(event, "can't find format field for binary printk"); return NULL; } - pevent->bprint_fmt_field = field; + tep->bprint_fmt_field = field; } - addr = tep_read_number(pevent, data + field->offset, field->size); + addr = tep_read_number(tep, data + field->offset, field->size); - printk = find_printk(pevent, addr); + printk = find_printk(tep, addr); if (!printk) { - if (asprintf(&format, "%%pf: (NO FORMAT FOUND at %llx)\n", addr) < 0) + if (asprintf(&format, "%%ps: (NO FORMAT FOUND at %llx)\n", addr) < 0) return NULL; return format; } - if (asprintf(&format, "%s: %s", "%pf", printk->printk) < 0) + if (asprintf(&format, "%s: %s", "%ps", printk->printk) < 0) return NULL; return format; } -static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size, - struct event_format *event, struct print_arg *arg) +static int print_mac_arg(struct trace_seq *s, const char *format, + void *data, int size, struct tep_event *event, + struct tep_print_arg *arg) { - unsigned char *buf; const char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x"; + bool reverse = false; + unsigned char *buf; + int ret = 0; - if (arg->type == PRINT_FUNC) { + if (arg->type == TEP_PRINT_FUNC) { process_defined_func(s, data, size, event, arg); - return; + return 0; } - if (arg->type != PRINT_FIELD) { + if (arg->type != TEP_PRINT_FIELD) { trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type); - return; + return 0; } - if (mac == 'm') + if (format[0] == 'm') { fmt = "%.2x%.2x%.2x%.2x%.2x%.2x"; + } else if (format[0] == 'M' && format[1] == 'F') { + fmt = "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x"; + ret++; + } + if (format[1] == 'R') { + reverse = true; + ret++; + } + if (!arg->field.field) { arg->field.field = tep_find_any_field(event, arg->field.name); if (!arg->field.field) { do_warning_event(event, "%s: field %s not found", __func__, arg->field.name); - return; + return ret; } } if (arg->field.field->size != 6) { trace_seq_printf(s, "INVALIDMAC"); - return; + return ret; } + buf = data + arg->field.field->offset; - trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); + if (reverse) + trace_seq_printf(s, fmt, buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]); + else + trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); + + return ret; } -static void print_ip4_addr(struct trace_seq *s, char i, unsigned char *buf) +static int parse_ip4_print_args(struct tep_handle *tep, + const char *ptr, bool *reverse) +{ + int ret = 0; + + *reverse = false; + + /* hnbl */ + switch (*ptr) { + case 'h': + if (tep->file_bigendian) + *reverse = false; + else + *reverse = true; + ret++; + break; + case 'l': + *reverse = true; + ret++; + break; + case 'n': + case 'b': + ret++; + /* fall through */ + default: + *reverse = false; + break; + } + + return ret; +} + +static void print_ip4_addr(struct trace_seq *s, char i, bool reverse, unsigned char *buf) { const char *fmt; @@ -4467,7 +4639,11 @@ else fmt = "%d.%d.%d.%d"; - trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3]); + if (reverse) + trace_seq_printf(s, fmt, buf[3], buf[2], buf[1], buf[0]); + else + trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3]); + } static inline bool ipv6_addr_v4mapped(const struct in6_addr *a) @@ -4550,7 +4726,7 @@ if (useIPv4) { if (needcolon) trace_seq_printf(s, ":"); - print_ip4_addr(s, 'I', &in6.s6_addr[12]); + print_ip4_addr(s, 'I', false, &in6.s6_addr[12]); } return; @@ -4576,19 +4752,23 @@ * %pISpc print an IP address based on sockaddr; p adds port. */ static int print_ipv4_arg(struct trace_seq *s, const char *ptr, char i, - void *data, int size, struct event_format *event, - struct print_arg *arg) + void *data, int size, struct tep_event *event, + struct tep_print_arg *arg) { + bool reverse = false; unsigned char *buf; + int ret; - if (arg->type == PRINT_FUNC) { + ret = parse_ip4_print_args(event->tep, ptr, &reverse); + + if (arg->type == TEP_PRINT_FUNC) { process_defined_func(s, data, size, event, arg); - return 0; + return ret; } - if (arg->type != PRINT_FIELD) { + if (arg->type != TEP_PRINT_FIELD) { trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type); - return 0; + return ret; } if (!arg->field.field) { @@ -4597,7 +4777,7 @@ if (!arg->field.field) { do_warning("%s: field %s not found", __func__, arg->field.name); - return 0; + return ret; } } @@ -4605,16 +4785,17 @@ if (arg->field.field->size != 4) { trace_seq_printf(s, "INVALIDIPv4"); - return 0; + return ret; } - print_ip4_addr(s, i, buf); - return 0; + print_ip4_addr(s, i, reverse, buf); + return ret; + } static int print_ipv6_arg(struct trace_seq *s, const char *ptr, char i, - void *data, int size, struct event_format *event, - struct print_arg *arg) + void *data, int size, struct tep_event *event, + struct tep_print_arg *arg) { char have_c = 0; unsigned char *buf; @@ -4627,12 +4808,12 @@ rc++; } - if (arg->type == PRINT_FUNC) { + if (arg->type == TEP_PRINT_FUNC) { process_defined_func(s, data, size, event, arg); return rc; } - if (arg->type != PRINT_FIELD) { + if (arg->type != TEP_PRINT_FIELD) { trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type); return rc; } @@ -4663,13 +4844,15 @@ } static int print_ipsa_arg(struct trace_seq *s, const char *ptr, char i, - void *data, int size, struct event_format *event, - struct print_arg *arg) + void *data, int size, struct tep_event *event, + struct tep_print_arg *arg) { char have_c = 0, have_p = 0; unsigned char *buf; struct sockaddr_storage *sa; + bool reverse = false; int rc = 0; + int ret; /* pISpc */ if (i == 'I') { @@ -4684,13 +4867,16 @@ rc++; } } + ret = parse_ip4_print_args(event->tep, ptr, &reverse); + ptr += ret; + rc += ret; - if (arg->type == PRINT_FUNC) { + if (arg->type == TEP_PRINT_FUNC) { process_defined_func(s, data, size, event, arg); return rc; } - if (arg->type != PRINT_FIELD) { + if (arg->type != TEP_PRINT_FIELD) { trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type); return rc; } @@ -4715,7 +4901,7 @@ return rc; } - print_ip4_addr(s, i, (unsigned char *) &sa4->sin_addr); + print_ip4_addr(s, i, reverse, (unsigned char *) &sa4->sin_addr); if (have_p) trace_seq_printf(s, ":%d", ntohs(sa4->sin_port)); @@ -4745,35 +4931,157 @@ } static int print_ip_arg(struct trace_seq *s, const char *ptr, - void *data, int size, struct event_format *event, - struct print_arg *arg) + void *data, int size, struct tep_event *event, + struct tep_print_arg *arg) { char i = *ptr; /* 'i' or 'I' */ - char ver; - int rc = 0; + int rc = 1; + /* IP version */ ptr++; - rc++; - ver = *ptr; - ptr++; - rc++; - - switch (ver) { + switch (*ptr) { case '4': - rc += print_ipv4_arg(s, ptr, i, data, size, event, arg); + rc += print_ipv4_arg(s, ptr + 1, i, data, size, event, arg); break; case '6': - rc += print_ipv6_arg(s, ptr, i, data, size, event, arg); + rc += print_ipv6_arg(s, ptr + 1, i, data, size, event, arg); break; case 'S': - rc += print_ipsa_arg(s, ptr, i, data, size, event, arg); + rc += print_ipsa_arg(s, ptr + 1, i, data, size, event, arg); break; default: return 0; } return rc; +} + +static const int guid_index[16] = {3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15}; +static const int uuid_index[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + +static int print_uuid_arg(struct trace_seq *s, const char *ptr, + void *data, int size, struct tep_event *event, + struct tep_print_arg *arg) +{ + const int *index = uuid_index; + char *format = "%02x"; + int ret = 0; + char *buf; + int i; + + switch (*(ptr + 1)) { + case 'L': + format = "%02X"; + /* fall through */ + case 'l': + index = guid_index; + ret++; + break; + case 'B': + format = "%02X"; + /* fall through */ + case 'b': + ret++; + break; + } + + if (arg->type == TEP_PRINT_FUNC) { + process_defined_func(s, data, size, event, arg); + return ret; + } + + if (arg->type != TEP_PRINT_FIELD) { + trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type); + return ret; + } + + if (!arg->field.field) { + arg->field.field = + tep_find_any_field(event, arg->field.name); + if (!arg->field.field) { + do_warning("%s: field %s not found", + __func__, arg->field.name); + return ret; + } + } + + if (arg->field.field->size != 16) { + trace_seq_printf(s, "INVALIDUUID"); + return ret; + } + + buf = data + arg->field.field->offset; + + for (i = 0; i < 16; i++) { + trace_seq_printf(s, format, buf[index[i]] & 0xff); + switch (i) { + case 3: + case 5: + case 7: + case 9: + trace_seq_printf(s, "-"); + break; + } + } + + return ret; +} + +static int print_raw_buff_arg(struct trace_seq *s, const char *ptr, + void *data, int size, struct tep_event *event, + struct tep_print_arg *arg, int print_len) +{ + int plen = print_len; + char *delim = " "; + int ret = 0; + char *buf; + int i; + unsigned long offset; + int arr_len; + + switch (*(ptr + 1)) { + case 'C': + delim = ":"; + ret++; + break; + case 'D': + delim = "-"; + ret++; + break; + case 'N': + delim = ""; + ret++; + break; + } + + if (arg->type == TEP_PRINT_FUNC) { + process_defined_func(s, data, size, event, arg); + return ret; + } + + if (arg->type != TEP_PRINT_DYNAMIC_ARRAY) { + trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type); + return ret; + } + + offset = tep_read_number(event->tep, + data + arg->dynarray.field->offset, + arg->dynarray.field->size); + arr_len = (unsigned long long)(offset >> 16); + buf = data + (offset & 0xffff); + + if (arr_len < plen) + plen = arr_len; + + if (plen < 1) + return ret; + + trace_seq_printf(s, "%02x", buf[0] & 0xff); + for (i = 1; i < plen; i++) + trace_seq_printf(s, "%s%02x", delim, buf[i] & 0xff); + + return ret; } static int is_printable_array(char *p, unsigned int len) @@ -4787,22 +5095,22 @@ } void tep_print_field(struct trace_seq *s, void *data, - struct format_field *field) + struct tep_format_field *field) { unsigned long long val; unsigned int offset, len, i; - struct tep_handle *pevent = field->event->pevent; + struct tep_handle *tep = field->event->tep; - if (field->flags & FIELD_IS_ARRAY) { + if (field->flags & TEP_FIELD_IS_ARRAY) { offset = field->offset; len = field->size; - if (field->flags & FIELD_IS_DYNAMIC) { - val = tep_read_number(pevent, data + offset, len); + if (field->flags & TEP_FIELD_IS_DYNAMIC) { + val = tep_read_number(tep, data + offset, len); offset = val; len = offset >> 16; offset &= 0xffff; } - if (field->flags & FIELD_IS_STRING && + if (field->flags & TEP_FIELD_IS_STRING && is_printable_array(data + offset, len)) { trace_seq_printf(s, "%s", (char *)data + offset); } else { @@ -4814,21 +5122,21 @@ *((unsigned char *)data + offset + i)); } trace_seq_putc(s, ']'); - field->flags &= ~FIELD_IS_STRING; + field->flags &= ~TEP_FIELD_IS_STRING; } } else { - val = tep_read_number(pevent, data + field->offset, + val = tep_read_number(tep, data + field->offset, field->size); - if (field->flags & FIELD_IS_POINTER) { + if (field->flags & TEP_FIELD_IS_POINTER) { trace_seq_printf(s, "0x%llx", val); - } else if (field->flags & FIELD_IS_SIGNED) { + } else if (field->flags & TEP_FIELD_IS_SIGNED) { switch (field->size) { case 4: /* * If field is long then print it in hex. * A long usually stores pointers. */ - if (field->flags & FIELD_IS_LONG) + if (field->flags & TEP_FIELD_IS_LONG) trace_seq_printf(s, "0x%x", (int)val); else trace_seq_printf(s, "%d", (int)val); @@ -4843,7 +5151,7 @@ trace_seq_printf(s, "%lld", val); } } else { - if (field->flags & FIELD_IS_LONG) + if (field->flags & TEP_FIELD_IS_LONG) trace_seq_printf(s, "0x%llx", val); else trace_seq_printf(s, "%llu", val); @@ -4852,9 +5160,9 @@ } void tep_print_fields(struct trace_seq *s, void *data, - int size __maybe_unused, struct event_format *event) + int size __maybe_unused, struct tep_event *event) { - struct format_field *field; + struct tep_format_field *field; field = event->format.fields; while (field) { @@ -4864,300 +5172,601 @@ } } -static void pretty_print(struct trace_seq *s, void *data, int size, struct event_format *event) +static int print_function(struct trace_seq *s, const char *format, + void *data, int size, struct tep_event *event, + struct tep_print_arg *arg) { - struct tep_handle *pevent = event->pevent; - struct print_fmt *print_fmt = &event->print_fmt; - struct print_arg *arg = print_fmt->args; - struct print_arg *args = NULL; - const char *ptr = print_fmt->format; - unsigned long long val; struct func_map *func; - const char *saveptr; - struct trace_seq p; - char *bprint_fmt = NULL; - char format[32]; - int show_func; - int len_as_arg; - int len_arg; - int len; - int ls; + unsigned long long val; - if (event->flags & EVENT_FL_FAILED) { + val = eval_num_arg(data, size, event, arg); + func = find_func(event->tep, val); + if (func) { + trace_seq_puts(s, func->func); + if (*format == 'F' || *format == 'S') + trace_seq_printf(s, "+0x%llx", val - func->addr); + } else { + if (event->tep->long_size == 4) + trace_seq_printf(s, "0x%lx", (long)val); + else + trace_seq_printf(s, "0x%llx", (long long)val); + } + + return 0; +} + +static int print_arg_pointer(struct trace_seq *s, const char *format, int plen, + void *data, int size, + struct tep_event *event, struct tep_print_arg *arg) +{ + unsigned long long val; + int ret = 1; + + if (arg->type == TEP_PRINT_BSTRING) { + trace_seq_puts(s, arg->string.string); + return 0; + } + while (*format) { + if (*format == 'p') { + format++; + break; + } + format++; + } + + switch (*format) { + case 'F': + case 'f': + case 'S': + case 's': + ret += print_function(s, format, data, size, event, arg); + break; + case 'M': + case 'm': + ret += print_mac_arg(s, format, data, size, event, arg); + break; + case 'I': + case 'i': + ret += print_ip_arg(s, format, data, size, event, arg); + break; + case 'U': + ret += print_uuid_arg(s, format, data, size, event, arg); + break; + case 'h': + ret += print_raw_buff_arg(s, format, data, size, event, arg, plen); + break; + default: + ret = 0; + val = eval_num_arg(data, size, event, arg); + trace_seq_printf(s, "%p", (void *)(intptr_t)val); + break; + } + + return ret; + +} + +static int print_arg_number(struct trace_seq *s, const char *format, int plen, + void *data, int size, int ls, + struct tep_event *event, struct tep_print_arg *arg) +{ + unsigned long long val; + + val = eval_num_arg(data, size, event, arg); + + switch (ls) { + case -2: + if (plen >= 0) + trace_seq_printf(s, format, plen, (char)val); + else + trace_seq_printf(s, format, (char)val); + break; + case -1: + if (plen >= 0) + trace_seq_printf(s, format, plen, (short)val); + else + trace_seq_printf(s, format, (short)val); + break; + case 0: + if (plen >= 0) + trace_seq_printf(s, format, plen, (int)val); + else + trace_seq_printf(s, format, (int)val); + break; + case 1: + if (plen >= 0) + trace_seq_printf(s, format, plen, (long)val); + else + trace_seq_printf(s, format, (long)val); + break; + case 2: + if (plen >= 0) + trace_seq_printf(s, format, plen, (long long)val); + else + trace_seq_printf(s, format, (long long)val); + break; + default: + do_warning_event(event, "bad count (%d)", ls); + event->flags |= TEP_EVENT_FL_FAILED; + } + return 0; +} + + +static void print_arg_string(struct trace_seq *s, const char *format, int plen, + void *data, int size, + struct tep_event *event, struct tep_print_arg *arg) +{ + struct trace_seq p; + + /* Use helper trace_seq */ + trace_seq_init(&p); + print_str_arg(&p, data, size, event, + format, plen, arg); + trace_seq_terminate(&p); + trace_seq_puts(s, p.buffer); + trace_seq_destroy(&p); +} + +static int parse_arg_format_pointer(const char *format) +{ + int ret = 0; + int index; + int loop; + + switch (*format) { + case 'F': + case 'S': + case 'f': + case 's': + ret++; + break; + case 'M': + case 'm': + /* [mM]R , [mM]F */ + switch (format[1]) { + case 'R': + case 'F': + ret++; + break; + } + ret++; + break; + case 'I': + case 'i': + index = 2; + loop = 1; + switch (format[1]) { + case 'S': + /*[S][pfs]*/ + while (loop) { + switch (format[index]) { + case 'p': + case 'f': + case 's': + ret++; + index++; + break; + default: + loop = 0; + break; + } + } + /* fall through */ + case '4': + /* [4S][hnbl] */ + switch (format[index]) { + case 'h': + case 'n': + case 'l': + case 'b': + ret++; + index++; + break; + } + if (format[1] == '4') { + ret++; + break; + } + /* fall through */ + case '6': + /* [6S]c */ + if (format[index] == 'c') + ret++; + ret++; + break; + } + ret++; + break; + case 'U': + switch (format[1]) { + case 'L': + case 'l': + case 'B': + case 'b': + ret++; + break; + } + ret++; + break; + case 'h': + switch (format[1]) { + case 'C': + case 'D': + case 'N': + ret++; + break; + } + ret++; + break; + default: + break; + } + + return ret; +} + +static void free_parse_args(struct tep_print_parse *arg) +{ + struct tep_print_parse *del; + + while (arg) { + del = arg; + arg = del->next; + free(del->format); + free(del); + } +} + +static int parse_arg_add(struct tep_print_parse **parse, char *format, + enum tep_print_parse_type type, + struct tep_print_arg *arg, + struct tep_print_arg *len_as_arg, + int ls) +{ + struct tep_print_parse *parg = NULL; + + parg = calloc(1, sizeof(*parg)); + if (!parg) + goto error; + parg->format = strdup(format); + if (!parg->format) + goto error; + parg->type = type; + parg->arg = arg; + parg->len_as_arg = len_as_arg; + parg->ls = ls; + *parse = parg; + return 0; +error: + if (parg) { + free(parg->format); + free(parg); + } + return -1; +} + +static int parse_arg_format(struct tep_print_parse **parse, + struct tep_event *event, + const char *format, struct tep_print_arg **arg) +{ + struct tep_print_arg *len_arg = NULL; + char print_format[32]; + const char *start = format; + int ret = 0; + int ls = 0; + int res; + int len; + + format++; + ret++; + for (; *format; format++) { + switch (*format) { + case '#': + /* FIXME: need to handle properly */ + break; + case 'h': + ls--; + break; + case 'l': + ls++; + break; + case 'L': + ls = 2; + break; + case '.': + case 'z': + case 'Z': + case '0' ... '9': + case '-': + break; + case '*': + /* The argument is the length. */ + if (!*arg) { + do_warning_event(event, "no argument match"); + event->flags |= TEP_EVENT_FL_FAILED; + goto out_failed; + } + if (len_arg) { + do_warning_event(event, "argument already matched"); + event->flags |= TEP_EVENT_FL_FAILED; + goto out_failed; + } + len_arg = *arg; + *arg = (*arg)->next; + break; + case 'p': + if (!*arg) { + do_warning_event(event, "no argument match"); + event->flags |= TEP_EVENT_FL_FAILED; + goto out_failed; + } + res = parse_arg_format_pointer(format + 1); + if (res > 0) { + format += res; + ret += res; + } + len = ((unsigned long)format + 1) - + (unsigned long)start; + /* should never happen */ + if (len > 31) { + do_warning_event(event, "bad format!"); + event->flags |= TEP_EVENT_FL_FAILED; + len = 31; + } + memcpy(print_format, start, len); + print_format[len] = 0; + + parse_arg_add(parse, print_format, + PRINT_FMT_ARG_POINTER, *arg, len_arg, ls); + *arg = (*arg)->next; + ret++; + return ret; + case 'd': + case 'u': + case 'i': + case 'x': + case 'X': + case 'o': + if (!*arg) { + do_warning_event(event, "no argument match"); + event->flags |= TEP_EVENT_FL_FAILED; + goto out_failed; + } + + len = ((unsigned long)format + 1) - + (unsigned long)start; + + /* should never happen */ + if (len > 30) { + do_warning_event(event, "bad format!"); + event->flags |= TEP_EVENT_FL_FAILED; + len = 31; + } + memcpy(print_format, start, len); + print_format[len] = 0; + + if (event->tep->long_size == 8 && ls == 1 && + sizeof(long) != 8) { + char *p; + + /* make %l into %ll */ + if (ls == 1 && (p = strchr(print_format, 'l'))) + memmove(p+1, p, strlen(p)+1); + ls = 2; + } + if (ls < -2 || ls > 2) { + do_warning_event(event, "bad count (%d)", ls); + event->flags |= TEP_EVENT_FL_FAILED; + } + parse_arg_add(parse, print_format, + PRINT_FMT_ARG_DIGIT, *arg, len_arg, ls); + *arg = (*arg)->next; + ret++; + return ret; + case 's': + if (!*arg) { + do_warning_event(event, "no matching argument"); + event->flags |= TEP_EVENT_FL_FAILED; + goto out_failed; + } + + len = ((unsigned long)format + 1) - + (unsigned long)start; + + /* should never happen */ + if (len > 31) { + do_warning_event(event, "bad format!"); + event->flags |= TEP_EVENT_FL_FAILED; + len = 31; + } + + memcpy(print_format, start, len); + print_format[len] = 0; + + parse_arg_add(parse, print_format, + PRINT_FMT_ARG_STRING, *arg, len_arg, 0); + *arg = (*arg)->next; + ret++; + return ret; + default: + snprintf(print_format, 32, ">%c<", *format); + parse_arg_add(parse, print_format, + PRINT_FMT_STRING, NULL, NULL, 0); + ret++; + return ret; + } + ret++; + } + +out_failed: + return ret; + +} + +static int parse_arg_string(struct tep_print_parse **parse, const char *format) +{ + struct trace_seq s; + int ret = 0; + + trace_seq_init(&s); + for (; *format; format++) { + if (*format == '\\') { + format++; + ret++; + switch (*format) { + case 'n': + trace_seq_putc(&s, '\n'); + break; + case 't': + trace_seq_putc(&s, '\t'); + break; + case 'r': + trace_seq_putc(&s, '\r'); + break; + case '\\': + trace_seq_putc(&s, '\\'); + break; + default: + trace_seq_putc(&s, *format); + break; + } + } else if (*format == '%') { + if (*(format + 1) == '%') { + trace_seq_putc(&s, '%'); + format++; + ret++; + } else + break; + } else + trace_seq_putc(&s, *format); + + ret++; + } + trace_seq_terminate(&s); + parse_arg_add(parse, s.buffer, PRINT_FMT_STRING, NULL, NULL, 0); + trace_seq_destroy(&s); + + return ret; +} + +static struct tep_print_parse * +parse_args(struct tep_event *event, const char *format, struct tep_print_arg *arg) +{ + struct tep_print_parse *parse_ret = NULL; + struct tep_print_parse **parse = NULL; + int ret; + int len; + + len = strlen(format); + while (*format) { + if (!parse_ret) + parse = &parse_ret; + if (*format == '%' && *(format + 1) != '%') + ret = parse_arg_format(parse, event, format, &arg); + else + ret = parse_arg_string(parse, format); + if (*parse) + parse = &((*parse)->next); + + len -= ret; + if (len > 0) + format += ret; + else + break; + } + return parse_ret; +} + +static void print_event_cache(struct tep_print_parse *parse, struct trace_seq *s, + void *data, int size, struct tep_event *event) +{ + int len_arg; + + while (parse) { + if (parse->len_as_arg) + len_arg = eval_num_arg(data, size, event, parse->len_as_arg); + switch (parse->type) { + case PRINT_FMT_ARG_DIGIT: + print_arg_number(s, parse->format, + parse->len_as_arg ? len_arg : -1, data, + size, parse->ls, event, parse->arg); + break; + case PRINT_FMT_ARG_POINTER: + print_arg_pointer(s, parse->format, + parse->len_as_arg ? len_arg : 1, + data, size, event, parse->arg); + break; + case PRINT_FMT_ARG_STRING: + print_arg_string(s, parse->format, + parse->len_as_arg ? len_arg : -1, + data, size, event, parse->arg); + break; + case PRINT_FMT_STRING: + default: + trace_seq_printf(s, "%s", parse->format); + break; + } + parse = parse->next; + } +} + +static void pretty_print(struct trace_seq *s, void *data, int size, struct tep_event *event) +{ + struct tep_print_parse *parse = event->print_fmt.print_cache; + struct tep_print_arg *args = NULL; + char *bprint_fmt = NULL; + + if (event->flags & TEP_EVENT_FL_FAILED) { trace_seq_printf(s, "[FAILED TO PARSE]"); tep_print_fields(s, data, size, event); return; } - if (event->flags & EVENT_FL_ISBPRINT) { + if (event->flags & TEP_EVENT_FL_ISBPRINT) { bprint_fmt = get_bprint_format(data, size, event); args = make_bprint_args(bprint_fmt, data, size, event); - arg = args; - ptr = bprint_fmt; + parse = parse_args(event, bprint_fmt, args); } - for (; *ptr; ptr++) { - ls = 0; - if (*ptr == '\\') { - ptr++; - switch (*ptr) { - case 'n': - trace_seq_putc(s, '\n'); - break; - case 't': - trace_seq_putc(s, '\t'); - break; - case 'r': - trace_seq_putc(s, '\r'); - break; - case '\\': - trace_seq_putc(s, '\\'); - break; - default: - trace_seq_putc(s, *ptr); - break; - } + print_event_cache(parse, s, data, size, event); - } else if (*ptr == '%') { - saveptr = ptr; - show_func = 0; - len_as_arg = 0; - cont_process: - ptr++; - switch (*ptr) { - case '%': - trace_seq_putc(s, '%'); - break; - case '#': - /* FIXME: need to handle properly */ - goto cont_process; - case 'h': - ls--; - goto cont_process; - case 'l': - ls++; - goto cont_process; - case 'L': - ls = 2; - goto cont_process; - case '*': - /* The argument is the length. */ - if (!arg) { - do_warning_event(event, "no argument match"); - event->flags |= EVENT_FL_FAILED; - goto out_failed; - } - len_arg = eval_num_arg(data, size, event, arg); - len_as_arg = 1; - arg = arg->next; - goto cont_process; - case '.': - case 'z': - case 'Z': - case '0' ... '9': - case '-': - goto cont_process; - case 'p': - if (pevent->long_size == 4) - ls = 1; - else - ls = 2; - - if (isalnum(ptr[1])) - ptr++; - - if (arg->type == PRINT_BSTRING) { - trace_seq_puts(s, arg->string.string); - arg = arg->next; - break; - } - - if (*ptr == 'F' || *ptr == 'f' || - *ptr == 'S' || *ptr == 's') { - show_func = *ptr; - } else if (*ptr == 'M' || *ptr == 'm') { - print_mac_arg(s, *ptr, data, size, event, arg); - arg = arg->next; - break; - } else if (*ptr == 'I' || *ptr == 'i') { - int n; - - n = print_ip_arg(s, ptr, data, size, event, arg); - if (n > 0) { - ptr += n - 1; - arg = arg->next; - break; - } - } - - /* fall through */ - case 'd': - case 'i': - case 'x': - case 'X': - case 'u': - if (!arg) { - do_warning_event(event, "no argument match"); - event->flags |= EVENT_FL_FAILED; - goto out_failed; - } - - len = ((unsigned long)ptr + 1) - - (unsigned long)saveptr; - - /* should never happen */ - if (len > 31) { - do_warning_event(event, "bad format!"); - event->flags |= EVENT_FL_FAILED; - len = 31; - } - - memcpy(format, saveptr, len); - format[len] = 0; - - val = eval_num_arg(data, size, event, arg); - arg = arg->next; - - if (show_func) { - func = find_func(pevent, val); - if (func) { - trace_seq_puts(s, func->func); - if (show_func == 'F') - trace_seq_printf(s, - "+0x%llx", - val - func->addr); - break; - } - } - if (pevent->long_size == 8 && ls == 1 && - sizeof(long) != 8) { - char *p; - - /* make %l into %ll */ - if (ls == 1 && (p = strchr(format, 'l'))) - memmove(p+1, p, strlen(p)+1); - else if (strcmp(format, "%p") == 0) - strcpy(format, "0x%llx"); - ls = 2; - } - switch (ls) { - case -2: - if (len_as_arg) - trace_seq_printf(s, format, len_arg, (char)val); - else - trace_seq_printf(s, format, (char)val); - break; - case -1: - if (len_as_arg) - trace_seq_printf(s, format, len_arg, (short)val); - else - trace_seq_printf(s, format, (short)val); - break; - case 0: - if (len_as_arg) - trace_seq_printf(s, format, len_arg, (int)val); - else - trace_seq_printf(s, format, (int)val); - break; - case 1: - if (len_as_arg) - trace_seq_printf(s, format, len_arg, (long)val); - else - trace_seq_printf(s, format, (long)val); - break; - case 2: - if (len_as_arg) - trace_seq_printf(s, format, len_arg, - (long long)val); - else - trace_seq_printf(s, format, (long long)val); - break; - default: - do_warning_event(event, "bad count (%d)", ls); - event->flags |= EVENT_FL_FAILED; - } - break; - case 's': - if (!arg) { - do_warning_event(event, "no matching argument"); - event->flags |= EVENT_FL_FAILED; - goto out_failed; - } - - len = ((unsigned long)ptr + 1) - - (unsigned long)saveptr; - - /* should never happen */ - if (len > 31) { - do_warning_event(event, "bad format!"); - event->flags |= EVENT_FL_FAILED; - len = 31; - } - - memcpy(format, saveptr, len); - format[len] = 0; - if (!len_as_arg) - len_arg = -1; - /* Use helper trace_seq */ - trace_seq_init(&p); - print_str_arg(&p, data, size, event, - format, len_arg, arg); - trace_seq_terminate(&p); - trace_seq_puts(s, p.buffer); - trace_seq_destroy(&p); - arg = arg->next; - break; - default: - trace_seq_printf(s, ">%c<", *ptr); - - } - } else - trace_seq_putc(s, *ptr); - } - - if (event->flags & EVENT_FL_FAILED) { -out_failed: - trace_seq_printf(s, "[FAILED TO PARSE]"); - } - - if (args) { + if (event->flags & TEP_EVENT_FL_ISBPRINT) { + free_parse_args(parse); free_args(args); free(bprint_fmt); } } -/** - * tep_data_lat_fmt - parse the data for the latency format - * @pevent: a handle to the pevent - * @s: the trace_seq to write to - * @record: the record to read from - * +/* * This parses out the Latency format (interrupts disabled, * need rescheduling, in hard/soft interrupt, preempt count * and lock depth) and places it into the trace_seq. */ -void tep_data_lat_fmt(struct tep_handle *pevent, - struct trace_seq *s, struct tep_record *record) +static void data_latency_format(struct tep_handle *tep, struct trace_seq *s, + char *format, struct tep_record *record) { static int check_lock_depth = 1; static int check_migrate_disable = 1; static int lock_depth_exists; static int migrate_disable_exists; unsigned int lat_flags; + struct trace_seq sq; unsigned int pc; - int lock_depth; - int migrate_disable; + int lock_depth = 0; + int migrate_disable = 0; int hardirq; int softirq; void *data = record->data; - lat_flags = parse_common_flags(pevent, data); - pc = parse_common_pc(pevent, data); + trace_seq_init(&sq); + lat_flags = parse_common_flags(tep, data); + pc = parse_common_pc(tep, data); /* lock_depth may not always exist */ if (lock_depth_exists) - lock_depth = parse_common_lock_depth(pevent, data); + lock_depth = parse_common_lock_depth(tep, data); else if (check_lock_depth) { - lock_depth = parse_common_lock_depth(pevent, data); + lock_depth = parse_common_lock_depth(tep, data); if (lock_depth < 0) check_lock_depth = 0; else @@ -5166,9 +5775,9 @@ /* migrate_disable may not always exist */ if (migrate_disable_exists) - migrate_disable = parse_common_migrate_disable(pevent, data); + migrate_disable = parse_common_migrate_disable(tep, data); else if (check_migrate_disable) { - migrate_disable = parse_common_migrate_disable(pevent, data); + migrate_disable = parse_common_migrate_disable(tep, data); if (migrate_disable < 0) check_migrate_disable = 0; else @@ -5178,7 +5787,7 @@ hardirq = lat_flags & TRACE_FLAG_HARDIRQ; softirq = lat_flags & TRACE_FLAG_SOFTIRQ; - trace_seq_printf(s, "%c%c%c", + trace_seq_printf(&sq, "%c%c%c", (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' : (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ? 'X' : '.', @@ -5188,162 +5797,158 @@ hardirq ? 'h' : softirq ? 's' : '.'); if (pc) - trace_seq_printf(s, "%x", pc); + trace_seq_printf(&sq, "%x", pc); else - trace_seq_putc(s, '.'); + trace_seq_printf(&sq, "."); if (migrate_disable_exists) { if (migrate_disable < 0) - trace_seq_putc(s, '.'); + trace_seq_printf(&sq, "."); else - trace_seq_printf(s, "%d", migrate_disable); + trace_seq_printf(&sq, "%d", migrate_disable); } if (lock_depth_exists) { if (lock_depth < 0) - trace_seq_putc(s, '.'); + trace_seq_printf(&sq, "."); else - trace_seq_printf(s, "%d", lock_depth); + trace_seq_printf(&sq, "%d", lock_depth); } + if (sq.state == TRACE_SEQ__MEM_ALLOC_FAILED) { + s->state = TRACE_SEQ__MEM_ALLOC_FAILED; + return; + } + + trace_seq_terminate(&sq); + trace_seq_puts(s, sq.buffer); + trace_seq_destroy(&sq); trace_seq_terminate(s); } /** * tep_data_type - parse out the given event type - * @pevent: a handle to the pevent + * @tep: a handle to the trace event parser context * @rec: the record to read from * * This returns the event id from the @rec. */ -int tep_data_type(struct tep_handle *pevent, struct tep_record *rec) +int tep_data_type(struct tep_handle *tep, struct tep_record *rec) { - return trace_parse_common_type(pevent, rec->data); -} - -/** - * tep_data_event_from_type - find the event by a given type - * @pevent: a handle to the pevent - * @type: the type of the event. - * - * This returns the event form a given @type; - */ -struct event_format *tep_data_event_from_type(struct tep_handle *pevent, int type) -{ - return tep_find_event(pevent, type); + return trace_parse_common_type(tep, rec->data); } /** * tep_data_pid - parse the PID from record - * @pevent: a handle to the pevent + * @tep: a handle to the trace event parser context * @rec: the record to parse * * This returns the PID from a record. */ -int tep_data_pid(struct tep_handle *pevent, struct tep_record *rec) +int tep_data_pid(struct tep_handle *tep, struct tep_record *rec) { - return parse_common_pid(pevent, rec->data); + return parse_common_pid(tep, rec->data); } /** * tep_data_preempt_count - parse the preempt count from the record - * @pevent: a handle to the pevent + * @tep: a handle to the trace event parser context * @rec: the record to parse * * This returns the preempt count from a record. */ -int tep_data_preempt_count(struct tep_handle *pevent, struct tep_record *rec) +int tep_data_preempt_count(struct tep_handle *tep, struct tep_record *rec) { - return parse_common_pc(pevent, rec->data); + return parse_common_pc(tep, rec->data); } /** * tep_data_flags - parse the latency flags from the record - * @pevent: a handle to the pevent + * @tep: a handle to the trace event parser context * @rec: the record to parse * * This returns the latency flags from a record. * * Use trace_flag_type enum for the flags (see event-parse.h). */ -int tep_data_flags(struct tep_handle *pevent, struct tep_record *rec) +int tep_data_flags(struct tep_handle *tep, struct tep_record *rec) { - return parse_common_flags(pevent, rec->data); + return parse_common_flags(tep, rec->data); } /** * tep_data_comm_from_pid - return the command line from PID - * @pevent: a handle to the pevent + * @tep: a handle to the trace event parser context * @pid: the PID of the task to search for * * This returns a pointer to the command line that has the given * @pid. */ -const char *tep_data_comm_from_pid(struct tep_handle *pevent, int pid) +const char *tep_data_comm_from_pid(struct tep_handle *tep, int pid) { const char *comm; - comm = find_cmdline(pevent, pid); + comm = find_cmdline(tep, pid); return comm; } -static struct cmdline * -pid_from_cmdlist(struct tep_handle *pevent, const char *comm, struct cmdline *next) +static struct tep_cmdline * +pid_from_cmdlist(struct tep_handle *tep, const char *comm, struct tep_cmdline *next) { struct cmdline_list *cmdlist = (struct cmdline_list *)next; if (cmdlist) cmdlist = cmdlist->next; else - cmdlist = pevent->cmdlist; + cmdlist = tep->cmdlist; while (cmdlist && strcmp(cmdlist->comm, comm) != 0) cmdlist = cmdlist->next; - return (struct cmdline *)cmdlist; + return (struct tep_cmdline *)cmdlist; } /** * tep_data_pid_from_comm - return the pid from a given comm - * @pevent: a handle to the pevent + * @tep: a handle to the trace event parser context * @comm: the cmdline to find the pid from * @next: the cmdline structure to find the next comm * * This returns the cmdline structure that holds a pid for a given * comm, or NULL if none found. As there may be more than one pid for * a given comm, the result of this call can be passed back into - * a recurring call in the @next paramater, and then it will find the + * a recurring call in the @next parameter, and then it will find the * next pid. - * Also, it does a linear seach, so it may be slow. + * Also, it does a linear search, so it may be slow. */ -struct cmdline *tep_data_pid_from_comm(struct tep_handle *pevent, const char *comm, - struct cmdline *next) +struct tep_cmdline *tep_data_pid_from_comm(struct tep_handle *tep, const char *comm, + struct tep_cmdline *next) { - struct cmdline *cmdline; + struct tep_cmdline *cmdline; /* * If the cmdlines have not been converted yet, then use * the list. */ - if (!pevent->cmdlines) - return pid_from_cmdlist(pevent, comm, next); + if (!tep->cmdlines) + return pid_from_cmdlist(tep, comm, next); if (next) { /* * The next pointer could have been still from * a previous call before cmdlines were created */ - if (next < pevent->cmdlines || - next >= pevent->cmdlines + pevent->cmdline_count) + if (next < tep->cmdlines || + next >= tep->cmdlines + tep->cmdline_count) next = NULL; else cmdline = next++; } if (!next) - cmdline = pevent->cmdlines; + cmdline = tep->cmdlines; - while (cmdline < pevent->cmdlines + pevent->cmdline_count) { + while (cmdline < tep->cmdlines + tep->cmdline_count) { if (strcmp(cmdline->comm, comm) == 0) return cmdline; cmdline++; @@ -5353,12 +5958,13 @@ /** * tep_cmdline_pid - return the pid associated to a given cmdline + * @tep: a handle to the trace event parser context * @cmdline: The cmdline structure to get the pid from * * Returns the pid for a give cmdline. If @cmdline is NULL, then * -1 is returned. */ -int tep_cmdline_pid(struct tep_handle *pevent, struct cmdline *cmdline) +int tep_cmdline_pid(struct tep_handle *tep, struct tep_cmdline *cmdline) { struct cmdline_list *cmdlist = (struct cmdline_list *)cmdline; @@ -5369,33 +5975,28 @@ * If cmdlines have not been created yet, or cmdline is * not part of the array, then treat it as a cmdlist instead. */ - if (!pevent->cmdlines || - cmdline < pevent->cmdlines || - cmdline >= pevent->cmdlines + pevent->cmdline_count) + if (!tep->cmdlines || + cmdline < tep->cmdlines || + cmdline >= tep->cmdlines + tep->cmdline_count) return cmdlist->pid; return cmdline->pid; } -/** - * tep_event_info - parse the data into the print format - * @s: the trace_seq to write to - * @event: the handle to the event - * @record: the record to read from - * +/* * This parses the raw @data using the given @event information and * writes the print format into the trace_seq. */ -void tep_event_info(struct trace_seq *s, struct event_format *event, - struct tep_record *record) +static void print_event_info(struct trace_seq *s, char *format, bool raw, + struct tep_event *event, struct tep_record *record) { int print_pretty = 1; - if (event->pevent->print_raw || (event->flags & EVENT_FL_PRINTRAW)) + if (raw || (event->flags & TEP_EVENT_FL_PRINTRAW)) tep_print_fields(s, record->data, record->size, event); else { - if (event->handler && !(event->flags & EVENT_FL_NOHANDLE)) + if (event->handler && !(event->flags & TEP_EVENT_FL_NOHANDLE)) print_pretty = event->handler(s, record, event, event->context); @@ -5406,29 +6007,16 @@ trace_seq_terminate(s); } -static bool is_timestamp_in_us(char *trace_clock, bool use_trace_clock) -{ - if (!use_trace_clock) - return true; - - if (!strcmp(trace_clock, "local") || !strcmp(trace_clock, "global") - || !strcmp(trace_clock, "uptime") || !strcmp(trace_clock, "perf")) - return true; - - /* trace_clock is setting in tsc or counter mode */ - return false; -} - /** * tep_find_event_by_record - return the event from a given record - * @pevent: a handle to the pevent + * @tep: a handle to the trace event parser context * @record: The record to get the event from * * Returns the associated event for a given record, or NULL if non is * is found. */ -struct event_format * -tep_find_event_by_record(struct tep_handle *pevent, struct tep_record *record) +struct tep_event * +tep_find_event_by_record(struct tep_handle *tep, struct tep_record *record) { int type; @@ -5437,142 +6025,208 @@ return NULL; } - type = trace_parse_common_type(pevent, record->data); + type = trace_parse_common_type(tep, record->data); - return tep_find_event(pevent, type); + return tep_find_event(tep, type); } -/** - * tep_print_event_task - Write the event task comm, pid and CPU - * @pevent: a handle to the pevent - * @s: the trace_seq to write to - * @event: the handle to the record's event - * @record: The record to get the event from - * - * Writes the tasks comm, pid and CPU to @s. +/* + * Writes the timestamp of the record into @s. Time divisor and precision can be + * specified as part of printf @format string. Example: + * "%3.1000d" - divide the time by 1000 and print the first 3 digits + * before the dot. Thus, the timestamp "123456000" will be printed as + * "123.456" */ -void tep_print_event_task(struct tep_handle *pevent, struct trace_seq *s, - struct event_format *event, - struct tep_record *record) +static void print_event_time(struct tep_handle *tep, struct trace_seq *s, + char *format, struct tep_event *event, + struct tep_record *record) { - void *data = record->data; + unsigned long long time; + char *divstr; + int prec = 0, pr; + int div = 0; + int p10 = 1; + + if (isdigit(*(format + 1))) + prec = atoi(format + 1); + divstr = strchr(format, '.'); + if (divstr && isdigit(*(divstr + 1))) + div = atoi(divstr + 1); + time = record->ts; + if (div) { + time += div / 2; + time /= div; + } + pr = prec; + while (pr--) + p10 *= 10; + + if (p10 > 1 && p10 < time) + trace_seq_printf(s, "%5llu.%0*llu", time / p10, prec, time % p10); + else + trace_seq_printf(s, "%12llu", time); +} + +struct print_event_type { + enum { + EVENT_TYPE_INT = 1, + EVENT_TYPE_STRING, + EVENT_TYPE_UNKNOWN, + } type; + char format[32]; +}; + +static void print_string(struct tep_handle *tep, struct trace_seq *s, + struct tep_record *record, struct tep_event *event, + const char *arg, struct print_event_type *type) +{ const char *comm; int pid; - pid = parse_common_pid(pevent, data); - comm = find_cmdline(pevent, pid); - - if (pevent->latency_format) { - trace_seq_printf(s, "%8.8s-%-5d %3d", - comm, pid, record->cpu); - } else - trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu); -} - -/** - * tep_print_event_time - Write the event timestamp - * @pevent: a handle to the pevent - * @s: the trace_seq to write to - * @event: the handle to the record's event - * @record: The record to get the event from - * @use_trace_clock: Set to parse according to the @pevent->trace_clock - * - * Writes the timestamp of the record into @s. - */ -void tep_print_event_time(struct tep_handle *pevent, struct trace_seq *s, - struct event_format *event, - struct tep_record *record, - bool use_trace_clock) -{ - unsigned long secs; - unsigned long usecs; - unsigned long nsecs; - int p; - bool use_usec_format; - - use_usec_format = is_timestamp_in_us(pevent->trace_clock, - use_trace_clock); - if (use_usec_format) { - secs = record->ts / NSEC_PER_SEC; - nsecs = record->ts - secs * NSEC_PER_SEC; + if (strncmp(arg, TEP_PRINT_LATENCY, strlen(TEP_PRINT_LATENCY)) == 0) { + data_latency_format(tep, s, type->format, record); + } else if (strncmp(arg, TEP_PRINT_COMM, strlen(TEP_PRINT_COMM)) == 0) { + pid = parse_common_pid(tep, record->data); + comm = find_cmdline(tep, pid); + trace_seq_printf(s, type->format, comm); + } else if (strncmp(arg, TEP_PRINT_INFO_RAW, strlen(TEP_PRINT_INFO_RAW)) == 0) { + print_event_info(s, type->format, true, event, record); + } else if (strncmp(arg, TEP_PRINT_INFO, strlen(TEP_PRINT_INFO)) == 0) { + print_event_info(s, type->format, false, event, record); + } else if (strncmp(arg, TEP_PRINT_NAME, strlen(TEP_PRINT_NAME)) == 0) { + trace_seq_printf(s, type->format, event->name); + } else { + trace_seq_printf(s, "[UNKNOWN TEP TYPE %s]", arg); } - if (pevent->latency_format) { - tep_data_lat_fmt(pevent, s, record); - } - - if (use_usec_format) { - if (pevent->flags & TEP_NSEC_OUTPUT) { - usecs = nsecs; - p = 9; - } else { - usecs = (nsecs + 500) / NSEC_PER_USEC; - /* To avoid usecs larger than 1 sec */ - if (usecs >= USEC_PER_SEC) { - usecs -= USEC_PER_SEC; - secs++; - } - p = 6; - } - - trace_seq_printf(s, " %5lu.%0*lu:", secs, p, usecs); - } else - trace_seq_printf(s, " %12llu:", record->ts); } -/** - * tep_print_event_data - Write the event data section - * @pevent: a handle to the pevent - * @s: the trace_seq to write to - * @event: the handle to the record's event - * @record: The record to get the event from - * - * Writes the parsing of the record's data to @s. - */ -void tep_print_event_data(struct tep_handle *pevent, struct trace_seq *s, - struct event_format *event, - struct tep_record *record) +static void print_int(struct tep_handle *tep, struct trace_seq *s, + struct tep_record *record, struct tep_event *event, + int arg, struct print_event_type *type) { - static const char *spaces = " "; /* 20 spaces */ - int len; + int param; - trace_seq_printf(s, " %s: ", event->name); - - /* Space out the event names evenly. */ - len = strlen(event->name); - if (len < 20) - trace_seq_printf(s, "%.*s", 20 - len, spaces); - - tep_event_info(s, event, record); -} - -void tep_print_event(struct tep_handle *pevent, struct trace_seq *s, - struct tep_record *record, bool use_trace_clock) -{ - struct event_format *event; - - event = tep_find_event_by_record(pevent, record); - if (!event) { - int i; - int type = trace_parse_common_type(pevent, record->data); - - do_warning("ug! no event found for type %d", type); - trace_seq_printf(s, "[UNKNOWN TYPE %d]", type); - for (i = 0; i < record->size; i++) - trace_seq_printf(s, " %02x", - ((unsigned char *)record->data)[i]); + switch (arg) { + case TEP_PRINT_CPU: + param = record->cpu; + break; + case TEP_PRINT_PID: + param = parse_common_pid(tep, record->data); + break; + case TEP_PRINT_TIME: + return print_event_time(tep, s, type->format, event, record); + default: return; } + trace_seq_printf(s, type->format, param); +} - tep_print_event_task(pevent, s, event, record); - tep_print_event_time(pevent, s, event, record, use_trace_clock); - tep_print_event_data(pevent, s, event, record); +static int tep_print_event_param_type(char *format, + struct print_event_type *type) +{ + char *str = format + 1; + int i = 1; + + type->type = EVENT_TYPE_UNKNOWN; + while (*str) { + switch (*str) { + case 'd': + case 'u': + case 'i': + case 'x': + case 'X': + case 'o': + type->type = EVENT_TYPE_INT; + break; + case 's': + type->type = EVENT_TYPE_STRING; + break; + } + str++; + i++; + if (type->type != EVENT_TYPE_UNKNOWN) + break; + } + memset(type->format, 0, 32); + memcpy(type->format, format, i < 32 ? i : 31); + return i; +} + +/** + * tep_print_event - Write various event information + * @tep: a handle to the trace event parser context + * @s: the trace_seq to write to + * @record: The record to get the event from + * @format: a printf format string. Supported event fileds: + * TEP_PRINT_PID, "%d" - event PID + * TEP_PRINT_CPU, "%d" - event CPU + * TEP_PRINT_COMM, "%s" - event command string + * TEP_PRINT_NAME, "%s" - event name + * TEP_PRINT_LATENCY, "%s" - event latency + * TEP_PRINT_TIME, %d - event time stamp. A divisor and precision + * can be specified as part of this format string: + * "%precision.divisord". Example: + * "%3.1000d" - divide the time by 1000 and print the first + * 3 digits before the dot. Thus, the time stamp + * "123456000" will be printed as "123.456" + * TEP_PRINT_INFO, "%s" - event information. If any width is specified in + * the format string, the event information will be printed + * in raw format. + * Writes the specified event information into @s. + */ +void tep_print_event(struct tep_handle *tep, struct trace_seq *s, + struct tep_record *record, const char *fmt, ...) +{ + struct print_event_type type; + char *format = strdup(fmt); + char *current = format; + char *str = format; + int offset; + va_list args; + struct tep_event *event; + + if (!format) + return; + + event = tep_find_event_by_record(tep, record); + va_start(args, fmt); + while (*current) { + current = strchr(str, '%'); + if (!current) { + trace_seq_puts(s, str); + break; + } + memset(&type, 0, sizeof(type)); + offset = tep_print_event_param_type(current, &type); + *current = '\0'; + trace_seq_puts(s, str); + current += offset; + switch (type.type) { + case EVENT_TYPE_STRING: + print_string(tep, s, record, event, + va_arg(args, char*), &type); + break; + case EVENT_TYPE_INT: + print_int(tep, s, record, event, + va_arg(args, int), &type); + break; + case EVENT_TYPE_UNKNOWN: + default: + trace_seq_printf(s, "[UNKNOWN TYPE]"); + break; + } + str = current; + + } + va_end(args); + free(format); } static int events_id_cmp(const void *a, const void *b) { - struct event_format * const * ea = a; - struct event_format * const * eb = b; + struct tep_event * const * ea = a; + struct tep_event * const * eb = b; if ((*ea)->id < (*eb)->id) return -1; @@ -5585,8 +6239,8 @@ static int events_name_cmp(const void *a, const void *b) { - struct event_format * const * ea = a; - struct event_format * const * eb = b; + struct tep_event * const * ea = a; + struct tep_event * const * eb = b; int res; res = strcmp((*ea)->name, (*eb)->name); @@ -5602,8 +6256,8 @@ static int events_system_cmp(const void *a, const void *b) { - struct event_format * const * ea = a; - struct event_format * const * eb = b; + struct tep_event * const * ea = a; + struct tep_event * const * eb = b; int res; res = strcmp((*ea)->system, (*eb)->system); @@ -5617,59 +6271,124 @@ return events_id_cmp(a, b); } -struct event_format **tep_list_events(struct tep_handle *pevent, enum event_sort_type sort_type) +static struct tep_event **list_events_copy(struct tep_handle *tep) { - struct event_format **events; + struct tep_event **events; + + if (!tep) + return NULL; + + events = malloc(sizeof(*events) * (tep->nr_events + 1)); + if (!events) + return NULL; + + memcpy(events, tep->events, sizeof(*events) * tep->nr_events); + events[tep->nr_events] = NULL; + return events; +} + +static void list_events_sort(struct tep_event **events, int nr_events, + enum tep_event_sort_type sort_type) +{ int (*sort)(const void *a, const void *b); - events = pevent->sort_events; + switch (sort_type) { + case TEP_EVENT_SORT_ID: + sort = events_id_cmp; + break; + case TEP_EVENT_SORT_NAME: + sort = events_name_cmp; + break; + case TEP_EVENT_SORT_SYSTEM: + sort = events_system_cmp; + break; + default: + sort = NULL; + } - if (events && pevent->last_type == sort_type) + if (sort) + qsort(events, nr_events, sizeof(*events), sort); +} + +/** + * tep_list_events - Get events, sorted by given criteria. + * @tep: a handle to the tep context + * @sort_type: desired sort order of the events in the array + * + * Returns an array of pointers to all events, sorted by the given + * @sort_type criteria. The last element of the array is NULL. The returned + * memory must not be freed, it is managed by the library. + * The function is not thread safe. + */ +struct tep_event **tep_list_events(struct tep_handle *tep, + enum tep_event_sort_type sort_type) +{ + struct tep_event **events; + + if (!tep) + return NULL; + + events = tep->sort_events; + if (events && tep->last_type == sort_type) return events; if (!events) { - events = malloc(sizeof(*events) * (pevent->nr_events + 1)); + events = list_events_copy(tep); if (!events) return NULL; - memcpy(events, pevent->events, sizeof(*events) * pevent->nr_events); - events[pevent->nr_events] = NULL; - - pevent->sort_events = events; + tep->sort_events = events; /* the internal events are sorted by id */ - if (sort_type == EVENT_SORT_ID) { - pevent->last_type = sort_type; + if (sort_type == TEP_EVENT_SORT_ID) { + tep->last_type = sort_type; return events; } } - switch (sort_type) { - case EVENT_SORT_ID: - sort = events_id_cmp; - break; - case EVENT_SORT_NAME: - sort = events_name_cmp; - break; - case EVENT_SORT_SYSTEM: - sort = events_system_cmp; - break; - default: - return events; - } - - qsort(events, pevent->nr_events, sizeof(*events), sort); - pevent->last_type = sort_type; + list_events_sort(events, tep->nr_events, sort_type); + tep->last_type = sort_type; return events; } -static struct format_field ** -get_event_fields(const char *type, const char *name, - int count, struct format_field *list) + +/** + * tep_list_events_copy - Thread safe version of tep_list_events() + * @tep: a handle to the tep context + * @sort_type: desired sort order of the events in the array + * + * Returns an array of pointers to all events, sorted by the given + * @sort_type criteria. The last element of the array is NULL. The returned + * array is newly allocated inside the function and must be freed by the caller + */ +struct tep_event **tep_list_events_copy(struct tep_handle *tep, + enum tep_event_sort_type sort_type) { - struct format_field **fields; - struct format_field *field; + struct tep_event **events; + + if (!tep) + return NULL; + + events = list_events_copy(tep); + if (!events) + return NULL; + + /* the internal events are sorted by id */ + if (sort_type == TEP_EVENT_SORT_ID) + return events; + + list_events_sort(events, tep->nr_events, sort_type); + + return events; +} + +static struct tep_format_field ** +get_event_fields(const char *type, const char *name, + int count, struct tep_format_field *list) +{ + struct tep_format_field **fields; + struct tep_format_field *field; int i = 0; fields = malloc(sizeof(*fields) * (count + 1)); @@ -5702,7 +6421,7 @@ * Returns an allocated array of fields. The last item in the array is NULL. * The array must be freed with free(). */ -struct format_field **tep_event_common_fields(struct event_format *event) +struct tep_format_field **tep_event_common_fields(struct tep_event *event) { return get_event_fields("common", event->name, event->format.nr_common, @@ -5716,14 +6435,14 @@ * Returns an allocated array of fields. The last item in the array is NULL. * The array must be freed with free(). */ -struct format_field **tep_event_fields(struct event_format *event) +struct tep_format_field **tep_event_fields(struct tep_event *event) { return get_event_fields("event", event->name, event->format.nr_fields, event->format.fields); } -static void print_fields(struct trace_seq *s, struct print_flag_sym *field) +static void print_fields(struct trace_seq *s, struct tep_print_flag_sym *field) { trace_seq_printf(s, "{ %s, %s }", field->value, field->str); if (field->next) { @@ -5733,22 +6452,22 @@ } /* for debugging */ -static void print_args(struct print_arg *args) +static void print_args(struct tep_print_arg *args) { int print_paren = 1; struct trace_seq s; switch (args->type) { - case PRINT_NULL: + case TEP_PRINT_NULL: printf("null"); break; - case PRINT_ATOM: + case TEP_PRINT_ATOM: printf("%s", args->atom.atom); break; - case PRINT_FIELD: + case TEP_PRINT_FIELD: printf("REC->%s", args->field.name); break; - case PRINT_FLAGS: + case TEP_PRINT_FLAGS: printf("__print_flags("); print_args(args->flags.field); printf(", %s, ", args->flags.delim); @@ -5758,7 +6477,7 @@ trace_seq_destroy(&s); printf(")"); break; - case PRINT_SYMBOL: + case TEP_PRINT_SYMBOL: printf("__print_symbolic("); print_args(args->symbol.field); printf(", "); @@ -5768,21 +6487,21 @@ trace_seq_destroy(&s); printf(")"); break; - case PRINT_HEX: + case TEP_PRINT_HEX: printf("__print_hex("); print_args(args->hex.field); printf(", "); print_args(args->hex.size); printf(")"); break; - case PRINT_HEX_STR: + case TEP_PRINT_HEX_STR: printf("__print_hex_str("); print_args(args->hex.field); printf(", "); print_args(args->hex.size); printf(")"); break; - case PRINT_INT_ARRAY: + case TEP_PRINT_INT_ARRAY: printf("__print_array("); print_args(args->int_array.field); printf(", "); @@ -5791,18 +6510,18 @@ print_args(args->int_array.el_size); printf(")"); break; - case PRINT_STRING: - case PRINT_BSTRING: + case TEP_PRINT_STRING: + case TEP_PRINT_BSTRING: printf("__get_str(%s)", args->string.string); break; - case PRINT_BITMASK: + case TEP_PRINT_BITMASK: printf("__get_bitmask(%s)", args->bitmask.bitmask); break; - case PRINT_TYPE: + case TEP_PRINT_TYPE: printf("(%s)", args->typecast.type); print_args(args->typecast.item); break; - case PRINT_OP: + case TEP_PRINT_OP: if (strcmp(args->op.op, ":") == 0) print_paren = 0; if (print_paren) @@ -5834,13 +6553,13 @@ save_input_buf_ptr = input_buf_ptr; save_input_buf_siz = input_buf_siz; - if (read_expected(EVENT_ITEM, "field") < 0) + if (read_expected(TEP_EVENT_ITEM, "field") < 0) return; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) return; /* type */ - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto fail; free_token(token); @@ -5848,42 +6567,42 @@ * If this is not a mandatory field, then test it first. */ if (mandatory) { - if (read_expected(EVENT_ITEM, field) < 0) + if (read_expected(TEP_EVENT_ITEM, field) < 0) return; } else { - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto fail; if (strcmp(token, field) != 0) goto discard; free_token(token); } - if (read_expected(EVENT_OP, ";") < 0) + if (read_expected(TEP_EVENT_OP, ";") < 0) return; - if (read_expected(EVENT_ITEM, "offset") < 0) + if (read_expected(TEP_EVENT_ITEM, "offset") < 0) return; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) return; - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto fail; *offset = atoi(token); free_token(token); - if (read_expected(EVENT_OP, ";") < 0) + if (read_expected(TEP_EVENT_OP, ";") < 0) return; - if (read_expected(EVENT_ITEM, "size") < 0) + if (read_expected(TEP_EVENT_ITEM, "size") < 0) return; - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) return; - if (read_expect_type(EVENT_ITEM, &token) < 0) + if (read_expect_type(TEP_EVENT_ITEM, &token) < 0) goto fail; *size = atoi(token); free_token(token); - if (read_expected(EVENT_OP, ";") < 0) + if (read_expected(TEP_EVENT_OP, ";") < 0) return; type = read_token(&token); - if (type != EVENT_NEWLINE) { + if (type != TEP_EVENT_NEWLINE) { /* newer versions of the kernel have a "signed" type */ - if (type != EVENT_ITEM) + if (type != TEP_EVENT_ITEM) goto fail; if (strcmp(token, "signed") != 0) @@ -5891,17 +6610,17 @@ free_token(token); - if (read_expected(EVENT_OP, ":") < 0) + if (read_expected(TEP_EVENT_OP, ":") < 0) return; - if (read_expect_type(EVENT_ITEM, &token)) + if (read_expect_type(TEP_EVENT_ITEM, &token)) goto fail; free_token(token); - if (read_expected(EVENT_OP, ";") < 0) + if (read_expected(TEP_EVENT_OP, ";") < 0) return; - if (read_expect_type(EVENT_NEWLINE, &token)) + if (read_expect_type(TEP_EVENT_NEWLINE, &token)) goto fail; } fail: @@ -5918,7 +6637,7 @@ /** * tep_parse_header_page - parse the data stored in the header page - * @pevent: the handle to the pevent + * @tep: a handle to the trace event parser context * @buf: the buffer storing the header page format string * @size: the size of @buf * @long_size: the long size to use if there is no header @@ -5928,7 +6647,7 @@ * * /sys/kernel/debug/tracing/events/header_page */ -int tep_parse_header_page(struct tep_handle *pevent, char *buf, unsigned long size, +int tep_parse_header_page(struct tep_handle *tep, char *buf, unsigned long size, int long_size) { int ignore; @@ -5938,27 +6657,27 @@ * Old kernels did not have header page info. * Sorry but we just use what we find here in user space. */ - pevent->header_page_ts_size = sizeof(long long); - pevent->header_page_size_size = long_size; - pevent->header_page_data_offset = sizeof(long long) + long_size; - pevent->old_format = 1; + tep->header_page_ts_size = sizeof(long long); + tep->header_page_size_size = long_size; + tep->header_page_data_offset = sizeof(long long) + long_size; + tep->old_format = 1; return -1; } init_input_buf(buf, size); - parse_header_field("timestamp", &pevent->header_page_ts_offset, - &pevent->header_page_ts_size, 1); - parse_header_field("commit", &pevent->header_page_size_offset, - &pevent->header_page_size_size, 1); - parse_header_field("overwrite", &pevent->header_page_overwrite, + parse_header_field("timestamp", &tep->header_page_ts_offset, + &tep->header_page_ts_size, 1); + parse_header_field("commit", &tep->header_page_size_offset, + &tep->header_page_size_size, 1); + parse_header_field("overwrite", &tep->header_page_overwrite, &ignore, 0); - parse_header_field("data", &pevent->header_page_data_offset, - &pevent->header_page_data_size, 1); + parse_header_field("data", &tep->header_page_data_offset, + &tep->header_page_data_size, 1); return 0; } -static int event_matches(struct event_format *event, +static int event_matches(struct tep_event *event, int id, const char *sys_name, const char *event_name) { @@ -5981,11 +6700,11 @@ free(handle); } -static int find_event_handle(struct tep_handle *pevent, struct event_format *event) +static int find_event_handle(struct tep_handle *tep, struct tep_event *event) { struct event_handler *handle, **next; - for (next = &pevent->handlers; *next; + for (next = &tep->handlers; *next; next = &(*next)->next) { handle = *next; if (event_matches(event, handle->id, @@ -6010,7 +6729,7 @@ } /** - * __tep_parse_format - parse the event format + * parse_format - parse the event format * @buf: the buffer storing the event format string * @size: the size of @buf * @sys: the system the event belongs to @@ -6022,11 +6741,11 @@ * * /sys/kernel/debug/tracing/events/.../.../format */ -enum tep_errno __tep_parse_format(struct event_format **eventp, - struct tep_handle *pevent, const char *buf, - unsigned long size, const char *sys) +static enum tep_errno parse_format(struct tep_event **eventp, + struct tep_handle *tep, const char *buf, + unsigned long size, const char *sys) { - struct event_format *event; + struct tep_event *event; int ret; init_input_buf(buf, size); @@ -6043,10 +6762,10 @@ } if (strcmp(sys, "ftrace") == 0) { - event->flags |= EVENT_FL_ISFTRACE; + event->flags |= TEP_EVENT_FL_ISFTRACE; if (strcmp(event->name, "bprint") == 0) - event->flags |= EVENT_FL_ISBPRINT; + event->flags |= TEP_EVENT_FL_ISBPRINT; } event->id = event_read_id(); @@ -6065,8 +6784,8 @@ goto event_alloc_failed; } - /* Add pevent to event so that it can be referenced */ - event->pevent = pevent; + /* Add tep to event so that it can be referenced */ + event->tep = tep; ret = event_read_format(event); if (ret < 0) { @@ -6078,7 +6797,7 @@ * If the event has an override, don't print warnings if the event * print format fails to parse. */ - if (pevent && find_event_handle(pevent, event)) + if (tep && find_event_handle(tep, event)) show_warning = 0; ret = event_read_print(event); @@ -6089,22 +6808,22 @@ goto event_parse_failed; } - if (!ret && (event->flags & EVENT_FL_ISFTRACE)) { - struct format_field *field; - struct print_arg *arg, **list; + if (!ret && (event->flags & TEP_EVENT_FL_ISFTRACE)) { + struct tep_format_field *field; + struct tep_print_arg *arg, **list; /* old ftrace had no args */ list = &event->print_fmt.args; for (field = event->format.fields; field; field = field->next) { arg = alloc_arg(); if (!arg) { - event->flags |= EVENT_FL_FAILED; + event->flags |= TEP_EVENT_FL_FAILED; return TEP_ERRNO__OLD_FTRACE_ARG_FAILED; } - arg->type = PRINT_FIELD; + arg->type = TEP_PRINT_FIELD; arg->field.name = strdup(field->name); if (!arg->field.name) { - event->flags |= EVENT_FL_FAILED; + event->flags |= TEP_EVENT_FL_FAILED; free_arg(arg); return TEP_ERRNO__OLD_FTRACE_ARG_FAILED; } @@ -6112,13 +6831,17 @@ *list = arg; list = &arg->next; } - return 0; } + + if (!(event->flags & TEP_EVENT_FL_ISBPRINT)) + event->print_fmt.print_cache = parse_args(event, + event->print_fmt.format, + event->print_fmt.args); return 0; event_parse_failed: - event->flags |= EVENT_FL_FAILED; + event->flags |= TEP_EVENT_FL_FAILED; return ret; event_alloc_failed: @@ -6130,18 +6853,18 @@ } static enum tep_errno -__parse_event(struct tep_handle *pevent, - struct event_format **eventp, +__parse_event(struct tep_handle *tep, + struct tep_event **eventp, const char *buf, unsigned long size, const char *sys) { - int ret = __tep_parse_format(eventp, pevent, buf, size, sys); - struct event_format *event = *eventp; + int ret = parse_format(eventp, tep, buf, size, sys); + struct tep_event *event = *eventp; if (event == NULL) return ret; - if (pevent && add_event(pevent, event)) { + if (tep && add_event(tep, event)) { ret = TEP_ERRNO__MEM_ALLOC_FAILED; goto event_add_failed; } @@ -6153,13 +6876,13 @@ return 0; event_add_failed: - tep_free_format(event); + free_tep_event(event); return ret; } /** * tep_parse_format - parse the event format - * @pevent: the handle to the pevent + * @tep: a handle to the trace event parser context * @eventp: returned format * @buf: the buffer storing the event format string * @size: the size of @buf @@ -6172,17 +6895,17 @@ * * /sys/kernel/debug/tracing/events/.../.../format */ -enum tep_errno tep_parse_format(struct tep_handle *pevent, - struct event_format **eventp, +enum tep_errno tep_parse_format(struct tep_handle *tep, + struct tep_event **eventp, const char *buf, unsigned long size, const char *sys) { - return __parse_event(pevent, eventp, buf, size, sys); + return __parse_event(tep, eventp, buf, size, sys); } /** * tep_parse_event - parse the event format - * @pevent: the handle to the pevent + * @tep: a handle to the trace event parser context * @buf: the buffer storing the event format string * @size: the size of @buf * @sys: the system the event belongs to @@ -6194,43 +6917,14 @@ * * /sys/kernel/debug/tracing/events/.../.../format */ -enum tep_errno tep_parse_event(struct tep_handle *pevent, const char *buf, +enum tep_errno tep_parse_event(struct tep_handle *tep, const char *buf, unsigned long size, const char *sys) { - struct event_format *event = NULL; - return __parse_event(pevent, &event, buf, size, sys); + struct tep_event *event = NULL; + return __parse_event(tep, &event, buf, size, sys); } -#undef _PE -#define _PE(code, str) str -static const char * const tep_error_str[] = { - TEP_ERRORS -}; -#undef _PE - -int tep_strerror(struct tep_handle *pevent __maybe_unused, - enum tep_errno errnum, char *buf, size_t buflen) -{ - int idx; - const char *msg; - - if (errnum >= 0) { - str_error_r(errnum, buf, buflen); - return 0; - } - - if (errnum <= __TEP_ERRNO__START || - errnum >= __TEP_ERRNO__END) - return -1; - - idx = errnum - __TEP_ERRNO__START - 1; - msg = tep_error_str[idx]; - snprintf(buf, buflen, "%s", msg); - - return 0; -} - -int get_field_val(struct trace_seq *s, struct format_field *field, +int get_field_val(struct trace_seq *s, struct tep_format_field *field, const char *name, struct tep_record *record, unsigned long long *val, int err) { @@ -6263,11 +6957,11 @@ * * On failure, it returns NULL. */ -void *tep_get_field_raw(struct trace_seq *s, struct event_format *event, +void *tep_get_field_raw(struct trace_seq *s, struct tep_event *event, const char *name, struct tep_record *record, int *len, int err) { - struct format_field *field; + struct tep_format_field *field; void *data = record->data; unsigned offset; int dummy; @@ -6288,9 +6982,9 @@ len = &dummy; offset = field->offset; - if (field->flags & FIELD_IS_DYNAMIC) { - offset = tep_read_number(event->pevent, - data + offset, field->size); + if (field->flags & TEP_FIELD_IS_DYNAMIC) { + offset = tep_read_number(event->tep, + data + offset, field->size); *len = offset >> 16; offset &= 0xffff; } else @@ -6310,11 +7004,11 @@ * * Returns 0 on success -1 on field not found. */ -int tep_get_field_val(struct trace_seq *s, struct event_format *event, +int tep_get_field_val(struct trace_seq *s, struct tep_event *event, const char *name, struct tep_record *record, unsigned long long *val, int err) { - struct format_field *field; + struct tep_format_field *field; if (!event) return -1; @@ -6335,11 +7029,11 @@ * * Returns 0 on success -1 on field not found. */ -int tep_get_common_field_val(struct trace_seq *s, struct event_format *event, +int tep_get_common_field_val(struct trace_seq *s, struct tep_event *event, const char *name, struct tep_record *record, unsigned long long *val, int err) { - struct format_field *field; + struct tep_format_field *field; if (!event) return -1; @@ -6360,11 +7054,11 @@ * * Returns 0 on success -1 on field not found. */ -int tep_get_any_field_val(struct trace_seq *s, struct event_format *event, +int tep_get_any_field_val(struct trace_seq *s, struct tep_event *event, const char *name, struct tep_record *record, unsigned long long *val, int err) { - struct format_field *field; + struct tep_format_field *field; if (!event) return -1; @@ -6383,13 +7077,14 @@ * @record: The record with the field name. * @err: print default error if failed. * - * Returns: 0 on success, -1 field not found, or 1 if buffer is full. + * Returns positive value on success, negative in case of an error, + * or 0 if buffer is full. */ int tep_print_num_field(struct trace_seq *s, const char *fmt, - struct event_format *event, const char *name, + struct tep_event *event, const char *name, struct tep_record *record, int err) { - struct format_field *field = tep_find_field(event, name); + struct tep_format_field *field = tep_find_field(event, name); unsigned long long val; if (!field) @@ -6415,14 +7110,15 @@ * @record: The record with the field name. * @err: print default error if failed. * - * Returns: 0 on success, -1 field not found, or 1 if buffer is full. + * Returns positive value on success, negative in case of an error, + * or 0 if buffer is full. */ int tep_print_func_field(struct trace_seq *s, const char *fmt, - struct event_format *event, const char *name, + struct tep_event *event, const char *name, struct tep_record *record, int err) { - struct format_field *field = tep_find_field(event, name); - struct tep_handle *pevent = event->pevent; + struct tep_format_field *field = tep_find_field(event, name); + struct tep_handle *tep = event->tep; unsigned long long val; struct func_map *func; char tmp[128]; @@ -6433,7 +7129,7 @@ if (tep_read_number_field(field, record->data, &val)) goto failed; - func = find_func(pevent, val); + func = find_func(tep, val); if (func) snprintf(tmp, 128, "%s/0x%llx", func->func, func->addr - val); @@ -6465,7 +7161,7 @@ /** * tep_register_print_function - register a helper function - * @pevent: the handle to the pevent + * @tep: a handle to the trace event parser context * @func: the function to process the helper function * @ret_type: the return type of the helper function * @name: the name of the helper function @@ -6478,7 +7174,7 @@ * The @parameters is a variable list of tep_func_arg_type enums that * must end with TEP_FUNC_ARG_VOID. */ -int tep_register_print_function(struct tep_handle *pevent, +int tep_register_print_function(struct tep_handle *tep, tep_func_handler func, enum tep_func_arg_type ret_type, char *name, ...) @@ -6490,7 +7186,7 @@ va_list ap; int ret; - func_handle = find_func_handler(pevent, name); + func_handle = find_func_handler(tep, name); if (func_handle) { /* * This is most like caused by the users own @@ -6498,7 +7194,7 @@ * system defaults. */ pr_stat("override of function helper '%s'", name); - remove_func_handler(pevent, name); + remove_func_handler(tep, name); } func_handle = calloc(1, sizeof(*func_handle)); @@ -6545,8 +7241,8 @@ } va_end(ap); - func_handle->next = pevent->func_handlers; - pevent->func_handlers = func_handle; + func_handle->next = tep->func_handlers; + tep->func_handlers = func_handle; return 0; out_free: @@ -6557,7 +7253,7 @@ /** * tep_unregister_print_function - unregister a helper function - * @pevent: the handle to the pevent + * @tep: a handle to the trace event parser context * @func: the function to process the helper function * @name: the name of the helper function * @@ -6565,28 +7261,28 @@ * * Returns 0 if the handler was removed successully, -1 otherwise. */ -int tep_unregister_print_function(struct tep_handle *pevent, +int tep_unregister_print_function(struct tep_handle *tep, tep_func_handler func, char *name) { struct tep_function_handler *func_handle; - func_handle = find_func_handler(pevent, name); + func_handle = find_func_handler(tep, name); if (func_handle && func_handle->func == func) { - remove_func_handler(pevent, name); + remove_func_handler(tep, name); return 0; } return -1; } -static struct event_format *search_event(struct tep_handle *pevent, int id, - const char *sys_name, - const char *event_name) +static struct tep_event *search_event(struct tep_handle *tep, int id, + const char *sys_name, + const char *event_name) { - struct event_format *event; + struct tep_event *event; if (id >= 0) { /* search by id */ - event = tep_find_event(pevent, id); + event = tep_find_event(tep, id); if (!event) return NULL; if (event_name && (strcmp(event_name, event->name) != 0)) @@ -6594,7 +7290,7 @@ if (sys_name && (strcmp(sys_name, event->system) != 0)) return NULL; } else { - event = tep_find_event_by_name(pevent, sys_name, event_name); + event = tep_find_event_by_name(tep, sys_name, event_name); if (!event) return NULL; } @@ -6603,7 +7299,7 @@ /** * tep_register_event_handler - register a way to parse an event - * @pevent: the handle to the pevent + * @tep: a handle to the trace event parser context * @id: the id of the event to register * @sys_name: the system name the event belongs to * @event_name: the name of the event @@ -6617,15 +7313,21 @@ * * If @id is >= 0, then it is used to find the event. * else @sys_name and @event_name are used. + * + * Returns: + * TEP_REGISTER_SUCCESS_OVERWRITE if an existing handler is overwritten + * TEP_REGISTER_SUCCESS if a new handler is registered successfully + * negative TEP_ERRNO_... in case of an error + * */ -int tep_register_event_handler(struct tep_handle *pevent, int id, +int tep_register_event_handler(struct tep_handle *tep, int id, const char *sys_name, const char *event_name, tep_event_handler_func func, void *context) { - struct event_format *event; + struct tep_event *event; struct event_handler *handle; - event = search_event(pevent, id, sys_name, event_name); + event = search_event(tep, id, sys_name, event_name); if (event == NULL) goto not_found; @@ -6634,7 +7336,7 @@ event->handler = func; event->context = context; - return 0; + return TEP_REGISTER_SUCCESS_OVERWRITE; not_found: /* Save for later use. */ @@ -6660,11 +7362,11 @@ } handle->func = func; - handle->next = pevent->handlers; - pevent->handlers = handle; + handle->next = tep->handlers; + tep->handlers = handle; handle->context = context; - return -1; + return TEP_REGISTER_SUCCESS; } static int handle_matches(struct event_handler *handler, int id, @@ -6688,7 +7390,7 @@ /** * tep_unregister_event_handler - unregister an existing event handler - * @pevent: the handle to the pevent + * @tep: a handle to the trace event parser context * @id: the id of the event to unregister * @sys_name: the system name the handler belongs to * @event_name: the name of the event handler @@ -6702,15 +7404,15 @@ * * Returns 0 if handler was removed successfully, -1 if event was not found. */ -int tep_unregister_event_handler(struct tep_handle *pevent, int id, +int tep_unregister_event_handler(struct tep_handle *tep, int id, const char *sys_name, const char *event_name, tep_event_handler_func func, void *context) { - struct event_format *event; + struct tep_event *event; struct event_handler *handle; struct event_handler **next; - event = search_event(pevent, id, sys_name, event_name); + event = search_event(tep, id, sys_name, event_name); if (event == NULL) goto not_found; @@ -6724,7 +7426,7 @@ } not_found: - for (next = &pevent->handlers; *next; next = &(*next)->next) { + for (next = &tep->handlers; *next; next = &(*next)->next) { handle = *next; if (handle_matches(handle, id, sys_name, event_name, func, context)) @@ -6741,24 +7443,33 @@ } /** - * tep_alloc - create a pevent handle + * tep_alloc - create a tep handle */ struct tep_handle *tep_alloc(void) { - struct tep_handle *pevent = calloc(1, sizeof(*pevent)); + struct tep_handle *tep = calloc(1, sizeof(*tep)); - if (pevent) - pevent->ref_count = 1; + if (tep) { + tep->ref_count = 1; + tep->host_bigendian = tep_is_bigendian(); + } - return pevent; + return tep; } -void tep_ref(struct tep_handle *pevent) +void tep_ref(struct tep_handle *tep) { - pevent->ref_count++; + tep->ref_count++; } -void tep_free_format_field(struct format_field *field) +int tep_get_ref(struct tep_handle *tep) +{ + if (tep) + return tep->ref_count; + return 0; +} + +__hidden void free_tep_format_field(struct tep_format_field *field) { free(field->type); if (field->alias != field->name) @@ -6767,24 +7478,24 @@ free(field); } -static void free_format_fields(struct format_field *field) +static void free_format_fields(struct tep_format_field *field) { - struct format_field *next; + struct tep_format_field *next; while (field) { next = field->next; - tep_free_format_field(field); + free_tep_format_field(field); field = next; } } -static void free_formats(struct format *format) +static void free_formats(struct tep_format *format) { free_format_fields(format->common_fields); free_format_fields(format->fields); } -void tep_free_format(struct event_format *event) +__hidden void free_tep_event(struct tep_event *event) { free(event->name); free(event->system); @@ -6793,15 +7504,15 @@ free(event->print_fmt.format); free_args(event->print_fmt.args); - + free_parse_args(event->print_fmt.print_cache); free(event); } /** - * tep_free - free a pevent handle - * @pevent: the pevent handle to free + * tep_free - free a tep handle + * @tep: the tep handle to free */ -void tep_free(struct tep_handle *pevent) +void tep_free(struct tep_handle *tep) { struct cmdline_list *cmdlist, *cmdnext; struct func_list *funclist, *funcnext; @@ -6810,21 +7521,21 @@ struct event_handler *handle; int i; - if (!pevent) + if (!tep) return; - cmdlist = pevent->cmdlist; - funclist = pevent->funclist; - printklist = pevent->printklist; + cmdlist = tep->cmdlist; + funclist = tep->funclist; + printklist = tep->printklist; - pevent->ref_count--; - if (pevent->ref_count) + tep->ref_count--; + if (tep->ref_count) return; - if (pevent->cmdlines) { - for (i = 0; i < pevent->cmdline_count; i++) - free(pevent->cmdlines[i].comm); - free(pevent->cmdlines); + if (tep->cmdlines) { + for (i = 0; i < tep->cmdline_count; i++) + free(tep->cmdlines[i].comm); + free(tep->cmdlines); } while (cmdlist) { @@ -6834,12 +7545,12 @@ cmdlist = cmdnext; } - if (pevent->func_map) { - for (i = 0; i < (int)pevent->func_count; i++) { - free(pevent->func_map[i].func); - free(pevent->func_map[i].mod); + if (tep->func_map) { + for (i = 0; i < (int)tep->func_count; i++) { + free(tep->func_map[i].func); + free(tep->func_map[i].mod); } - free(pevent->func_map); + free(tep->func_map); } while (funclist) { @@ -6850,16 +7561,16 @@ funclist = funcnext; } - while (pevent->func_handlers) { - func_handler = pevent->func_handlers; - pevent->func_handlers = func_handler->next; + while (tep->func_handlers) { + func_handler = tep->func_handlers; + tep->func_handlers = func_handler->next; free_func_handle(func_handler); } - if (pevent->printk_map) { - for (i = 0; i < (int)pevent->printk_count; i++) - free(pevent->printk_map[i].printk); - free(pevent->printk_map); + if (tep->printk_map) { + for (i = 0; i < (int)tep->printk_count; i++) + free(tep->printk_map[i].printk); + free(tep->printk_map); } while (printklist) { @@ -6869,24 +7580,24 @@ printklist = printknext; } - for (i = 0; i < pevent->nr_events; i++) - tep_free_format(pevent->events[i]); + for (i = 0; i < tep->nr_events; i++) + free_tep_event(tep->events[i]); - while (pevent->handlers) { - handle = pevent->handlers; - pevent->handlers = handle->next; + while (tep->handlers) { + handle = tep->handlers; + tep->handlers = handle->next; free_handler(handle); } - free(pevent->trace_clock); - free(pevent->events); - free(pevent->sort_events); - free(pevent->func_resolver); + free(tep->events); + free(tep->sort_events); + free(tep->func_resolver); + free_tep_plugin_paths(tep); - free(pevent); + free(tep); } -void tep_unref(struct tep_handle *pevent) +void tep_unref(struct tep_handle *tep) { - tep_free(pevent); + tep_free(tep); } -- Gitblit v1.6.2