1*4882a593Smuzhiyun // SPDX-License-Identifier: LGPL-2.1
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * The parts for function graph printing was taken and modified from the
7*4882a593Smuzhiyun * Linux Kernel that were written by
8*4882a593Smuzhiyun * - Copyright (C) 2009 Frederic Weisbecker,
9*4882a593Smuzhiyun * Frederic Weisbecker gave his permission to relicense the code to
10*4882a593Smuzhiyun * the Lesser General Public License.
11*4882a593Smuzhiyun */
12*4882a593Smuzhiyun #include <inttypes.h>
13*4882a593Smuzhiyun #include <stdio.h>
14*4882a593Smuzhiyun #include <stdlib.h>
15*4882a593Smuzhiyun #include <string.h>
16*4882a593Smuzhiyun #include <stdarg.h>
17*4882a593Smuzhiyun #include <ctype.h>
18*4882a593Smuzhiyun #include <errno.h>
19*4882a593Smuzhiyun #include <stdint.h>
20*4882a593Smuzhiyun #include <limits.h>
21*4882a593Smuzhiyun #include <linux/time64.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #include <netinet/in.h>
24*4882a593Smuzhiyun #include "event-parse.h"
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #include "event-parse-local.h"
27*4882a593Smuzhiyun #include "event-utils.h"
28*4882a593Smuzhiyun #include "trace-seq.h"
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun static const char *input_buf;
31*4882a593Smuzhiyun static unsigned long long input_buf_ptr;
32*4882a593Smuzhiyun static unsigned long long input_buf_siz;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun static int is_flag_field;
35*4882a593Smuzhiyun static int is_symbolic_field;
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun static int show_warning = 1;
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #define do_warning(fmt, ...) \
40*4882a593Smuzhiyun do { \
41*4882a593Smuzhiyun if (show_warning) \
42*4882a593Smuzhiyun warning(fmt, ##__VA_ARGS__); \
43*4882a593Smuzhiyun } while (0)
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun #define do_warning_event(event, fmt, ...) \
46*4882a593Smuzhiyun do { \
47*4882a593Smuzhiyun if (!show_warning) \
48*4882a593Smuzhiyun continue; \
49*4882a593Smuzhiyun \
50*4882a593Smuzhiyun if (event) \
51*4882a593Smuzhiyun warning("[%s:%s] " fmt, event->system, \
52*4882a593Smuzhiyun event->name, ##__VA_ARGS__); \
53*4882a593Smuzhiyun else \
54*4882a593Smuzhiyun warning(fmt, ##__VA_ARGS__); \
55*4882a593Smuzhiyun } while (0)
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun /**
58*4882a593Smuzhiyun * init_input_buf - init buffer for parsing
59*4882a593Smuzhiyun * @buf: buffer to parse
60*4882a593Smuzhiyun * @size: the size of the buffer
61*4882a593Smuzhiyun *
62*4882a593Smuzhiyun * Initializes the internal buffer that tep_read_token() will parse.
63*4882a593Smuzhiyun */
init_input_buf(const char * buf,unsigned long long size)64*4882a593Smuzhiyun __hidden void init_input_buf(const char *buf, unsigned long long size)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun input_buf = buf;
67*4882a593Smuzhiyun input_buf_siz = size;
68*4882a593Smuzhiyun input_buf_ptr = 0;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun
get_input_buf(void)71*4882a593Smuzhiyun __hidden const char *get_input_buf(void)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun return input_buf;
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
get_input_buf_ptr(void)76*4882a593Smuzhiyun __hidden unsigned long long get_input_buf_ptr(void)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun return input_buf_ptr;
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun struct event_handler {
82*4882a593Smuzhiyun struct event_handler *next;
83*4882a593Smuzhiyun int id;
84*4882a593Smuzhiyun const char *sys_name;
85*4882a593Smuzhiyun const char *event_name;
86*4882a593Smuzhiyun tep_event_handler_func func;
87*4882a593Smuzhiyun void *context;
88*4882a593Smuzhiyun };
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun struct func_params {
91*4882a593Smuzhiyun struct func_params *next;
92*4882a593Smuzhiyun enum tep_func_arg_type type;
93*4882a593Smuzhiyun };
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun struct tep_function_handler {
96*4882a593Smuzhiyun struct tep_function_handler *next;
97*4882a593Smuzhiyun enum tep_func_arg_type ret_type;
98*4882a593Smuzhiyun char *name;
99*4882a593Smuzhiyun tep_func_handler func;
100*4882a593Smuzhiyun struct func_params *params;
101*4882a593Smuzhiyun int nr_args;
102*4882a593Smuzhiyun };
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun static unsigned long long
105*4882a593Smuzhiyun process_defined_func(struct trace_seq *s, void *data, int size,
106*4882a593Smuzhiyun struct tep_event *event, struct tep_print_arg *arg);
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun static void free_func_handle(struct tep_function_handler *func);
109*4882a593Smuzhiyun
breakpoint(void)110*4882a593Smuzhiyun void breakpoint(void)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun static int x;
113*4882a593Smuzhiyun x++;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
alloc_arg(void)116*4882a593Smuzhiyun static struct tep_print_arg *alloc_arg(void)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun return calloc(1, sizeof(struct tep_print_arg));
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun struct tep_cmdline {
122*4882a593Smuzhiyun char *comm;
123*4882a593Smuzhiyun int pid;
124*4882a593Smuzhiyun };
125*4882a593Smuzhiyun
cmdline_cmp(const void * a,const void * b)126*4882a593Smuzhiyun static int cmdline_cmp(const void *a, const void *b)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun const struct tep_cmdline *ca = a;
129*4882a593Smuzhiyun const struct tep_cmdline *cb = b;
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun if (ca->pid < cb->pid)
132*4882a593Smuzhiyun return -1;
133*4882a593Smuzhiyun if (ca->pid > cb->pid)
134*4882a593Smuzhiyun return 1;
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun return 0;
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun /* Looking for where to place the key */
cmdline_slot_cmp(const void * a,const void * b)140*4882a593Smuzhiyun static int cmdline_slot_cmp(const void *a, const void *b)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun const struct tep_cmdline *ca = a;
143*4882a593Smuzhiyun const struct tep_cmdline *cb = b;
144*4882a593Smuzhiyun const struct tep_cmdline *cb1 = cb + 1;
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun if (ca->pid < cb->pid)
147*4882a593Smuzhiyun return -1;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun if (ca->pid > cb->pid) {
150*4882a593Smuzhiyun if (ca->pid <= cb1->pid)
151*4882a593Smuzhiyun return 0;
152*4882a593Smuzhiyun return 1;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun return 0;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun struct cmdline_list {
159*4882a593Smuzhiyun struct cmdline_list *next;
160*4882a593Smuzhiyun char *comm;
161*4882a593Smuzhiyun int pid;
162*4882a593Smuzhiyun };
163*4882a593Smuzhiyun
cmdline_init(struct tep_handle * tep)164*4882a593Smuzhiyun static int cmdline_init(struct tep_handle *tep)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun struct cmdline_list *cmdlist = tep->cmdlist;
167*4882a593Smuzhiyun struct cmdline_list *item;
168*4882a593Smuzhiyun struct tep_cmdline *cmdlines;
169*4882a593Smuzhiyun int i;
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun cmdlines = malloc(sizeof(*cmdlines) * tep->cmdline_count);
172*4882a593Smuzhiyun if (!cmdlines)
173*4882a593Smuzhiyun return -1;
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun i = 0;
176*4882a593Smuzhiyun while (cmdlist) {
177*4882a593Smuzhiyun cmdlines[i].pid = cmdlist->pid;
178*4882a593Smuzhiyun cmdlines[i].comm = cmdlist->comm;
179*4882a593Smuzhiyun i++;
180*4882a593Smuzhiyun item = cmdlist;
181*4882a593Smuzhiyun cmdlist = cmdlist->next;
182*4882a593Smuzhiyun free(item);
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun qsort(cmdlines, tep->cmdline_count, sizeof(*cmdlines), cmdline_cmp);
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun tep->cmdlines = cmdlines;
188*4882a593Smuzhiyun tep->cmdlist = NULL;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun return 0;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
find_cmdline(struct tep_handle * tep,int pid)193*4882a593Smuzhiyun static const char *find_cmdline(struct tep_handle *tep, int pid)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun const struct tep_cmdline *comm;
196*4882a593Smuzhiyun struct tep_cmdline key;
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun if (!pid)
199*4882a593Smuzhiyun return "<idle>";
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun if (!tep->cmdlines && cmdline_init(tep))
202*4882a593Smuzhiyun return "<not enough memory for cmdlines!>";
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun key.pid = pid;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun comm = bsearch(&key, tep->cmdlines, tep->cmdline_count,
207*4882a593Smuzhiyun sizeof(*tep->cmdlines), cmdline_cmp);
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun if (comm)
210*4882a593Smuzhiyun return comm->comm;
211*4882a593Smuzhiyun return "<...>";
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun /**
215*4882a593Smuzhiyun * tep_is_pid_registered - return if a pid has a cmdline registered
216*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
217*4882a593Smuzhiyun * @pid: The pid to check if it has a cmdline registered with.
218*4882a593Smuzhiyun *
219*4882a593Smuzhiyun * Returns true if the pid has a cmdline mapped to it
220*4882a593Smuzhiyun * false otherwise.
221*4882a593Smuzhiyun */
tep_is_pid_registered(struct tep_handle * tep,int pid)222*4882a593Smuzhiyun bool tep_is_pid_registered(struct tep_handle *tep, int pid)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun const struct tep_cmdline *comm;
225*4882a593Smuzhiyun struct tep_cmdline key;
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun if (!pid)
228*4882a593Smuzhiyun return true;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun if (!tep->cmdlines && cmdline_init(tep))
231*4882a593Smuzhiyun return false;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun key.pid = pid;
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun comm = bsearch(&key, tep->cmdlines, tep->cmdline_count,
236*4882a593Smuzhiyun sizeof(*tep->cmdlines), cmdline_cmp);
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun if (comm)
239*4882a593Smuzhiyun return true;
240*4882a593Smuzhiyun return false;
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun /*
244*4882a593Smuzhiyun * If the command lines have been converted to an array, then
245*4882a593Smuzhiyun * we must add this pid. This is much slower than when cmdlines
246*4882a593Smuzhiyun * are added before the array is initialized.
247*4882a593Smuzhiyun */
add_new_comm(struct tep_handle * tep,const char * comm,int pid,bool override)248*4882a593Smuzhiyun static int add_new_comm(struct tep_handle *tep,
249*4882a593Smuzhiyun const char *comm, int pid, bool override)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun struct tep_cmdline *cmdlines = tep->cmdlines;
252*4882a593Smuzhiyun struct tep_cmdline *cmdline;
253*4882a593Smuzhiyun struct tep_cmdline key;
254*4882a593Smuzhiyun char *new_comm;
255*4882a593Smuzhiyun int cnt;
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun if (!pid)
258*4882a593Smuzhiyun return 0;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun /* avoid duplicates */
261*4882a593Smuzhiyun key.pid = pid;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun cmdline = bsearch(&key, tep->cmdlines, tep->cmdline_count,
264*4882a593Smuzhiyun sizeof(*tep->cmdlines), cmdline_cmp);
265*4882a593Smuzhiyun if (cmdline) {
266*4882a593Smuzhiyun if (!override) {
267*4882a593Smuzhiyun errno = EEXIST;
268*4882a593Smuzhiyun return -1;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun new_comm = strdup(comm);
271*4882a593Smuzhiyun if (!new_comm) {
272*4882a593Smuzhiyun errno = ENOMEM;
273*4882a593Smuzhiyun return -1;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun free(cmdline->comm);
276*4882a593Smuzhiyun cmdline->comm = new_comm;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun return 0;
279*4882a593Smuzhiyun }
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun cmdlines = realloc(cmdlines, sizeof(*cmdlines) * (tep->cmdline_count + 1));
282*4882a593Smuzhiyun if (!cmdlines) {
283*4882a593Smuzhiyun errno = ENOMEM;
284*4882a593Smuzhiyun return -1;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun tep->cmdlines = cmdlines;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun key.comm = strdup(comm);
289*4882a593Smuzhiyun if (!key.comm) {
290*4882a593Smuzhiyun errno = ENOMEM;
291*4882a593Smuzhiyun return -1;
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun if (!tep->cmdline_count) {
295*4882a593Smuzhiyun /* no entries yet */
296*4882a593Smuzhiyun tep->cmdlines[0] = key;
297*4882a593Smuzhiyun tep->cmdline_count++;
298*4882a593Smuzhiyun return 0;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun /* Now find where we want to store the new cmdline */
302*4882a593Smuzhiyun cmdline = bsearch(&key, tep->cmdlines, tep->cmdline_count - 1,
303*4882a593Smuzhiyun sizeof(*tep->cmdlines), cmdline_slot_cmp);
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun cnt = tep->cmdline_count;
306*4882a593Smuzhiyun if (cmdline) {
307*4882a593Smuzhiyun /* cmdline points to the one before the spot we want */
308*4882a593Smuzhiyun cmdline++;
309*4882a593Smuzhiyun cnt -= cmdline - tep->cmdlines;
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun } else {
312*4882a593Smuzhiyun /* The new entry is either before or after the list */
313*4882a593Smuzhiyun if (key.pid > tep->cmdlines[tep->cmdline_count - 1].pid) {
314*4882a593Smuzhiyun tep->cmdlines[tep->cmdline_count++] = key;
315*4882a593Smuzhiyun return 0;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun cmdline = &tep->cmdlines[0];
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun memmove(cmdline + 1, cmdline, (cnt * sizeof(*cmdline)));
320*4882a593Smuzhiyun *cmdline = key;
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun tep->cmdline_count++;
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun return 0;
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun
_tep_register_comm(struct tep_handle * tep,const char * comm,int pid,bool override)327*4882a593Smuzhiyun static int _tep_register_comm(struct tep_handle *tep,
328*4882a593Smuzhiyun const char *comm, int pid, bool override)
329*4882a593Smuzhiyun {
330*4882a593Smuzhiyun struct cmdline_list *item;
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun if (tep->cmdlines)
333*4882a593Smuzhiyun return add_new_comm(tep, comm, pid, override);
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun item = malloc(sizeof(*item));
336*4882a593Smuzhiyun if (!item)
337*4882a593Smuzhiyun return -1;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun if (comm)
340*4882a593Smuzhiyun item->comm = strdup(comm);
341*4882a593Smuzhiyun else
342*4882a593Smuzhiyun item->comm = strdup("<...>");
343*4882a593Smuzhiyun if (!item->comm) {
344*4882a593Smuzhiyun free(item);
345*4882a593Smuzhiyun return -1;
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun item->pid = pid;
348*4882a593Smuzhiyun item->next = tep->cmdlist;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun tep->cmdlist = item;
351*4882a593Smuzhiyun tep->cmdline_count++;
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun return 0;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun /**
357*4882a593Smuzhiyun * tep_register_comm - register a pid / comm mapping
358*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
359*4882a593Smuzhiyun * @comm: the command line to register
360*4882a593Smuzhiyun * @pid: the pid to map the command line to
361*4882a593Smuzhiyun *
362*4882a593Smuzhiyun * This adds a mapping to search for command line names with
363*4882a593Smuzhiyun * a given pid. The comm is duplicated. If a command with the same pid
364*4882a593Smuzhiyun * already exist, -1 is returned and errno is set to EEXIST
365*4882a593Smuzhiyun */
tep_register_comm(struct tep_handle * tep,const char * comm,int pid)366*4882a593Smuzhiyun int tep_register_comm(struct tep_handle *tep, const char *comm, int pid)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun return _tep_register_comm(tep, comm, pid, false);
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun /**
372*4882a593Smuzhiyun * tep_override_comm - register a pid / comm mapping
373*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
374*4882a593Smuzhiyun * @comm: the command line to register
375*4882a593Smuzhiyun * @pid: the pid to map the command line to
376*4882a593Smuzhiyun *
377*4882a593Smuzhiyun * This adds a mapping to search for command line names with
378*4882a593Smuzhiyun * a given pid. The comm is duplicated. If a command with the same pid
379*4882a593Smuzhiyun * already exist, the command string is udapted with the new one
380*4882a593Smuzhiyun */
tep_override_comm(struct tep_handle * tep,const char * comm,int pid)381*4882a593Smuzhiyun int tep_override_comm(struct tep_handle *tep, const char *comm, int pid)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun if (!tep->cmdlines && cmdline_init(tep)) {
384*4882a593Smuzhiyun errno = ENOMEM;
385*4882a593Smuzhiyun return -1;
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun return _tep_register_comm(tep, comm, pid, true);
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun struct func_map {
391*4882a593Smuzhiyun unsigned long long addr;
392*4882a593Smuzhiyun char *func;
393*4882a593Smuzhiyun char *mod;
394*4882a593Smuzhiyun };
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun struct func_list {
397*4882a593Smuzhiyun struct func_list *next;
398*4882a593Smuzhiyun unsigned long long addr;
399*4882a593Smuzhiyun char *func;
400*4882a593Smuzhiyun char *mod;
401*4882a593Smuzhiyun };
402*4882a593Smuzhiyun
func_cmp(const void * a,const void * b)403*4882a593Smuzhiyun static int func_cmp(const void *a, const void *b)
404*4882a593Smuzhiyun {
405*4882a593Smuzhiyun const struct func_map *fa = a;
406*4882a593Smuzhiyun const struct func_map *fb = b;
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun if (fa->addr < fb->addr)
409*4882a593Smuzhiyun return -1;
410*4882a593Smuzhiyun if (fa->addr > fb->addr)
411*4882a593Smuzhiyun return 1;
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun return 0;
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun /*
417*4882a593Smuzhiyun * We are searching for a record in between, not an exact
418*4882a593Smuzhiyun * match.
419*4882a593Smuzhiyun */
func_bcmp(const void * a,const void * b)420*4882a593Smuzhiyun static int func_bcmp(const void *a, const void *b)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun const struct func_map *fa = a;
423*4882a593Smuzhiyun const struct func_map *fb = b;
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun if ((fa->addr == fb->addr) ||
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun (fa->addr > fb->addr &&
428*4882a593Smuzhiyun fa->addr < (fb+1)->addr))
429*4882a593Smuzhiyun return 0;
430*4882a593Smuzhiyun
431*4882a593Smuzhiyun if (fa->addr < fb->addr)
432*4882a593Smuzhiyun return -1;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun return 1;
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun
func_map_init(struct tep_handle * tep)437*4882a593Smuzhiyun static int func_map_init(struct tep_handle *tep)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun struct func_list *funclist;
440*4882a593Smuzhiyun struct func_list *item;
441*4882a593Smuzhiyun struct func_map *func_map;
442*4882a593Smuzhiyun int i;
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun func_map = malloc(sizeof(*func_map) * (tep->func_count + 1));
445*4882a593Smuzhiyun if (!func_map)
446*4882a593Smuzhiyun return -1;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun funclist = tep->funclist;
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun i = 0;
451*4882a593Smuzhiyun while (funclist) {
452*4882a593Smuzhiyun func_map[i].func = funclist->func;
453*4882a593Smuzhiyun func_map[i].addr = funclist->addr;
454*4882a593Smuzhiyun func_map[i].mod = funclist->mod;
455*4882a593Smuzhiyun i++;
456*4882a593Smuzhiyun item = funclist;
457*4882a593Smuzhiyun funclist = funclist->next;
458*4882a593Smuzhiyun free(item);
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun qsort(func_map, tep->func_count, sizeof(*func_map), func_cmp);
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun /*
464*4882a593Smuzhiyun * Add a special record at the end.
465*4882a593Smuzhiyun */
466*4882a593Smuzhiyun func_map[tep->func_count].func = NULL;
467*4882a593Smuzhiyun func_map[tep->func_count].addr = 0;
468*4882a593Smuzhiyun func_map[tep->func_count].mod = NULL;
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun tep->func_map = func_map;
471*4882a593Smuzhiyun tep->funclist = NULL;
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun return 0;
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun static struct func_map *
__find_func(struct tep_handle * tep,unsigned long long addr)477*4882a593Smuzhiyun __find_func(struct tep_handle *tep, unsigned long long addr)
478*4882a593Smuzhiyun {
479*4882a593Smuzhiyun struct func_map *func;
480*4882a593Smuzhiyun struct func_map key;
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun if (!tep->func_map)
483*4882a593Smuzhiyun func_map_init(tep);
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun key.addr = addr;
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun func = bsearch(&key, tep->func_map, tep->func_count,
488*4882a593Smuzhiyun sizeof(*tep->func_map), func_bcmp);
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun return func;
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun struct func_resolver {
494*4882a593Smuzhiyun tep_func_resolver_t *func;
495*4882a593Smuzhiyun void *priv;
496*4882a593Smuzhiyun struct func_map map;
497*4882a593Smuzhiyun };
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun /**
500*4882a593Smuzhiyun * tep_set_function_resolver - set an alternative function resolver
501*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
502*4882a593Smuzhiyun * @resolver: function to be used
503*4882a593Smuzhiyun * @priv: resolver function private state.
504*4882a593Smuzhiyun *
505*4882a593Smuzhiyun * Some tools may have already a way to resolve kernel functions, allow them to
506*4882a593Smuzhiyun * keep using it instead of duplicating all the entries inside tep->funclist.
507*4882a593Smuzhiyun */
tep_set_function_resolver(struct tep_handle * tep,tep_func_resolver_t * func,void * priv)508*4882a593Smuzhiyun int tep_set_function_resolver(struct tep_handle *tep,
509*4882a593Smuzhiyun tep_func_resolver_t *func, void *priv)
510*4882a593Smuzhiyun {
511*4882a593Smuzhiyun struct func_resolver *resolver = malloc(sizeof(*resolver));
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun if (resolver == NULL)
514*4882a593Smuzhiyun return -1;
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun resolver->func = func;
517*4882a593Smuzhiyun resolver->priv = priv;
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun free(tep->func_resolver);
520*4882a593Smuzhiyun tep->func_resolver = resolver;
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun return 0;
523*4882a593Smuzhiyun }
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun /**
526*4882a593Smuzhiyun * tep_reset_function_resolver - reset alternative function resolver
527*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
528*4882a593Smuzhiyun *
529*4882a593Smuzhiyun * Stop using whatever alternative resolver was set, use the default
530*4882a593Smuzhiyun * one instead.
531*4882a593Smuzhiyun */
tep_reset_function_resolver(struct tep_handle * tep)532*4882a593Smuzhiyun void tep_reset_function_resolver(struct tep_handle *tep)
533*4882a593Smuzhiyun {
534*4882a593Smuzhiyun free(tep->func_resolver);
535*4882a593Smuzhiyun tep->func_resolver = NULL;
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun static struct func_map *
find_func(struct tep_handle * tep,unsigned long long addr)539*4882a593Smuzhiyun find_func(struct tep_handle *tep, unsigned long long addr)
540*4882a593Smuzhiyun {
541*4882a593Smuzhiyun struct func_map *map;
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun if (!tep->func_resolver)
544*4882a593Smuzhiyun return __find_func(tep, addr);
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun map = &tep->func_resolver->map;
547*4882a593Smuzhiyun map->mod = NULL;
548*4882a593Smuzhiyun map->addr = addr;
549*4882a593Smuzhiyun map->func = tep->func_resolver->func(tep->func_resolver->priv,
550*4882a593Smuzhiyun &map->addr, &map->mod);
551*4882a593Smuzhiyun if (map->func == NULL)
552*4882a593Smuzhiyun return NULL;
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun return map;
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun /**
558*4882a593Smuzhiyun * tep_find_function - find a function by a given address
559*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
560*4882a593Smuzhiyun * @addr: the address to find the function with
561*4882a593Smuzhiyun *
562*4882a593Smuzhiyun * Returns a pointer to the function stored that has the given
563*4882a593Smuzhiyun * address. Note, the address does not have to be exact, it
564*4882a593Smuzhiyun * will select the function that would contain the address.
565*4882a593Smuzhiyun */
tep_find_function(struct tep_handle * tep,unsigned long long addr)566*4882a593Smuzhiyun const char *tep_find_function(struct tep_handle *tep, unsigned long long addr)
567*4882a593Smuzhiyun {
568*4882a593Smuzhiyun struct func_map *map;
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun map = find_func(tep, addr);
571*4882a593Smuzhiyun if (!map)
572*4882a593Smuzhiyun return NULL;
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun return map->func;
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun /**
578*4882a593Smuzhiyun * tep_find_function_address - find a function address by a given address
579*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
580*4882a593Smuzhiyun * @addr: the address to find the function with
581*4882a593Smuzhiyun *
582*4882a593Smuzhiyun * Returns the address the function starts at. This can be used in
583*4882a593Smuzhiyun * conjunction with tep_find_function to print both the function
584*4882a593Smuzhiyun * name and the function offset.
585*4882a593Smuzhiyun */
586*4882a593Smuzhiyun unsigned long long
tep_find_function_address(struct tep_handle * tep,unsigned long long addr)587*4882a593Smuzhiyun tep_find_function_address(struct tep_handle *tep, unsigned long long addr)
588*4882a593Smuzhiyun {
589*4882a593Smuzhiyun struct func_map *map;
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun map = find_func(tep, addr);
592*4882a593Smuzhiyun if (!map)
593*4882a593Smuzhiyun return 0;
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun return map->addr;
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun /**
599*4882a593Smuzhiyun * tep_register_function - register a function with a given address
600*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
601*4882a593Smuzhiyun * @function: the function name to register
602*4882a593Smuzhiyun * @addr: the address the function starts at
603*4882a593Smuzhiyun * @mod: the kernel module the function may be in (NULL for none)
604*4882a593Smuzhiyun *
605*4882a593Smuzhiyun * This registers a function name with an address and module.
606*4882a593Smuzhiyun * The @func passed in is duplicated.
607*4882a593Smuzhiyun */
tep_register_function(struct tep_handle * tep,char * func,unsigned long long addr,char * mod)608*4882a593Smuzhiyun int tep_register_function(struct tep_handle *tep, char *func,
609*4882a593Smuzhiyun unsigned long long addr, char *mod)
610*4882a593Smuzhiyun {
611*4882a593Smuzhiyun struct func_list *item = malloc(sizeof(*item));
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun if (!item)
614*4882a593Smuzhiyun return -1;
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun item->next = tep->funclist;
617*4882a593Smuzhiyun item->func = strdup(func);
618*4882a593Smuzhiyun if (!item->func)
619*4882a593Smuzhiyun goto out_free;
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun if (mod) {
622*4882a593Smuzhiyun item->mod = strdup(mod);
623*4882a593Smuzhiyun if (!item->mod)
624*4882a593Smuzhiyun goto out_free_func;
625*4882a593Smuzhiyun } else
626*4882a593Smuzhiyun item->mod = NULL;
627*4882a593Smuzhiyun item->addr = addr;
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun tep->funclist = item;
630*4882a593Smuzhiyun tep->func_count++;
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun return 0;
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun out_free_func:
635*4882a593Smuzhiyun free(item->func);
636*4882a593Smuzhiyun item->func = NULL;
637*4882a593Smuzhiyun out_free:
638*4882a593Smuzhiyun free(item);
639*4882a593Smuzhiyun errno = ENOMEM;
640*4882a593Smuzhiyun return -1;
641*4882a593Smuzhiyun }
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun /**
644*4882a593Smuzhiyun * tep_print_funcs - print out the stored functions
645*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
646*4882a593Smuzhiyun *
647*4882a593Smuzhiyun * This prints out the stored functions.
648*4882a593Smuzhiyun */
tep_print_funcs(struct tep_handle * tep)649*4882a593Smuzhiyun void tep_print_funcs(struct tep_handle *tep)
650*4882a593Smuzhiyun {
651*4882a593Smuzhiyun int i;
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun if (!tep->func_map)
654*4882a593Smuzhiyun func_map_init(tep);
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun for (i = 0; i < (int)tep->func_count; i++) {
657*4882a593Smuzhiyun printf("%016llx %s",
658*4882a593Smuzhiyun tep->func_map[i].addr,
659*4882a593Smuzhiyun tep->func_map[i].func);
660*4882a593Smuzhiyun if (tep->func_map[i].mod)
661*4882a593Smuzhiyun printf(" [%s]\n", tep->func_map[i].mod);
662*4882a593Smuzhiyun else
663*4882a593Smuzhiyun printf("\n");
664*4882a593Smuzhiyun }
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun struct printk_map {
668*4882a593Smuzhiyun unsigned long long addr;
669*4882a593Smuzhiyun char *printk;
670*4882a593Smuzhiyun };
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun struct printk_list {
673*4882a593Smuzhiyun struct printk_list *next;
674*4882a593Smuzhiyun unsigned long long addr;
675*4882a593Smuzhiyun char *printk;
676*4882a593Smuzhiyun };
677*4882a593Smuzhiyun
printk_cmp(const void * a,const void * b)678*4882a593Smuzhiyun static int printk_cmp(const void *a, const void *b)
679*4882a593Smuzhiyun {
680*4882a593Smuzhiyun const struct printk_map *pa = a;
681*4882a593Smuzhiyun const struct printk_map *pb = b;
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun if (pa->addr < pb->addr)
684*4882a593Smuzhiyun return -1;
685*4882a593Smuzhiyun if (pa->addr > pb->addr)
686*4882a593Smuzhiyun return 1;
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun return 0;
689*4882a593Smuzhiyun }
690*4882a593Smuzhiyun
printk_map_init(struct tep_handle * tep)691*4882a593Smuzhiyun static int printk_map_init(struct tep_handle *tep)
692*4882a593Smuzhiyun {
693*4882a593Smuzhiyun struct printk_list *printklist;
694*4882a593Smuzhiyun struct printk_list *item;
695*4882a593Smuzhiyun struct printk_map *printk_map;
696*4882a593Smuzhiyun int i;
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun printk_map = malloc(sizeof(*printk_map) * (tep->printk_count + 1));
699*4882a593Smuzhiyun if (!printk_map)
700*4882a593Smuzhiyun return -1;
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun printklist = tep->printklist;
703*4882a593Smuzhiyun
704*4882a593Smuzhiyun i = 0;
705*4882a593Smuzhiyun while (printklist) {
706*4882a593Smuzhiyun printk_map[i].printk = printklist->printk;
707*4882a593Smuzhiyun printk_map[i].addr = printklist->addr;
708*4882a593Smuzhiyun i++;
709*4882a593Smuzhiyun item = printklist;
710*4882a593Smuzhiyun printklist = printklist->next;
711*4882a593Smuzhiyun free(item);
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun qsort(printk_map, tep->printk_count, sizeof(*printk_map), printk_cmp);
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun tep->printk_map = printk_map;
717*4882a593Smuzhiyun tep->printklist = NULL;
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun return 0;
720*4882a593Smuzhiyun }
721*4882a593Smuzhiyun
722*4882a593Smuzhiyun static struct printk_map *
find_printk(struct tep_handle * tep,unsigned long long addr)723*4882a593Smuzhiyun find_printk(struct tep_handle *tep, unsigned long long addr)
724*4882a593Smuzhiyun {
725*4882a593Smuzhiyun struct printk_map *printk;
726*4882a593Smuzhiyun struct printk_map key;
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun if (!tep->printk_map && printk_map_init(tep))
729*4882a593Smuzhiyun return NULL;
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun key.addr = addr;
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun printk = bsearch(&key, tep->printk_map, tep->printk_count,
734*4882a593Smuzhiyun sizeof(*tep->printk_map), printk_cmp);
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun return printk;
737*4882a593Smuzhiyun }
738*4882a593Smuzhiyun
739*4882a593Smuzhiyun /**
740*4882a593Smuzhiyun * tep_register_print_string - register a string by its address
741*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
742*4882a593Smuzhiyun * @fmt: the string format to register
743*4882a593Smuzhiyun * @addr: the address the string was located at
744*4882a593Smuzhiyun *
745*4882a593Smuzhiyun * This registers a string by the address it was stored in the kernel.
746*4882a593Smuzhiyun * The @fmt passed in is duplicated.
747*4882a593Smuzhiyun */
tep_register_print_string(struct tep_handle * tep,const char * fmt,unsigned long long addr)748*4882a593Smuzhiyun int tep_register_print_string(struct tep_handle *tep, const char *fmt,
749*4882a593Smuzhiyun unsigned long long addr)
750*4882a593Smuzhiyun {
751*4882a593Smuzhiyun struct printk_list *item = malloc(sizeof(*item));
752*4882a593Smuzhiyun char *p;
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun if (!item)
755*4882a593Smuzhiyun return -1;
756*4882a593Smuzhiyun
757*4882a593Smuzhiyun item->next = tep->printklist;
758*4882a593Smuzhiyun item->addr = addr;
759*4882a593Smuzhiyun
760*4882a593Smuzhiyun /* Strip off quotes and '\n' from the end */
761*4882a593Smuzhiyun if (fmt[0] == '"')
762*4882a593Smuzhiyun fmt++;
763*4882a593Smuzhiyun item->printk = strdup(fmt);
764*4882a593Smuzhiyun if (!item->printk)
765*4882a593Smuzhiyun goto out_free;
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun p = item->printk + strlen(item->printk) - 1;
768*4882a593Smuzhiyun if (*p == '"')
769*4882a593Smuzhiyun *p = 0;
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun p -= 2;
772*4882a593Smuzhiyun if (strcmp(p, "\\n") == 0)
773*4882a593Smuzhiyun *p = 0;
774*4882a593Smuzhiyun
775*4882a593Smuzhiyun tep->printklist = item;
776*4882a593Smuzhiyun tep->printk_count++;
777*4882a593Smuzhiyun
778*4882a593Smuzhiyun return 0;
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun out_free:
781*4882a593Smuzhiyun free(item);
782*4882a593Smuzhiyun errno = ENOMEM;
783*4882a593Smuzhiyun return -1;
784*4882a593Smuzhiyun }
785*4882a593Smuzhiyun
786*4882a593Smuzhiyun /**
787*4882a593Smuzhiyun * tep_print_printk - print out the stored strings
788*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
789*4882a593Smuzhiyun *
790*4882a593Smuzhiyun * This prints the string formats that were stored.
791*4882a593Smuzhiyun */
tep_print_printk(struct tep_handle * tep)792*4882a593Smuzhiyun void tep_print_printk(struct tep_handle *tep)
793*4882a593Smuzhiyun {
794*4882a593Smuzhiyun int i;
795*4882a593Smuzhiyun
796*4882a593Smuzhiyun if (!tep->printk_map)
797*4882a593Smuzhiyun printk_map_init(tep);
798*4882a593Smuzhiyun
799*4882a593Smuzhiyun for (i = 0; i < (int)tep->printk_count; i++) {
800*4882a593Smuzhiyun printf("%016llx %s\n",
801*4882a593Smuzhiyun tep->printk_map[i].addr,
802*4882a593Smuzhiyun tep->printk_map[i].printk);
803*4882a593Smuzhiyun }
804*4882a593Smuzhiyun }
805*4882a593Smuzhiyun
alloc_event(void)806*4882a593Smuzhiyun static struct tep_event *alloc_event(void)
807*4882a593Smuzhiyun {
808*4882a593Smuzhiyun return calloc(1, sizeof(struct tep_event));
809*4882a593Smuzhiyun }
810*4882a593Smuzhiyun
add_event(struct tep_handle * tep,struct tep_event * event)811*4882a593Smuzhiyun static int add_event(struct tep_handle *tep, struct tep_event *event)
812*4882a593Smuzhiyun {
813*4882a593Smuzhiyun int i;
814*4882a593Smuzhiyun struct tep_event **events = realloc(tep->events, sizeof(event) *
815*4882a593Smuzhiyun (tep->nr_events + 1));
816*4882a593Smuzhiyun if (!events)
817*4882a593Smuzhiyun return -1;
818*4882a593Smuzhiyun
819*4882a593Smuzhiyun tep->events = events;
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun for (i = 0; i < tep->nr_events; i++) {
822*4882a593Smuzhiyun if (tep->events[i]->id > event->id)
823*4882a593Smuzhiyun break;
824*4882a593Smuzhiyun }
825*4882a593Smuzhiyun if (i < tep->nr_events)
826*4882a593Smuzhiyun memmove(&tep->events[i + 1],
827*4882a593Smuzhiyun &tep->events[i],
828*4882a593Smuzhiyun sizeof(event) * (tep->nr_events - i));
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun tep->events[i] = event;
831*4882a593Smuzhiyun tep->nr_events++;
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun event->tep = tep;
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun return 0;
836*4882a593Smuzhiyun }
837*4882a593Smuzhiyun
event_item_type(enum tep_event_type type)838*4882a593Smuzhiyun static int event_item_type(enum tep_event_type type)
839*4882a593Smuzhiyun {
840*4882a593Smuzhiyun switch (type) {
841*4882a593Smuzhiyun case TEP_EVENT_ITEM ... TEP_EVENT_SQUOTE:
842*4882a593Smuzhiyun return 1;
843*4882a593Smuzhiyun case TEP_EVENT_ERROR ... TEP_EVENT_DELIM:
844*4882a593Smuzhiyun default:
845*4882a593Smuzhiyun return 0;
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun }
848*4882a593Smuzhiyun
free_flag_sym(struct tep_print_flag_sym * fsym)849*4882a593Smuzhiyun static void free_flag_sym(struct tep_print_flag_sym *fsym)
850*4882a593Smuzhiyun {
851*4882a593Smuzhiyun struct tep_print_flag_sym *next;
852*4882a593Smuzhiyun
853*4882a593Smuzhiyun while (fsym) {
854*4882a593Smuzhiyun next = fsym->next;
855*4882a593Smuzhiyun free(fsym->value);
856*4882a593Smuzhiyun free(fsym->str);
857*4882a593Smuzhiyun free(fsym);
858*4882a593Smuzhiyun fsym = next;
859*4882a593Smuzhiyun }
860*4882a593Smuzhiyun }
861*4882a593Smuzhiyun
free_arg(struct tep_print_arg * arg)862*4882a593Smuzhiyun static void free_arg(struct tep_print_arg *arg)
863*4882a593Smuzhiyun {
864*4882a593Smuzhiyun struct tep_print_arg *farg;
865*4882a593Smuzhiyun
866*4882a593Smuzhiyun if (!arg)
867*4882a593Smuzhiyun return;
868*4882a593Smuzhiyun
869*4882a593Smuzhiyun switch (arg->type) {
870*4882a593Smuzhiyun case TEP_PRINT_ATOM:
871*4882a593Smuzhiyun free(arg->atom.atom);
872*4882a593Smuzhiyun break;
873*4882a593Smuzhiyun case TEP_PRINT_FIELD:
874*4882a593Smuzhiyun free(arg->field.name);
875*4882a593Smuzhiyun break;
876*4882a593Smuzhiyun case TEP_PRINT_FLAGS:
877*4882a593Smuzhiyun free_arg(arg->flags.field);
878*4882a593Smuzhiyun free(arg->flags.delim);
879*4882a593Smuzhiyun free_flag_sym(arg->flags.flags);
880*4882a593Smuzhiyun break;
881*4882a593Smuzhiyun case TEP_PRINT_SYMBOL:
882*4882a593Smuzhiyun free_arg(arg->symbol.field);
883*4882a593Smuzhiyun free_flag_sym(arg->symbol.symbols);
884*4882a593Smuzhiyun break;
885*4882a593Smuzhiyun case TEP_PRINT_HEX:
886*4882a593Smuzhiyun case TEP_PRINT_HEX_STR:
887*4882a593Smuzhiyun free_arg(arg->hex.field);
888*4882a593Smuzhiyun free_arg(arg->hex.size);
889*4882a593Smuzhiyun break;
890*4882a593Smuzhiyun case TEP_PRINT_INT_ARRAY:
891*4882a593Smuzhiyun free_arg(arg->int_array.field);
892*4882a593Smuzhiyun free_arg(arg->int_array.count);
893*4882a593Smuzhiyun free_arg(arg->int_array.el_size);
894*4882a593Smuzhiyun break;
895*4882a593Smuzhiyun case TEP_PRINT_TYPE:
896*4882a593Smuzhiyun free(arg->typecast.type);
897*4882a593Smuzhiyun free_arg(arg->typecast.item);
898*4882a593Smuzhiyun break;
899*4882a593Smuzhiyun case TEP_PRINT_STRING:
900*4882a593Smuzhiyun case TEP_PRINT_BSTRING:
901*4882a593Smuzhiyun free(arg->string.string);
902*4882a593Smuzhiyun break;
903*4882a593Smuzhiyun case TEP_PRINT_BITMASK:
904*4882a593Smuzhiyun free(arg->bitmask.bitmask);
905*4882a593Smuzhiyun break;
906*4882a593Smuzhiyun case TEP_PRINT_DYNAMIC_ARRAY:
907*4882a593Smuzhiyun case TEP_PRINT_DYNAMIC_ARRAY_LEN:
908*4882a593Smuzhiyun free(arg->dynarray.index);
909*4882a593Smuzhiyun break;
910*4882a593Smuzhiyun case TEP_PRINT_OP:
911*4882a593Smuzhiyun free(arg->op.op);
912*4882a593Smuzhiyun free_arg(arg->op.left);
913*4882a593Smuzhiyun free_arg(arg->op.right);
914*4882a593Smuzhiyun break;
915*4882a593Smuzhiyun case TEP_PRINT_FUNC:
916*4882a593Smuzhiyun while (arg->func.args) {
917*4882a593Smuzhiyun farg = arg->func.args;
918*4882a593Smuzhiyun arg->func.args = farg->next;
919*4882a593Smuzhiyun free_arg(farg);
920*4882a593Smuzhiyun }
921*4882a593Smuzhiyun break;
922*4882a593Smuzhiyun
923*4882a593Smuzhiyun case TEP_PRINT_NULL:
924*4882a593Smuzhiyun default:
925*4882a593Smuzhiyun break;
926*4882a593Smuzhiyun }
927*4882a593Smuzhiyun
928*4882a593Smuzhiyun free(arg);
929*4882a593Smuzhiyun }
930*4882a593Smuzhiyun
get_type(int ch)931*4882a593Smuzhiyun static enum tep_event_type get_type(int ch)
932*4882a593Smuzhiyun {
933*4882a593Smuzhiyun if (ch == '\n')
934*4882a593Smuzhiyun return TEP_EVENT_NEWLINE;
935*4882a593Smuzhiyun if (isspace(ch))
936*4882a593Smuzhiyun return TEP_EVENT_SPACE;
937*4882a593Smuzhiyun if (isalnum(ch) || ch == '_')
938*4882a593Smuzhiyun return TEP_EVENT_ITEM;
939*4882a593Smuzhiyun if (ch == '\'')
940*4882a593Smuzhiyun return TEP_EVENT_SQUOTE;
941*4882a593Smuzhiyun if (ch == '"')
942*4882a593Smuzhiyun return TEP_EVENT_DQUOTE;
943*4882a593Smuzhiyun if (!isprint(ch))
944*4882a593Smuzhiyun return TEP_EVENT_NONE;
945*4882a593Smuzhiyun if (ch == '(' || ch == ')' || ch == ',')
946*4882a593Smuzhiyun return TEP_EVENT_DELIM;
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun return TEP_EVENT_OP;
949*4882a593Smuzhiyun }
950*4882a593Smuzhiyun
__read_char(void)951*4882a593Smuzhiyun static int __read_char(void)
952*4882a593Smuzhiyun {
953*4882a593Smuzhiyun if (input_buf_ptr >= input_buf_siz)
954*4882a593Smuzhiyun return -1;
955*4882a593Smuzhiyun
956*4882a593Smuzhiyun return input_buf[input_buf_ptr++];
957*4882a593Smuzhiyun }
958*4882a593Smuzhiyun
959*4882a593Smuzhiyun /**
960*4882a593Smuzhiyun * peek_char - peek at the next character that will be read
961*4882a593Smuzhiyun *
962*4882a593Smuzhiyun * Returns the next character read, or -1 if end of buffer.
963*4882a593Smuzhiyun */
peek_char(void)964*4882a593Smuzhiyun __hidden int peek_char(void)
965*4882a593Smuzhiyun {
966*4882a593Smuzhiyun if (input_buf_ptr >= input_buf_siz)
967*4882a593Smuzhiyun return -1;
968*4882a593Smuzhiyun
969*4882a593Smuzhiyun return input_buf[input_buf_ptr];
970*4882a593Smuzhiyun }
971*4882a593Smuzhiyun
extend_token(char ** tok,char * buf,int size)972*4882a593Smuzhiyun static int extend_token(char **tok, char *buf, int size)
973*4882a593Smuzhiyun {
974*4882a593Smuzhiyun char *newtok = realloc(*tok, size);
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun if (!newtok) {
977*4882a593Smuzhiyun free(*tok);
978*4882a593Smuzhiyun *tok = NULL;
979*4882a593Smuzhiyun return -1;
980*4882a593Smuzhiyun }
981*4882a593Smuzhiyun
982*4882a593Smuzhiyun if (!*tok)
983*4882a593Smuzhiyun strcpy(newtok, buf);
984*4882a593Smuzhiyun else
985*4882a593Smuzhiyun strcat(newtok, buf);
986*4882a593Smuzhiyun *tok = newtok;
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun return 0;
989*4882a593Smuzhiyun }
990*4882a593Smuzhiyun
991*4882a593Smuzhiyun static enum tep_event_type force_token(const char *str, char **tok);
992*4882a593Smuzhiyun
__read_token(char ** tok)993*4882a593Smuzhiyun static enum tep_event_type __read_token(char **tok)
994*4882a593Smuzhiyun {
995*4882a593Smuzhiyun char buf[BUFSIZ];
996*4882a593Smuzhiyun int ch, last_ch, quote_ch, next_ch;
997*4882a593Smuzhiyun int i = 0;
998*4882a593Smuzhiyun int tok_size = 0;
999*4882a593Smuzhiyun enum tep_event_type type;
1000*4882a593Smuzhiyun
1001*4882a593Smuzhiyun *tok = NULL;
1002*4882a593Smuzhiyun
1003*4882a593Smuzhiyun
1004*4882a593Smuzhiyun ch = __read_char();
1005*4882a593Smuzhiyun if (ch < 0)
1006*4882a593Smuzhiyun return TEP_EVENT_NONE;
1007*4882a593Smuzhiyun
1008*4882a593Smuzhiyun type = get_type(ch);
1009*4882a593Smuzhiyun if (type == TEP_EVENT_NONE)
1010*4882a593Smuzhiyun return type;
1011*4882a593Smuzhiyun
1012*4882a593Smuzhiyun buf[i++] = ch;
1013*4882a593Smuzhiyun
1014*4882a593Smuzhiyun switch (type) {
1015*4882a593Smuzhiyun case TEP_EVENT_NEWLINE:
1016*4882a593Smuzhiyun case TEP_EVENT_DELIM:
1017*4882a593Smuzhiyun if (asprintf(tok, "%c", ch) < 0)
1018*4882a593Smuzhiyun return TEP_EVENT_ERROR;
1019*4882a593Smuzhiyun
1020*4882a593Smuzhiyun return type;
1021*4882a593Smuzhiyun
1022*4882a593Smuzhiyun case TEP_EVENT_OP:
1023*4882a593Smuzhiyun switch (ch) {
1024*4882a593Smuzhiyun case '-':
1025*4882a593Smuzhiyun next_ch = peek_char();
1026*4882a593Smuzhiyun if (next_ch == '>') {
1027*4882a593Smuzhiyun buf[i++] = __read_char();
1028*4882a593Smuzhiyun break;
1029*4882a593Smuzhiyun }
1030*4882a593Smuzhiyun /* fall through */
1031*4882a593Smuzhiyun case '+':
1032*4882a593Smuzhiyun case '|':
1033*4882a593Smuzhiyun case '&':
1034*4882a593Smuzhiyun case '>':
1035*4882a593Smuzhiyun case '<':
1036*4882a593Smuzhiyun last_ch = ch;
1037*4882a593Smuzhiyun ch = peek_char();
1038*4882a593Smuzhiyun if (ch != last_ch)
1039*4882a593Smuzhiyun goto test_equal;
1040*4882a593Smuzhiyun buf[i++] = __read_char();
1041*4882a593Smuzhiyun switch (last_ch) {
1042*4882a593Smuzhiyun case '>':
1043*4882a593Smuzhiyun case '<':
1044*4882a593Smuzhiyun goto test_equal;
1045*4882a593Smuzhiyun default:
1046*4882a593Smuzhiyun break;
1047*4882a593Smuzhiyun }
1048*4882a593Smuzhiyun break;
1049*4882a593Smuzhiyun case '!':
1050*4882a593Smuzhiyun case '=':
1051*4882a593Smuzhiyun goto test_equal;
1052*4882a593Smuzhiyun default: /* what should we do instead? */
1053*4882a593Smuzhiyun break;
1054*4882a593Smuzhiyun }
1055*4882a593Smuzhiyun buf[i] = 0;
1056*4882a593Smuzhiyun *tok = strdup(buf);
1057*4882a593Smuzhiyun return type;
1058*4882a593Smuzhiyun
1059*4882a593Smuzhiyun test_equal:
1060*4882a593Smuzhiyun ch = peek_char();
1061*4882a593Smuzhiyun if (ch == '=')
1062*4882a593Smuzhiyun buf[i++] = __read_char();
1063*4882a593Smuzhiyun goto out;
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun case TEP_EVENT_DQUOTE:
1066*4882a593Smuzhiyun case TEP_EVENT_SQUOTE:
1067*4882a593Smuzhiyun /* don't keep quotes */
1068*4882a593Smuzhiyun i--;
1069*4882a593Smuzhiyun quote_ch = ch;
1070*4882a593Smuzhiyun last_ch = 0;
1071*4882a593Smuzhiyun concat:
1072*4882a593Smuzhiyun do {
1073*4882a593Smuzhiyun if (i == (BUFSIZ - 1)) {
1074*4882a593Smuzhiyun buf[i] = 0;
1075*4882a593Smuzhiyun tok_size += BUFSIZ;
1076*4882a593Smuzhiyun
1077*4882a593Smuzhiyun if (extend_token(tok, buf, tok_size) < 0)
1078*4882a593Smuzhiyun return TEP_EVENT_NONE;
1079*4882a593Smuzhiyun i = 0;
1080*4882a593Smuzhiyun }
1081*4882a593Smuzhiyun last_ch = ch;
1082*4882a593Smuzhiyun ch = __read_char();
1083*4882a593Smuzhiyun buf[i++] = ch;
1084*4882a593Smuzhiyun /* the '\' '\' will cancel itself */
1085*4882a593Smuzhiyun if (ch == '\\' && last_ch == '\\')
1086*4882a593Smuzhiyun last_ch = 0;
1087*4882a593Smuzhiyun } while (ch != quote_ch || last_ch == '\\');
1088*4882a593Smuzhiyun /* remove the last quote */
1089*4882a593Smuzhiyun i--;
1090*4882a593Smuzhiyun
1091*4882a593Smuzhiyun /*
1092*4882a593Smuzhiyun * For strings (double quotes) check the next token.
1093*4882a593Smuzhiyun * If it is another string, concatinate the two.
1094*4882a593Smuzhiyun */
1095*4882a593Smuzhiyun if (type == TEP_EVENT_DQUOTE) {
1096*4882a593Smuzhiyun unsigned long long save_input_buf_ptr = input_buf_ptr;
1097*4882a593Smuzhiyun
1098*4882a593Smuzhiyun do {
1099*4882a593Smuzhiyun ch = __read_char();
1100*4882a593Smuzhiyun } while (isspace(ch));
1101*4882a593Smuzhiyun if (ch == '"')
1102*4882a593Smuzhiyun goto concat;
1103*4882a593Smuzhiyun input_buf_ptr = save_input_buf_ptr;
1104*4882a593Smuzhiyun }
1105*4882a593Smuzhiyun
1106*4882a593Smuzhiyun goto out;
1107*4882a593Smuzhiyun
1108*4882a593Smuzhiyun case TEP_EVENT_ERROR ... TEP_EVENT_SPACE:
1109*4882a593Smuzhiyun case TEP_EVENT_ITEM:
1110*4882a593Smuzhiyun default:
1111*4882a593Smuzhiyun break;
1112*4882a593Smuzhiyun }
1113*4882a593Smuzhiyun
1114*4882a593Smuzhiyun while (get_type(peek_char()) == type) {
1115*4882a593Smuzhiyun if (i == (BUFSIZ - 1)) {
1116*4882a593Smuzhiyun buf[i] = 0;
1117*4882a593Smuzhiyun tok_size += BUFSIZ;
1118*4882a593Smuzhiyun
1119*4882a593Smuzhiyun if (extend_token(tok, buf, tok_size) < 0)
1120*4882a593Smuzhiyun return TEP_EVENT_NONE;
1121*4882a593Smuzhiyun i = 0;
1122*4882a593Smuzhiyun }
1123*4882a593Smuzhiyun ch = __read_char();
1124*4882a593Smuzhiyun buf[i++] = ch;
1125*4882a593Smuzhiyun }
1126*4882a593Smuzhiyun
1127*4882a593Smuzhiyun out:
1128*4882a593Smuzhiyun buf[i] = 0;
1129*4882a593Smuzhiyun if (extend_token(tok, buf, tok_size + i + 1) < 0)
1130*4882a593Smuzhiyun return TEP_EVENT_NONE;
1131*4882a593Smuzhiyun
1132*4882a593Smuzhiyun if (type == TEP_EVENT_ITEM) {
1133*4882a593Smuzhiyun /*
1134*4882a593Smuzhiyun * Older versions of the kernel has a bug that
1135*4882a593Smuzhiyun * creates invalid symbols and will break the mac80211
1136*4882a593Smuzhiyun * parsing. This is a work around to that bug.
1137*4882a593Smuzhiyun *
1138*4882a593Smuzhiyun * See Linux kernel commit:
1139*4882a593Smuzhiyun * 811cb50baf63461ce0bdb234927046131fc7fa8b
1140*4882a593Smuzhiyun */
1141*4882a593Smuzhiyun if (strcmp(*tok, "LOCAL_PR_FMT") == 0) {
1142*4882a593Smuzhiyun free(*tok);
1143*4882a593Smuzhiyun *tok = NULL;
1144*4882a593Smuzhiyun return force_token("\"%s\" ", tok);
1145*4882a593Smuzhiyun } else if (strcmp(*tok, "STA_PR_FMT") == 0) {
1146*4882a593Smuzhiyun free(*tok);
1147*4882a593Smuzhiyun *tok = NULL;
1148*4882a593Smuzhiyun return force_token("\" sta:%pM\" ", tok);
1149*4882a593Smuzhiyun } else if (strcmp(*tok, "VIF_PR_FMT") == 0) {
1150*4882a593Smuzhiyun free(*tok);
1151*4882a593Smuzhiyun *tok = NULL;
1152*4882a593Smuzhiyun return force_token("\" vif:%p(%d)\" ", tok);
1153*4882a593Smuzhiyun }
1154*4882a593Smuzhiyun }
1155*4882a593Smuzhiyun
1156*4882a593Smuzhiyun return type;
1157*4882a593Smuzhiyun }
1158*4882a593Smuzhiyun
force_token(const char * str,char ** tok)1159*4882a593Smuzhiyun static enum tep_event_type force_token(const char *str, char **tok)
1160*4882a593Smuzhiyun {
1161*4882a593Smuzhiyun const char *save_input_buf;
1162*4882a593Smuzhiyun unsigned long long save_input_buf_ptr;
1163*4882a593Smuzhiyun unsigned long long save_input_buf_siz;
1164*4882a593Smuzhiyun enum tep_event_type type;
1165*4882a593Smuzhiyun
1166*4882a593Smuzhiyun /* save off the current input pointers */
1167*4882a593Smuzhiyun save_input_buf = input_buf;
1168*4882a593Smuzhiyun save_input_buf_ptr = input_buf_ptr;
1169*4882a593Smuzhiyun save_input_buf_siz = input_buf_siz;
1170*4882a593Smuzhiyun
1171*4882a593Smuzhiyun init_input_buf(str, strlen(str));
1172*4882a593Smuzhiyun
1173*4882a593Smuzhiyun type = __read_token(tok);
1174*4882a593Smuzhiyun
1175*4882a593Smuzhiyun /* reset back to original token */
1176*4882a593Smuzhiyun input_buf = save_input_buf;
1177*4882a593Smuzhiyun input_buf_ptr = save_input_buf_ptr;
1178*4882a593Smuzhiyun input_buf_siz = save_input_buf_siz;
1179*4882a593Smuzhiyun
1180*4882a593Smuzhiyun return type;
1181*4882a593Smuzhiyun }
1182*4882a593Smuzhiyun
1183*4882a593Smuzhiyun /**
1184*4882a593Smuzhiyun * free_token - free a token returned by tep_read_token
1185*4882a593Smuzhiyun * @token: the token to free
1186*4882a593Smuzhiyun */
free_token(char * tok)1187*4882a593Smuzhiyun __hidden void free_token(char *tok)
1188*4882a593Smuzhiyun {
1189*4882a593Smuzhiyun if (tok)
1190*4882a593Smuzhiyun free(tok);
1191*4882a593Smuzhiyun }
1192*4882a593Smuzhiyun
1193*4882a593Smuzhiyun /**
1194*4882a593Smuzhiyun * read_token - access to utilities to use the tep parser
1195*4882a593Smuzhiyun * @tok: The token to return
1196*4882a593Smuzhiyun *
1197*4882a593Smuzhiyun * This will parse tokens from the string given by
1198*4882a593Smuzhiyun * tep_init_data().
1199*4882a593Smuzhiyun *
1200*4882a593Smuzhiyun * Returns the token type.
1201*4882a593Smuzhiyun */
read_token(char ** tok)1202*4882a593Smuzhiyun __hidden enum tep_event_type read_token(char **tok)
1203*4882a593Smuzhiyun {
1204*4882a593Smuzhiyun enum tep_event_type type;
1205*4882a593Smuzhiyun
1206*4882a593Smuzhiyun for (;;) {
1207*4882a593Smuzhiyun type = __read_token(tok);
1208*4882a593Smuzhiyun if (type != TEP_EVENT_SPACE)
1209*4882a593Smuzhiyun return type;
1210*4882a593Smuzhiyun
1211*4882a593Smuzhiyun free_token(*tok);
1212*4882a593Smuzhiyun }
1213*4882a593Smuzhiyun
1214*4882a593Smuzhiyun /* not reached */
1215*4882a593Smuzhiyun *tok = NULL;
1216*4882a593Smuzhiyun return TEP_EVENT_NONE;
1217*4882a593Smuzhiyun }
1218*4882a593Smuzhiyun
1219*4882a593Smuzhiyun /* no newline */
read_token_item(char ** tok)1220*4882a593Smuzhiyun static enum tep_event_type read_token_item(char **tok)
1221*4882a593Smuzhiyun {
1222*4882a593Smuzhiyun enum tep_event_type type;
1223*4882a593Smuzhiyun
1224*4882a593Smuzhiyun for (;;) {
1225*4882a593Smuzhiyun type = __read_token(tok);
1226*4882a593Smuzhiyun if (type != TEP_EVENT_SPACE && type != TEP_EVENT_NEWLINE)
1227*4882a593Smuzhiyun return type;
1228*4882a593Smuzhiyun free_token(*tok);
1229*4882a593Smuzhiyun *tok = NULL;
1230*4882a593Smuzhiyun }
1231*4882a593Smuzhiyun
1232*4882a593Smuzhiyun /* not reached */
1233*4882a593Smuzhiyun *tok = NULL;
1234*4882a593Smuzhiyun return TEP_EVENT_NONE;
1235*4882a593Smuzhiyun }
1236*4882a593Smuzhiyun
test_type(enum tep_event_type type,enum tep_event_type expect)1237*4882a593Smuzhiyun static int test_type(enum tep_event_type type, enum tep_event_type expect)
1238*4882a593Smuzhiyun {
1239*4882a593Smuzhiyun if (type != expect) {
1240*4882a593Smuzhiyun do_warning("Error: expected type %d but read %d",
1241*4882a593Smuzhiyun expect, type);
1242*4882a593Smuzhiyun return -1;
1243*4882a593Smuzhiyun }
1244*4882a593Smuzhiyun return 0;
1245*4882a593Smuzhiyun }
1246*4882a593Smuzhiyun
test_type_token(enum tep_event_type type,const char * token,enum tep_event_type expect,const char * expect_tok)1247*4882a593Smuzhiyun static int test_type_token(enum tep_event_type type, const char *token,
1248*4882a593Smuzhiyun enum tep_event_type expect, const char *expect_tok)
1249*4882a593Smuzhiyun {
1250*4882a593Smuzhiyun if (type != expect) {
1251*4882a593Smuzhiyun do_warning("Error: expected type %d but read %d",
1252*4882a593Smuzhiyun expect, type);
1253*4882a593Smuzhiyun return -1;
1254*4882a593Smuzhiyun }
1255*4882a593Smuzhiyun
1256*4882a593Smuzhiyun if (strcmp(token, expect_tok) != 0) {
1257*4882a593Smuzhiyun do_warning("Error: expected '%s' but read '%s'",
1258*4882a593Smuzhiyun expect_tok, token);
1259*4882a593Smuzhiyun return -1;
1260*4882a593Smuzhiyun }
1261*4882a593Smuzhiyun return 0;
1262*4882a593Smuzhiyun }
1263*4882a593Smuzhiyun
__read_expect_type(enum tep_event_type expect,char ** tok,int newline_ok)1264*4882a593Smuzhiyun static int __read_expect_type(enum tep_event_type expect, char **tok, int newline_ok)
1265*4882a593Smuzhiyun {
1266*4882a593Smuzhiyun enum tep_event_type type;
1267*4882a593Smuzhiyun
1268*4882a593Smuzhiyun if (newline_ok)
1269*4882a593Smuzhiyun type = read_token(tok);
1270*4882a593Smuzhiyun else
1271*4882a593Smuzhiyun type = read_token_item(tok);
1272*4882a593Smuzhiyun return test_type(type, expect);
1273*4882a593Smuzhiyun }
1274*4882a593Smuzhiyun
read_expect_type(enum tep_event_type expect,char ** tok)1275*4882a593Smuzhiyun static int read_expect_type(enum tep_event_type expect, char **tok)
1276*4882a593Smuzhiyun {
1277*4882a593Smuzhiyun return __read_expect_type(expect, tok, 1);
1278*4882a593Smuzhiyun }
1279*4882a593Smuzhiyun
__read_expected(enum tep_event_type expect,const char * str,int newline_ok)1280*4882a593Smuzhiyun static int __read_expected(enum tep_event_type expect, const char *str,
1281*4882a593Smuzhiyun int newline_ok)
1282*4882a593Smuzhiyun {
1283*4882a593Smuzhiyun enum tep_event_type type;
1284*4882a593Smuzhiyun char *token;
1285*4882a593Smuzhiyun int ret;
1286*4882a593Smuzhiyun
1287*4882a593Smuzhiyun if (newline_ok)
1288*4882a593Smuzhiyun type = read_token(&token);
1289*4882a593Smuzhiyun else
1290*4882a593Smuzhiyun type = read_token_item(&token);
1291*4882a593Smuzhiyun
1292*4882a593Smuzhiyun ret = test_type_token(type, token, expect, str);
1293*4882a593Smuzhiyun
1294*4882a593Smuzhiyun free_token(token);
1295*4882a593Smuzhiyun
1296*4882a593Smuzhiyun return ret;
1297*4882a593Smuzhiyun }
1298*4882a593Smuzhiyun
read_expected(enum tep_event_type expect,const char * str)1299*4882a593Smuzhiyun static int read_expected(enum tep_event_type expect, const char *str)
1300*4882a593Smuzhiyun {
1301*4882a593Smuzhiyun return __read_expected(expect, str, 1);
1302*4882a593Smuzhiyun }
1303*4882a593Smuzhiyun
read_expected_item(enum tep_event_type expect,const char * str)1304*4882a593Smuzhiyun static int read_expected_item(enum tep_event_type expect, const char *str)
1305*4882a593Smuzhiyun {
1306*4882a593Smuzhiyun return __read_expected(expect, str, 0);
1307*4882a593Smuzhiyun }
1308*4882a593Smuzhiyun
event_read_name(void)1309*4882a593Smuzhiyun static char *event_read_name(void)
1310*4882a593Smuzhiyun {
1311*4882a593Smuzhiyun char *token;
1312*4882a593Smuzhiyun
1313*4882a593Smuzhiyun if (read_expected(TEP_EVENT_ITEM, "name") < 0)
1314*4882a593Smuzhiyun return NULL;
1315*4882a593Smuzhiyun
1316*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ":") < 0)
1317*4882a593Smuzhiyun return NULL;
1318*4882a593Smuzhiyun
1319*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
1320*4882a593Smuzhiyun goto fail;
1321*4882a593Smuzhiyun
1322*4882a593Smuzhiyun return token;
1323*4882a593Smuzhiyun
1324*4882a593Smuzhiyun fail:
1325*4882a593Smuzhiyun free_token(token);
1326*4882a593Smuzhiyun return NULL;
1327*4882a593Smuzhiyun }
1328*4882a593Smuzhiyun
event_read_id(void)1329*4882a593Smuzhiyun static int event_read_id(void)
1330*4882a593Smuzhiyun {
1331*4882a593Smuzhiyun char *token;
1332*4882a593Smuzhiyun int id;
1333*4882a593Smuzhiyun
1334*4882a593Smuzhiyun if (read_expected_item(TEP_EVENT_ITEM, "ID") < 0)
1335*4882a593Smuzhiyun return -1;
1336*4882a593Smuzhiyun
1337*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ":") < 0)
1338*4882a593Smuzhiyun return -1;
1339*4882a593Smuzhiyun
1340*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
1341*4882a593Smuzhiyun goto fail;
1342*4882a593Smuzhiyun
1343*4882a593Smuzhiyun id = strtoul(token, NULL, 0);
1344*4882a593Smuzhiyun free_token(token);
1345*4882a593Smuzhiyun return id;
1346*4882a593Smuzhiyun
1347*4882a593Smuzhiyun fail:
1348*4882a593Smuzhiyun free_token(token);
1349*4882a593Smuzhiyun return -1;
1350*4882a593Smuzhiyun }
1351*4882a593Smuzhiyun
field_is_string(struct tep_format_field * field)1352*4882a593Smuzhiyun static int field_is_string(struct tep_format_field *field)
1353*4882a593Smuzhiyun {
1354*4882a593Smuzhiyun if ((field->flags & TEP_FIELD_IS_ARRAY) &&
1355*4882a593Smuzhiyun (strstr(field->type, "char") || strstr(field->type, "u8") ||
1356*4882a593Smuzhiyun strstr(field->type, "s8")))
1357*4882a593Smuzhiyun return 1;
1358*4882a593Smuzhiyun
1359*4882a593Smuzhiyun return 0;
1360*4882a593Smuzhiyun }
1361*4882a593Smuzhiyun
field_is_dynamic(struct tep_format_field * field)1362*4882a593Smuzhiyun static int field_is_dynamic(struct tep_format_field *field)
1363*4882a593Smuzhiyun {
1364*4882a593Smuzhiyun if (strncmp(field->type, "__data_loc", 10) == 0)
1365*4882a593Smuzhiyun return 1;
1366*4882a593Smuzhiyun
1367*4882a593Smuzhiyun return 0;
1368*4882a593Smuzhiyun }
1369*4882a593Smuzhiyun
field_is_long(struct tep_format_field * field)1370*4882a593Smuzhiyun static int field_is_long(struct tep_format_field *field)
1371*4882a593Smuzhiyun {
1372*4882a593Smuzhiyun /* includes long long */
1373*4882a593Smuzhiyun if (strstr(field->type, "long"))
1374*4882a593Smuzhiyun return 1;
1375*4882a593Smuzhiyun
1376*4882a593Smuzhiyun return 0;
1377*4882a593Smuzhiyun }
1378*4882a593Smuzhiyun
type_size(const char * name)1379*4882a593Smuzhiyun static unsigned int type_size(const char *name)
1380*4882a593Smuzhiyun {
1381*4882a593Smuzhiyun /* This covers all TEP_FIELD_IS_STRING types. */
1382*4882a593Smuzhiyun static struct {
1383*4882a593Smuzhiyun const char *type;
1384*4882a593Smuzhiyun unsigned int size;
1385*4882a593Smuzhiyun } table[] = {
1386*4882a593Smuzhiyun { "u8", 1 },
1387*4882a593Smuzhiyun { "u16", 2 },
1388*4882a593Smuzhiyun { "u32", 4 },
1389*4882a593Smuzhiyun { "u64", 8 },
1390*4882a593Smuzhiyun { "s8", 1 },
1391*4882a593Smuzhiyun { "s16", 2 },
1392*4882a593Smuzhiyun { "s32", 4 },
1393*4882a593Smuzhiyun { "s64", 8 },
1394*4882a593Smuzhiyun { "char", 1 },
1395*4882a593Smuzhiyun { },
1396*4882a593Smuzhiyun };
1397*4882a593Smuzhiyun int i;
1398*4882a593Smuzhiyun
1399*4882a593Smuzhiyun for (i = 0; table[i].type; i++) {
1400*4882a593Smuzhiyun if (!strcmp(table[i].type, name))
1401*4882a593Smuzhiyun return table[i].size;
1402*4882a593Smuzhiyun }
1403*4882a593Smuzhiyun
1404*4882a593Smuzhiyun return 0;
1405*4882a593Smuzhiyun }
1406*4882a593Smuzhiyun
append(char ** buf,const char * delim,const char * str)1407*4882a593Smuzhiyun static int append(char **buf, const char *delim, const char *str)
1408*4882a593Smuzhiyun {
1409*4882a593Smuzhiyun char *new_buf;
1410*4882a593Smuzhiyun
1411*4882a593Smuzhiyun new_buf = realloc(*buf, strlen(*buf) + strlen(delim) + strlen(str) + 1);
1412*4882a593Smuzhiyun if (!new_buf)
1413*4882a593Smuzhiyun return -1;
1414*4882a593Smuzhiyun strcat(new_buf, delim);
1415*4882a593Smuzhiyun strcat(new_buf, str);
1416*4882a593Smuzhiyun *buf = new_buf;
1417*4882a593Smuzhiyun return 0;
1418*4882a593Smuzhiyun }
1419*4882a593Smuzhiyun
event_read_fields(struct tep_event * event,struct tep_format_field ** fields)1420*4882a593Smuzhiyun static int event_read_fields(struct tep_event *event, struct tep_format_field **fields)
1421*4882a593Smuzhiyun {
1422*4882a593Smuzhiyun struct tep_format_field *field = NULL;
1423*4882a593Smuzhiyun enum tep_event_type type;
1424*4882a593Smuzhiyun char *token;
1425*4882a593Smuzhiyun char *last_token;
1426*4882a593Smuzhiyun char *delim = " ";
1427*4882a593Smuzhiyun int count = 0;
1428*4882a593Smuzhiyun int ret;
1429*4882a593Smuzhiyun
1430*4882a593Smuzhiyun do {
1431*4882a593Smuzhiyun unsigned int size_dynamic = 0;
1432*4882a593Smuzhiyun
1433*4882a593Smuzhiyun type = read_token(&token);
1434*4882a593Smuzhiyun if (type == TEP_EVENT_NEWLINE) {
1435*4882a593Smuzhiyun free_token(token);
1436*4882a593Smuzhiyun return count;
1437*4882a593Smuzhiyun }
1438*4882a593Smuzhiyun
1439*4882a593Smuzhiyun count++;
1440*4882a593Smuzhiyun
1441*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_ITEM, "field"))
1442*4882a593Smuzhiyun goto fail;
1443*4882a593Smuzhiyun free_token(token);
1444*4882a593Smuzhiyun
1445*4882a593Smuzhiyun type = read_token(&token);
1446*4882a593Smuzhiyun /*
1447*4882a593Smuzhiyun * The ftrace fields may still use the "special" name.
1448*4882a593Smuzhiyun * Just ignore it.
1449*4882a593Smuzhiyun */
1450*4882a593Smuzhiyun if (event->flags & TEP_EVENT_FL_ISFTRACE &&
1451*4882a593Smuzhiyun type == TEP_EVENT_ITEM && strcmp(token, "special") == 0) {
1452*4882a593Smuzhiyun free_token(token);
1453*4882a593Smuzhiyun type = read_token(&token);
1454*4882a593Smuzhiyun }
1455*4882a593Smuzhiyun
1456*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_OP, ":") < 0)
1457*4882a593Smuzhiyun goto fail;
1458*4882a593Smuzhiyun
1459*4882a593Smuzhiyun free_token(token);
1460*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
1461*4882a593Smuzhiyun goto fail;
1462*4882a593Smuzhiyun
1463*4882a593Smuzhiyun last_token = token;
1464*4882a593Smuzhiyun
1465*4882a593Smuzhiyun field = calloc(1, sizeof(*field));
1466*4882a593Smuzhiyun if (!field)
1467*4882a593Smuzhiyun goto fail;
1468*4882a593Smuzhiyun
1469*4882a593Smuzhiyun field->event = event;
1470*4882a593Smuzhiyun
1471*4882a593Smuzhiyun /* read the rest of the type */
1472*4882a593Smuzhiyun for (;;) {
1473*4882a593Smuzhiyun type = read_token(&token);
1474*4882a593Smuzhiyun if (type == TEP_EVENT_ITEM ||
1475*4882a593Smuzhiyun (type == TEP_EVENT_OP && strcmp(token, "*") == 0) ||
1476*4882a593Smuzhiyun /*
1477*4882a593Smuzhiyun * Some of the ftrace fields are broken and have
1478*4882a593Smuzhiyun * an illegal "." in them.
1479*4882a593Smuzhiyun */
1480*4882a593Smuzhiyun (event->flags & TEP_EVENT_FL_ISFTRACE &&
1481*4882a593Smuzhiyun type == TEP_EVENT_OP && strcmp(token, ".") == 0)) {
1482*4882a593Smuzhiyun
1483*4882a593Smuzhiyun if (strcmp(token, "*") == 0)
1484*4882a593Smuzhiyun field->flags |= TEP_FIELD_IS_POINTER;
1485*4882a593Smuzhiyun
1486*4882a593Smuzhiyun if (field->type) {
1487*4882a593Smuzhiyun ret = append(&field->type, delim, last_token);
1488*4882a593Smuzhiyun free(last_token);
1489*4882a593Smuzhiyun if (ret < 0)
1490*4882a593Smuzhiyun goto fail;
1491*4882a593Smuzhiyun } else
1492*4882a593Smuzhiyun field->type = last_token;
1493*4882a593Smuzhiyun last_token = token;
1494*4882a593Smuzhiyun delim = " ";
1495*4882a593Smuzhiyun continue;
1496*4882a593Smuzhiyun }
1497*4882a593Smuzhiyun
1498*4882a593Smuzhiyun /* Handle __attribute__((user)) */
1499*4882a593Smuzhiyun if ((type == TEP_EVENT_DELIM) &&
1500*4882a593Smuzhiyun strcmp("__attribute__", last_token) == 0 &&
1501*4882a593Smuzhiyun token[0] == '(') {
1502*4882a593Smuzhiyun int depth = 1;
1503*4882a593Smuzhiyun int ret;
1504*4882a593Smuzhiyun
1505*4882a593Smuzhiyun ret = append(&field->type, " ", last_token);
1506*4882a593Smuzhiyun ret |= append(&field->type, "", "(");
1507*4882a593Smuzhiyun if (ret < 0)
1508*4882a593Smuzhiyun goto fail;
1509*4882a593Smuzhiyun
1510*4882a593Smuzhiyun delim = " ";
1511*4882a593Smuzhiyun while ((type = read_token(&token)) != TEP_EVENT_NONE) {
1512*4882a593Smuzhiyun if (type == TEP_EVENT_DELIM) {
1513*4882a593Smuzhiyun if (token[0] == '(')
1514*4882a593Smuzhiyun depth++;
1515*4882a593Smuzhiyun else if (token[0] == ')')
1516*4882a593Smuzhiyun depth--;
1517*4882a593Smuzhiyun if (!depth)
1518*4882a593Smuzhiyun break;
1519*4882a593Smuzhiyun ret = append(&field->type, "", token);
1520*4882a593Smuzhiyun delim = "";
1521*4882a593Smuzhiyun } else {
1522*4882a593Smuzhiyun ret = append(&field->type, delim, token);
1523*4882a593Smuzhiyun delim = " ";
1524*4882a593Smuzhiyun }
1525*4882a593Smuzhiyun if (ret < 0)
1526*4882a593Smuzhiyun goto fail;
1527*4882a593Smuzhiyun free(last_token);
1528*4882a593Smuzhiyun last_token = token;
1529*4882a593Smuzhiyun }
1530*4882a593Smuzhiyun continue;
1531*4882a593Smuzhiyun }
1532*4882a593Smuzhiyun break;
1533*4882a593Smuzhiyun }
1534*4882a593Smuzhiyun
1535*4882a593Smuzhiyun if (!field->type) {
1536*4882a593Smuzhiyun do_warning_event(event, "%s: no type found", __func__);
1537*4882a593Smuzhiyun goto fail;
1538*4882a593Smuzhiyun }
1539*4882a593Smuzhiyun field->name = field->alias = last_token;
1540*4882a593Smuzhiyun
1541*4882a593Smuzhiyun if (test_type(type, TEP_EVENT_OP))
1542*4882a593Smuzhiyun goto fail;
1543*4882a593Smuzhiyun
1544*4882a593Smuzhiyun if (strcmp(token, "[") == 0) {
1545*4882a593Smuzhiyun enum tep_event_type last_type = type;
1546*4882a593Smuzhiyun char *brackets = token;
1547*4882a593Smuzhiyun
1548*4882a593Smuzhiyun field->flags |= TEP_FIELD_IS_ARRAY;
1549*4882a593Smuzhiyun
1550*4882a593Smuzhiyun type = read_token(&token);
1551*4882a593Smuzhiyun
1552*4882a593Smuzhiyun if (type == TEP_EVENT_ITEM)
1553*4882a593Smuzhiyun field->arraylen = strtoul(token, NULL, 0);
1554*4882a593Smuzhiyun else
1555*4882a593Smuzhiyun field->arraylen = 0;
1556*4882a593Smuzhiyun
1557*4882a593Smuzhiyun while (strcmp(token, "]") != 0) {
1558*4882a593Smuzhiyun const char *delim;
1559*4882a593Smuzhiyun
1560*4882a593Smuzhiyun if (last_type == TEP_EVENT_ITEM &&
1561*4882a593Smuzhiyun type == TEP_EVENT_ITEM)
1562*4882a593Smuzhiyun delim = " ";
1563*4882a593Smuzhiyun else
1564*4882a593Smuzhiyun delim = "";
1565*4882a593Smuzhiyun
1566*4882a593Smuzhiyun last_type = type;
1567*4882a593Smuzhiyun
1568*4882a593Smuzhiyun ret = append(&brackets, delim, token);
1569*4882a593Smuzhiyun if (ret < 0) {
1570*4882a593Smuzhiyun free(brackets);
1571*4882a593Smuzhiyun goto fail;
1572*4882a593Smuzhiyun }
1573*4882a593Smuzhiyun /* We only care about the last token */
1574*4882a593Smuzhiyun field->arraylen = strtoul(token, NULL, 0);
1575*4882a593Smuzhiyun free_token(token);
1576*4882a593Smuzhiyun type = read_token(&token);
1577*4882a593Smuzhiyun if (type == TEP_EVENT_NONE) {
1578*4882a593Smuzhiyun free(brackets);
1579*4882a593Smuzhiyun do_warning_event(event, "failed to find token");
1580*4882a593Smuzhiyun goto fail;
1581*4882a593Smuzhiyun }
1582*4882a593Smuzhiyun }
1583*4882a593Smuzhiyun
1584*4882a593Smuzhiyun free_token(token);
1585*4882a593Smuzhiyun
1586*4882a593Smuzhiyun ret = append(&brackets, "", "]");
1587*4882a593Smuzhiyun if (ret < 0) {
1588*4882a593Smuzhiyun free(brackets);
1589*4882a593Smuzhiyun goto fail;
1590*4882a593Smuzhiyun }
1591*4882a593Smuzhiyun
1592*4882a593Smuzhiyun /* add brackets to type */
1593*4882a593Smuzhiyun
1594*4882a593Smuzhiyun type = read_token(&token);
1595*4882a593Smuzhiyun /*
1596*4882a593Smuzhiyun * If the next token is not an OP, then it is of
1597*4882a593Smuzhiyun * the format: type [] item;
1598*4882a593Smuzhiyun */
1599*4882a593Smuzhiyun if (type == TEP_EVENT_ITEM) {
1600*4882a593Smuzhiyun ret = append(&field->type, " ", field->name);
1601*4882a593Smuzhiyun if (ret < 0) {
1602*4882a593Smuzhiyun free(brackets);
1603*4882a593Smuzhiyun goto fail;
1604*4882a593Smuzhiyun }
1605*4882a593Smuzhiyun ret = append(&field->type, "", brackets);
1606*4882a593Smuzhiyun
1607*4882a593Smuzhiyun size_dynamic = type_size(field->name);
1608*4882a593Smuzhiyun free_token(field->name);
1609*4882a593Smuzhiyun field->name = field->alias = token;
1610*4882a593Smuzhiyun type = read_token(&token);
1611*4882a593Smuzhiyun } else {
1612*4882a593Smuzhiyun ret = append(&field->type, "", brackets);
1613*4882a593Smuzhiyun if (ret < 0) {
1614*4882a593Smuzhiyun free(brackets);
1615*4882a593Smuzhiyun goto fail;
1616*4882a593Smuzhiyun }
1617*4882a593Smuzhiyun }
1618*4882a593Smuzhiyun free(brackets);
1619*4882a593Smuzhiyun }
1620*4882a593Smuzhiyun
1621*4882a593Smuzhiyun if (field_is_string(field))
1622*4882a593Smuzhiyun field->flags |= TEP_FIELD_IS_STRING;
1623*4882a593Smuzhiyun if (field_is_dynamic(field))
1624*4882a593Smuzhiyun field->flags |= TEP_FIELD_IS_DYNAMIC;
1625*4882a593Smuzhiyun if (field_is_long(field))
1626*4882a593Smuzhiyun field->flags |= TEP_FIELD_IS_LONG;
1627*4882a593Smuzhiyun
1628*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_OP, ";"))
1629*4882a593Smuzhiyun goto fail;
1630*4882a593Smuzhiyun free_token(token);
1631*4882a593Smuzhiyun
1632*4882a593Smuzhiyun if (read_expected(TEP_EVENT_ITEM, "offset") < 0)
1633*4882a593Smuzhiyun goto fail_expect;
1634*4882a593Smuzhiyun
1635*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ":") < 0)
1636*4882a593Smuzhiyun goto fail_expect;
1637*4882a593Smuzhiyun
1638*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_ITEM, &token))
1639*4882a593Smuzhiyun goto fail;
1640*4882a593Smuzhiyun field->offset = strtoul(token, NULL, 0);
1641*4882a593Smuzhiyun free_token(token);
1642*4882a593Smuzhiyun
1643*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ";") < 0)
1644*4882a593Smuzhiyun goto fail_expect;
1645*4882a593Smuzhiyun
1646*4882a593Smuzhiyun if (read_expected(TEP_EVENT_ITEM, "size") < 0)
1647*4882a593Smuzhiyun goto fail_expect;
1648*4882a593Smuzhiyun
1649*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ":") < 0)
1650*4882a593Smuzhiyun goto fail_expect;
1651*4882a593Smuzhiyun
1652*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_ITEM, &token))
1653*4882a593Smuzhiyun goto fail;
1654*4882a593Smuzhiyun field->size = strtoul(token, NULL, 0);
1655*4882a593Smuzhiyun free_token(token);
1656*4882a593Smuzhiyun
1657*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ";") < 0)
1658*4882a593Smuzhiyun goto fail_expect;
1659*4882a593Smuzhiyun
1660*4882a593Smuzhiyun type = read_token(&token);
1661*4882a593Smuzhiyun if (type != TEP_EVENT_NEWLINE) {
1662*4882a593Smuzhiyun /* newer versions of the kernel have a "signed" type */
1663*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_ITEM, "signed"))
1664*4882a593Smuzhiyun goto fail;
1665*4882a593Smuzhiyun
1666*4882a593Smuzhiyun free_token(token);
1667*4882a593Smuzhiyun
1668*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ":") < 0)
1669*4882a593Smuzhiyun goto fail_expect;
1670*4882a593Smuzhiyun
1671*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_ITEM, &token))
1672*4882a593Smuzhiyun goto fail;
1673*4882a593Smuzhiyun
1674*4882a593Smuzhiyun if (strtoul(token, NULL, 0))
1675*4882a593Smuzhiyun field->flags |= TEP_FIELD_IS_SIGNED;
1676*4882a593Smuzhiyun
1677*4882a593Smuzhiyun free_token(token);
1678*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ";") < 0)
1679*4882a593Smuzhiyun goto fail_expect;
1680*4882a593Smuzhiyun
1681*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_NEWLINE, &token))
1682*4882a593Smuzhiyun goto fail;
1683*4882a593Smuzhiyun }
1684*4882a593Smuzhiyun
1685*4882a593Smuzhiyun free_token(token);
1686*4882a593Smuzhiyun
1687*4882a593Smuzhiyun if (field->flags & TEP_FIELD_IS_ARRAY) {
1688*4882a593Smuzhiyun if (field->arraylen)
1689*4882a593Smuzhiyun field->elementsize = field->size / field->arraylen;
1690*4882a593Smuzhiyun else if (field->flags & TEP_FIELD_IS_DYNAMIC)
1691*4882a593Smuzhiyun field->elementsize = size_dynamic;
1692*4882a593Smuzhiyun else if (field->flags & TEP_FIELD_IS_STRING)
1693*4882a593Smuzhiyun field->elementsize = 1;
1694*4882a593Smuzhiyun else if (field->flags & TEP_FIELD_IS_LONG)
1695*4882a593Smuzhiyun field->elementsize = event->tep ?
1696*4882a593Smuzhiyun event->tep->long_size :
1697*4882a593Smuzhiyun sizeof(long);
1698*4882a593Smuzhiyun } else
1699*4882a593Smuzhiyun field->elementsize = field->size;
1700*4882a593Smuzhiyun
1701*4882a593Smuzhiyun *fields = field;
1702*4882a593Smuzhiyun fields = &field->next;
1703*4882a593Smuzhiyun
1704*4882a593Smuzhiyun } while (1);
1705*4882a593Smuzhiyun
1706*4882a593Smuzhiyun return 0;
1707*4882a593Smuzhiyun
1708*4882a593Smuzhiyun fail:
1709*4882a593Smuzhiyun free_token(token);
1710*4882a593Smuzhiyun fail_expect:
1711*4882a593Smuzhiyun if (field) {
1712*4882a593Smuzhiyun free(field->type);
1713*4882a593Smuzhiyun free(field->name);
1714*4882a593Smuzhiyun free(field);
1715*4882a593Smuzhiyun }
1716*4882a593Smuzhiyun return -1;
1717*4882a593Smuzhiyun }
1718*4882a593Smuzhiyun
event_read_format(struct tep_event * event)1719*4882a593Smuzhiyun static int event_read_format(struct tep_event *event)
1720*4882a593Smuzhiyun {
1721*4882a593Smuzhiyun char *token;
1722*4882a593Smuzhiyun int ret;
1723*4882a593Smuzhiyun
1724*4882a593Smuzhiyun if (read_expected_item(TEP_EVENT_ITEM, "format") < 0)
1725*4882a593Smuzhiyun return -1;
1726*4882a593Smuzhiyun
1727*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ":") < 0)
1728*4882a593Smuzhiyun return -1;
1729*4882a593Smuzhiyun
1730*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_NEWLINE, &token))
1731*4882a593Smuzhiyun goto fail;
1732*4882a593Smuzhiyun free_token(token);
1733*4882a593Smuzhiyun
1734*4882a593Smuzhiyun ret = event_read_fields(event, &event->format.common_fields);
1735*4882a593Smuzhiyun if (ret < 0)
1736*4882a593Smuzhiyun return ret;
1737*4882a593Smuzhiyun event->format.nr_common = ret;
1738*4882a593Smuzhiyun
1739*4882a593Smuzhiyun ret = event_read_fields(event, &event->format.fields);
1740*4882a593Smuzhiyun if (ret < 0)
1741*4882a593Smuzhiyun return ret;
1742*4882a593Smuzhiyun event->format.nr_fields = ret;
1743*4882a593Smuzhiyun
1744*4882a593Smuzhiyun return 0;
1745*4882a593Smuzhiyun
1746*4882a593Smuzhiyun fail:
1747*4882a593Smuzhiyun free_token(token);
1748*4882a593Smuzhiyun return -1;
1749*4882a593Smuzhiyun }
1750*4882a593Smuzhiyun
1751*4882a593Smuzhiyun static enum tep_event_type
1752*4882a593Smuzhiyun process_arg_token(struct tep_event *event, struct tep_print_arg *arg,
1753*4882a593Smuzhiyun char **tok, enum tep_event_type type);
1754*4882a593Smuzhiyun
1755*4882a593Smuzhiyun static enum tep_event_type
process_arg(struct tep_event * event,struct tep_print_arg * arg,char ** tok)1756*4882a593Smuzhiyun process_arg(struct tep_event *event, struct tep_print_arg *arg, char **tok)
1757*4882a593Smuzhiyun {
1758*4882a593Smuzhiyun enum tep_event_type type;
1759*4882a593Smuzhiyun char *token;
1760*4882a593Smuzhiyun
1761*4882a593Smuzhiyun type = read_token(&token);
1762*4882a593Smuzhiyun *tok = token;
1763*4882a593Smuzhiyun
1764*4882a593Smuzhiyun return process_arg_token(event, arg, tok, type);
1765*4882a593Smuzhiyun }
1766*4882a593Smuzhiyun
1767*4882a593Smuzhiyun static enum tep_event_type
1768*4882a593Smuzhiyun process_op(struct tep_event *event, struct tep_print_arg *arg, char **tok);
1769*4882a593Smuzhiyun
1770*4882a593Smuzhiyun /*
1771*4882a593Smuzhiyun * For __print_symbolic() and __print_flags, we need to completely
1772*4882a593Smuzhiyun * evaluate the first argument, which defines what to print next.
1773*4882a593Smuzhiyun */
1774*4882a593Smuzhiyun static enum tep_event_type
process_field_arg(struct tep_event * event,struct tep_print_arg * arg,char ** tok)1775*4882a593Smuzhiyun process_field_arg(struct tep_event *event, struct tep_print_arg *arg, char **tok)
1776*4882a593Smuzhiyun {
1777*4882a593Smuzhiyun enum tep_event_type type;
1778*4882a593Smuzhiyun
1779*4882a593Smuzhiyun type = process_arg(event, arg, tok);
1780*4882a593Smuzhiyun
1781*4882a593Smuzhiyun while (type == TEP_EVENT_OP) {
1782*4882a593Smuzhiyun type = process_op(event, arg, tok);
1783*4882a593Smuzhiyun }
1784*4882a593Smuzhiyun
1785*4882a593Smuzhiyun return type;
1786*4882a593Smuzhiyun }
1787*4882a593Smuzhiyun
1788*4882a593Smuzhiyun static enum tep_event_type
process_cond(struct tep_event * event,struct tep_print_arg * top,char ** tok)1789*4882a593Smuzhiyun process_cond(struct tep_event *event, struct tep_print_arg *top, char **tok)
1790*4882a593Smuzhiyun {
1791*4882a593Smuzhiyun struct tep_print_arg *arg, *left, *right;
1792*4882a593Smuzhiyun enum tep_event_type type;
1793*4882a593Smuzhiyun char *token = NULL;
1794*4882a593Smuzhiyun
1795*4882a593Smuzhiyun arg = alloc_arg();
1796*4882a593Smuzhiyun left = alloc_arg();
1797*4882a593Smuzhiyun right = alloc_arg();
1798*4882a593Smuzhiyun
1799*4882a593Smuzhiyun if (!arg || !left || !right) {
1800*4882a593Smuzhiyun do_warning_event(event, "%s: not enough memory!", __func__);
1801*4882a593Smuzhiyun /* arg will be freed at out_free */
1802*4882a593Smuzhiyun free_arg(left);
1803*4882a593Smuzhiyun free_arg(right);
1804*4882a593Smuzhiyun goto out_free;
1805*4882a593Smuzhiyun }
1806*4882a593Smuzhiyun
1807*4882a593Smuzhiyun arg->type = TEP_PRINT_OP;
1808*4882a593Smuzhiyun arg->op.left = left;
1809*4882a593Smuzhiyun arg->op.right = right;
1810*4882a593Smuzhiyun
1811*4882a593Smuzhiyun *tok = NULL;
1812*4882a593Smuzhiyun type = process_arg(event, left, &token);
1813*4882a593Smuzhiyun
1814*4882a593Smuzhiyun again:
1815*4882a593Smuzhiyun if (type == TEP_EVENT_ERROR)
1816*4882a593Smuzhiyun goto out_free;
1817*4882a593Smuzhiyun
1818*4882a593Smuzhiyun /* Handle other operations in the arguments */
1819*4882a593Smuzhiyun if (type == TEP_EVENT_OP && strcmp(token, ":") != 0) {
1820*4882a593Smuzhiyun type = process_op(event, left, &token);
1821*4882a593Smuzhiyun goto again;
1822*4882a593Smuzhiyun }
1823*4882a593Smuzhiyun
1824*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_OP, ":"))
1825*4882a593Smuzhiyun goto out_free;
1826*4882a593Smuzhiyun
1827*4882a593Smuzhiyun arg->op.op = token;
1828*4882a593Smuzhiyun
1829*4882a593Smuzhiyun type = process_arg(event, right, &token);
1830*4882a593Smuzhiyun
1831*4882a593Smuzhiyun top->op.right = arg;
1832*4882a593Smuzhiyun
1833*4882a593Smuzhiyun *tok = token;
1834*4882a593Smuzhiyun return type;
1835*4882a593Smuzhiyun
1836*4882a593Smuzhiyun out_free:
1837*4882a593Smuzhiyun /* Top may point to itself */
1838*4882a593Smuzhiyun top->op.right = NULL;
1839*4882a593Smuzhiyun free_token(token);
1840*4882a593Smuzhiyun free_arg(arg);
1841*4882a593Smuzhiyun return TEP_EVENT_ERROR;
1842*4882a593Smuzhiyun }
1843*4882a593Smuzhiyun
1844*4882a593Smuzhiyun static enum tep_event_type
process_array(struct tep_event * event,struct tep_print_arg * top,char ** tok)1845*4882a593Smuzhiyun process_array(struct tep_event *event, struct tep_print_arg *top, char **tok)
1846*4882a593Smuzhiyun {
1847*4882a593Smuzhiyun struct tep_print_arg *arg;
1848*4882a593Smuzhiyun enum tep_event_type type;
1849*4882a593Smuzhiyun char *token = NULL;
1850*4882a593Smuzhiyun
1851*4882a593Smuzhiyun arg = alloc_arg();
1852*4882a593Smuzhiyun if (!arg) {
1853*4882a593Smuzhiyun do_warning_event(event, "%s: not enough memory!", __func__);
1854*4882a593Smuzhiyun /* '*tok' is set to top->op.op. No need to free. */
1855*4882a593Smuzhiyun *tok = NULL;
1856*4882a593Smuzhiyun return TEP_EVENT_ERROR;
1857*4882a593Smuzhiyun }
1858*4882a593Smuzhiyun
1859*4882a593Smuzhiyun *tok = NULL;
1860*4882a593Smuzhiyun type = process_arg(event, arg, &token);
1861*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_OP, "]"))
1862*4882a593Smuzhiyun goto out_free;
1863*4882a593Smuzhiyun
1864*4882a593Smuzhiyun top->op.right = arg;
1865*4882a593Smuzhiyun
1866*4882a593Smuzhiyun free_token(token);
1867*4882a593Smuzhiyun type = read_token_item(&token);
1868*4882a593Smuzhiyun *tok = token;
1869*4882a593Smuzhiyun
1870*4882a593Smuzhiyun return type;
1871*4882a593Smuzhiyun
1872*4882a593Smuzhiyun out_free:
1873*4882a593Smuzhiyun free_token(token);
1874*4882a593Smuzhiyun free_arg(arg);
1875*4882a593Smuzhiyun return TEP_EVENT_ERROR;
1876*4882a593Smuzhiyun }
1877*4882a593Smuzhiyun
get_op_prio(char * op)1878*4882a593Smuzhiyun static int get_op_prio(char *op)
1879*4882a593Smuzhiyun {
1880*4882a593Smuzhiyun if (!op[1]) {
1881*4882a593Smuzhiyun switch (op[0]) {
1882*4882a593Smuzhiyun case '~':
1883*4882a593Smuzhiyun case '!':
1884*4882a593Smuzhiyun return 4;
1885*4882a593Smuzhiyun case '*':
1886*4882a593Smuzhiyun case '/':
1887*4882a593Smuzhiyun case '%':
1888*4882a593Smuzhiyun return 6;
1889*4882a593Smuzhiyun case '+':
1890*4882a593Smuzhiyun case '-':
1891*4882a593Smuzhiyun return 7;
1892*4882a593Smuzhiyun /* '>>' and '<<' are 8 */
1893*4882a593Smuzhiyun case '<':
1894*4882a593Smuzhiyun case '>':
1895*4882a593Smuzhiyun return 9;
1896*4882a593Smuzhiyun /* '==' and '!=' are 10 */
1897*4882a593Smuzhiyun case '&':
1898*4882a593Smuzhiyun return 11;
1899*4882a593Smuzhiyun case '^':
1900*4882a593Smuzhiyun return 12;
1901*4882a593Smuzhiyun case '|':
1902*4882a593Smuzhiyun return 13;
1903*4882a593Smuzhiyun case '?':
1904*4882a593Smuzhiyun return 16;
1905*4882a593Smuzhiyun default:
1906*4882a593Smuzhiyun do_warning("unknown op '%c'", op[0]);
1907*4882a593Smuzhiyun return -1;
1908*4882a593Smuzhiyun }
1909*4882a593Smuzhiyun } else {
1910*4882a593Smuzhiyun if (strcmp(op, "++") == 0 ||
1911*4882a593Smuzhiyun strcmp(op, "--") == 0) {
1912*4882a593Smuzhiyun return 3;
1913*4882a593Smuzhiyun } else if (strcmp(op, ">>") == 0 ||
1914*4882a593Smuzhiyun strcmp(op, "<<") == 0) {
1915*4882a593Smuzhiyun return 8;
1916*4882a593Smuzhiyun } else if (strcmp(op, ">=") == 0 ||
1917*4882a593Smuzhiyun strcmp(op, "<=") == 0) {
1918*4882a593Smuzhiyun return 9;
1919*4882a593Smuzhiyun } else if (strcmp(op, "==") == 0 ||
1920*4882a593Smuzhiyun strcmp(op, "!=") == 0) {
1921*4882a593Smuzhiyun return 10;
1922*4882a593Smuzhiyun } else if (strcmp(op, "&&") == 0) {
1923*4882a593Smuzhiyun return 14;
1924*4882a593Smuzhiyun } else if (strcmp(op, "||") == 0) {
1925*4882a593Smuzhiyun return 15;
1926*4882a593Smuzhiyun } else {
1927*4882a593Smuzhiyun do_warning("unknown op '%s'", op);
1928*4882a593Smuzhiyun return -1;
1929*4882a593Smuzhiyun }
1930*4882a593Smuzhiyun }
1931*4882a593Smuzhiyun }
1932*4882a593Smuzhiyun
set_op_prio(struct tep_print_arg * arg)1933*4882a593Smuzhiyun static int set_op_prio(struct tep_print_arg *arg)
1934*4882a593Smuzhiyun {
1935*4882a593Smuzhiyun
1936*4882a593Smuzhiyun /* single ops are the greatest */
1937*4882a593Smuzhiyun if (!arg->op.left || arg->op.left->type == TEP_PRINT_NULL)
1938*4882a593Smuzhiyun arg->op.prio = 0;
1939*4882a593Smuzhiyun else
1940*4882a593Smuzhiyun arg->op.prio = get_op_prio(arg->op.op);
1941*4882a593Smuzhiyun
1942*4882a593Smuzhiyun return arg->op.prio;
1943*4882a593Smuzhiyun }
1944*4882a593Smuzhiyun
1945*4882a593Smuzhiyun /* Note, *tok does not get freed, but will most likely be saved */
1946*4882a593Smuzhiyun static enum tep_event_type
process_op(struct tep_event * event,struct tep_print_arg * arg,char ** tok)1947*4882a593Smuzhiyun process_op(struct tep_event *event, struct tep_print_arg *arg, char **tok)
1948*4882a593Smuzhiyun {
1949*4882a593Smuzhiyun struct tep_print_arg *left, *right = NULL;
1950*4882a593Smuzhiyun enum tep_event_type type;
1951*4882a593Smuzhiyun char *token;
1952*4882a593Smuzhiyun
1953*4882a593Smuzhiyun /* the op is passed in via tok */
1954*4882a593Smuzhiyun token = *tok;
1955*4882a593Smuzhiyun
1956*4882a593Smuzhiyun if (arg->type == TEP_PRINT_OP && !arg->op.left) {
1957*4882a593Smuzhiyun /* handle single op */
1958*4882a593Smuzhiyun if (token[1]) {
1959*4882a593Smuzhiyun do_warning_event(event, "bad op token %s", token);
1960*4882a593Smuzhiyun goto out_free;
1961*4882a593Smuzhiyun }
1962*4882a593Smuzhiyun switch (token[0]) {
1963*4882a593Smuzhiyun case '~':
1964*4882a593Smuzhiyun case '!':
1965*4882a593Smuzhiyun case '+':
1966*4882a593Smuzhiyun case '-':
1967*4882a593Smuzhiyun break;
1968*4882a593Smuzhiyun default:
1969*4882a593Smuzhiyun do_warning_event(event, "bad op token %s", token);
1970*4882a593Smuzhiyun goto out_free;
1971*4882a593Smuzhiyun
1972*4882a593Smuzhiyun }
1973*4882a593Smuzhiyun
1974*4882a593Smuzhiyun /* make an empty left */
1975*4882a593Smuzhiyun left = alloc_arg();
1976*4882a593Smuzhiyun if (!left)
1977*4882a593Smuzhiyun goto out_warn_free;
1978*4882a593Smuzhiyun
1979*4882a593Smuzhiyun left->type = TEP_PRINT_NULL;
1980*4882a593Smuzhiyun arg->op.left = left;
1981*4882a593Smuzhiyun
1982*4882a593Smuzhiyun right = alloc_arg();
1983*4882a593Smuzhiyun if (!right)
1984*4882a593Smuzhiyun goto out_warn_free;
1985*4882a593Smuzhiyun
1986*4882a593Smuzhiyun arg->op.right = right;
1987*4882a593Smuzhiyun
1988*4882a593Smuzhiyun /* do not free the token, it belongs to an op */
1989*4882a593Smuzhiyun *tok = NULL;
1990*4882a593Smuzhiyun type = process_arg(event, right, tok);
1991*4882a593Smuzhiyun
1992*4882a593Smuzhiyun } else if (strcmp(token, "?") == 0) {
1993*4882a593Smuzhiyun
1994*4882a593Smuzhiyun left = alloc_arg();
1995*4882a593Smuzhiyun if (!left)
1996*4882a593Smuzhiyun goto out_warn_free;
1997*4882a593Smuzhiyun
1998*4882a593Smuzhiyun /* copy the top arg to the left */
1999*4882a593Smuzhiyun *left = *arg;
2000*4882a593Smuzhiyun
2001*4882a593Smuzhiyun arg->type = TEP_PRINT_OP;
2002*4882a593Smuzhiyun arg->op.op = token;
2003*4882a593Smuzhiyun arg->op.left = left;
2004*4882a593Smuzhiyun arg->op.prio = 0;
2005*4882a593Smuzhiyun
2006*4882a593Smuzhiyun /* it will set arg->op.right */
2007*4882a593Smuzhiyun type = process_cond(event, arg, tok);
2008*4882a593Smuzhiyun
2009*4882a593Smuzhiyun } else if (strcmp(token, ">>") == 0 ||
2010*4882a593Smuzhiyun strcmp(token, "<<") == 0 ||
2011*4882a593Smuzhiyun strcmp(token, "&") == 0 ||
2012*4882a593Smuzhiyun strcmp(token, "|") == 0 ||
2013*4882a593Smuzhiyun strcmp(token, "&&") == 0 ||
2014*4882a593Smuzhiyun strcmp(token, "||") == 0 ||
2015*4882a593Smuzhiyun strcmp(token, "-") == 0 ||
2016*4882a593Smuzhiyun strcmp(token, "+") == 0 ||
2017*4882a593Smuzhiyun strcmp(token, "*") == 0 ||
2018*4882a593Smuzhiyun strcmp(token, "^") == 0 ||
2019*4882a593Smuzhiyun strcmp(token, "/") == 0 ||
2020*4882a593Smuzhiyun strcmp(token, "%") == 0 ||
2021*4882a593Smuzhiyun strcmp(token, "<") == 0 ||
2022*4882a593Smuzhiyun strcmp(token, ">") == 0 ||
2023*4882a593Smuzhiyun strcmp(token, "<=") == 0 ||
2024*4882a593Smuzhiyun strcmp(token, ">=") == 0 ||
2025*4882a593Smuzhiyun strcmp(token, "==") == 0 ||
2026*4882a593Smuzhiyun strcmp(token, "!=") == 0) {
2027*4882a593Smuzhiyun
2028*4882a593Smuzhiyun left = alloc_arg();
2029*4882a593Smuzhiyun if (!left)
2030*4882a593Smuzhiyun goto out_warn_free;
2031*4882a593Smuzhiyun
2032*4882a593Smuzhiyun /* copy the top arg to the left */
2033*4882a593Smuzhiyun *left = *arg;
2034*4882a593Smuzhiyun
2035*4882a593Smuzhiyun arg->type = TEP_PRINT_OP;
2036*4882a593Smuzhiyun arg->op.op = token;
2037*4882a593Smuzhiyun arg->op.left = left;
2038*4882a593Smuzhiyun arg->op.right = NULL;
2039*4882a593Smuzhiyun
2040*4882a593Smuzhiyun if (set_op_prio(arg) == -1) {
2041*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_FAILED;
2042*4882a593Smuzhiyun /* arg->op.op (= token) will be freed at out_free */
2043*4882a593Smuzhiyun arg->op.op = NULL;
2044*4882a593Smuzhiyun goto out_free;
2045*4882a593Smuzhiyun }
2046*4882a593Smuzhiyun
2047*4882a593Smuzhiyun type = read_token_item(&token);
2048*4882a593Smuzhiyun *tok = token;
2049*4882a593Smuzhiyun
2050*4882a593Smuzhiyun /* could just be a type pointer */
2051*4882a593Smuzhiyun if ((strcmp(arg->op.op, "*") == 0) &&
2052*4882a593Smuzhiyun type == TEP_EVENT_DELIM && (strcmp(token, ")") == 0)) {
2053*4882a593Smuzhiyun int ret;
2054*4882a593Smuzhiyun
2055*4882a593Smuzhiyun if (left->type != TEP_PRINT_ATOM) {
2056*4882a593Smuzhiyun do_warning_event(event, "bad pointer type");
2057*4882a593Smuzhiyun goto out_free;
2058*4882a593Smuzhiyun }
2059*4882a593Smuzhiyun ret = append(&left->atom.atom, " ", "*");
2060*4882a593Smuzhiyun if (ret < 0)
2061*4882a593Smuzhiyun goto out_warn_free;
2062*4882a593Smuzhiyun
2063*4882a593Smuzhiyun free(arg->op.op);
2064*4882a593Smuzhiyun *arg = *left;
2065*4882a593Smuzhiyun free(left);
2066*4882a593Smuzhiyun
2067*4882a593Smuzhiyun return type;
2068*4882a593Smuzhiyun }
2069*4882a593Smuzhiyun
2070*4882a593Smuzhiyun right = alloc_arg();
2071*4882a593Smuzhiyun if (!right)
2072*4882a593Smuzhiyun goto out_warn_free;
2073*4882a593Smuzhiyun
2074*4882a593Smuzhiyun type = process_arg_token(event, right, tok, type);
2075*4882a593Smuzhiyun if (type == TEP_EVENT_ERROR) {
2076*4882a593Smuzhiyun free_arg(right);
2077*4882a593Smuzhiyun /* token was freed in process_arg_token() via *tok */
2078*4882a593Smuzhiyun token = NULL;
2079*4882a593Smuzhiyun goto out_free;
2080*4882a593Smuzhiyun }
2081*4882a593Smuzhiyun
2082*4882a593Smuzhiyun if (right->type == TEP_PRINT_OP &&
2083*4882a593Smuzhiyun get_op_prio(arg->op.op) < get_op_prio(right->op.op)) {
2084*4882a593Smuzhiyun struct tep_print_arg tmp;
2085*4882a593Smuzhiyun
2086*4882a593Smuzhiyun /* rotate ops according to the priority */
2087*4882a593Smuzhiyun arg->op.right = right->op.left;
2088*4882a593Smuzhiyun
2089*4882a593Smuzhiyun tmp = *arg;
2090*4882a593Smuzhiyun *arg = *right;
2091*4882a593Smuzhiyun *right = tmp;
2092*4882a593Smuzhiyun
2093*4882a593Smuzhiyun arg->op.left = right;
2094*4882a593Smuzhiyun } else {
2095*4882a593Smuzhiyun arg->op.right = right;
2096*4882a593Smuzhiyun }
2097*4882a593Smuzhiyun
2098*4882a593Smuzhiyun } else if (strcmp(token, "[") == 0) {
2099*4882a593Smuzhiyun
2100*4882a593Smuzhiyun left = alloc_arg();
2101*4882a593Smuzhiyun if (!left)
2102*4882a593Smuzhiyun goto out_warn_free;
2103*4882a593Smuzhiyun
2104*4882a593Smuzhiyun *left = *arg;
2105*4882a593Smuzhiyun
2106*4882a593Smuzhiyun arg->type = TEP_PRINT_OP;
2107*4882a593Smuzhiyun arg->op.op = token;
2108*4882a593Smuzhiyun arg->op.left = left;
2109*4882a593Smuzhiyun
2110*4882a593Smuzhiyun arg->op.prio = 0;
2111*4882a593Smuzhiyun
2112*4882a593Smuzhiyun /* it will set arg->op.right */
2113*4882a593Smuzhiyun type = process_array(event, arg, tok);
2114*4882a593Smuzhiyun
2115*4882a593Smuzhiyun } else {
2116*4882a593Smuzhiyun do_warning_event(event, "unknown op '%s'", token);
2117*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_FAILED;
2118*4882a593Smuzhiyun /* the arg is now the left side */
2119*4882a593Smuzhiyun goto out_free;
2120*4882a593Smuzhiyun }
2121*4882a593Smuzhiyun
2122*4882a593Smuzhiyun if (type == TEP_EVENT_OP && strcmp(*tok, ":") != 0) {
2123*4882a593Smuzhiyun int prio;
2124*4882a593Smuzhiyun
2125*4882a593Smuzhiyun /* higher prios need to be closer to the root */
2126*4882a593Smuzhiyun prio = get_op_prio(*tok);
2127*4882a593Smuzhiyun
2128*4882a593Smuzhiyun if (prio > arg->op.prio)
2129*4882a593Smuzhiyun return process_op(event, arg, tok);
2130*4882a593Smuzhiyun
2131*4882a593Smuzhiyun return process_op(event, right, tok);
2132*4882a593Smuzhiyun }
2133*4882a593Smuzhiyun
2134*4882a593Smuzhiyun return type;
2135*4882a593Smuzhiyun
2136*4882a593Smuzhiyun out_warn_free:
2137*4882a593Smuzhiyun do_warning_event(event, "%s: not enough memory!", __func__);
2138*4882a593Smuzhiyun out_free:
2139*4882a593Smuzhiyun free_token(token);
2140*4882a593Smuzhiyun *tok = NULL;
2141*4882a593Smuzhiyun return TEP_EVENT_ERROR;
2142*4882a593Smuzhiyun }
2143*4882a593Smuzhiyun
2144*4882a593Smuzhiyun static enum tep_event_type
process_entry(struct tep_event * event __maybe_unused,struct tep_print_arg * arg,char ** tok)2145*4882a593Smuzhiyun process_entry(struct tep_event *event __maybe_unused, struct tep_print_arg *arg,
2146*4882a593Smuzhiyun char **tok)
2147*4882a593Smuzhiyun {
2148*4882a593Smuzhiyun enum tep_event_type type;
2149*4882a593Smuzhiyun char *field;
2150*4882a593Smuzhiyun char *token;
2151*4882a593Smuzhiyun
2152*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, "->") < 0)
2153*4882a593Smuzhiyun goto out_err;
2154*4882a593Smuzhiyun
2155*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
2156*4882a593Smuzhiyun goto out_free;
2157*4882a593Smuzhiyun field = token;
2158*4882a593Smuzhiyun
2159*4882a593Smuzhiyun arg->type = TEP_PRINT_FIELD;
2160*4882a593Smuzhiyun arg->field.name = field;
2161*4882a593Smuzhiyun
2162*4882a593Smuzhiyun if (is_flag_field) {
2163*4882a593Smuzhiyun arg->field.field = tep_find_any_field(event, arg->field.name);
2164*4882a593Smuzhiyun arg->field.field->flags |= TEP_FIELD_IS_FLAG;
2165*4882a593Smuzhiyun is_flag_field = 0;
2166*4882a593Smuzhiyun } else if (is_symbolic_field) {
2167*4882a593Smuzhiyun arg->field.field = tep_find_any_field(event, arg->field.name);
2168*4882a593Smuzhiyun arg->field.field->flags |= TEP_FIELD_IS_SYMBOLIC;
2169*4882a593Smuzhiyun is_symbolic_field = 0;
2170*4882a593Smuzhiyun }
2171*4882a593Smuzhiyun
2172*4882a593Smuzhiyun type = read_token(&token);
2173*4882a593Smuzhiyun *tok = token;
2174*4882a593Smuzhiyun
2175*4882a593Smuzhiyun return type;
2176*4882a593Smuzhiyun
2177*4882a593Smuzhiyun out_free:
2178*4882a593Smuzhiyun free_token(token);
2179*4882a593Smuzhiyun out_err:
2180*4882a593Smuzhiyun *tok = NULL;
2181*4882a593Smuzhiyun return TEP_EVENT_ERROR;
2182*4882a593Smuzhiyun }
2183*4882a593Smuzhiyun
alloc_and_process_delim(struct tep_event * event,char * next_token,struct tep_print_arg ** print_arg)2184*4882a593Smuzhiyun static int alloc_and_process_delim(struct tep_event *event, char *next_token,
2185*4882a593Smuzhiyun struct tep_print_arg **print_arg)
2186*4882a593Smuzhiyun {
2187*4882a593Smuzhiyun struct tep_print_arg *field;
2188*4882a593Smuzhiyun enum tep_event_type type;
2189*4882a593Smuzhiyun char *token;
2190*4882a593Smuzhiyun int ret = 0;
2191*4882a593Smuzhiyun
2192*4882a593Smuzhiyun field = alloc_arg();
2193*4882a593Smuzhiyun if (!field) {
2194*4882a593Smuzhiyun do_warning_event(event, "%s: not enough memory!", __func__);
2195*4882a593Smuzhiyun errno = ENOMEM;
2196*4882a593Smuzhiyun return -1;
2197*4882a593Smuzhiyun }
2198*4882a593Smuzhiyun
2199*4882a593Smuzhiyun type = process_arg(event, field, &token);
2200*4882a593Smuzhiyun
2201*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_DELIM, next_token)) {
2202*4882a593Smuzhiyun errno = EINVAL;
2203*4882a593Smuzhiyun ret = -1;
2204*4882a593Smuzhiyun free_arg(field);
2205*4882a593Smuzhiyun goto out_free_token;
2206*4882a593Smuzhiyun }
2207*4882a593Smuzhiyun
2208*4882a593Smuzhiyun *print_arg = field;
2209*4882a593Smuzhiyun
2210*4882a593Smuzhiyun out_free_token:
2211*4882a593Smuzhiyun free_token(token);
2212*4882a593Smuzhiyun
2213*4882a593Smuzhiyun return ret;
2214*4882a593Smuzhiyun }
2215*4882a593Smuzhiyun
2216*4882a593Smuzhiyun static char *arg_eval (struct tep_print_arg *arg);
2217*4882a593Smuzhiyun
2218*4882a593Smuzhiyun static unsigned long long
eval_type_str(unsigned long long val,const char * type,int pointer)2219*4882a593Smuzhiyun eval_type_str(unsigned long long val, const char *type, int pointer)
2220*4882a593Smuzhiyun {
2221*4882a593Smuzhiyun int sign = 0;
2222*4882a593Smuzhiyun char *ref;
2223*4882a593Smuzhiyun int len;
2224*4882a593Smuzhiyun
2225*4882a593Smuzhiyun len = strlen(type);
2226*4882a593Smuzhiyun
2227*4882a593Smuzhiyun if (pointer) {
2228*4882a593Smuzhiyun
2229*4882a593Smuzhiyun if (type[len-1] != '*') {
2230*4882a593Smuzhiyun do_warning("pointer expected with non pointer type");
2231*4882a593Smuzhiyun return val;
2232*4882a593Smuzhiyun }
2233*4882a593Smuzhiyun
2234*4882a593Smuzhiyun ref = malloc(len);
2235*4882a593Smuzhiyun if (!ref) {
2236*4882a593Smuzhiyun do_warning("%s: not enough memory!", __func__);
2237*4882a593Smuzhiyun return val;
2238*4882a593Smuzhiyun }
2239*4882a593Smuzhiyun memcpy(ref, type, len);
2240*4882a593Smuzhiyun
2241*4882a593Smuzhiyun /* chop off the " *" */
2242*4882a593Smuzhiyun ref[len - 2] = 0;
2243*4882a593Smuzhiyun
2244*4882a593Smuzhiyun val = eval_type_str(val, ref, 0);
2245*4882a593Smuzhiyun free(ref);
2246*4882a593Smuzhiyun return val;
2247*4882a593Smuzhiyun }
2248*4882a593Smuzhiyun
2249*4882a593Smuzhiyun /* check if this is a pointer */
2250*4882a593Smuzhiyun if (type[len - 1] == '*')
2251*4882a593Smuzhiyun return val;
2252*4882a593Smuzhiyun
2253*4882a593Smuzhiyun /* Try to figure out the arg size*/
2254*4882a593Smuzhiyun if (strncmp(type, "struct", 6) == 0)
2255*4882a593Smuzhiyun /* all bets off */
2256*4882a593Smuzhiyun return val;
2257*4882a593Smuzhiyun
2258*4882a593Smuzhiyun if (strcmp(type, "u8") == 0)
2259*4882a593Smuzhiyun return val & 0xff;
2260*4882a593Smuzhiyun
2261*4882a593Smuzhiyun if (strcmp(type, "u16") == 0)
2262*4882a593Smuzhiyun return val & 0xffff;
2263*4882a593Smuzhiyun
2264*4882a593Smuzhiyun if (strcmp(type, "u32") == 0)
2265*4882a593Smuzhiyun return val & 0xffffffff;
2266*4882a593Smuzhiyun
2267*4882a593Smuzhiyun if (strcmp(type, "u64") == 0 ||
2268*4882a593Smuzhiyun strcmp(type, "s64") == 0)
2269*4882a593Smuzhiyun return val;
2270*4882a593Smuzhiyun
2271*4882a593Smuzhiyun if (strcmp(type, "s8") == 0)
2272*4882a593Smuzhiyun return (unsigned long long)(char)val & 0xff;
2273*4882a593Smuzhiyun
2274*4882a593Smuzhiyun if (strcmp(type, "s16") == 0)
2275*4882a593Smuzhiyun return (unsigned long long)(short)val & 0xffff;
2276*4882a593Smuzhiyun
2277*4882a593Smuzhiyun if (strcmp(type, "s32") == 0)
2278*4882a593Smuzhiyun return (unsigned long long)(int)val & 0xffffffff;
2279*4882a593Smuzhiyun
2280*4882a593Smuzhiyun if (strncmp(type, "unsigned ", 9) == 0) {
2281*4882a593Smuzhiyun sign = 0;
2282*4882a593Smuzhiyun type += 9;
2283*4882a593Smuzhiyun }
2284*4882a593Smuzhiyun
2285*4882a593Smuzhiyun if (strcmp(type, "char") == 0) {
2286*4882a593Smuzhiyun if (sign)
2287*4882a593Smuzhiyun return (unsigned long long)(char)val & 0xff;
2288*4882a593Smuzhiyun else
2289*4882a593Smuzhiyun return val & 0xff;
2290*4882a593Smuzhiyun }
2291*4882a593Smuzhiyun
2292*4882a593Smuzhiyun if (strcmp(type, "short") == 0) {
2293*4882a593Smuzhiyun if (sign)
2294*4882a593Smuzhiyun return (unsigned long long)(short)val & 0xffff;
2295*4882a593Smuzhiyun else
2296*4882a593Smuzhiyun return val & 0xffff;
2297*4882a593Smuzhiyun }
2298*4882a593Smuzhiyun
2299*4882a593Smuzhiyun if (strcmp(type, "int") == 0) {
2300*4882a593Smuzhiyun if (sign)
2301*4882a593Smuzhiyun return (unsigned long long)(int)val & 0xffffffff;
2302*4882a593Smuzhiyun else
2303*4882a593Smuzhiyun return val & 0xffffffff;
2304*4882a593Smuzhiyun }
2305*4882a593Smuzhiyun
2306*4882a593Smuzhiyun return val;
2307*4882a593Smuzhiyun }
2308*4882a593Smuzhiyun
2309*4882a593Smuzhiyun /*
2310*4882a593Smuzhiyun * Try to figure out the type.
2311*4882a593Smuzhiyun */
2312*4882a593Smuzhiyun static unsigned long long
eval_type(unsigned long long val,struct tep_print_arg * arg,int pointer)2313*4882a593Smuzhiyun eval_type(unsigned long long val, struct tep_print_arg *arg, int pointer)
2314*4882a593Smuzhiyun {
2315*4882a593Smuzhiyun if (arg->type != TEP_PRINT_TYPE) {
2316*4882a593Smuzhiyun do_warning("expected type argument");
2317*4882a593Smuzhiyun return 0;
2318*4882a593Smuzhiyun }
2319*4882a593Smuzhiyun
2320*4882a593Smuzhiyun return eval_type_str(val, arg->typecast.type, pointer);
2321*4882a593Smuzhiyun }
2322*4882a593Smuzhiyun
arg_num_eval(struct tep_print_arg * arg,long long * val)2323*4882a593Smuzhiyun static int arg_num_eval(struct tep_print_arg *arg, long long *val)
2324*4882a593Smuzhiyun {
2325*4882a593Smuzhiyun long long left, right;
2326*4882a593Smuzhiyun int ret = 1;
2327*4882a593Smuzhiyun
2328*4882a593Smuzhiyun switch (arg->type) {
2329*4882a593Smuzhiyun case TEP_PRINT_ATOM:
2330*4882a593Smuzhiyun *val = strtoll(arg->atom.atom, NULL, 0);
2331*4882a593Smuzhiyun break;
2332*4882a593Smuzhiyun case TEP_PRINT_TYPE:
2333*4882a593Smuzhiyun ret = arg_num_eval(arg->typecast.item, val);
2334*4882a593Smuzhiyun if (!ret)
2335*4882a593Smuzhiyun break;
2336*4882a593Smuzhiyun *val = eval_type(*val, arg, 0);
2337*4882a593Smuzhiyun break;
2338*4882a593Smuzhiyun case TEP_PRINT_OP:
2339*4882a593Smuzhiyun switch (arg->op.op[0]) {
2340*4882a593Smuzhiyun case '|':
2341*4882a593Smuzhiyun ret = arg_num_eval(arg->op.left, &left);
2342*4882a593Smuzhiyun if (!ret)
2343*4882a593Smuzhiyun break;
2344*4882a593Smuzhiyun ret = arg_num_eval(arg->op.right, &right);
2345*4882a593Smuzhiyun if (!ret)
2346*4882a593Smuzhiyun break;
2347*4882a593Smuzhiyun if (arg->op.op[1])
2348*4882a593Smuzhiyun *val = left || right;
2349*4882a593Smuzhiyun else
2350*4882a593Smuzhiyun *val = left | right;
2351*4882a593Smuzhiyun break;
2352*4882a593Smuzhiyun case '&':
2353*4882a593Smuzhiyun ret = arg_num_eval(arg->op.left, &left);
2354*4882a593Smuzhiyun if (!ret)
2355*4882a593Smuzhiyun break;
2356*4882a593Smuzhiyun ret = arg_num_eval(arg->op.right, &right);
2357*4882a593Smuzhiyun if (!ret)
2358*4882a593Smuzhiyun break;
2359*4882a593Smuzhiyun if (arg->op.op[1])
2360*4882a593Smuzhiyun *val = left && right;
2361*4882a593Smuzhiyun else
2362*4882a593Smuzhiyun *val = left & right;
2363*4882a593Smuzhiyun break;
2364*4882a593Smuzhiyun case '<':
2365*4882a593Smuzhiyun ret = arg_num_eval(arg->op.left, &left);
2366*4882a593Smuzhiyun if (!ret)
2367*4882a593Smuzhiyun break;
2368*4882a593Smuzhiyun ret = arg_num_eval(arg->op.right, &right);
2369*4882a593Smuzhiyun if (!ret)
2370*4882a593Smuzhiyun break;
2371*4882a593Smuzhiyun switch (arg->op.op[1]) {
2372*4882a593Smuzhiyun case 0:
2373*4882a593Smuzhiyun *val = left < right;
2374*4882a593Smuzhiyun break;
2375*4882a593Smuzhiyun case '<':
2376*4882a593Smuzhiyun *val = left << right;
2377*4882a593Smuzhiyun break;
2378*4882a593Smuzhiyun case '=':
2379*4882a593Smuzhiyun *val = left <= right;
2380*4882a593Smuzhiyun break;
2381*4882a593Smuzhiyun default:
2382*4882a593Smuzhiyun do_warning("unknown op '%s'", arg->op.op);
2383*4882a593Smuzhiyun ret = 0;
2384*4882a593Smuzhiyun }
2385*4882a593Smuzhiyun break;
2386*4882a593Smuzhiyun case '>':
2387*4882a593Smuzhiyun ret = arg_num_eval(arg->op.left, &left);
2388*4882a593Smuzhiyun if (!ret)
2389*4882a593Smuzhiyun break;
2390*4882a593Smuzhiyun ret = arg_num_eval(arg->op.right, &right);
2391*4882a593Smuzhiyun if (!ret)
2392*4882a593Smuzhiyun break;
2393*4882a593Smuzhiyun switch (arg->op.op[1]) {
2394*4882a593Smuzhiyun case 0:
2395*4882a593Smuzhiyun *val = left > right;
2396*4882a593Smuzhiyun break;
2397*4882a593Smuzhiyun case '>':
2398*4882a593Smuzhiyun *val = left >> right;
2399*4882a593Smuzhiyun break;
2400*4882a593Smuzhiyun case '=':
2401*4882a593Smuzhiyun *val = left >= right;
2402*4882a593Smuzhiyun break;
2403*4882a593Smuzhiyun default:
2404*4882a593Smuzhiyun do_warning("unknown op '%s'", arg->op.op);
2405*4882a593Smuzhiyun ret = 0;
2406*4882a593Smuzhiyun }
2407*4882a593Smuzhiyun break;
2408*4882a593Smuzhiyun case '=':
2409*4882a593Smuzhiyun ret = arg_num_eval(arg->op.left, &left);
2410*4882a593Smuzhiyun if (!ret)
2411*4882a593Smuzhiyun break;
2412*4882a593Smuzhiyun ret = arg_num_eval(arg->op.right, &right);
2413*4882a593Smuzhiyun if (!ret)
2414*4882a593Smuzhiyun break;
2415*4882a593Smuzhiyun
2416*4882a593Smuzhiyun if (arg->op.op[1] != '=') {
2417*4882a593Smuzhiyun do_warning("unknown op '%s'", arg->op.op);
2418*4882a593Smuzhiyun ret = 0;
2419*4882a593Smuzhiyun } else
2420*4882a593Smuzhiyun *val = left == right;
2421*4882a593Smuzhiyun break;
2422*4882a593Smuzhiyun case '!':
2423*4882a593Smuzhiyun ret = arg_num_eval(arg->op.left, &left);
2424*4882a593Smuzhiyun if (!ret)
2425*4882a593Smuzhiyun break;
2426*4882a593Smuzhiyun ret = arg_num_eval(arg->op.right, &right);
2427*4882a593Smuzhiyun if (!ret)
2428*4882a593Smuzhiyun break;
2429*4882a593Smuzhiyun
2430*4882a593Smuzhiyun switch (arg->op.op[1]) {
2431*4882a593Smuzhiyun case '=':
2432*4882a593Smuzhiyun *val = left != right;
2433*4882a593Smuzhiyun break;
2434*4882a593Smuzhiyun default:
2435*4882a593Smuzhiyun do_warning("unknown op '%s'", arg->op.op);
2436*4882a593Smuzhiyun ret = 0;
2437*4882a593Smuzhiyun }
2438*4882a593Smuzhiyun break;
2439*4882a593Smuzhiyun case '-':
2440*4882a593Smuzhiyun /* check for negative */
2441*4882a593Smuzhiyun if (arg->op.left->type == TEP_PRINT_NULL)
2442*4882a593Smuzhiyun left = 0;
2443*4882a593Smuzhiyun else
2444*4882a593Smuzhiyun ret = arg_num_eval(arg->op.left, &left);
2445*4882a593Smuzhiyun if (!ret)
2446*4882a593Smuzhiyun break;
2447*4882a593Smuzhiyun ret = arg_num_eval(arg->op.right, &right);
2448*4882a593Smuzhiyun if (!ret)
2449*4882a593Smuzhiyun break;
2450*4882a593Smuzhiyun *val = left - right;
2451*4882a593Smuzhiyun break;
2452*4882a593Smuzhiyun case '+':
2453*4882a593Smuzhiyun if (arg->op.left->type == TEP_PRINT_NULL)
2454*4882a593Smuzhiyun left = 0;
2455*4882a593Smuzhiyun else
2456*4882a593Smuzhiyun ret = arg_num_eval(arg->op.left, &left);
2457*4882a593Smuzhiyun if (!ret)
2458*4882a593Smuzhiyun break;
2459*4882a593Smuzhiyun ret = arg_num_eval(arg->op.right, &right);
2460*4882a593Smuzhiyun if (!ret)
2461*4882a593Smuzhiyun break;
2462*4882a593Smuzhiyun *val = left + right;
2463*4882a593Smuzhiyun break;
2464*4882a593Smuzhiyun case '~':
2465*4882a593Smuzhiyun ret = arg_num_eval(arg->op.right, &right);
2466*4882a593Smuzhiyun if (!ret)
2467*4882a593Smuzhiyun break;
2468*4882a593Smuzhiyun *val = ~right;
2469*4882a593Smuzhiyun break;
2470*4882a593Smuzhiyun default:
2471*4882a593Smuzhiyun do_warning("unknown op '%s'", arg->op.op);
2472*4882a593Smuzhiyun ret = 0;
2473*4882a593Smuzhiyun }
2474*4882a593Smuzhiyun break;
2475*4882a593Smuzhiyun
2476*4882a593Smuzhiyun case TEP_PRINT_NULL:
2477*4882a593Smuzhiyun case TEP_PRINT_FIELD ... TEP_PRINT_SYMBOL:
2478*4882a593Smuzhiyun case TEP_PRINT_STRING:
2479*4882a593Smuzhiyun case TEP_PRINT_BSTRING:
2480*4882a593Smuzhiyun case TEP_PRINT_BITMASK:
2481*4882a593Smuzhiyun default:
2482*4882a593Smuzhiyun do_warning("invalid eval type %d", arg->type);
2483*4882a593Smuzhiyun ret = 0;
2484*4882a593Smuzhiyun
2485*4882a593Smuzhiyun }
2486*4882a593Smuzhiyun return ret;
2487*4882a593Smuzhiyun }
2488*4882a593Smuzhiyun
arg_eval(struct tep_print_arg * arg)2489*4882a593Smuzhiyun static char *arg_eval (struct tep_print_arg *arg)
2490*4882a593Smuzhiyun {
2491*4882a593Smuzhiyun long long val;
2492*4882a593Smuzhiyun static char buf[24];
2493*4882a593Smuzhiyun
2494*4882a593Smuzhiyun switch (arg->type) {
2495*4882a593Smuzhiyun case TEP_PRINT_ATOM:
2496*4882a593Smuzhiyun return arg->atom.atom;
2497*4882a593Smuzhiyun case TEP_PRINT_TYPE:
2498*4882a593Smuzhiyun return arg_eval(arg->typecast.item);
2499*4882a593Smuzhiyun case TEP_PRINT_OP:
2500*4882a593Smuzhiyun if (!arg_num_eval(arg, &val))
2501*4882a593Smuzhiyun break;
2502*4882a593Smuzhiyun sprintf(buf, "%lld", val);
2503*4882a593Smuzhiyun return buf;
2504*4882a593Smuzhiyun
2505*4882a593Smuzhiyun case TEP_PRINT_NULL:
2506*4882a593Smuzhiyun case TEP_PRINT_FIELD ... TEP_PRINT_SYMBOL:
2507*4882a593Smuzhiyun case TEP_PRINT_STRING:
2508*4882a593Smuzhiyun case TEP_PRINT_BSTRING:
2509*4882a593Smuzhiyun case TEP_PRINT_BITMASK:
2510*4882a593Smuzhiyun default:
2511*4882a593Smuzhiyun do_warning("invalid eval type %d", arg->type);
2512*4882a593Smuzhiyun break;
2513*4882a593Smuzhiyun }
2514*4882a593Smuzhiyun
2515*4882a593Smuzhiyun return NULL;
2516*4882a593Smuzhiyun }
2517*4882a593Smuzhiyun
2518*4882a593Smuzhiyun static enum tep_event_type
process_fields(struct tep_event * event,struct tep_print_flag_sym ** list,char ** tok)2519*4882a593Smuzhiyun process_fields(struct tep_event *event, struct tep_print_flag_sym **list, char **tok)
2520*4882a593Smuzhiyun {
2521*4882a593Smuzhiyun enum tep_event_type type;
2522*4882a593Smuzhiyun struct tep_print_arg *arg = NULL;
2523*4882a593Smuzhiyun struct tep_print_flag_sym *field;
2524*4882a593Smuzhiyun char *token = *tok;
2525*4882a593Smuzhiyun char *value;
2526*4882a593Smuzhiyun
2527*4882a593Smuzhiyun do {
2528*4882a593Smuzhiyun free_token(token);
2529*4882a593Smuzhiyun type = read_token_item(&token);
2530*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_OP, "{"))
2531*4882a593Smuzhiyun break;
2532*4882a593Smuzhiyun
2533*4882a593Smuzhiyun arg = alloc_arg();
2534*4882a593Smuzhiyun if (!arg)
2535*4882a593Smuzhiyun goto out_free;
2536*4882a593Smuzhiyun
2537*4882a593Smuzhiyun free_token(token);
2538*4882a593Smuzhiyun type = process_arg(event, arg, &token);
2539*4882a593Smuzhiyun
2540*4882a593Smuzhiyun if (type == TEP_EVENT_OP)
2541*4882a593Smuzhiyun type = process_op(event, arg, &token);
2542*4882a593Smuzhiyun
2543*4882a593Smuzhiyun if (type == TEP_EVENT_ERROR)
2544*4882a593Smuzhiyun goto out_free;
2545*4882a593Smuzhiyun
2546*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_DELIM, ","))
2547*4882a593Smuzhiyun goto out_free;
2548*4882a593Smuzhiyun
2549*4882a593Smuzhiyun field = calloc(1, sizeof(*field));
2550*4882a593Smuzhiyun if (!field)
2551*4882a593Smuzhiyun goto out_free;
2552*4882a593Smuzhiyun
2553*4882a593Smuzhiyun value = arg_eval(arg);
2554*4882a593Smuzhiyun if (value == NULL)
2555*4882a593Smuzhiyun goto out_free_field;
2556*4882a593Smuzhiyun field->value = strdup(value);
2557*4882a593Smuzhiyun if (field->value == NULL)
2558*4882a593Smuzhiyun goto out_free_field;
2559*4882a593Smuzhiyun
2560*4882a593Smuzhiyun free_arg(arg);
2561*4882a593Smuzhiyun arg = alloc_arg();
2562*4882a593Smuzhiyun if (!arg)
2563*4882a593Smuzhiyun goto out_free;
2564*4882a593Smuzhiyun
2565*4882a593Smuzhiyun free_token(token);
2566*4882a593Smuzhiyun type = process_arg(event, arg, &token);
2567*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_OP, "}"))
2568*4882a593Smuzhiyun goto out_free_field;
2569*4882a593Smuzhiyun
2570*4882a593Smuzhiyun value = arg_eval(arg);
2571*4882a593Smuzhiyun if (value == NULL)
2572*4882a593Smuzhiyun goto out_free_field;
2573*4882a593Smuzhiyun field->str = strdup(value);
2574*4882a593Smuzhiyun if (field->str == NULL)
2575*4882a593Smuzhiyun goto out_free_field;
2576*4882a593Smuzhiyun free_arg(arg);
2577*4882a593Smuzhiyun arg = NULL;
2578*4882a593Smuzhiyun
2579*4882a593Smuzhiyun *list = field;
2580*4882a593Smuzhiyun list = &field->next;
2581*4882a593Smuzhiyun
2582*4882a593Smuzhiyun free_token(token);
2583*4882a593Smuzhiyun type = read_token_item(&token);
2584*4882a593Smuzhiyun } while (type == TEP_EVENT_DELIM && strcmp(token, ",") == 0);
2585*4882a593Smuzhiyun
2586*4882a593Smuzhiyun *tok = token;
2587*4882a593Smuzhiyun return type;
2588*4882a593Smuzhiyun
2589*4882a593Smuzhiyun out_free_field:
2590*4882a593Smuzhiyun free_flag_sym(field);
2591*4882a593Smuzhiyun out_free:
2592*4882a593Smuzhiyun free_arg(arg);
2593*4882a593Smuzhiyun free_token(token);
2594*4882a593Smuzhiyun *tok = NULL;
2595*4882a593Smuzhiyun
2596*4882a593Smuzhiyun return TEP_EVENT_ERROR;
2597*4882a593Smuzhiyun }
2598*4882a593Smuzhiyun
2599*4882a593Smuzhiyun static enum tep_event_type
process_flags(struct tep_event * event,struct tep_print_arg * arg,char ** tok)2600*4882a593Smuzhiyun process_flags(struct tep_event *event, struct tep_print_arg *arg, char **tok)
2601*4882a593Smuzhiyun {
2602*4882a593Smuzhiyun struct tep_print_arg *field;
2603*4882a593Smuzhiyun enum tep_event_type type;
2604*4882a593Smuzhiyun char *token = NULL;
2605*4882a593Smuzhiyun
2606*4882a593Smuzhiyun memset(arg, 0, sizeof(*arg));
2607*4882a593Smuzhiyun arg->type = TEP_PRINT_FLAGS;
2608*4882a593Smuzhiyun
2609*4882a593Smuzhiyun field = alloc_arg();
2610*4882a593Smuzhiyun if (!field) {
2611*4882a593Smuzhiyun do_warning_event(event, "%s: not enough memory!", __func__);
2612*4882a593Smuzhiyun goto out_free;
2613*4882a593Smuzhiyun }
2614*4882a593Smuzhiyun
2615*4882a593Smuzhiyun type = process_field_arg(event, field, &token);
2616*4882a593Smuzhiyun
2617*4882a593Smuzhiyun /* Handle operations in the first argument */
2618*4882a593Smuzhiyun while (type == TEP_EVENT_OP)
2619*4882a593Smuzhiyun type = process_op(event, field, &token);
2620*4882a593Smuzhiyun
2621*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_DELIM, ","))
2622*4882a593Smuzhiyun goto out_free_field;
2623*4882a593Smuzhiyun free_token(token);
2624*4882a593Smuzhiyun
2625*4882a593Smuzhiyun arg->flags.field = field;
2626*4882a593Smuzhiyun
2627*4882a593Smuzhiyun type = read_token_item(&token);
2628*4882a593Smuzhiyun if (event_item_type(type)) {
2629*4882a593Smuzhiyun arg->flags.delim = token;
2630*4882a593Smuzhiyun type = read_token_item(&token);
2631*4882a593Smuzhiyun }
2632*4882a593Smuzhiyun
2633*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_DELIM, ","))
2634*4882a593Smuzhiyun goto out_free;
2635*4882a593Smuzhiyun
2636*4882a593Smuzhiyun type = process_fields(event, &arg->flags.flags, &token);
2637*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_DELIM, ")"))
2638*4882a593Smuzhiyun goto out_free;
2639*4882a593Smuzhiyun
2640*4882a593Smuzhiyun free_token(token);
2641*4882a593Smuzhiyun type = read_token_item(tok);
2642*4882a593Smuzhiyun return type;
2643*4882a593Smuzhiyun
2644*4882a593Smuzhiyun out_free_field:
2645*4882a593Smuzhiyun free_arg(field);
2646*4882a593Smuzhiyun out_free:
2647*4882a593Smuzhiyun free_token(token);
2648*4882a593Smuzhiyun *tok = NULL;
2649*4882a593Smuzhiyun return TEP_EVENT_ERROR;
2650*4882a593Smuzhiyun }
2651*4882a593Smuzhiyun
2652*4882a593Smuzhiyun static enum tep_event_type
process_symbols(struct tep_event * event,struct tep_print_arg * arg,char ** tok)2653*4882a593Smuzhiyun process_symbols(struct tep_event *event, struct tep_print_arg *arg, char **tok)
2654*4882a593Smuzhiyun {
2655*4882a593Smuzhiyun struct tep_print_arg *field;
2656*4882a593Smuzhiyun enum tep_event_type type;
2657*4882a593Smuzhiyun char *token = NULL;
2658*4882a593Smuzhiyun
2659*4882a593Smuzhiyun memset(arg, 0, sizeof(*arg));
2660*4882a593Smuzhiyun arg->type = TEP_PRINT_SYMBOL;
2661*4882a593Smuzhiyun
2662*4882a593Smuzhiyun field = alloc_arg();
2663*4882a593Smuzhiyun if (!field) {
2664*4882a593Smuzhiyun do_warning_event(event, "%s: not enough memory!", __func__);
2665*4882a593Smuzhiyun goto out_free;
2666*4882a593Smuzhiyun }
2667*4882a593Smuzhiyun
2668*4882a593Smuzhiyun type = process_field_arg(event, field, &token);
2669*4882a593Smuzhiyun
2670*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_DELIM, ","))
2671*4882a593Smuzhiyun goto out_free_field;
2672*4882a593Smuzhiyun
2673*4882a593Smuzhiyun arg->symbol.field = field;
2674*4882a593Smuzhiyun
2675*4882a593Smuzhiyun type = process_fields(event, &arg->symbol.symbols, &token);
2676*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_DELIM, ")"))
2677*4882a593Smuzhiyun goto out_free;
2678*4882a593Smuzhiyun
2679*4882a593Smuzhiyun free_token(token);
2680*4882a593Smuzhiyun type = read_token_item(tok);
2681*4882a593Smuzhiyun return type;
2682*4882a593Smuzhiyun
2683*4882a593Smuzhiyun out_free_field:
2684*4882a593Smuzhiyun free_arg(field);
2685*4882a593Smuzhiyun out_free:
2686*4882a593Smuzhiyun free_token(token);
2687*4882a593Smuzhiyun *tok = NULL;
2688*4882a593Smuzhiyun return TEP_EVENT_ERROR;
2689*4882a593Smuzhiyun }
2690*4882a593Smuzhiyun
2691*4882a593Smuzhiyun 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)2692*4882a593Smuzhiyun process_hex_common(struct tep_event *event, struct tep_print_arg *arg,
2693*4882a593Smuzhiyun char **tok, enum tep_print_arg_type type)
2694*4882a593Smuzhiyun {
2695*4882a593Smuzhiyun memset(arg, 0, sizeof(*arg));
2696*4882a593Smuzhiyun arg->type = type;
2697*4882a593Smuzhiyun
2698*4882a593Smuzhiyun if (alloc_and_process_delim(event, ",", &arg->hex.field))
2699*4882a593Smuzhiyun goto out;
2700*4882a593Smuzhiyun
2701*4882a593Smuzhiyun if (alloc_and_process_delim(event, ")", &arg->hex.size))
2702*4882a593Smuzhiyun goto free_field;
2703*4882a593Smuzhiyun
2704*4882a593Smuzhiyun return read_token_item(tok);
2705*4882a593Smuzhiyun
2706*4882a593Smuzhiyun free_field:
2707*4882a593Smuzhiyun free_arg(arg->hex.field);
2708*4882a593Smuzhiyun arg->hex.field = NULL;
2709*4882a593Smuzhiyun out:
2710*4882a593Smuzhiyun *tok = NULL;
2711*4882a593Smuzhiyun return TEP_EVENT_ERROR;
2712*4882a593Smuzhiyun }
2713*4882a593Smuzhiyun
2714*4882a593Smuzhiyun static enum tep_event_type
process_hex(struct tep_event * event,struct tep_print_arg * arg,char ** tok)2715*4882a593Smuzhiyun process_hex(struct tep_event *event, struct tep_print_arg *arg, char **tok)
2716*4882a593Smuzhiyun {
2717*4882a593Smuzhiyun return process_hex_common(event, arg, tok, TEP_PRINT_HEX);
2718*4882a593Smuzhiyun }
2719*4882a593Smuzhiyun
2720*4882a593Smuzhiyun static enum tep_event_type
process_hex_str(struct tep_event * event,struct tep_print_arg * arg,char ** tok)2721*4882a593Smuzhiyun process_hex_str(struct tep_event *event, struct tep_print_arg *arg,
2722*4882a593Smuzhiyun char **tok)
2723*4882a593Smuzhiyun {
2724*4882a593Smuzhiyun return process_hex_common(event, arg, tok, TEP_PRINT_HEX_STR);
2725*4882a593Smuzhiyun }
2726*4882a593Smuzhiyun
2727*4882a593Smuzhiyun static enum tep_event_type
process_int_array(struct tep_event * event,struct tep_print_arg * arg,char ** tok)2728*4882a593Smuzhiyun process_int_array(struct tep_event *event, struct tep_print_arg *arg, char **tok)
2729*4882a593Smuzhiyun {
2730*4882a593Smuzhiyun memset(arg, 0, sizeof(*arg));
2731*4882a593Smuzhiyun arg->type = TEP_PRINT_INT_ARRAY;
2732*4882a593Smuzhiyun
2733*4882a593Smuzhiyun if (alloc_and_process_delim(event, ",", &arg->int_array.field))
2734*4882a593Smuzhiyun goto out;
2735*4882a593Smuzhiyun
2736*4882a593Smuzhiyun if (alloc_and_process_delim(event, ",", &arg->int_array.count))
2737*4882a593Smuzhiyun goto free_field;
2738*4882a593Smuzhiyun
2739*4882a593Smuzhiyun if (alloc_and_process_delim(event, ")", &arg->int_array.el_size))
2740*4882a593Smuzhiyun goto free_size;
2741*4882a593Smuzhiyun
2742*4882a593Smuzhiyun return read_token_item(tok);
2743*4882a593Smuzhiyun
2744*4882a593Smuzhiyun free_size:
2745*4882a593Smuzhiyun free_arg(arg->int_array.count);
2746*4882a593Smuzhiyun arg->int_array.count = NULL;
2747*4882a593Smuzhiyun free_field:
2748*4882a593Smuzhiyun free_arg(arg->int_array.field);
2749*4882a593Smuzhiyun arg->int_array.field = NULL;
2750*4882a593Smuzhiyun out:
2751*4882a593Smuzhiyun *tok = NULL;
2752*4882a593Smuzhiyun return TEP_EVENT_ERROR;
2753*4882a593Smuzhiyun }
2754*4882a593Smuzhiyun
2755*4882a593Smuzhiyun static enum tep_event_type
process_dynamic_array(struct tep_event * event,struct tep_print_arg * arg,char ** tok)2756*4882a593Smuzhiyun process_dynamic_array(struct tep_event *event, struct tep_print_arg *arg, char **tok)
2757*4882a593Smuzhiyun {
2758*4882a593Smuzhiyun struct tep_format_field *field;
2759*4882a593Smuzhiyun enum tep_event_type type;
2760*4882a593Smuzhiyun char *token;
2761*4882a593Smuzhiyun
2762*4882a593Smuzhiyun memset(arg, 0, sizeof(*arg));
2763*4882a593Smuzhiyun arg->type = TEP_PRINT_DYNAMIC_ARRAY;
2764*4882a593Smuzhiyun
2765*4882a593Smuzhiyun /*
2766*4882a593Smuzhiyun * The item within the parenthesis is another field that holds
2767*4882a593Smuzhiyun * the index into where the array starts.
2768*4882a593Smuzhiyun */
2769*4882a593Smuzhiyun type = read_token(&token);
2770*4882a593Smuzhiyun *tok = token;
2771*4882a593Smuzhiyun if (type != TEP_EVENT_ITEM)
2772*4882a593Smuzhiyun goto out_free;
2773*4882a593Smuzhiyun
2774*4882a593Smuzhiyun /* Find the field */
2775*4882a593Smuzhiyun
2776*4882a593Smuzhiyun field = tep_find_field(event, token);
2777*4882a593Smuzhiyun if (!field)
2778*4882a593Smuzhiyun goto out_free;
2779*4882a593Smuzhiyun
2780*4882a593Smuzhiyun arg->dynarray.field = field;
2781*4882a593Smuzhiyun arg->dynarray.index = 0;
2782*4882a593Smuzhiyun
2783*4882a593Smuzhiyun if (read_expected(TEP_EVENT_DELIM, ")") < 0)
2784*4882a593Smuzhiyun goto out_free;
2785*4882a593Smuzhiyun
2786*4882a593Smuzhiyun free_token(token);
2787*4882a593Smuzhiyun type = read_token_item(&token);
2788*4882a593Smuzhiyun *tok = token;
2789*4882a593Smuzhiyun if (type != TEP_EVENT_OP || strcmp(token, "[") != 0)
2790*4882a593Smuzhiyun return type;
2791*4882a593Smuzhiyun
2792*4882a593Smuzhiyun free_token(token);
2793*4882a593Smuzhiyun arg = alloc_arg();
2794*4882a593Smuzhiyun if (!arg) {
2795*4882a593Smuzhiyun do_warning_event(event, "%s: not enough memory!", __func__);
2796*4882a593Smuzhiyun *tok = NULL;
2797*4882a593Smuzhiyun return TEP_EVENT_ERROR;
2798*4882a593Smuzhiyun }
2799*4882a593Smuzhiyun
2800*4882a593Smuzhiyun type = process_arg(event, arg, &token);
2801*4882a593Smuzhiyun if (type == TEP_EVENT_ERROR)
2802*4882a593Smuzhiyun goto out_free_arg;
2803*4882a593Smuzhiyun
2804*4882a593Smuzhiyun if (!test_type_token(type, token, TEP_EVENT_OP, "]"))
2805*4882a593Smuzhiyun goto out_free_arg;
2806*4882a593Smuzhiyun
2807*4882a593Smuzhiyun free_token(token);
2808*4882a593Smuzhiyun type = read_token_item(tok);
2809*4882a593Smuzhiyun return type;
2810*4882a593Smuzhiyun
2811*4882a593Smuzhiyun out_free_arg:
2812*4882a593Smuzhiyun free_arg(arg);
2813*4882a593Smuzhiyun out_free:
2814*4882a593Smuzhiyun free_token(token);
2815*4882a593Smuzhiyun *tok = NULL;
2816*4882a593Smuzhiyun return TEP_EVENT_ERROR;
2817*4882a593Smuzhiyun }
2818*4882a593Smuzhiyun
2819*4882a593Smuzhiyun static enum tep_event_type
process_dynamic_array_len(struct tep_event * event,struct tep_print_arg * arg,char ** tok)2820*4882a593Smuzhiyun process_dynamic_array_len(struct tep_event *event, struct tep_print_arg *arg,
2821*4882a593Smuzhiyun char **tok)
2822*4882a593Smuzhiyun {
2823*4882a593Smuzhiyun struct tep_format_field *field;
2824*4882a593Smuzhiyun enum tep_event_type type;
2825*4882a593Smuzhiyun char *token;
2826*4882a593Smuzhiyun
2827*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
2828*4882a593Smuzhiyun goto out_free;
2829*4882a593Smuzhiyun
2830*4882a593Smuzhiyun arg->type = TEP_PRINT_DYNAMIC_ARRAY_LEN;
2831*4882a593Smuzhiyun
2832*4882a593Smuzhiyun /* Find the field */
2833*4882a593Smuzhiyun field = tep_find_field(event, token);
2834*4882a593Smuzhiyun if (!field)
2835*4882a593Smuzhiyun goto out_free;
2836*4882a593Smuzhiyun
2837*4882a593Smuzhiyun arg->dynarray.field = field;
2838*4882a593Smuzhiyun arg->dynarray.index = 0;
2839*4882a593Smuzhiyun
2840*4882a593Smuzhiyun if (read_expected(TEP_EVENT_DELIM, ")") < 0)
2841*4882a593Smuzhiyun goto out_err;
2842*4882a593Smuzhiyun
2843*4882a593Smuzhiyun free_token(token);
2844*4882a593Smuzhiyun type = read_token(&token);
2845*4882a593Smuzhiyun *tok = token;
2846*4882a593Smuzhiyun
2847*4882a593Smuzhiyun return type;
2848*4882a593Smuzhiyun
2849*4882a593Smuzhiyun out_free:
2850*4882a593Smuzhiyun free_token(token);
2851*4882a593Smuzhiyun out_err:
2852*4882a593Smuzhiyun *tok = NULL;
2853*4882a593Smuzhiyun return TEP_EVENT_ERROR;
2854*4882a593Smuzhiyun }
2855*4882a593Smuzhiyun
2856*4882a593Smuzhiyun static enum tep_event_type
process_paren(struct tep_event * event,struct tep_print_arg * arg,char ** tok)2857*4882a593Smuzhiyun process_paren(struct tep_event *event, struct tep_print_arg *arg, char **tok)
2858*4882a593Smuzhiyun {
2859*4882a593Smuzhiyun struct tep_print_arg *item_arg;
2860*4882a593Smuzhiyun enum tep_event_type type;
2861*4882a593Smuzhiyun char *token;
2862*4882a593Smuzhiyun
2863*4882a593Smuzhiyun type = process_arg(event, arg, &token);
2864*4882a593Smuzhiyun
2865*4882a593Smuzhiyun if (type == TEP_EVENT_ERROR)
2866*4882a593Smuzhiyun goto out_free;
2867*4882a593Smuzhiyun
2868*4882a593Smuzhiyun if (type == TEP_EVENT_OP)
2869*4882a593Smuzhiyun type = process_op(event, arg, &token);
2870*4882a593Smuzhiyun
2871*4882a593Smuzhiyun if (type == TEP_EVENT_ERROR)
2872*4882a593Smuzhiyun goto out_free;
2873*4882a593Smuzhiyun
2874*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_DELIM, ")"))
2875*4882a593Smuzhiyun goto out_free;
2876*4882a593Smuzhiyun
2877*4882a593Smuzhiyun free_token(token);
2878*4882a593Smuzhiyun type = read_token_item(&token);
2879*4882a593Smuzhiyun
2880*4882a593Smuzhiyun /*
2881*4882a593Smuzhiyun * If the next token is an item or another open paren, then
2882*4882a593Smuzhiyun * this was a typecast.
2883*4882a593Smuzhiyun */
2884*4882a593Smuzhiyun if (event_item_type(type) ||
2885*4882a593Smuzhiyun (type == TEP_EVENT_DELIM && strcmp(token, "(") == 0)) {
2886*4882a593Smuzhiyun
2887*4882a593Smuzhiyun /* make this a typecast and contine */
2888*4882a593Smuzhiyun
2889*4882a593Smuzhiyun /* prevous must be an atom */
2890*4882a593Smuzhiyun if (arg->type != TEP_PRINT_ATOM) {
2891*4882a593Smuzhiyun do_warning_event(event, "previous needed to be TEP_PRINT_ATOM");
2892*4882a593Smuzhiyun goto out_free;
2893*4882a593Smuzhiyun }
2894*4882a593Smuzhiyun
2895*4882a593Smuzhiyun item_arg = alloc_arg();
2896*4882a593Smuzhiyun if (!item_arg) {
2897*4882a593Smuzhiyun do_warning_event(event, "%s: not enough memory!",
2898*4882a593Smuzhiyun __func__);
2899*4882a593Smuzhiyun goto out_free;
2900*4882a593Smuzhiyun }
2901*4882a593Smuzhiyun
2902*4882a593Smuzhiyun arg->type = TEP_PRINT_TYPE;
2903*4882a593Smuzhiyun arg->typecast.type = arg->atom.atom;
2904*4882a593Smuzhiyun arg->typecast.item = item_arg;
2905*4882a593Smuzhiyun type = process_arg_token(event, item_arg, &token, type);
2906*4882a593Smuzhiyun
2907*4882a593Smuzhiyun }
2908*4882a593Smuzhiyun
2909*4882a593Smuzhiyun *tok = token;
2910*4882a593Smuzhiyun return type;
2911*4882a593Smuzhiyun
2912*4882a593Smuzhiyun out_free:
2913*4882a593Smuzhiyun free_token(token);
2914*4882a593Smuzhiyun *tok = NULL;
2915*4882a593Smuzhiyun return TEP_EVENT_ERROR;
2916*4882a593Smuzhiyun }
2917*4882a593Smuzhiyun
2918*4882a593Smuzhiyun
2919*4882a593Smuzhiyun static enum tep_event_type
process_str(struct tep_event * event __maybe_unused,struct tep_print_arg * arg,char ** tok)2920*4882a593Smuzhiyun process_str(struct tep_event *event __maybe_unused, struct tep_print_arg *arg,
2921*4882a593Smuzhiyun char **tok)
2922*4882a593Smuzhiyun {
2923*4882a593Smuzhiyun enum tep_event_type type;
2924*4882a593Smuzhiyun char *token;
2925*4882a593Smuzhiyun
2926*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
2927*4882a593Smuzhiyun goto out_free;
2928*4882a593Smuzhiyun
2929*4882a593Smuzhiyun arg->type = TEP_PRINT_STRING;
2930*4882a593Smuzhiyun arg->string.string = token;
2931*4882a593Smuzhiyun arg->string.offset = -1;
2932*4882a593Smuzhiyun
2933*4882a593Smuzhiyun if (read_expected(TEP_EVENT_DELIM, ")") < 0)
2934*4882a593Smuzhiyun goto out_err;
2935*4882a593Smuzhiyun
2936*4882a593Smuzhiyun type = read_token(&token);
2937*4882a593Smuzhiyun *tok = token;
2938*4882a593Smuzhiyun
2939*4882a593Smuzhiyun return type;
2940*4882a593Smuzhiyun
2941*4882a593Smuzhiyun out_free:
2942*4882a593Smuzhiyun free_token(token);
2943*4882a593Smuzhiyun out_err:
2944*4882a593Smuzhiyun *tok = NULL;
2945*4882a593Smuzhiyun return TEP_EVENT_ERROR;
2946*4882a593Smuzhiyun }
2947*4882a593Smuzhiyun
2948*4882a593Smuzhiyun static enum tep_event_type
process_bitmask(struct tep_event * event __maybe_unused,struct tep_print_arg * arg,char ** tok)2949*4882a593Smuzhiyun process_bitmask(struct tep_event *event __maybe_unused, struct tep_print_arg *arg,
2950*4882a593Smuzhiyun char **tok)
2951*4882a593Smuzhiyun {
2952*4882a593Smuzhiyun enum tep_event_type type;
2953*4882a593Smuzhiyun char *token;
2954*4882a593Smuzhiyun
2955*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
2956*4882a593Smuzhiyun goto out_free;
2957*4882a593Smuzhiyun
2958*4882a593Smuzhiyun arg->type = TEP_PRINT_BITMASK;
2959*4882a593Smuzhiyun arg->bitmask.bitmask = token;
2960*4882a593Smuzhiyun arg->bitmask.offset = -1;
2961*4882a593Smuzhiyun
2962*4882a593Smuzhiyun if (read_expected(TEP_EVENT_DELIM, ")") < 0)
2963*4882a593Smuzhiyun goto out_err;
2964*4882a593Smuzhiyun
2965*4882a593Smuzhiyun type = read_token(&token);
2966*4882a593Smuzhiyun *tok = token;
2967*4882a593Smuzhiyun
2968*4882a593Smuzhiyun return type;
2969*4882a593Smuzhiyun
2970*4882a593Smuzhiyun out_free:
2971*4882a593Smuzhiyun free_token(token);
2972*4882a593Smuzhiyun out_err:
2973*4882a593Smuzhiyun *tok = NULL;
2974*4882a593Smuzhiyun return TEP_EVENT_ERROR;
2975*4882a593Smuzhiyun }
2976*4882a593Smuzhiyun
2977*4882a593Smuzhiyun static struct tep_function_handler *
find_func_handler(struct tep_handle * tep,char * func_name)2978*4882a593Smuzhiyun find_func_handler(struct tep_handle *tep, char *func_name)
2979*4882a593Smuzhiyun {
2980*4882a593Smuzhiyun struct tep_function_handler *func;
2981*4882a593Smuzhiyun
2982*4882a593Smuzhiyun if (!tep)
2983*4882a593Smuzhiyun return NULL;
2984*4882a593Smuzhiyun
2985*4882a593Smuzhiyun for (func = tep->func_handlers; func; func = func->next) {
2986*4882a593Smuzhiyun if (strcmp(func->name, func_name) == 0)
2987*4882a593Smuzhiyun break;
2988*4882a593Smuzhiyun }
2989*4882a593Smuzhiyun
2990*4882a593Smuzhiyun return func;
2991*4882a593Smuzhiyun }
2992*4882a593Smuzhiyun
remove_func_handler(struct tep_handle * tep,char * func_name)2993*4882a593Smuzhiyun static void remove_func_handler(struct tep_handle *tep, char *func_name)
2994*4882a593Smuzhiyun {
2995*4882a593Smuzhiyun struct tep_function_handler *func;
2996*4882a593Smuzhiyun struct tep_function_handler **next;
2997*4882a593Smuzhiyun
2998*4882a593Smuzhiyun next = &tep->func_handlers;
2999*4882a593Smuzhiyun while ((func = *next)) {
3000*4882a593Smuzhiyun if (strcmp(func->name, func_name) == 0) {
3001*4882a593Smuzhiyun *next = func->next;
3002*4882a593Smuzhiyun free_func_handle(func);
3003*4882a593Smuzhiyun break;
3004*4882a593Smuzhiyun }
3005*4882a593Smuzhiyun next = &func->next;
3006*4882a593Smuzhiyun }
3007*4882a593Smuzhiyun }
3008*4882a593Smuzhiyun
3009*4882a593Smuzhiyun static enum tep_event_type
process_func_handler(struct tep_event * event,struct tep_function_handler * func,struct tep_print_arg * arg,char ** tok)3010*4882a593Smuzhiyun process_func_handler(struct tep_event *event, struct tep_function_handler *func,
3011*4882a593Smuzhiyun struct tep_print_arg *arg, char **tok)
3012*4882a593Smuzhiyun {
3013*4882a593Smuzhiyun struct tep_print_arg **next_arg;
3014*4882a593Smuzhiyun struct tep_print_arg *farg;
3015*4882a593Smuzhiyun enum tep_event_type type;
3016*4882a593Smuzhiyun char *token;
3017*4882a593Smuzhiyun int i;
3018*4882a593Smuzhiyun
3019*4882a593Smuzhiyun arg->type = TEP_PRINT_FUNC;
3020*4882a593Smuzhiyun arg->func.func = func;
3021*4882a593Smuzhiyun
3022*4882a593Smuzhiyun *tok = NULL;
3023*4882a593Smuzhiyun
3024*4882a593Smuzhiyun next_arg = &(arg->func.args);
3025*4882a593Smuzhiyun for (i = 0; i < func->nr_args; i++) {
3026*4882a593Smuzhiyun farg = alloc_arg();
3027*4882a593Smuzhiyun if (!farg) {
3028*4882a593Smuzhiyun do_warning_event(event, "%s: not enough memory!",
3029*4882a593Smuzhiyun __func__);
3030*4882a593Smuzhiyun return TEP_EVENT_ERROR;
3031*4882a593Smuzhiyun }
3032*4882a593Smuzhiyun
3033*4882a593Smuzhiyun type = process_arg(event, farg, &token);
3034*4882a593Smuzhiyun if (i < (func->nr_args - 1)) {
3035*4882a593Smuzhiyun if (type != TEP_EVENT_DELIM || strcmp(token, ",") != 0) {
3036*4882a593Smuzhiyun do_warning_event(event,
3037*4882a593Smuzhiyun "Error: function '%s()' expects %d arguments but event %s only uses %d",
3038*4882a593Smuzhiyun func->name, func->nr_args,
3039*4882a593Smuzhiyun event->name, i + 1);
3040*4882a593Smuzhiyun goto err;
3041*4882a593Smuzhiyun }
3042*4882a593Smuzhiyun } else {
3043*4882a593Smuzhiyun if (type != TEP_EVENT_DELIM || strcmp(token, ")") != 0) {
3044*4882a593Smuzhiyun do_warning_event(event,
3045*4882a593Smuzhiyun "Error: function '%s()' only expects %d arguments but event %s has more",
3046*4882a593Smuzhiyun func->name, func->nr_args, event->name);
3047*4882a593Smuzhiyun goto err;
3048*4882a593Smuzhiyun }
3049*4882a593Smuzhiyun }
3050*4882a593Smuzhiyun
3051*4882a593Smuzhiyun *next_arg = farg;
3052*4882a593Smuzhiyun next_arg = &(farg->next);
3053*4882a593Smuzhiyun free_token(token);
3054*4882a593Smuzhiyun }
3055*4882a593Smuzhiyun
3056*4882a593Smuzhiyun type = read_token(&token);
3057*4882a593Smuzhiyun *tok = token;
3058*4882a593Smuzhiyun
3059*4882a593Smuzhiyun return type;
3060*4882a593Smuzhiyun
3061*4882a593Smuzhiyun err:
3062*4882a593Smuzhiyun free_arg(farg);
3063*4882a593Smuzhiyun free_token(token);
3064*4882a593Smuzhiyun return TEP_EVENT_ERROR;
3065*4882a593Smuzhiyun }
3066*4882a593Smuzhiyun
3067*4882a593Smuzhiyun static enum tep_event_type
process_builtin_expect(struct tep_event * event,struct tep_print_arg * arg,char ** tok)3068*4882a593Smuzhiyun process_builtin_expect(struct tep_event *event, struct tep_print_arg *arg, char **tok)
3069*4882a593Smuzhiyun {
3070*4882a593Smuzhiyun enum tep_event_type type;
3071*4882a593Smuzhiyun char *token = NULL;
3072*4882a593Smuzhiyun
3073*4882a593Smuzhiyun /* Handle __builtin_expect( cond, #) */
3074*4882a593Smuzhiyun type = process_arg(event, arg, &token);
3075*4882a593Smuzhiyun
3076*4882a593Smuzhiyun if (type != TEP_EVENT_DELIM || token[0] != ',')
3077*4882a593Smuzhiyun goto out_free;
3078*4882a593Smuzhiyun
3079*4882a593Smuzhiyun free_token(token);
3080*4882a593Smuzhiyun
3081*4882a593Smuzhiyun /* We don't care what the second parameter is of the __builtin_expect() */
3082*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
3083*4882a593Smuzhiyun goto out_free;
3084*4882a593Smuzhiyun
3085*4882a593Smuzhiyun if (read_expected(TEP_EVENT_DELIM, ")") < 0)
3086*4882a593Smuzhiyun goto out_free;
3087*4882a593Smuzhiyun
3088*4882a593Smuzhiyun free_token(token);
3089*4882a593Smuzhiyun type = read_token_item(tok);
3090*4882a593Smuzhiyun return type;
3091*4882a593Smuzhiyun
3092*4882a593Smuzhiyun out_free:
3093*4882a593Smuzhiyun free_token(token);
3094*4882a593Smuzhiyun *tok = NULL;
3095*4882a593Smuzhiyun return TEP_EVENT_ERROR;
3096*4882a593Smuzhiyun }
3097*4882a593Smuzhiyun
3098*4882a593Smuzhiyun static enum tep_event_type
process_function(struct tep_event * event,struct tep_print_arg * arg,char * token,char ** tok)3099*4882a593Smuzhiyun process_function(struct tep_event *event, struct tep_print_arg *arg,
3100*4882a593Smuzhiyun char *token, char **tok)
3101*4882a593Smuzhiyun {
3102*4882a593Smuzhiyun struct tep_function_handler *func;
3103*4882a593Smuzhiyun
3104*4882a593Smuzhiyun if (strcmp(token, "__print_flags") == 0) {
3105*4882a593Smuzhiyun free_token(token);
3106*4882a593Smuzhiyun is_flag_field = 1;
3107*4882a593Smuzhiyun return process_flags(event, arg, tok);
3108*4882a593Smuzhiyun }
3109*4882a593Smuzhiyun if (strcmp(token, "__print_symbolic") == 0) {
3110*4882a593Smuzhiyun free_token(token);
3111*4882a593Smuzhiyun is_symbolic_field = 1;
3112*4882a593Smuzhiyun return process_symbols(event, arg, tok);
3113*4882a593Smuzhiyun }
3114*4882a593Smuzhiyun if (strcmp(token, "__print_hex") == 0) {
3115*4882a593Smuzhiyun free_token(token);
3116*4882a593Smuzhiyun return process_hex(event, arg, tok);
3117*4882a593Smuzhiyun }
3118*4882a593Smuzhiyun if (strcmp(token, "__print_hex_str") == 0) {
3119*4882a593Smuzhiyun free_token(token);
3120*4882a593Smuzhiyun return process_hex_str(event, arg, tok);
3121*4882a593Smuzhiyun }
3122*4882a593Smuzhiyun if (strcmp(token, "__print_array") == 0) {
3123*4882a593Smuzhiyun free_token(token);
3124*4882a593Smuzhiyun return process_int_array(event, arg, tok);
3125*4882a593Smuzhiyun }
3126*4882a593Smuzhiyun if (strcmp(token, "__get_str") == 0) {
3127*4882a593Smuzhiyun free_token(token);
3128*4882a593Smuzhiyun return process_str(event, arg, tok);
3129*4882a593Smuzhiyun }
3130*4882a593Smuzhiyun if (strcmp(token, "__get_bitmask") == 0) {
3131*4882a593Smuzhiyun free_token(token);
3132*4882a593Smuzhiyun return process_bitmask(event, arg, tok);
3133*4882a593Smuzhiyun }
3134*4882a593Smuzhiyun if (strcmp(token, "__get_dynamic_array") == 0) {
3135*4882a593Smuzhiyun free_token(token);
3136*4882a593Smuzhiyun return process_dynamic_array(event, arg, tok);
3137*4882a593Smuzhiyun }
3138*4882a593Smuzhiyun if (strcmp(token, "__get_dynamic_array_len") == 0) {
3139*4882a593Smuzhiyun free_token(token);
3140*4882a593Smuzhiyun return process_dynamic_array_len(event, arg, tok);
3141*4882a593Smuzhiyun }
3142*4882a593Smuzhiyun if (strcmp(token, "__builtin_expect") == 0) {
3143*4882a593Smuzhiyun free_token(token);
3144*4882a593Smuzhiyun return process_builtin_expect(event, arg, tok);
3145*4882a593Smuzhiyun }
3146*4882a593Smuzhiyun
3147*4882a593Smuzhiyun func = find_func_handler(event->tep, token);
3148*4882a593Smuzhiyun if (func) {
3149*4882a593Smuzhiyun free_token(token);
3150*4882a593Smuzhiyun return process_func_handler(event, func, arg, tok);
3151*4882a593Smuzhiyun }
3152*4882a593Smuzhiyun
3153*4882a593Smuzhiyun do_warning_event(event, "function %s not defined", token);
3154*4882a593Smuzhiyun free_token(token);
3155*4882a593Smuzhiyun return TEP_EVENT_ERROR;
3156*4882a593Smuzhiyun }
3157*4882a593Smuzhiyun
3158*4882a593Smuzhiyun static enum tep_event_type
process_arg_token(struct tep_event * event,struct tep_print_arg * arg,char ** tok,enum tep_event_type type)3159*4882a593Smuzhiyun process_arg_token(struct tep_event *event, struct tep_print_arg *arg,
3160*4882a593Smuzhiyun char **tok, enum tep_event_type type)
3161*4882a593Smuzhiyun {
3162*4882a593Smuzhiyun char *token;
3163*4882a593Smuzhiyun char *atom;
3164*4882a593Smuzhiyun
3165*4882a593Smuzhiyun token = *tok;
3166*4882a593Smuzhiyun
3167*4882a593Smuzhiyun switch (type) {
3168*4882a593Smuzhiyun case TEP_EVENT_ITEM:
3169*4882a593Smuzhiyun if (strcmp(token, "REC") == 0) {
3170*4882a593Smuzhiyun free_token(token);
3171*4882a593Smuzhiyun type = process_entry(event, arg, &token);
3172*4882a593Smuzhiyun break;
3173*4882a593Smuzhiyun }
3174*4882a593Smuzhiyun atom = token;
3175*4882a593Smuzhiyun /* test the next token */
3176*4882a593Smuzhiyun type = read_token_item(&token);
3177*4882a593Smuzhiyun
3178*4882a593Smuzhiyun /*
3179*4882a593Smuzhiyun * If the next token is a parenthesis, then this
3180*4882a593Smuzhiyun * is a function.
3181*4882a593Smuzhiyun */
3182*4882a593Smuzhiyun if (type == TEP_EVENT_DELIM && strcmp(token, "(") == 0) {
3183*4882a593Smuzhiyun free_token(token);
3184*4882a593Smuzhiyun token = NULL;
3185*4882a593Smuzhiyun /* this will free atom. */
3186*4882a593Smuzhiyun type = process_function(event, arg, atom, &token);
3187*4882a593Smuzhiyun break;
3188*4882a593Smuzhiyun }
3189*4882a593Smuzhiyun /* atoms can be more than one token long */
3190*4882a593Smuzhiyun while (type == TEP_EVENT_ITEM) {
3191*4882a593Smuzhiyun int ret;
3192*4882a593Smuzhiyun
3193*4882a593Smuzhiyun ret = append(&atom, " ", token);
3194*4882a593Smuzhiyun if (ret < 0) {
3195*4882a593Smuzhiyun free(atom);
3196*4882a593Smuzhiyun *tok = NULL;
3197*4882a593Smuzhiyun free_token(token);
3198*4882a593Smuzhiyun return TEP_EVENT_ERROR;
3199*4882a593Smuzhiyun }
3200*4882a593Smuzhiyun free_token(token);
3201*4882a593Smuzhiyun type = read_token_item(&token);
3202*4882a593Smuzhiyun }
3203*4882a593Smuzhiyun
3204*4882a593Smuzhiyun arg->type = TEP_PRINT_ATOM;
3205*4882a593Smuzhiyun arg->atom.atom = atom;
3206*4882a593Smuzhiyun break;
3207*4882a593Smuzhiyun
3208*4882a593Smuzhiyun case TEP_EVENT_DQUOTE:
3209*4882a593Smuzhiyun case TEP_EVENT_SQUOTE:
3210*4882a593Smuzhiyun arg->type = TEP_PRINT_ATOM;
3211*4882a593Smuzhiyun arg->atom.atom = token;
3212*4882a593Smuzhiyun type = read_token_item(&token);
3213*4882a593Smuzhiyun break;
3214*4882a593Smuzhiyun case TEP_EVENT_DELIM:
3215*4882a593Smuzhiyun if (strcmp(token, "(") == 0) {
3216*4882a593Smuzhiyun free_token(token);
3217*4882a593Smuzhiyun type = process_paren(event, arg, &token);
3218*4882a593Smuzhiyun break;
3219*4882a593Smuzhiyun }
3220*4882a593Smuzhiyun case TEP_EVENT_OP:
3221*4882a593Smuzhiyun /* handle single ops */
3222*4882a593Smuzhiyun arg->type = TEP_PRINT_OP;
3223*4882a593Smuzhiyun arg->op.op = token;
3224*4882a593Smuzhiyun arg->op.left = NULL;
3225*4882a593Smuzhiyun type = process_op(event, arg, &token);
3226*4882a593Smuzhiyun
3227*4882a593Smuzhiyun /* On error, the op is freed */
3228*4882a593Smuzhiyun if (type == TEP_EVENT_ERROR)
3229*4882a593Smuzhiyun arg->op.op = NULL;
3230*4882a593Smuzhiyun
3231*4882a593Smuzhiyun /* return error type if errored */
3232*4882a593Smuzhiyun break;
3233*4882a593Smuzhiyun
3234*4882a593Smuzhiyun case TEP_EVENT_ERROR ... TEP_EVENT_NEWLINE:
3235*4882a593Smuzhiyun default:
3236*4882a593Smuzhiyun do_warning_event(event, "unexpected type %d", type);
3237*4882a593Smuzhiyun return TEP_EVENT_ERROR;
3238*4882a593Smuzhiyun }
3239*4882a593Smuzhiyun *tok = token;
3240*4882a593Smuzhiyun
3241*4882a593Smuzhiyun return type;
3242*4882a593Smuzhiyun }
3243*4882a593Smuzhiyun
event_read_print_args(struct tep_event * event,struct tep_print_arg ** list)3244*4882a593Smuzhiyun static int event_read_print_args(struct tep_event *event, struct tep_print_arg **list)
3245*4882a593Smuzhiyun {
3246*4882a593Smuzhiyun enum tep_event_type type = TEP_EVENT_ERROR;
3247*4882a593Smuzhiyun struct tep_print_arg *arg;
3248*4882a593Smuzhiyun char *token;
3249*4882a593Smuzhiyun int args = 0;
3250*4882a593Smuzhiyun
3251*4882a593Smuzhiyun do {
3252*4882a593Smuzhiyun if (type == TEP_EVENT_NEWLINE) {
3253*4882a593Smuzhiyun type = read_token_item(&token);
3254*4882a593Smuzhiyun continue;
3255*4882a593Smuzhiyun }
3256*4882a593Smuzhiyun
3257*4882a593Smuzhiyun arg = alloc_arg();
3258*4882a593Smuzhiyun if (!arg) {
3259*4882a593Smuzhiyun do_warning_event(event, "%s: not enough memory!",
3260*4882a593Smuzhiyun __func__);
3261*4882a593Smuzhiyun return -1;
3262*4882a593Smuzhiyun }
3263*4882a593Smuzhiyun
3264*4882a593Smuzhiyun type = process_arg(event, arg, &token);
3265*4882a593Smuzhiyun
3266*4882a593Smuzhiyun if (type == TEP_EVENT_ERROR) {
3267*4882a593Smuzhiyun free_token(token);
3268*4882a593Smuzhiyun free_arg(arg);
3269*4882a593Smuzhiyun return -1;
3270*4882a593Smuzhiyun }
3271*4882a593Smuzhiyun
3272*4882a593Smuzhiyun *list = arg;
3273*4882a593Smuzhiyun args++;
3274*4882a593Smuzhiyun
3275*4882a593Smuzhiyun if (type == TEP_EVENT_OP) {
3276*4882a593Smuzhiyun type = process_op(event, arg, &token);
3277*4882a593Smuzhiyun free_token(token);
3278*4882a593Smuzhiyun if (type == TEP_EVENT_ERROR) {
3279*4882a593Smuzhiyun *list = NULL;
3280*4882a593Smuzhiyun free_arg(arg);
3281*4882a593Smuzhiyun return -1;
3282*4882a593Smuzhiyun }
3283*4882a593Smuzhiyun list = &arg->next;
3284*4882a593Smuzhiyun continue;
3285*4882a593Smuzhiyun }
3286*4882a593Smuzhiyun
3287*4882a593Smuzhiyun if (type == TEP_EVENT_DELIM && strcmp(token, ",") == 0) {
3288*4882a593Smuzhiyun free_token(token);
3289*4882a593Smuzhiyun *list = arg;
3290*4882a593Smuzhiyun list = &arg->next;
3291*4882a593Smuzhiyun continue;
3292*4882a593Smuzhiyun }
3293*4882a593Smuzhiyun break;
3294*4882a593Smuzhiyun } while (type != TEP_EVENT_NONE);
3295*4882a593Smuzhiyun
3296*4882a593Smuzhiyun if (type != TEP_EVENT_NONE && type != TEP_EVENT_ERROR)
3297*4882a593Smuzhiyun free_token(token);
3298*4882a593Smuzhiyun
3299*4882a593Smuzhiyun return args;
3300*4882a593Smuzhiyun }
3301*4882a593Smuzhiyun
event_read_print(struct tep_event * event)3302*4882a593Smuzhiyun static int event_read_print(struct tep_event *event)
3303*4882a593Smuzhiyun {
3304*4882a593Smuzhiyun enum tep_event_type type;
3305*4882a593Smuzhiyun char *token;
3306*4882a593Smuzhiyun int ret;
3307*4882a593Smuzhiyun
3308*4882a593Smuzhiyun if (read_expected_item(TEP_EVENT_ITEM, "print") < 0)
3309*4882a593Smuzhiyun return -1;
3310*4882a593Smuzhiyun
3311*4882a593Smuzhiyun if (read_expected(TEP_EVENT_ITEM, "fmt") < 0)
3312*4882a593Smuzhiyun return -1;
3313*4882a593Smuzhiyun
3314*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ":") < 0)
3315*4882a593Smuzhiyun return -1;
3316*4882a593Smuzhiyun
3317*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_DQUOTE, &token) < 0)
3318*4882a593Smuzhiyun goto fail;
3319*4882a593Smuzhiyun
3320*4882a593Smuzhiyun concat:
3321*4882a593Smuzhiyun event->print_fmt.format = token;
3322*4882a593Smuzhiyun event->print_fmt.args = NULL;
3323*4882a593Smuzhiyun
3324*4882a593Smuzhiyun /* ok to have no arg */
3325*4882a593Smuzhiyun type = read_token_item(&token);
3326*4882a593Smuzhiyun
3327*4882a593Smuzhiyun if (type == TEP_EVENT_NONE)
3328*4882a593Smuzhiyun return 0;
3329*4882a593Smuzhiyun
3330*4882a593Smuzhiyun /* Handle concatenation of print lines */
3331*4882a593Smuzhiyun if (type == TEP_EVENT_DQUOTE) {
3332*4882a593Smuzhiyun char *cat;
3333*4882a593Smuzhiyun
3334*4882a593Smuzhiyun if (asprintf(&cat, "%s%s", event->print_fmt.format, token) < 0)
3335*4882a593Smuzhiyun goto fail;
3336*4882a593Smuzhiyun free_token(token);
3337*4882a593Smuzhiyun free_token(event->print_fmt.format);
3338*4882a593Smuzhiyun event->print_fmt.format = NULL;
3339*4882a593Smuzhiyun token = cat;
3340*4882a593Smuzhiyun goto concat;
3341*4882a593Smuzhiyun }
3342*4882a593Smuzhiyun
3343*4882a593Smuzhiyun if (test_type_token(type, token, TEP_EVENT_DELIM, ","))
3344*4882a593Smuzhiyun goto fail;
3345*4882a593Smuzhiyun
3346*4882a593Smuzhiyun free_token(token);
3347*4882a593Smuzhiyun
3348*4882a593Smuzhiyun ret = event_read_print_args(event, &event->print_fmt.args);
3349*4882a593Smuzhiyun if (ret < 0)
3350*4882a593Smuzhiyun return -1;
3351*4882a593Smuzhiyun
3352*4882a593Smuzhiyun return ret;
3353*4882a593Smuzhiyun
3354*4882a593Smuzhiyun fail:
3355*4882a593Smuzhiyun free_token(token);
3356*4882a593Smuzhiyun return -1;
3357*4882a593Smuzhiyun }
3358*4882a593Smuzhiyun
3359*4882a593Smuzhiyun /**
3360*4882a593Smuzhiyun * tep_find_common_field - return a common field by event
3361*4882a593Smuzhiyun * @event: handle for the event
3362*4882a593Smuzhiyun * @name: the name of the common field to return
3363*4882a593Smuzhiyun *
3364*4882a593Smuzhiyun * Returns a common field from the event by the given @name.
3365*4882a593Smuzhiyun * This only searches the common fields and not all field.
3366*4882a593Smuzhiyun */
3367*4882a593Smuzhiyun struct tep_format_field *
tep_find_common_field(struct tep_event * event,const char * name)3368*4882a593Smuzhiyun tep_find_common_field(struct tep_event *event, const char *name)
3369*4882a593Smuzhiyun {
3370*4882a593Smuzhiyun struct tep_format_field *format;
3371*4882a593Smuzhiyun
3372*4882a593Smuzhiyun for (format = event->format.common_fields;
3373*4882a593Smuzhiyun format; format = format->next) {
3374*4882a593Smuzhiyun if (strcmp(format->name, name) == 0)
3375*4882a593Smuzhiyun break;
3376*4882a593Smuzhiyun }
3377*4882a593Smuzhiyun
3378*4882a593Smuzhiyun return format;
3379*4882a593Smuzhiyun }
3380*4882a593Smuzhiyun
3381*4882a593Smuzhiyun /**
3382*4882a593Smuzhiyun * tep_find_field - find a non-common field
3383*4882a593Smuzhiyun * @event: handle for the event
3384*4882a593Smuzhiyun * @name: the name of the non-common field
3385*4882a593Smuzhiyun *
3386*4882a593Smuzhiyun * Returns a non-common field by the given @name.
3387*4882a593Smuzhiyun * This does not search common fields.
3388*4882a593Smuzhiyun */
3389*4882a593Smuzhiyun struct tep_format_field *
tep_find_field(struct tep_event * event,const char * name)3390*4882a593Smuzhiyun tep_find_field(struct tep_event *event, const char *name)
3391*4882a593Smuzhiyun {
3392*4882a593Smuzhiyun struct tep_format_field *format;
3393*4882a593Smuzhiyun
3394*4882a593Smuzhiyun for (format = event->format.fields;
3395*4882a593Smuzhiyun format; format = format->next) {
3396*4882a593Smuzhiyun if (strcmp(format->name, name) == 0)
3397*4882a593Smuzhiyun break;
3398*4882a593Smuzhiyun }
3399*4882a593Smuzhiyun
3400*4882a593Smuzhiyun return format;
3401*4882a593Smuzhiyun }
3402*4882a593Smuzhiyun
3403*4882a593Smuzhiyun /**
3404*4882a593Smuzhiyun * tep_find_any_field - find any field by name
3405*4882a593Smuzhiyun * @event: handle for the event
3406*4882a593Smuzhiyun * @name: the name of the field
3407*4882a593Smuzhiyun *
3408*4882a593Smuzhiyun * Returns a field by the given @name.
3409*4882a593Smuzhiyun * This searches the common field names first, then
3410*4882a593Smuzhiyun * the non-common ones if a common one was not found.
3411*4882a593Smuzhiyun */
3412*4882a593Smuzhiyun struct tep_format_field *
tep_find_any_field(struct tep_event * event,const char * name)3413*4882a593Smuzhiyun tep_find_any_field(struct tep_event *event, const char *name)
3414*4882a593Smuzhiyun {
3415*4882a593Smuzhiyun struct tep_format_field *format;
3416*4882a593Smuzhiyun
3417*4882a593Smuzhiyun format = tep_find_common_field(event, name);
3418*4882a593Smuzhiyun if (format)
3419*4882a593Smuzhiyun return format;
3420*4882a593Smuzhiyun return tep_find_field(event, name);
3421*4882a593Smuzhiyun }
3422*4882a593Smuzhiyun
3423*4882a593Smuzhiyun /**
3424*4882a593Smuzhiyun * tep_read_number - read a number from data
3425*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
3426*4882a593Smuzhiyun * @ptr: the raw data
3427*4882a593Smuzhiyun * @size: the size of the data that holds the number
3428*4882a593Smuzhiyun *
3429*4882a593Smuzhiyun * Returns the number (converted to host) from the
3430*4882a593Smuzhiyun * raw data.
3431*4882a593Smuzhiyun */
tep_read_number(struct tep_handle * tep,const void * ptr,int size)3432*4882a593Smuzhiyun unsigned long long tep_read_number(struct tep_handle *tep,
3433*4882a593Smuzhiyun const void *ptr, int size)
3434*4882a593Smuzhiyun {
3435*4882a593Smuzhiyun unsigned long long val;
3436*4882a593Smuzhiyun
3437*4882a593Smuzhiyun switch (size) {
3438*4882a593Smuzhiyun case 1:
3439*4882a593Smuzhiyun return *(unsigned char *)ptr;
3440*4882a593Smuzhiyun case 2:
3441*4882a593Smuzhiyun return data2host2(tep, *(unsigned short *)ptr);
3442*4882a593Smuzhiyun case 4:
3443*4882a593Smuzhiyun return data2host4(tep, *(unsigned int *)ptr);
3444*4882a593Smuzhiyun case 8:
3445*4882a593Smuzhiyun memcpy(&val, (ptr), sizeof(unsigned long long));
3446*4882a593Smuzhiyun return data2host8(tep, val);
3447*4882a593Smuzhiyun default:
3448*4882a593Smuzhiyun /* BUG! */
3449*4882a593Smuzhiyun return 0;
3450*4882a593Smuzhiyun }
3451*4882a593Smuzhiyun }
3452*4882a593Smuzhiyun
3453*4882a593Smuzhiyun /**
3454*4882a593Smuzhiyun * tep_read_number_field - read a number from data
3455*4882a593Smuzhiyun * @field: a handle to the field
3456*4882a593Smuzhiyun * @data: the raw data to read
3457*4882a593Smuzhiyun * @value: the value to place the number in
3458*4882a593Smuzhiyun *
3459*4882a593Smuzhiyun * Reads raw data according to a field offset and size,
3460*4882a593Smuzhiyun * and translates it into @value.
3461*4882a593Smuzhiyun *
3462*4882a593Smuzhiyun * Returns 0 on success, -1 otherwise.
3463*4882a593Smuzhiyun */
tep_read_number_field(struct tep_format_field * field,const void * data,unsigned long long * value)3464*4882a593Smuzhiyun int tep_read_number_field(struct tep_format_field *field, const void *data,
3465*4882a593Smuzhiyun unsigned long long *value)
3466*4882a593Smuzhiyun {
3467*4882a593Smuzhiyun if (!field)
3468*4882a593Smuzhiyun return -1;
3469*4882a593Smuzhiyun switch (field->size) {
3470*4882a593Smuzhiyun case 1:
3471*4882a593Smuzhiyun case 2:
3472*4882a593Smuzhiyun case 4:
3473*4882a593Smuzhiyun case 8:
3474*4882a593Smuzhiyun *value = tep_read_number(field->event->tep,
3475*4882a593Smuzhiyun data + field->offset, field->size);
3476*4882a593Smuzhiyun return 0;
3477*4882a593Smuzhiyun default:
3478*4882a593Smuzhiyun return -1;
3479*4882a593Smuzhiyun }
3480*4882a593Smuzhiyun }
3481*4882a593Smuzhiyun
get_common_info(struct tep_handle * tep,const char * type,int * offset,int * size)3482*4882a593Smuzhiyun static int get_common_info(struct tep_handle *tep,
3483*4882a593Smuzhiyun const char *type, int *offset, int *size)
3484*4882a593Smuzhiyun {
3485*4882a593Smuzhiyun struct tep_event *event;
3486*4882a593Smuzhiyun struct tep_format_field *field;
3487*4882a593Smuzhiyun
3488*4882a593Smuzhiyun /*
3489*4882a593Smuzhiyun * All events should have the same common elements.
3490*4882a593Smuzhiyun * Pick any event to find where the type is;
3491*4882a593Smuzhiyun */
3492*4882a593Smuzhiyun if (!tep->events) {
3493*4882a593Smuzhiyun do_warning("no event_list!");
3494*4882a593Smuzhiyun return -1;
3495*4882a593Smuzhiyun }
3496*4882a593Smuzhiyun
3497*4882a593Smuzhiyun event = tep->events[0];
3498*4882a593Smuzhiyun field = tep_find_common_field(event, type);
3499*4882a593Smuzhiyun if (!field)
3500*4882a593Smuzhiyun return -1;
3501*4882a593Smuzhiyun
3502*4882a593Smuzhiyun *offset = field->offset;
3503*4882a593Smuzhiyun *size = field->size;
3504*4882a593Smuzhiyun
3505*4882a593Smuzhiyun return 0;
3506*4882a593Smuzhiyun }
3507*4882a593Smuzhiyun
__parse_common(struct tep_handle * tep,void * data,int * size,int * offset,const char * name)3508*4882a593Smuzhiyun static int __parse_common(struct tep_handle *tep, void *data,
3509*4882a593Smuzhiyun int *size, int *offset, const char *name)
3510*4882a593Smuzhiyun {
3511*4882a593Smuzhiyun int ret;
3512*4882a593Smuzhiyun
3513*4882a593Smuzhiyun if (!*size) {
3514*4882a593Smuzhiyun ret = get_common_info(tep, name, offset, size);
3515*4882a593Smuzhiyun if (ret < 0)
3516*4882a593Smuzhiyun return ret;
3517*4882a593Smuzhiyun }
3518*4882a593Smuzhiyun return tep_read_number(tep, data + *offset, *size);
3519*4882a593Smuzhiyun }
3520*4882a593Smuzhiyun
trace_parse_common_type(struct tep_handle * tep,void * data)3521*4882a593Smuzhiyun static int trace_parse_common_type(struct tep_handle *tep, void *data)
3522*4882a593Smuzhiyun {
3523*4882a593Smuzhiyun return __parse_common(tep, data,
3524*4882a593Smuzhiyun &tep->type_size, &tep->type_offset,
3525*4882a593Smuzhiyun "common_type");
3526*4882a593Smuzhiyun }
3527*4882a593Smuzhiyun
parse_common_pid(struct tep_handle * tep,void * data)3528*4882a593Smuzhiyun static int parse_common_pid(struct tep_handle *tep, void *data)
3529*4882a593Smuzhiyun {
3530*4882a593Smuzhiyun return __parse_common(tep, data,
3531*4882a593Smuzhiyun &tep->pid_size, &tep->pid_offset,
3532*4882a593Smuzhiyun "common_pid");
3533*4882a593Smuzhiyun }
3534*4882a593Smuzhiyun
parse_common_pc(struct tep_handle * tep,void * data)3535*4882a593Smuzhiyun static int parse_common_pc(struct tep_handle *tep, void *data)
3536*4882a593Smuzhiyun {
3537*4882a593Smuzhiyun return __parse_common(tep, data,
3538*4882a593Smuzhiyun &tep->pc_size, &tep->pc_offset,
3539*4882a593Smuzhiyun "common_preempt_count");
3540*4882a593Smuzhiyun }
3541*4882a593Smuzhiyun
parse_common_flags(struct tep_handle * tep,void * data)3542*4882a593Smuzhiyun static int parse_common_flags(struct tep_handle *tep, void *data)
3543*4882a593Smuzhiyun {
3544*4882a593Smuzhiyun return __parse_common(tep, data,
3545*4882a593Smuzhiyun &tep->flags_size, &tep->flags_offset,
3546*4882a593Smuzhiyun "common_flags");
3547*4882a593Smuzhiyun }
3548*4882a593Smuzhiyun
parse_common_lock_depth(struct tep_handle * tep,void * data)3549*4882a593Smuzhiyun static int parse_common_lock_depth(struct tep_handle *tep, void *data)
3550*4882a593Smuzhiyun {
3551*4882a593Smuzhiyun return __parse_common(tep, data,
3552*4882a593Smuzhiyun &tep->ld_size, &tep->ld_offset,
3553*4882a593Smuzhiyun "common_lock_depth");
3554*4882a593Smuzhiyun }
3555*4882a593Smuzhiyun
parse_common_migrate_disable(struct tep_handle * tep,void * data)3556*4882a593Smuzhiyun static int parse_common_migrate_disable(struct tep_handle *tep, void *data)
3557*4882a593Smuzhiyun {
3558*4882a593Smuzhiyun return __parse_common(tep, data,
3559*4882a593Smuzhiyun &tep->ld_size, &tep->ld_offset,
3560*4882a593Smuzhiyun "common_migrate_disable");
3561*4882a593Smuzhiyun }
3562*4882a593Smuzhiyun
3563*4882a593Smuzhiyun static int events_id_cmp(const void *a, const void *b);
3564*4882a593Smuzhiyun
3565*4882a593Smuzhiyun /**
3566*4882a593Smuzhiyun * tep_find_event - find an event by given id
3567*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
3568*4882a593Smuzhiyun * @id: the id of the event
3569*4882a593Smuzhiyun *
3570*4882a593Smuzhiyun * Returns an event that has a given @id.
3571*4882a593Smuzhiyun */
tep_find_event(struct tep_handle * tep,int id)3572*4882a593Smuzhiyun struct tep_event *tep_find_event(struct tep_handle *tep, int id)
3573*4882a593Smuzhiyun {
3574*4882a593Smuzhiyun struct tep_event **eventptr;
3575*4882a593Smuzhiyun struct tep_event key;
3576*4882a593Smuzhiyun struct tep_event *pkey = &key;
3577*4882a593Smuzhiyun
3578*4882a593Smuzhiyun /* Check cache first */
3579*4882a593Smuzhiyun if (tep->last_event && tep->last_event->id == id)
3580*4882a593Smuzhiyun return tep->last_event;
3581*4882a593Smuzhiyun
3582*4882a593Smuzhiyun key.id = id;
3583*4882a593Smuzhiyun
3584*4882a593Smuzhiyun eventptr = bsearch(&pkey, tep->events, tep->nr_events,
3585*4882a593Smuzhiyun sizeof(*tep->events), events_id_cmp);
3586*4882a593Smuzhiyun
3587*4882a593Smuzhiyun if (eventptr) {
3588*4882a593Smuzhiyun tep->last_event = *eventptr;
3589*4882a593Smuzhiyun return *eventptr;
3590*4882a593Smuzhiyun }
3591*4882a593Smuzhiyun
3592*4882a593Smuzhiyun return NULL;
3593*4882a593Smuzhiyun }
3594*4882a593Smuzhiyun
3595*4882a593Smuzhiyun /**
3596*4882a593Smuzhiyun * tep_find_event_by_name - find an event by given name
3597*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
3598*4882a593Smuzhiyun * @sys: the system name to search for
3599*4882a593Smuzhiyun * @name: the name of the event to search for
3600*4882a593Smuzhiyun *
3601*4882a593Smuzhiyun * This returns an event with a given @name and under the system
3602*4882a593Smuzhiyun * @sys. If @sys is NULL the first event with @name is returned.
3603*4882a593Smuzhiyun */
3604*4882a593Smuzhiyun struct tep_event *
tep_find_event_by_name(struct tep_handle * tep,const char * sys,const char * name)3605*4882a593Smuzhiyun tep_find_event_by_name(struct tep_handle *tep,
3606*4882a593Smuzhiyun const char *sys, const char *name)
3607*4882a593Smuzhiyun {
3608*4882a593Smuzhiyun struct tep_event *event = NULL;
3609*4882a593Smuzhiyun int i;
3610*4882a593Smuzhiyun
3611*4882a593Smuzhiyun if (tep->last_event &&
3612*4882a593Smuzhiyun strcmp(tep->last_event->name, name) == 0 &&
3613*4882a593Smuzhiyun (!sys || strcmp(tep->last_event->system, sys) == 0))
3614*4882a593Smuzhiyun return tep->last_event;
3615*4882a593Smuzhiyun
3616*4882a593Smuzhiyun for (i = 0; i < tep->nr_events; i++) {
3617*4882a593Smuzhiyun event = tep->events[i];
3618*4882a593Smuzhiyun if (strcmp(event->name, name) == 0) {
3619*4882a593Smuzhiyun if (!sys)
3620*4882a593Smuzhiyun break;
3621*4882a593Smuzhiyun if (strcmp(event->system, sys) == 0)
3622*4882a593Smuzhiyun break;
3623*4882a593Smuzhiyun }
3624*4882a593Smuzhiyun }
3625*4882a593Smuzhiyun if (i == tep->nr_events)
3626*4882a593Smuzhiyun event = NULL;
3627*4882a593Smuzhiyun
3628*4882a593Smuzhiyun tep->last_event = event;
3629*4882a593Smuzhiyun return event;
3630*4882a593Smuzhiyun }
3631*4882a593Smuzhiyun
3632*4882a593Smuzhiyun static unsigned long long
eval_num_arg(void * data,int size,struct tep_event * event,struct tep_print_arg * arg)3633*4882a593Smuzhiyun eval_num_arg(void *data, int size, struct tep_event *event, struct tep_print_arg *arg)
3634*4882a593Smuzhiyun {
3635*4882a593Smuzhiyun struct tep_handle *tep = event->tep;
3636*4882a593Smuzhiyun unsigned long long val = 0;
3637*4882a593Smuzhiyun unsigned long long left, right;
3638*4882a593Smuzhiyun struct tep_print_arg *typearg = NULL;
3639*4882a593Smuzhiyun struct tep_print_arg *larg;
3640*4882a593Smuzhiyun unsigned long offset;
3641*4882a593Smuzhiyun unsigned int field_size;
3642*4882a593Smuzhiyun
3643*4882a593Smuzhiyun switch (arg->type) {
3644*4882a593Smuzhiyun case TEP_PRINT_NULL:
3645*4882a593Smuzhiyun /* ?? */
3646*4882a593Smuzhiyun return 0;
3647*4882a593Smuzhiyun case TEP_PRINT_ATOM:
3648*4882a593Smuzhiyun return strtoull(arg->atom.atom, NULL, 0);
3649*4882a593Smuzhiyun case TEP_PRINT_FIELD:
3650*4882a593Smuzhiyun if (!arg->field.field) {
3651*4882a593Smuzhiyun arg->field.field = tep_find_any_field(event, arg->field.name);
3652*4882a593Smuzhiyun if (!arg->field.field)
3653*4882a593Smuzhiyun goto out_warning_field;
3654*4882a593Smuzhiyun
3655*4882a593Smuzhiyun }
3656*4882a593Smuzhiyun /* must be a number */
3657*4882a593Smuzhiyun val = tep_read_number(tep, data + arg->field.field->offset,
3658*4882a593Smuzhiyun arg->field.field->size);
3659*4882a593Smuzhiyun break;
3660*4882a593Smuzhiyun case TEP_PRINT_FLAGS:
3661*4882a593Smuzhiyun case TEP_PRINT_SYMBOL:
3662*4882a593Smuzhiyun case TEP_PRINT_INT_ARRAY:
3663*4882a593Smuzhiyun case TEP_PRINT_HEX:
3664*4882a593Smuzhiyun case TEP_PRINT_HEX_STR:
3665*4882a593Smuzhiyun break;
3666*4882a593Smuzhiyun case TEP_PRINT_TYPE:
3667*4882a593Smuzhiyun val = eval_num_arg(data, size, event, arg->typecast.item);
3668*4882a593Smuzhiyun return eval_type(val, arg, 0);
3669*4882a593Smuzhiyun case TEP_PRINT_STRING:
3670*4882a593Smuzhiyun case TEP_PRINT_BSTRING:
3671*4882a593Smuzhiyun case TEP_PRINT_BITMASK:
3672*4882a593Smuzhiyun return 0;
3673*4882a593Smuzhiyun case TEP_PRINT_FUNC: {
3674*4882a593Smuzhiyun struct trace_seq s;
3675*4882a593Smuzhiyun trace_seq_init(&s);
3676*4882a593Smuzhiyun val = process_defined_func(&s, data, size, event, arg);
3677*4882a593Smuzhiyun trace_seq_destroy(&s);
3678*4882a593Smuzhiyun return val;
3679*4882a593Smuzhiyun }
3680*4882a593Smuzhiyun case TEP_PRINT_OP:
3681*4882a593Smuzhiyun if (strcmp(arg->op.op, "[") == 0) {
3682*4882a593Smuzhiyun /*
3683*4882a593Smuzhiyun * Arrays are special, since we don't want
3684*4882a593Smuzhiyun * to read the arg as is.
3685*4882a593Smuzhiyun */
3686*4882a593Smuzhiyun right = eval_num_arg(data, size, event, arg->op.right);
3687*4882a593Smuzhiyun
3688*4882a593Smuzhiyun /* handle typecasts */
3689*4882a593Smuzhiyun larg = arg->op.left;
3690*4882a593Smuzhiyun while (larg->type == TEP_PRINT_TYPE) {
3691*4882a593Smuzhiyun if (!typearg)
3692*4882a593Smuzhiyun typearg = larg;
3693*4882a593Smuzhiyun larg = larg->typecast.item;
3694*4882a593Smuzhiyun }
3695*4882a593Smuzhiyun
3696*4882a593Smuzhiyun /* Default to long size */
3697*4882a593Smuzhiyun field_size = tep->long_size;
3698*4882a593Smuzhiyun
3699*4882a593Smuzhiyun switch (larg->type) {
3700*4882a593Smuzhiyun case TEP_PRINT_DYNAMIC_ARRAY:
3701*4882a593Smuzhiyun offset = tep_read_number(tep,
3702*4882a593Smuzhiyun data + larg->dynarray.field->offset,
3703*4882a593Smuzhiyun larg->dynarray.field->size);
3704*4882a593Smuzhiyun if (larg->dynarray.field->elementsize)
3705*4882a593Smuzhiyun field_size = larg->dynarray.field->elementsize;
3706*4882a593Smuzhiyun /*
3707*4882a593Smuzhiyun * The actual length of the dynamic array is stored
3708*4882a593Smuzhiyun * in the top half of the field, and the offset
3709*4882a593Smuzhiyun * is in the bottom half of the 32 bit field.
3710*4882a593Smuzhiyun */
3711*4882a593Smuzhiyun offset &= 0xffff;
3712*4882a593Smuzhiyun offset += right;
3713*4882a593Smuzhiyun break;
3714*4882a593Smuzhiyun case TEP_PRINT_FIELD:
3715*4882a593Smuzhiyun if (!larg->field.field) {
3716*4882a593Smuzhiyun larg->field.field =
3717*4882a593Smuzhiyun tep_find_any_field(event, larg->field.name);
3718*4882a593Smuzhiyun if (!larg->field.field) {
3719*4882a593Smuzhiyun arg = larg;
3720*4882a593Smuzhiyun goto out_warning_field;
3721*4882a593Smuzhiyun }
3722*4882a593Smuzhiyun }
3723*4882a593Smuzhiyun field_size = larg->field.field->elementsize;
3724*4882a593Smuzhiyun offset = larg->field.field->offset +
3725*4882a593Smuzhiyun right * larg->field.field->elementsize;
3726*4882a593Smuzhiyun break;
3727*4882a593Smuzhiyun default:
3728*4882a593Smuzhiyun goto default_op; /* oops, all bets off */
3729*4882a593Smuzhiyun }
3730*4882a593Smuzhiyun val = tep_read_number(tep,
3731*4882a593Smuzhiyun data + offset, field_size);
3732*4882a593Smuzhiyun if (typearg)
3733*4882a593Smuzhiyun val = eval_type(val, typearg, 1);
3734*4882a593Smuzhiyun break;
3735*4882a593Smuzhiyun } else if (strcmp(arg->op.op, "?") == 0) {
3736*4882a593Smuzhiyun left = eval_num_arg(data, size, event, arg->op.left);
3737*4882a593Smuzhiyun arg = arg->op.right;
3738*4882a593Smuzhiyun if (left)
3739*4882a593Smuzhiyun val = eval_num_arg(data, size, event, arg->op.left);
3740*4882a593Smuzhiyun else
3741*4882a593Smuzhiyun val = eval_num_arg(data, size, event, arg->op.right);
3742*4882a593Smuzhiyun break;
3743*4882a593Smuzhiyun }
3744*4882a593Smuzhiyun default_op:
3745*4882a593Smuzhiyun left = eval_num_arg(data, size, event, arg->op.left);
3746*4882a593Smuzhiyun right = eval_num_arg(data, size, event, arg->op.right);
3747*4882a593Smuzhiyun switch (arg->op.op[0]) {
3748*4882a593Smuzhiyun case '!':
3749*4882a593Smuzhiyun switch (arg->op.op[1]) {
3750*4882a593Smuzhiyun case 0:
3751*4882a593Smuzhiyun val = !right;
3752*4882a593Smuzhiyun break;
3753*4882a593Smuzhiyun case '=':
3754*4882a593Smuzhiyun val = left != right;
3755*4882a593Smuzhiyun break;
3756*4882a593Smuzhiyun default:
3757*4882a593Smuzhiyun goto out_warning_op;
3758*4882a593Smuzhiyun }
3759*4882a593Smuzhiyun break;
3760*4882a593Smuzhiyun case '~':
3761*4882a593Smuzhiyun val = ~right;
3762*4882a593Smuzhiyun break;
3763*4882a593Smuzhiyun case '|':
3764*4882a593Smuzhiyun if (arg->op.op[1])
3765*4882a593Smuzhiyun val = left || right;
3766*4882a593Smuzhiyun else
3767*4882a593Smuzhiyun val = left | right;
3768*4882a593Smuzhiyun break;
3769*4882a593Smuzhiyun case '&':
3770*4882a593Smuzhiyun if (arg->op.op[1])
3771*4882a593Smuzhiyun val = left && right;
3772*4882a593Smuzhiyun else
3773*4882a593Smuzhiyun val = left & right;
3774*4882a593Smuzhiyun break;
3775*4882a593Smuzhiyun case '<':
3776*4882a593Smuzhiyun switch (arg->op.op[1]) {
3777*4882a593Smuzhiyun case 0:
3778*4882a593Smuzhiyun val = left < right;
3779*4882a593Smuzhiyun break;
3780*4882a593Smuzhiyun case '<':
3781*4882a593Smuzhiyun val = left << right;
3782*4882a593Smuzhiyun break;
3783*4882a593Smuzhiyun case '=':
3784*4882a593Smuzhiyun val = left <= right;
3785*4882a593Smuzhiyun break;
3786*4882a593Smuzhiyun default:
3787*4882a593Smuzhiyun goto out_warning_op;
3788*4882a593Smuzhiyun }
3789*4882a593Smuzhiyun break;
3790*4882a593Smuzhiyun case '>':
3791*4882a593Smuzhiyun switch (arg->op.op[1]) {
3792*4882a593Smuzhiyun case 0:
3793*4882a593Smuzhiyun val = left > right;
3794*4882a593Smuzhiyun break;
3795*4882a593Smuzhiyun case '>':
3796*4882a593Smuzhiyun val = left >> right;
3797*4882a593Smuzhiyun break;
3798*4882a593Smuzhiyun case '=':
3799*4882a593Smuzhiyun val = left >= right;
3800*4882a593Smuzhiyun break;
3801*4882a593Smuzhiyun default:
3802*4882a593Smuzhiyun goto out_warning_op;
3803*4882a593Smuzhiyun }
3804*4882a593Smuzhiyun break;
3805*4882a593Smuzhiyun case '=':
3806*4882a593Smuzhiyun if (arg->op.op[1] != '=')
3807*4882a593Smuzhiyun goto out_warning_op;
3808*4882a593Smuzhiyun
3809*4882a593Smuzhiyun val = left == right;
3810*4882a593Smuzhiyun break;
3811*4882a593Smuzhiyun case '-':
3812*4882a593Smuzhiyun val = left - right;
3813*4882a593Smuzhiyun break;
3814*4882a593Smuzhiyun case '+':
3815*4882a593Smuzhiyun val = left + right;
3816*4882a593Smuzhiyun break;
3817*4882a593Smuzhiyun case '/':
3818*4882a593Smuzhiyun val = left / right;
3819*4882a593Smuzhiyun break;
3820*4882a593Smuzhiyun case '%':
3821*4882a593Smuzhiyun val = left % right;
3822*4882a593Smuzhiyun break;
3823*4882a593Smuzhiyun case '*':
3824*4882a593Smuzhiyun val = left * right;
3825*4882a593Smuzhiyun break;
3826*4882a593Smuzhiyun default:
3827*4882a593Smuzhiyun goto out_warning_op;
3828*4882a593Smuzhiyun }
3829*4882a593Smuzhiyun break;
3830*4882a593Smuzhiyun case TEP_PRINT_DYNAMIC_ARRAY_LEN:
3831*4882a593Smuzhiyun offset = tep_read_number(tep,
3832*4882a593Smuzhiyun data + arg->dynarray.field->offset,
3833*4882a593Smuzhiyun arg->dynarray.field->size);
3834*4882a593Smuzhiyun /*
3835*4882a593Smuzhiyun * The total allocated length of the dynamic array is
3836*4882a593Smuzhiyun * stored in the top half of the field, and the offset
3837*4882a593Smuzhiyun * is in the bottom half of the 32 bit field.
3838*4882a593Smuzhiyun */
3839*4882a593Smuzhiyun val = (unsigned long long)(offset >> 16);
3840*4882a593Smuzhiyun break;
3841*4882a593Smuzhiyun case TEP_PRINT_DYNAMIC_ARRAY:
3842*4882a593Smuzhiyun /* Without [], we pass the address to the dynamic data */
3843*4882a593Smuzhiyun offset = tep_read_number(tep,
3844*4882a593Smuzhiyun data + arg->dynarray.field->offset,
3845*4882a593Smuzhiyun arg->dynarray.field->size);
3846*4882a593Smuzhiyun /*
3847*4882a593Smuzhiyun * The total allocated length of the dynamic array is
3848*4882a593Smuzhiyun * stored in the top half of the field, and the offset
3849*4882a593Smuzhiyun * is in the bottom half of the 32 bit field.
3850*4882a593Smuzhiyun */
3851*4882a593Smuzhiyun offset &= 0xffff;
3852*4882a593Smuzhiyun val = (unsigned long long)((unsigned long)data + offset);
3853*4882a593Smuzhiyun break;
3854*4882a593Smuzhiyun default: /* not sure what to do there */
3855*4882a593Smuzhiyun return 0;
3856*4882a593Smuzhiyun }
3857*4882a593Smuzhiyun return val;
3858*4882a593Smuzhiyun
3859*4882a593Smuzhiyun out_warning_op:
3860*4882a593Smuzhiyun do_warning_event(event, "%s: unknown op '%s'", __func__, arg->op.op);
3861*4882a593Smuzhiyun return 0;
3862*4882a593Smuzhiyun
3863*4882a593Smuzhiyun out_warning_field:
3864*4882a593Smuzhiyun do_warning_event(event, "%s: field %s not found",
3865*4882a593Smuzhiyun __func__, arg->field.name);
3866*4882a593Smuzhiyun return 0;
3867*4882a593Smuzhiyun }
3868*4882a593Smuzhiyun
3869*4882a593Smuzhiyun struct flag {
3870*4882a593Smuzhiyun const char *name;
3871*4882a593Smuzhiyun unsigned long long value;
3872*4882a593Smuzhiyun };
3873*4882a593Smuzhiyun
3874*4882a593Smuzhiyun static const struct flag flags[] = {
3875*4882a593Smuzhiyun { "HI_SOFTIRQ", 0 },
3876*4882a593Smuzhiyun { "TIMER_SOFTIRQ", 1 },
3877*4882a593Smuzhiyun { "NET_TX_SOFTIRQ", 2 },
3878*4882a593Smuzhiyun { "NET_RX_SOFTIRQ", 3 },
3879*4882a593Smuzhiyun { "BLOCK_SOFTIRQ", 4 },
3880*4882a593Smuzhiyun { "IRQ_POLL_SOFTIRQ", 5 },
3881*4882a593Smuzhiyun { "TASKLET_SOFTIRQ", 6 },
3882*4882a593Smuzhiyun { "SCHED_SOFTIRQ", 7 },
3883*4882a593Smuzhiyun { "HRTIMER_SOFTIRQ", 8 },
3884*4882a593Smuzhiyun { "RCU_SOFTIRQ", 9 },
3885*4882a593Smuzhiyun
3886*4882a593Smuzhiyun { "HRTIMER_NORESTART", 0 },
3887*4882a593Smuzhiyun { "HRTIMER_RESTART", 1 },
3888*4882a593Smuzhiyun };
3889*4882a593Smuzhiyun
eval_flag(const char * flag)3890*4882a593Smuzhiyun static long long eval_flag(const char *flag)
3891*4882a593Smuzhiyun {
3892*4882a593Smuzhiyun int i;
3893*4882a593Smuzhiyun
3894*4882a593Smuzhiyun /*
3895*4882a593Smuzhiyun * Some flags in the format files do not get converted.
3896*4882a593Smuzhiyun * If the flag is not numeric, see if it is something that
3897*4882a593Smuzhiyun * we already know about.
3898*4882a593Smuzhiyun */
3899*4882a593Smuzhiyun if (isdigit(flag[0]))
3900*4882a593Smuzhiyun return strtoull(flag, NULL, 0);
3901*4882a593Smuzhiyun
3902*4882a593Smuzhiyun for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++)
3903*4882a593Smuzhiyun if (strcmp(flags[i].name, flag) == 0)
3904*4882a593Smuzhiyun return flags[i].value;
3905*4882a593Smuzhiyun
3906*4882a593Smuzhiyun return -1LL;
3907*4882a593Smuzhiyun }
3908*4882a593Smuzhiyun
print_str_to_seq(struct trace_seq * s,const char * format,int len_arg,const char * str)3909*4882a593Smuzhiyun static void print_str_to_seq(struct trace_seq *s, const char *format,
3910*4882a593Smuzhiyun int len_arg, const char *str)
3911*4882a593Smuzhiyun {
3912*4882a593Smuzhiyun if (len_arg >= 0)
3913*4882a593Smuzhiyun trace_seq_printf(s, format, len_arg, str);
3914*4882a593Smuzhiyun else
3915*4882a593Smuzhiyun trace_seq_printf(s, format, str);
3916*4882a593Smuzhiyun }
3917*4882a593Smuzhiyun
print_bitmask_to_seq(struct tep_handle * tep,struct trace_seq * s,const char * format,int len_arg,const void * data,int size)3918*4882a593Smuzhiyun static void print_bitmask_to_seq(struct tep_handle *tep,
3919*4882a593Smuzhiyun struct trace_seq *s, const char *format,
3920*4882a593Smuzhiyun int len_arg, const void *data, int size)
3921*4882a593Smuzhiyun {
3922*4882a593Smuzhiyun int nr_bits = size * 8;
3923*4882a593Smuzhiyun int str_size = (nr_bits + 3) / 4;
3924*4882a593Smuzhiyun int len = 0;
3925*4882a593Smuzhiyun char buf[3];
3926*4882a593Smuzhiyun char *str;
3927*4882a593Smuzhiyun int index;
3928*4882a593Smuzhiyun int i;
3929*4882a593Smuzhiyun
3930*4882a593Smuzhiyun /*
3931*4882a593Smuzhiyun * The kernel likes to put in commas every 32 bits, we
3932*4882a593Smuzhiyun * can do the same.
3933*4882a593Smuzhiyun */
3934*4882a593Smuzhiyun str_size += (nr_bits - 1) / 32;
3935*4882a593Smuzhiyun
3936*4882a593Smuzhiyun str = malloc(str_size + 1);
3937*4882a593Smuzhiyun if (!str) {
3938*4882a593Smuzhiyun do_warning("%s: not enough memory!", __func__);
3939*4882a593Smuzhiyun return;
3940*4882a593Smuzhiyun }
3941*4882a593Smuzhiyun str[str_size] = 0;
3942*4882a593Smuzhiyun
3943*4882a593Smuzhiyun /* Start out with -2 for the two chars per byte */
3944*4882a593Smuzhiyun for (i = str_size - 2; i >= 0; i -= 2) {
3945*4882a593Smuzhiyun /*
3946*4882a593Smuzhiyun * data points to a bit mask of size bytes.
3947*4882a593Smuzhiyun * In the kernel, this is an array of long words, thus
3948*4882a593Smuzhiyun * endianness is very important.
3949*4882a593Smuzhiyun */
3950*4882a593Smuzhiyun if (tep->file_bigendian)
3951*4882a593Smuzhiyun index = size - (len + 1);
3952*4882a593Smuzhiyun else
3953*4882a593Smuzhiyun index = len;
3954*4882a593Smuzhiyun
3955*4882a593Smuzhiyun snprintf(buf, 3, "%02x", *((unsigned char *)data + index));
3956*4882a593Smuzhiyun memcpy(str + i, buf, 2);
3957*4882a593Smuzhiyun len++;
3958*4882a593Smuzhiyun if (!(len & 3) && i > 0) {
3959*4882a593Smuzhiyun i--;
3960*4882a593Smuzhiyun str[i] = ',';
3961*4882a593Smuzhiyun }
3962*4882a593Smuzhiyun }
3963*4882a593Smuzhiyun
3964*4882a593Smuzhiyun if (len_arg >= 0)
3965*4882a593Smuzhiyun trace_seq_printf(s, format, len_arg, str);
3966*4882a593Smuzhiyun else
3967*4882a593Smuzhiyun trace_seq_printf(s, format, str);
3968*4882a593Smuzhiyun
3969*4882a593Smuzhiyun free(str);
3970*4882a593Smuzhiyun }
3971*4882a593Smuzhiyun
print_str_arg(struct trace_seq * s,void * data,int size,struct tep_event * event,const char * format,int len_arg,struct tep_print_arg * arg)3972*4882a593Smuzhiyun static void print_str_arg(struct trace_seq *s, void *data, int size,
3973*4882a593Smuzhiyun struct tep_event *event, const char *format,
3974*4882a593Smuzhiyun int len_arg, struct tep_print_arg *arg)
3975*4882a593Smuzhiyun {
3976*4882a593Smuzhiyun struct tep_handle *tep = event->tep;
3977*4882a593Smuzhiyun struct tep_print_flag_sym *flag;
3978*4882a593Smuzhiyun struct tep_format_field *field;
3979*4882a593Smuzhiyun struct printk_map *printk;
3980*4882a593Smuzhiyun long long val, fval;
3981*4882a593Smuzhiyun unsigned long long addr;
3982*4882a593Smuzhiyun char *str;
3983*4882a593Smuzhiyun unsigned char *hex;
3984*4882a593Smuzhiyun int print;
3985*4882a593Smuzhiyun int i, len;
3986*4882a593Smuzhiyun
3987*4882a593Smuzhiyun switch (arg->type) {
3988*4882a593Smuzhiyun case TEP_PRINT_NULL:
3989*4882a593Smuzhiyun /* ?? */
3990*4882a593Smuzhiyun return;
3991*4882a593Smuzhiyun case TEP_PRINT_ATOM:
3992*4882a593Smuzhiyun print_str_to_seq(s, format, len_arg, arg->atom.atom);
3993*4882a593Smuzhiyun return;
3994*4882a593Smuzhiyun case TEP_PRINT_FIELD:
3995*4882a593Smuzhiyun field = arg->field.field;
3996*4882a593Smuzhiyun if (!field) {
3997*4882a593Smuzhiyun field = tep_find_any_field(event, arg->field.name);
3998*4882a593Smuzhiyun if (!field) {
3999*4882a593Smuzhiyun str = arg->field.name;
4000*4882a593Smuzhiyun goto out_warning_field;
4001*4882a593Smuzhiyun }
4002*4882a593Smuzhiyun arg->field.field = field;
4003*4882a593Smuzhiyun }
4004*4882a593Smuzhiyun /* Zero sized fields, mean the rest of the data */
4005*4882a593Smuzhiyun len = field->size ? : size - field->offset;
4006*4882a593Smuzhiyun
4007*4882a593Smuzhiyun /*
4008*4882a593Smuzhiyun * Some events pass in pointers. If this is not an array
4009*4882a593Smuzhiyun * and the size is the same as long_size, assume that it
4010*4882a593Smuzhiyun * is a pointer.
4011*4882a593Smuzhiyun */
4012*4882a593Smuzhiyun if (!(field->flags & TEP_FIELD_IS_ARRAY) &&
4013*4882a593Smuzhiyun field->size == tep->long_size) {
4014*4882a593Smuzhiyun
4015*4882a593Smuzhiyun /* Handle heterogeneous recording and processing
4016*4882a593Smuzhiyun * architectures
4017*4882a593Smuzhiyun *
4018*4882a593Smuzhiyun * CASE I:
4019*4882a593Smuzhiyun * Traces recorded on 32-bit devices (32-bit
4020*4882a593Smuzhiyun * addressing) and processed on 64-bit devices:
4021*4882a593Smuzhiyun * In this case, only 32 bits should be read.
4022*4882a593Smuzhiyun *
4023*4882a593Smuzhiyun * CASE II:
4024*4882a593Smuzhiyun * Traces recorded on 64 bit devices and processed
4025*4882a593Smuzhiyun * on 32-bit devices:
4026*4882a593Smuzhiyun * In this case, 64 bits must be read.
4027*4882a593Smuzhiyun */
4028*4882a593Smuzhiyun addr = (tep->long_size == 8) ?
4029*4882a593Smuzhiyun *(unsigned long long *)(data + field->offset) :
4030*4882a593Smuzhiyun (unsigned long long)*(unsigned int *)(data + field->offset);
4031*4882a593Smuzhiyun
4032*4882a593Smuzhiyun /* Check if it matches a print format */
4033*4882a593Smuzhiyun printk = find_printk(tep, addr);
4034*4882a593Smuzhiyun if (printk)
4035*4882a593Smuzhiyun trace_seq_puts(s, printk->printk);
4036*4882a593Smuzhiyun else
4037*4882a593Smuzhiyun trace_seq_printf(s, "%llx", addr);
4038*4882a593Smuzhiyun break;
4039*4882a593Smuzhiyun }
4040*4882a593Smuzhiyun str = malloc(len + 1);
4041*4882a593Smuzhiyun if (!str) {
4042*4882a593Smuzhiyun do_warning_event(event, "%s: not enough memory!",
4043*4882a593Smuzhiyun __func__);
4044*4882a593Smuzhiyun return;
4045*4882a593Smuzhiyun }
4046*4882a593Smuzhiyun memcpy(str, data + field->offset, len);
4047*4882a593Smuzhiyun str[len] = 0;
4048*4882a593Smuzhiyun print_str_to_seq(s, format, len_arg, str);
4049*4882a593Smuzhiyun free(str);
4050*4882a593Smuzhiyun break;
4051*4882a593Smuzhiyun case TEP_PRINT_FLAGS:
4052*4882a593Smuzhiyun val = eval_num_arg(data, size, event, arg->flags.field);
4053*4882a593Smuzhiyun print = 0;
4054*4882a593Smuzhiyun for (flag = arg->flags.flags; flag; flag = flag->next) {
4055*4882a593Smuzhiyun fval = eval_flag(flag->value);
4056*4882a593Smuzhiyun if (!val && fval < 0) {
4057*4882a593Smuzhiyun print_str_to_seq(s, format, len_arg, flag->str);
4058*4882a593Smuzhiyun break;
4059*4882a593Smuzhiyun }
4060*4882a593Smuzhiyun if (fval > 0 && (val & fval) == fval) {
4061*4882a593Smuzhiyun if (print && arg->flags.delim)
4062*4882a593Smuzhiyun trace_seq_puts(s, arg->flags.delim);
4063*4882a593Smuzhiyun print_str_to_seq(s, format, len_arg, flag->str);
4064*4882a593Smuzhiyun print = 1;
4065*4882a593Smuzhiyun val &= ~fval;
4066*4882a593Smuzhiyun }
4067*4882a593Smuzhiyun }
4068*4882a593Smuzhiyun if (val) {
4069*4882a593Smuzhiyun if (print && arg->flags.delim)
4070*4882a593Smuzhiyun trace_seq_puts(s, arg->flags.delim);
4071*4882a593Smuzhiyun trace_seq_printf(s, "0x%llx", val);
4072*4882a593Smuzhiyun }
4073*4882a593Smuzhiyun break;
4074*4882a593Smuzhiyun case TEP_PRINT_SYMBOL:
4075*4882a593Smuzhiyun val = eval_num_arg(data, size, event, arg->symbol.field);
4076*4882a593Smuzhiyun for (flag = arg->symbol.symbols; flag; flag = flag->next) {
4077*4882a593Smuzhiyun fval = eval_flag(flag->value);
4078*4882a593Smuzhiyun if (val == fval) {
4079*4882a593Smuzhiyun print_str_to_seq(s, format, len_arg, flag->str);
4080*4882a593Smuzhiyun break;
4081*4882a593Smuzhiyun }
4082*4882a593Smuzhiyun }
4083*4882a593Smuzhiyun if (!flag)
4084*4882a593Smuzhiyun trace_seq_printf(s, "0x%llx", val);
4085*4882a593Smuzhiyun break;
4086*4882a593Smuzhiyun case TEP_PRINT_HEX:
4087*4882a593Smuzhiyun case TEP_PRINT_HEX_STR:
4088*4882a593Smuzhiyun if (arg->hex.field->type == TEP_PRINT_DYNAMIC_ARRAY) {
4089*4882a593Smuzhiyun unsigned long offset;
4090*4882a593Smuzhiyun offset = tep_read_number(tep,
4091*4882a593Smuzhiyun data + arg->hex.field->dynarray.field->offset,
4092*4882a593Smuzhiyun arg->hex.field->dynarray.field->size);
4093*4882a593Smuzhiyun hex = data + (offset & 0xffff);
4094*4882a593Smuzhiyun } else {
4095*4882a593Smuzhiyun field = arg->hex.field->field.field;
4096*4882a593Smuzhiyun if (!field) {
4097*4882a593Smuzhiyun str = arg->hex.field->field.name;
4098*4882a593Smuzhiyun field = tep_find_any_field(event, str);
4099*4882a593Smuzhiyun if (!field)
4100*4882a593Smuzhiyun goto out_warning_field;
4101*4882a593Smuzhiyun arg->hex.field->field.field = field;
4102*4882a593Smuzhiyun }
4103*4882a593Smuzhiyun hex = data + field->offset;
4104*4882a593Smuzhiyun }
4105*4882a593Smuzhiyun len = eval_num_arg(data, size, event, arg->hex.size);
4106*4882a593Smuzhiyun for (i = 0; i < len; i++) {
4107*4882a593Smuzhiyun if (i && arg->type == TEP_PRINT_HEX)
4108*4882a593Smuzhiyun trace_seq_putc(s, ' ');
4109*4882a593Smuzhiyun trace_seq_printf(s, "%02x", hex[i]);
4110*4882a593Smuzhiyun }
4111*4882a593Smuzhiyun break;
4112*4882a593Smuzhiyun
4113*4882a593Smuzhiyun case TEP_PRINT_INT_ARRAY: {
4114*4882a593Smuzhiyun void *num;
4115*4882a593Smuzhiyun int el_size;
4116*4882a593Smuzhiyun
4117*4882a593Smuzhiyun if (arg->int_array.field->type == TEP_PRINT_DYNAMIC_ARRAY) {
4118*4882a593Smuzhiyun unsigned long offset;
4119*4882a593Smuzhiyun struct tep_format_field *field =
4120*4882a593Smuzhiyun arg->int_array.field->dynarray.field;
4121*4882a593Smuzhiyun offset = tep_read_number(tep,
4122*4882a593Smuzhiyun data + field->offset,
4123*4882a593Smuzhiyun field->size);
4124*4882a593Smuzhiyun num = data + (offset & 0xffff);
4125*4882a593Smuzhiyun } else {
4126*4882a593Smuzhiyun field = arg->int_array.field->field.field;
4127*4882a593Smuzhiyun if (!field) {
4128*4882a593Smuzhiyun str = arg->int_array.field->field.name;
4129*4882a593Smuzhiyun field = tep_find_any_field(event, str);
4130*4882a593Smuzhiyun if (!field)
4131*4882a593Smuzhiyun goto out_warning_field;
4132*4882a593Smuzhiyun arg->int_array.field->field.field = field;
4133*4882a593Smuzhiyun }
4134*4882a593Smuzhiyun num = data + field->offset;
4135*4882a593Smuzhiyun }
4136*4882a593Smuzhiyun len = eval_num_arg(data, size, event, arg->int_array.count);
4137*4882a593Smuzhiyun el_size = eval_num_arg(data, size, event,
4138*4882a593Smuzhiyun arg->int_array.el_size);
4139*4882a593Smuzhiyun for (i = 0; i < len; i++) {
4140*4882a593Smuzhiyun if (i)
4141*4882a593Smuzhiyun trace_seq_putc(s, ' ');
4142*4882a593Smuzhiyun
4143*4882a593Smuzhiyun if (el_size == 1) {
4144*4882a593Smuzhiyun trace_seq_printf(s, "%u", *(uint8_t *)num);
4145*4882a593Smuzhiyun } else if (el_size == 2) {
4146*4882a593Smuzhiyun trace_seq_printf(s, "%u", *(uint16_t *)num);
4147*4882a593Smuzhiyun } else if (el_size == 4) {
4148*4882a593Smuzhiyun trace_seq_printf(s, "%u", *(uint32_t *)num);
4149*4882a593Smuzhiyun } else if (el_size == 8) {
4150*4882a593Smuzhiyun trace_seq_printf(s, "%"PRIu64, *(uint64_t *)num);
4151*4882a593Smuzhiyun } else {
4152*4882a593Smuzhiyun trace_seq_printf(s, "BAD SIZE:%d 0x%x",
4153*4882a593Smuzhiyun el_size, *(uint8_t *)num);
4154*4882a593Smuzhiyun el_size = 1;
4155*4882a593Smuzhiyun }
4156*4882a593Smuzhiyun
4157*4882a593Smuzhiyun num += el_size;
4158*4882a593Smuzhiyun }
4159*4882a593Smuzhiyun break;
4160*4882a593Smuzhiyun }
4161*4882a593Smuzhiyun case TEP_PRINT_TYPE:
4162*4882a593Smuzhiyun break;
4163*4882a593Smuzhiyun case TEP_PRINT_STRING: {
4164*4882a593Smuzhiyun int str_offset;
4165*4882a593Smuzhiyun
4166*4882a593Smuzhiyun if (arg->string.offset == -1) {
4167*4882a593Smuzhiyun struct tep_format_field *f;
4168*4882a593Smuzhiyun
4169*4882a593Smuzhiyun f = tep_find_any_field(event, arg->string.string);
4170*4882a593Smuzhiyun arg->string.offset = f->offset;
4171*4882a593Smuzhiyun }
4172*4882a593Smuzhiyun str_offset = data2host4(tep, *(unsigned int *)(data + arg->string.offset));
4173*4882a593Smuzhiyun str_offset &= 0xffff;
4174*4882a593Smuzhiyun print_str_to_seq(s, format, len_arg, ((char *)data) + str_offset);
4175*4882a593Smuzhiyun break;
4176*4882a593Smuzhiyun }
4177*4882a593Smuzhiyun case TEP_PRINT_BSTRING:
4178*4882a593Smuzhiyun print_str_to_seq(s, format, len_arg, arg->string.string);
4179*4882a593Smuzhiyun break;
4180*4882a593Smuzhiyun case TEP_PRINT_BITMASK: {
4181*4882a593Smuzhiyun int bitmask_offset;
4182*4882a593Smuzhiyun int bitmask_size;
4183*4882a593Smuzhiyun
4184*4882a593Smuzhiyun if (arg->bitmask.offset == -1) {
4185*4882a593Smuzhiyun struct tep_format_field *f;
4186*4882a593Smuzhiyun
4187*4882a593Smuzhiyun f = tep_find_any_field(event, arg->bitmask.bitmask);
4188*4882a593Smuzhiyun arg->bitmask.offset = f->offset;
4189*4882a593Smuzhiyun }
4190*4882a593Smuzhiyun bitmask_offset = data2host4(tep, *(unsigned int *)(data + arg->bitmask.offset));
4191*4882a593Smuzhiyun bitmask_size = bitmask_offset >> 16;
4192*4882a593Smuzhiyun bitmask_offset &= 0xffff;
4193*4882a593Smuzhiyun print_bitmask_to_seq(tep, s, format, len_arg,
4194*4882a593Smuzhiyun data + bitmask_offset, bitmask_size);
4195*4882a593Smuzhiyun break;
4196*4882a593Smuzhiyun }
4197*4882a593Smuzhiyun case TEP_PRINT_OP:
4198*4882a593Smuzhiyun /*
4199*4882a593Smuzhiyun * The only op for string should be ? :
4200*4882a593Smuzhiyun */
4201*4882a593Smuzhiyun if (arg->op.op[0] != '?')
4202*4882a593Smuzhiyun return;
4203*4882a593Smuzhiyun val = eval_num_arg(data, size, event, arg->op.left);
4204*4882a593Smuzhiyun if (val)
4205*4882a593Smuzhiyun print_str_arg(s, data, size, event,
4206*4882a593Smuzhiyun format, len_arg, arg->op.right->op.left);
4207*4882a593Smuzhiyun else
4208*4882a593Smuzhiyun print_str_arg(s, data, size, event,
4209*4882a593Smuzhiyun format, len_arg, arg->op.right->op.right);
4210*4882a593Smuzhiyun break;
4211*4882a593Smuzhiyun case TEP_PRINT_FUNC:
4212*4882a593Smuzhiyun process_defined_func(s, data, size, event, arg);
4213*4882a593Smuzhiyun break;
4214*4882a593Smuzhiyun default:
4215*4882a593Smuzhiyun /* well... */
4216*4882a593Smuzhiyun break;
4217*4882a593Smuzhiyun }
4218*4882a593Smuzhiyun
4219*4882a593Smuzhiyun return;
4220*4882a593Smuzhiyun
4221*4882a593Smuzhiyun out_warning_field:
4222*4882a593Smuzhiyun do_warning_event(event, "%s: field %s not found",
4223*4882a593Smuzhiyun __func__, arg->field.name);
4224*4882a593Smuzhiyun }
4225*4882a593Smuzhiyun
4226*4882a593Smuzhiyun static unsigned long long
process_defined_func(struct trace_seq * s,void * data,int size,struct tep_event * event,struct tep_print_arg * arg)4227*4882a593Smuzhiyun process_defined_func(struct trace_seq *s, void *data, int size,
4228*4882a593Smuzhiyun struct tep_event *event, struct tep_print_arg *arg)
4229*4882a593Smuzhiyun {
4230*4882a593Smuzhiyun struct tep_function_handler *func_handle = arg->func.func;
4231*4882a593Smuzhiyun struct func_params *param;
4232*4882a593Smuzhiyun unsigned long long *args;
4233*4882a593Smuzhiyun unsigned long long ret;
4234*4882a593Smuzhiyun struct tep_print_arg *farg;
4235*4882a593Smuzhiyun struct trace_seq str;
4236*4882a593Smuzhiyun struct save_str {
4237*4882a593Smuzhiyun struct save_str *next;
4238*4882a593Smuzhiyun char *str;
4239*4882a593Smuzhiyun } *strings = NULL, *string;
4240*4882a593Smuzhiyun int i;
4241*4882a593Smuzhiyun
4242*4882a593Smuzhiyun if (!func_handle->nr_args) {
4243*4882a593Smuzhiyun ret = (*func_handle->func)(s, NULL);
4244*4882a593Smuzhiyun goto out;
4245*4882a593Smuzhiyun }
4246*4882a593Smuzhiyun
4247*4882a593Smuzhiyun farg = arg->func.args;
4248*4882a593Smuzhiyun param = func_handle->params;
4249*4882a593Smuzhiyun
4250*4882a593Smuzhiyun ret = ULLONG_MAX;
4251*4882a593Smuzhiyun args = malloc(sizeof(*args) * func_handle->nr_args);
4252*4882a593Smuzhiyun if (!args)
4253*4882a593Smuzhiyun goto out;
4254*4882a593Smuzhiyun
4255*4882a593Smuzhiyun for (i = 0; i < func_handle->nr_args; i++) {
4256*4882a593Smuzhiyun switch (param->type) {
4257*4882a593Smuzhiyun case TEP_FUNC_ARG_INT:
4258*4882a593Smuzhiyun case TEP_FUNC_ARG_LONG:
4259*4882a593Smuzhiyun case TEP_FUNC_ARG_PTR:
4260*4882a593Smuzhiyun args[i] = eval_num_arg(data, size, event, farg);
4261*4882a593Smuzhiyun break;
4262*4882a593Smuzhiyun case TEP_FUNC_ARG_STRING:
4263*4882a593Smuzhiyun trace_seq_init(&str);
4264*4882a593Smuzhiyun print_str_arg(&str, data, size, event, "%s", -1, farg);
4265*4882a593Smuzhiyun trace_seq_terminate(&str);
4266*4882a593Smuzhiyun string = malloc(sizeof(*string));
4267*4882a593Smuzhiyun if (!string) {
4268*4882a593Smuzhiyun do_warning_event(event, "%s(%d): malloc str",
4269*4882a593Smuzhiyun __func__, __LINE__);
4270*4882a593Smuzhiyun goto out_free;
4271*4882a593Smuzhiyun }
4272*4882a593Smuzhiyun string->next = strings;
4273*4882a593Smuzhiyun string->str = strdup(str.buffer);
4274*4882a593Smuzhiyun if (!string->str) {
4275*4882a593Smuzhiyun free(string);
4276*4882a593Smuzhiyun do_warning_event(event, "%s(%d): malloc str",
4277*4882a593Smuzhiyun __func__, __LINE__);
4278*4882a593Smuzhiyun goto out_free;
4279*4882a593Smuzhiyun }
4280*4882a593Smuzhiyun args[i] = (uintptr_t)string->str;
4281*4882a593Smuzhiyun strings = string;
4282*4882a593Smuzhiyun trace_seq_destroy(&str);
4283*4882a593Smuzhiyun break;
4284*4882a593Smuzhiyun default:
4285*4882a593Smuzhiyun /*
4286*4882a593Smuzhiyun * Something went totally wrong, this is not
4287*4882a593Smuzhiyun * an input error, something in this code broke.
4288*4882a593Smuzhiyun */
4289*4882a593Smuzhiyun do_warning_event(event, "Unexpected end of arguments\n");
4290*4882a593Smuzhiyun goto out_free;
4291*4882a593Smuzhiyun }
4292*4882a593Smuzhiyun farg = farg->next;
4293*4882a593Smuzhiyun param = param->next;
4294*4882a593Smuzhiyun }
4295*4882a593Smuzhiyun
4296*4882a593Smuzhiyun ret = (*func_handle->func)(s, args);
4297*4882a593Smuzhiyun out_free:
4298*4882a593Smuzhiyun free(args);
4299*4882a593Smuzhiyun while (strings) {
4300*4882a593Smuzhiyun string = strings;
4301*4882a593Smuzhiyun strings = string->next;
4302*4882a593Smuzhiyun free(string->str);
4303*4882a593Smuzhiyun free(string);
4304*4882a593Smuzhiyun }
4305*4882a593Smuzhiyun
4306*4882a593Smuzhiyun out:
4307*4882a593Smuzhiyun /* TBD : handle return type here */
4308*4882a593Smuzhiyun return ret;
4309*4882a593Smuzhiyun }
4310*4882a593Smuzhiyun
free_args(struct tep_print_arg * args)4311*4882a593Smuzhiyun static void free_args(struct tep_print_arg *args)
4312*4882a593Smuzhiyun {
4313*4882a593Smuzhiyun struct tep_print_arg *next;
4314*4882a593Smuzhiyun
4315*4882a593Smuzhiyun while (args) {
4316*4882a593Smuzhiyun next = args->next;
4317*4882a593Smuzhiyun
4318*4882a593Smuzhiyun free_arg(args);
4319*4882a593Smuzhiyun args = next;
4320*4882a593Smuzhiyun }
4321*4882a593Smuzhiyun }
4322*4882a593Smuzhiyun
make_bprint_args(char * fmt,void * data,int size,struct tep_event * event)4323*4882a593Smuzhiyun static struct tep_print_arg *make_bprint_args(char *fmt, void *data, int size, struct tep_event *event)
4324*4882a593Smuzhiyun {
4325*4882a593Smuzhiyun struct tep_handle *tep = event->tep;
4326*4882a593Smuzhiyun struct tep_format_field *field, *ip_field;
4327*4882a593Smuzhiyun struct tep_print_arg *args, *arg, **next;
4328*4882a593Smuzhiyun unsigned long long ip, val;
4329*4882a593Smuzhiyun char *ptr;
4330*4882a593Smuzhiyun void *bptr;
4331*4882a593Smuzhiyun int vsize = 0;
4332*4882a593Smuzhiyun
4333*4882a593Smuzhiyun field = tep->bprint_buf_field;
4334*4882a593Smuzhiyun ip_field = tep->bprint_ip_field;
4335*4882a593Smuzhiyun
4336*4882a593Smuzhiyun if (!field) {
4337*4882a593Smuzhiyun field = tep_find_field(event, "buf");
4338*4882a593Smuzhiyun if (!field) {
4339*4882a593Smuzhiyun do_warning_event(event, "can't find buffer field for binary printk");
4340*4882a593Smuzhiyun return NULL;
4341*4882a593Smuzhiyun }
4342*4882a593Smuzhiyun ip_field = tep_find_field(event, "ip");
4343*4882a593Smuzhiyun if (!ip_field) {
4344*4882a593Smuzhiyun do_warning_event(event, "can't find ip field for binary printk");
4345*4882a593Smuzhiyun return NULL;
4346*4882a593Smuzhiyun }
4347*4882a593Smuzhiyun tep->bprint_buf_field = field;
4348*4882a593Smuzhiyun tep->bprint_ip_field = ip_field;
4349*4882a593Smuzhiyun }
4350*4882a593Smuzhiyun
4351*4882a593Smuzhiyun ip = tep_read_number(tep, data + ip_field->offset, ip_field->size);
4352*4882a593Smuzhiyun
4353*4882a593Smuzhiyun /*
4354*4882a593Smuzhiyun * The first arg is the IP pointer.
4355*4882a593Smuzhiyun */
4356*4882a593Smuzhiyun args = alloc_arg();
4357*4882a593Smuzhiyun if (!args) {
4358*4882a593Smuzhiyun do_warning_event(event, "%s(%d): not enough memory!",
4359*4882a593Smuzhiyun __func__, __LINE__);
4360*4882a593Smuzhiyun return NULL;
4361*4882a593Smuzhiyun }
4362*4882a593Smuzhiyun arg = args;
4363*4882a593Smuzhiyun arg->next = NULL;
4364*4882a593Smuzhiyun next = &arg->next;
4365*4882a593Smuzhiyun
4366*4882a593Smuzhiyun arg->type = TEP_PRINT_ATOM;
4367*4882a593Smuzhiyun
4368*4882a593Smuzhiyun if (asprintf(&arg->atom.atom, "%lld", ip) < 0)
4369*4882a593Smuzhiyun goto out_free;
4370*4882a593Smuzhiyun
4371*4882a593Smuzhiyun /* skip the first "%ps: " */
4372*4882a593Smuzhiyun for (ptr = fmt + 5, bptr = data + field->offset;
4373*4882a593Smuzhiyun bptr < data + size && *ptr; ptr++) {
4374*4882a593Smuzhiyun int ls = 0;
4375*4882a593Smuzhiyun
4376*4882a593Smuzhiyun if (*ptr == '%') {
4377*4882a593Smuzhiyun process_again:
4378*4882a593Smuzhiyun ptr++;
4379*4882a593Smuzhiyun switch (*ptr) {
4380*4882a593Smuzhiyun case '%':
4381*4882a593Smuzhiyun break;
4382*4882a593Smuzhiyun case 'l':
4383*4882a593Smuzhiyun ls++;
4384*4882a593Smuzhiyun goto process_again;
4385*4882a593Smuzhiyun case 'L':
4386*4882a593Smuzhiyun ls = 2;
4387*4882a593Smuzhiyun goto process_again;
4388*4882a593Smuzhiyun case '0' ... '9':
4389*4882a593Smuzhiyun goto process_again;
4390*4882a593Smuzhiyun case '.':
4391*4882a593Smuzhiyun goto process_again;
4392*4882a593Smuzhiyun case 'z':
4393*4882a593Smuzhiyun case 'Z':
4394*4882a593Smuzhiyun ls = 1;
4395*4882a593Smuzhiyun goto process_again;
4396*4882a593Smuzhiyun case 'p':
4397*4882a593Smuzhiyun ls = 1;
4398*4882a593Smuzhiyun if (isalnum(ptr[1])) {
4399*4882a593Smuzhiyun ptr++;
4400*4882a593Smuzhiyun /* Check for special pointers */
4401*4882a593Smuzhiyun switch (*ptr) {
4402*4882a593Smuzhiyun case 's':
4403*4882a593Smuzhiyun case 'S':
4404*4882a593Smuzhiyun case 'x':
4405*4882a593Smuzhiyun break;
4406*4882a593Smuzhiyun case 'f':
4407*4882a593Smuzhiyun case 'F':
4408*4882a593Smuzhiyun /*
4409*4882a593Smuzhiyun * Pre-5.5 kernels use %pf and
4410*4882a593Smuzhiyun * %pF for printing symbols
4411*4882a593Smuzhiyun * while kernels since 5.5 use
4412*4882a593Smuzhiyun * %pfw for fwnodes. So check
4413*4882a593Smuzhiyun * %p[fF] isn't followed by 'w'.
4414*4882a593Smuzhiyun */
4415*4882a593Smuzhiyun if (ptr[1] != 'w')
4416*4882a593Smuzhiyun break;
4417*4882a593Smuzhiyun /* fall through */
4418*4882a593Smuzhiyun default:
4419*4882a593Smuzhiyun /*
4420*4882a593Smuzhiyun * Older kernels do not process
4421*4882a593Smuzhiyun * dereferenced pointers.
4422*4882a593Smuzhiyun * Only process if the pointer
4423*4882a593Smuzhiyun * value is a printable.
4424*4882a593Smuzhiyun */
4425*4882a593Smuzhiyun if (isprint(*(char *)bptr))
4426*4882a593Smuzhiyun goto process_string;
4427*4882a593Smuzhiyun }
4428*4882a593Smuzhiyun }
4429*4882a593Smuzhiyun /* fall through */
4430*4882a593Smuzhiyun case 'd':
4431*4882a593Smuzhiyun case 'u':
4432*4882a593Smuzhiyun case 'i':
4433*4882a593Smuzhiyun case 'x':
4434*4882a593Smuzhiyun case 'X':
4435*4882a593Smuzhiyun case 'o':
4436*4882a593Smuzhiyun switch (ls) {
4437*4882a593Smuzhiyun case 0:
4438*4882a593Smuzhiyun vsize = 4;
4439*4882a593Smuzhiyun break;
4440*4882a593Smuzhiyun case 1:
4441*4882a593Smuzhiyun vsize = tep->long_size;
4442*4882a593Smuzhiyun break;
4443*4882a593Smuzhiyun case 2:
4444*4882a593Smuzhiyun vsize = 8;
4445*4882a593Smuzhiyun break;
4446*4882a593Smuzhiyun default:
4447*4882a593Smuzhiyun vsize = ls; /* ? */
4448*4882a593Smuzhiyun break;
4449*4882a593Smuzhiyun }
4450*4882a593Smuzhiyun /* fall through */
4451*4882a593Smuzhiyun case '*':
4452*4882a593Smuzhiyun if (*ptr == '*')
4453*4882a593Smuzhiyun vsize = 4;
4454*4882a593Smuzhiyun
4455*4882a593Smuzhiyun /* the pointers are always 4 bytes aligned */
4456*4882a593Smuzhiyun bptr = (void *)(((unsigned long)bptr + 3) &
4457*4882a593Smuzhiyun ~3);
4458*4882a593Smuzhiyun val = tep_read_number(tep, bptr, vsize);
4459*4882a593Smuzhiyun bptr += vsize;
4460*4882a593Smuzhiyun arg = alloc_arg();
4461*4882a593Smuzhiyun if (!arg) {
4462*4882a593Smuzhiyun do_warning_event(event, "%s(%d): not enough memory!",
4463*4882a593Smuzhiyun __func__, __LINE__);
4464*4882a593Smuzhiyun goto out_free;
4465*4882a593Smuzhiyun }
4466*4882a593Smuzhiyun arg->next = NULL;
4467*4882a593Smuzhiyun arg->type = TEP_PRINT_ATOM;
4468*4882a593Smuzhiyun if (asprintf(&arg->atom.atom, "%lld", val) < 0) {
4469*4882a593Smuzhiyun free(arg);
4470*4882a593Smuzhiyun goto out_free;
4471*4882a593Smuzhiyun }
4472*4882a593Smuzhiyun *next = arg;
4473*4882a593Smuzhiyun next = &arg->next;
4474*4882a593Smuzhiyun /*
4475*4882a593Smuzhiyun * The '*' case means that an arg is used as the length.
4476*4882a593Smuzhiyun * We need to continue to figure out for what.
4477*4882a593Smuzhiyun */
4478*4882a593Smuzhiyun if (*ptr == '*')
4479*4882a593Smuzhiyun goto process_again;
4480*4882a593Smuzhiyun
4481*4882a593Smuzhiyun break;
4482*4882a593Smuzhiyun case 's':
4483*4882a593Smuzhiyun process_string:
4484*4882a593Smuzhiyun arg = alloc_arg();
4485*4882a593Smuzhiyun if (!arg) {
4486*4882a593Smuzhiyun do_warning_event(event, "%s(%d): not enough memory!",
4487*4882a593Smuzhiyun __func__, __LINE__);
4488*4882a593Smuzhiyun goto out_free;
4489*4882a593Smuzhiyun }
4490*4882a593Smuzhiyun arg->next = NULL;
4491*4882a593Smuzhiyun arg->type = TEP_PRINT_BSTRING;
4492*4882a593Smuzhiyun arg->string.string = strdup(bptr);
4493*4882a593Smuzhiyun if (!arg->string.string)
4494*4882a593Smuzhiyun goto out_free;
4495*4882a593Smuzhiyun bptr += strlen(bptr) + 1;
4496*4882a593Smuzhiyun *next = arg;
4497*4882a593Smuzhiyun next = &arg->next;
4498*4882a593Smuzhiyun default:
4499*4882a593Smuzhiyun break;
4500*4882a593Smuzhiyun }
4501*4882a593Smuzhiyun }
4502*4882a593Smuzhiyun }
4503*4882a593Smuzhiyun
4504*4882a593Smuzhiyun return args;
4505*4882a593Smuzhiyun
4506*4882a593Smuzhiyun out_free:
4507*4882a593Smuzhiyun free_args(args);
4508*4882a593Smuzhiyun return NULL;
4509*4882a593Smuzhiyun }
4510*4882a593Smuzhiyun
4511*4882a593Smuzhiyun static char *
get_bprint_format(void * data,int size __maybe_unused,struct tep_event * event)4512*4882a593Smuzhiyun get_bprint_format(void *data, int size __maybe_unused,
4513*4882a593Smuzhiyun struct tep_event *event)
4514*4882a593Smuzhiyun {
4515*4882a593Smuzhiyun struct tep_handle *tep = event->tep;
4516*4882a593Smuzhiyun unsigned long long addr;
4517*4882a593Smuzhiyun struct tep_format_field *field;
4518*4882a593Smuzhiyun struct printk_map *printk;
4519*4882a593Smuzhiyun char *format;
4520*4882a593Smuzhiyun
4521*4882a593Smuzhiyun field = tep->bprint_fmt_field;
4522*4882a593Smuzhiyun
4523*4882a593Smuzhiyun if (!field) {
4524*4882a593Smuzhiyun field = tep_find_field(event, "fmt");
4525*4882a593Smuzhiyun if (!field) {
4526*4882a593Smuzhiyun do_warning_event(event, "can't find format field for binary printk");
4527*4882a593Smuzhiyun return NULL;
4528*4882a593Smuzhiyun }
4529*4882a593Smuzhiyun tep->bprint_fmt_field = field;
4530*4882a593Smuzhiyun }
4531*4882a593Smuzhiyun
4532*4882a593Smuzhiyun addr = tep_read_number(tep, data + field->offset, field->size);
4533*4882a593Smuzhiyun
4534*4882a593Smuzhiyun printk = find_printk(tep, addr);
4535*4882a593Smuzhiyun if (!printk) {
4536*4882a593Smuzhiyun if (asprintf(&format, "%%ps: (NO FORMAT FOUND at %llx)\n", addr) < 0)
4537*4882a593Smuzhiyun return NULL;
4538*4882a593Smuzhiyun return format;
4539*4882a593Smuzhiyun }
4540*4882a593Smuzhiyun
4541*4882a593Smuzhiyun if (asprintf(&format, "%s: %s", "%ps", printk->printk) < 0)
4542*4882a593Smuzhiyun return NULL;
4543*4882a593Smuzhiyun
4544*4882a593Smuzhiyun return format;
4545*4882a593Smuzhiyun }
4546*4882a593Smuzhiyun
print_mac_arg(struct trace_seq * s,const char * format,void * data,int size,struct tep_event * event,struct tep_print_arg * arg)4547*4882a593Smuzhiyun static int print_mac_arg(struct trace_seq *s, const char *format,
4548*4882a593Smuzhiyun void *data, int size, struct tep_event *event,
4549*4882a593Smuzhiyun struct tep_print_arg *arg)
4550*4882a593Smuzhiyun {
4551*4882a593Smuzhiyun const char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x";
4552*4882a593Smuzhiyun bool reverse = false;
4553*4882a593Smuzhiyun unsigned char *buf;
4554*4882a593Smuzhiyun int ret = 0;
4555*4882a593Smuzhiyun
4556*4882a593Smuzhiyun if (arg->type == TEP_PRINT_FUNC) {
4557*4882a593Smuzhiyun process_defined_func(s, data, size, event, arg);
4558*4882a593Smuzhiyun return 0;
4559*4882a593Smuzhiyun }
4560*4882a593Smuzhiyun
4561*4882a593Smuzhiyun if (arg->type != TEP_PRINT_FIELD) {
4562*4882a593Smuzhiyun trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d",
4563*4882a593Smuzhiyun arg->type);
4564*4882a593Smuzhiyun return 0;
4565*4882a593Smuzhiyun }
4566*4882a593Smuzhiyun
4567*4882a593Smuzhiyun if (format[0] == 'm') {
4568*4882a593Smuzhiyun fmt = "%.2x%.2x%.2x%.2x%.2x%.2x";
4569*4882a593Smuzhiyun } else if (format[0] == 'M' && format[1] == 'F') {
4570*4882a593Smuzhiyun fmt = "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x";
4571*4882a593Smuzhiyun ret++;
4572*4882a593Smuzhiyun }
4573*4882a593Smuzhiyun if (format[1] == 'R') {
4574*4882a593Smuzhiyun reverse = true;
4575*4882a593Smuzhiyun ret++;
4576*4882a593Smuzhiyun }
4577*4882a593Smuzhiyun
4578*4882a593Smuzhiyun if (!arg->field.field) {
4579*4882a593Smuzhiyun arg->field.field =
4580*4882a593Smuzhiyun tep_find_any_field(event, arg->field.name);
4581*4882a593Smuzhiyun if (!arg->field.field) {
4582*4882a593Smuzhiyun do_warning_event(event, "%s: field %s not found",
4583*4882a593Smuzhiyun __func__, arg->field.name);
4584*4882a593Smuzhiyun return ret;
4585*4882a593Smuzhiyun }
4586*4882a593Smuzhiyun }
4587*4882a593Smuzhiyun if (arg->field.field->size != 6) {
4588*4882a593Smuzhiyun trace_seq_printf(s, "INVALIDMAC");
4589*4882a593Smuzhiyun return ret;
4590*4882a593Smuzhiyun }
4591*4882a593Smuzhiyun
4592*4882a593Smuzhiyun buf = data + arg->field.field->offset;
4593*4882a593Smuzhiyun if (reverse)
4594*4882a593Smuzhiyun trace_seq_printf(s, fmt, buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]);
4595*4882a593Smuzhiyun else
4596*4882a593Smuzhiyun trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
4597*4882a593Smuzhiyun
4598*4882a593Smuzhiyun return ret;
4599*4882a593Smuzhiyun }
4600*4882a593Smuzhiyun
parse_ip4_print_args(struct tep_handle * tep,const char * ptr,bool * reverse)4601*4882a593Smuzhiyun static int parse_ip4_print_args(struct tep_handle *tep,
4602*4882a593Smuzhiyun const char *ptr, bool *reverse)
4603*4882a593Smuzhiyun {
4604*4882a593Smuzhiyun int ret = 0;
4605*4882a593Smuzhiyun
4606*4882a593Smuzhiyun *reverse = false;
4607*4882a593Smuzhiyun
4608*4882a593Smuzhiyun /* hnbl */
4609*4882a593Smuzhiyun switch (*ptr) {
4610*4882a593Smuzhiyun case 'h':
4611*4882a593Smuzhiyun if (tep->file_bigendian)
4612*4882a593Smuzhiyun *reverse = false;
4613*4882a593Smuzhiyun else
4614*4882a593Smuzhiyun *reverse = true;
4615*4882a593Smuzhiyun ret++;
4616*4882a593Smuzhiyun break;
4617*4882a593Smuzhiyun case 'l':
4618*4882a593Smuzhiyun *reverse = true;
4619*4882a593Smuzhiyun ret++;
4620*4882a593Smuzhiyun break;
4621*4882a593Smuzhiyun case 'n':
4622*4882a593Smuzhiyun case 'b':
4623*4882a593Smuzhiyun ret++;
4624*4882a593Smuzhiyun /* fall through */
4625*4882a593Smuzhiyun default:
4626*4882a593Smuzhiyun *reverse = false;
4627*4882a593Smuzhiyun break;
4628*4882a593Smuzhiyun }
4629*4882a593Smuzhiyun
4630*4882a593Smuzhiyun return ret;
4631*4882a593Smuzhiyun }
4632*4882a593Smuzhiyun
print_ip4_addr(struct trace_seq * s,char i,bool reverse,unsigned char * buf)4633*4882a593Smuzhiyun static void print_ip4_addr(struct trace_seq *s, char i, bool reverse, unsigned char *buf)
4634*4882a593Smuzhiyun {
4635*4882a593Smuzhiyun const char *fmt;
4636*4882a593Smuzhiyun
4637*4882a593Smuzhiyun if (i == 'i')
4638*4882a593Smuzhiyun fmt = "%03d.%03d.%03d.%03d";
4639*4882a593Smuzhiyun else
4640*4882a593Smuzhiyun fmt = "%d.%d.%d.%d";
4641*4882a593Smuzhiyun
4642*4882a593Smuzhiyun if (reverse)
4643*4882a593Smuzhiyun trace_seq_printf(s, fmt, buf[3], buf[2], buf[1], buf[0]);
4644*4882a593Smuzhiyun else
4645*4882a593Smuzhiyun trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3]);
4646*4882a593Smuzhiyun
4647*4882a593Smuzhiyun }
4648*4882a593Smuzhiyun
ipv6_addr_v4mapped(const struct in6_addr * a)4649*4882a593Smuzhiyun static inline bool ipv6_addr_v4mapped(const struct in6_addr *a)
4650*4882a593Smuzhiyun {
4651*4882a593Smuzhiyun return ((unsigned long)(a->s6_addr32[0] | a->s6_addr32[1]) |
4652*4882a593Smuzhiyun (unsigned long)(a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0UL;
4653*4882a593Smuzhiyun }
4654*4882a593Smuzhiyun
ipv6_addr_is_isatap(const struct in6_addr * addr)4655*4882a593Smuzhiyun static inline bool ipv6_addr_is_isatap(const struct in6_addr *addr)
4656*4882a593Smuzhiyun {
4657*4882a593Smuzhiyun return (addr->s6_addr32[2] | htonl(0x02000000)) == htonl(0x02005EFE);
4658*4882a593Smuzhiyun }
4659*4882a593Smuzhiyun
print_ip6c_addr(struct trace_seq * s,unsigned char * addr)4660*4882a593Smuzhiyun static void print_ip6c_addr(struct trace_seq *s, unsigned char *addr)
4661*4882a593Smuzhiyun {
4662*4882a593Smuzhiyun int i, j, range;
4663*4882a593Smuzhiyun unsigned char zerolength[8];
4664*4882a593Smuzhiyun int longest = 1;
4665*4882a593Smuzhiyun int colonpos = -1;
4666*4882a593Smuzhiyun uint16_t word;
4667*4882a593Smuzhiyun uint8_t hi, lo;
4668*4882a593Smuzhiyun bool needcolon = false;
4669*4882a593Smuzhiyun bool useIPv4;
4670*4882a593Smuzhiyun struct in6_addr in6;
4671*4882a593Smuzhiyun
4672*4882a593Smuzhiyun memcpy(&in6, addr, sizeof(struct in6_addr));
4673*4882a593Smuzhiyun
4674*4882a593Smuzhiyun useIPv4 = ipv6_addr_v4mapped(&in6) || ipv6_addr_is_isatap(&in6);
4675*4882a593Smuzhiyun
4676*4882a593Smuzhiyun memset(zerolength, 0, sizeof(zerolength));
4677*4882a593Smuzhiyun
4678*4882a593Smuzhiyun if (useIPv4)
4679*4882a593Smuzhiyun range = 6;
4680*4882a593Smuzhiyun else
4681*4882a593Smuzhiyun range = 8;
4682*4882a593Smuzhiyun
4683*4882a593Smuzhiyun /* find position of longest 0 run */
4684*4882a593Smuzhiyun for (i = 0; i < range; i++) {
4685*4882a593Smuzhiyun for (j = i; j < range; j++) {
4686*4882a593Smuzhiyun if (in6.s6_addr16[j] != 0)
4687*4882a593Smuzhiyun break;
4688*4882a593Smuzhiyun zerolength[i]++;
4689*4882a593Smuzhiyun }
4690*4882a593Smuzhiyun }
4691*4882a593Smuzhiyun for (i = 0; i < range; i++) {
4692*4882a593Smuzhiyun if (zerolength[i] > longest) {
4693*4882a593Smuzhiyun longest = zerolength[i];
4694*4882a593Smuzhiyun colonpos = i;
4695*4882a593Smuzhiyun }
4696*4882a593Smuzhiyun }
4697*4882a593Smuzhiyun if (longest == 1) /* don't compress a single 0 */
4698*4882a593Smuzhiyun colonpos = -1;
4699*4882a593Smuzhiyun
4700*4882a593Smuzhiyun /* emit address */
4701*4882a593Smuzhiyun for (i = 0; i < range; i++) {
4702*4882a593Smuzhiyun if (i == colonpos) {
4703*4882a593Smuzhiyun if (needcolon || i == 0)
4704*4882a593Smuzhiyun trace_seq_printf(s, ":");
4705*4882a593Smuzhiyun trace_seq_printf(s, ":");
4706*4882a593Smuzhiyun needcolon = false;
4707*4882a593Smuzhiyun i += longest - 1;
4708*4882a593Smuzhiyun continue;
4709*4882a593Smuzhiyun }
4710*4882a593Smuzhiyun if (needcolon) {
4711*4882a593Smuzhiyun trace_seq_printf(s, ":");
4712*4882a593Smuzhiyun needcolon = false;
4713*4882a593Smuzhiyun }
4714*4882a593Smuzhiyun /* hex u16 without leading 0s */
4715*4882a593Smuzhiyun word = ntohs(in6.s6_addr16[i]);
4716*4882a593Smuzhiyun hi = word >> 8;
4717*4882a593Smuzhiyun lo = word & 0xff;
4718*4882a593Smuzhiyun if (hi)
4719*4882a593Smuzhiyun trace_seq_printf(s, "%x%02x", hi, lo);
4720*4882a593Smuzhiyun else
4721*4882a593Smuzhiyun trace_seq_printf(s, "%x", lo);
4722*4882a593Smuzhiyun
4723*4882a593Smuzhiyun needcolon = true;
4724*4882a593Smuzhiyun }
4725*4882a593Smuzhiyun
4726*4882a593Smuzhiyun if (useIPv4) {
4727*4882a593Smuzhiyun if (needcolon)
4728*4882a593Smuzhiyun trace_seq_printf(s, ":");
4729*4882a593Smuzhiyun print_ip4_addr(s, 'I', false, &in6.s6_addr[12]);
4730*4882a593Smuzhiyun }
4731*4882a593Smuzhiyun
4732*4882a593Smuzhiyun return;
4733*4882a593Smuzhiyun }
4734*4882a593Smuzhiyun
print_ip6_addr(struct trace_seq * s,char i,unsigned char * buf)4735*4882a593Smuzhiyun static void print_ip6_addr(struct trace_seq *s, char i, unsigned char *buf)
4736*4882a593Smuzhiyun {
4737*4882a593Smuzhiyun int j;
4738*4882a593Smuzhiyun
4739*4882a593Smuzhiyun for (j = 0; j < 16; j += 2) {
4740*4882a593Smuzhiyun trace_seq_printf(s, "%02x%02x", buf[j], buf[j+1]);
4741*4882a593Smuzhiyun if (i == 'I' && j < 14)
4742*4882a593Smuzhiyun trace_seq_printf(s, ":");
4743*4882a593Smuzhiyun }
4744*4882a593Smuzhiyun }
4745*4882a593Smuzhiyun
4746*4882a593Smuzhiyun /*
4747*4882a593Smuzhiyun * %pi4 print an IPv4 address with leading zeros
4748*4882a593Smuzhiyun * %pI4 print an IPv4 address without leading zeros
4749*4882a593Smuzhiyun * %pi6 print an IPv6 address without colons
4750*4882a593Smuzhiyun * %pI6 print an IPv6 address with colons
4751*4882a593Smuzhiyun * %pI6c print an IPv6 address in compressed form with colons
4752*4882a593Smuzhiyun * %pISpc print an IP address based on sockaddr; p adds port.
4753*4882a593Smuzhiyun */
print_ipv4_arg(struct trace_seq * s,const char * ptr,char i,void * data,int size,struct tep_event * event,struct tep_print_arg * arg)4754*4882a593Smuzhiyun static int print_ipv4_arg(struct trace_seq *s, const char *ptr, char i,
4755*4882a593Smuzhiyun void *data, int size, struct tep_event *event,
4756*4882a593Smuzhiyun struct tep_print_arg *arg)
4757*4882a593Smuzhiyun {
4758*4882a593Smuzhiyun bool reverse = false;
4759*4882a593Smuzhiyun unsigned char *buf;
4760*4882a593Smuzhiyun int ret;
4761*4882a593Smuzhiyun
4762*4882a593Smuzhiyun ret = parse_ip4_print_args(event->tep, ptr, &reverse);
4763*4882a593Smuzhiyun
4764*4882a593Smuzhiyun if (arg->type == TEP_PRINT_FUNC) {
4765*4882a593Smuzhiyun process_defined_func(s, data, size, event, arg);
4766*4882a593Smuzhiyun return ret;
4767*4882a593Smuzhiyun }
4768*4882a593Smuzhiyun
4769*4882a593Smuzhiyun if (arg->type != TEP_PRINT_FIELD) {
4770*4882a593Smuzhiyun trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
4771*4882a593Smuzhiyun return ret;
4772*4882a593Smuzhiyun }
4773*4882a593Smuzhiyun
4774*4882a593Smuzhiyun if (!arg->field.field) {
4775*4882a593Smuzhiyun arg->field.field =
4776*4882a593Smuzhiyun tep_find_any_field(event, arg->field.name);
4777*4882a593Smuzhiyun if (!arg->field.field) {
4778*4882a593Smuzhiyun do_warning("%s: field %s not found",
4779*4882a593Smuzhiyun __func__, arg->field.name);
4780*4882a593Smuzhiyun return ret;
4781*4882a593Smuzhiyun }
4782*4882a593Smuzhiyun }
4783*4882a593Smuzhiyun
4784*4882a593Smuzhiyun buf = data + arg->field.field->offset;
4785*4882a593Smuzhiyun
4786*4882a593Smuzhiyun if (arg->field.field->size != 4) {
4787*4882a593Smuzhiyun trace_seq_printf(s, "INVALIDIPv4");
4788*4882a593Smuzhiyun return ret;
4789*4882a593Smuzhiyun }
4790*4882a593Smuzhiyun
4791*4882a593Smuzhiyun print_ip4_addr(s, i, reverse, buf);
4792*4882a593Smuzhiyun return ret;
4793*4882a593Smuzhiyun
4794*4882a593Smuzhiyun }
4795*4882a593Smuzhiyun
print_ipv6_arg(struct trace_seq * s,const char * ptr,char i,void * data,int size,struct tep_event * event,struct tep_print_arg * arg)4796*4882a593Smuzhiyun static int print_ipv6_arg(struct trace_seq *s, const char *ptr, char i,
4797*4882a593Smuzhiyun void *data, int size, struct tep_event *event,
4798*4882a593Smuzhiyun struct tep_print_arg *arg)
4799*4882a593Smuzhiyun {
4800*4882a593Smuzhiyun char have_c = 0;
4801*4882a593Smuzhiyun unsigned char *buf;
4802*4882a593Smuzhiyun int rc = 0;
4803*4882a593Smuzhiyun
4804*4882a593Smuzhiyun /* pI6c */
4805*4882a593Smuzhiyun if (i == 'I' && *ptr == 'c') {
4806*4882a593Smuzhiyun have_c = 1;
4807*4882a593Smuzhiyun ptr++;
4808*4882a593Smuzhiyun rc++;
4809*4882a593Smuzhiyun }
4810*4882a593Smuzhiyun
4811*4882a593Smuzhiyun if (arg->type == TEP_PRINT_FUNC) {
4812*4882a593Smuzhiyun process_defined_func(s, data, size, event, arg);
4813*4882a593Smuzhiyun return rc;
4814*4882a593Smuzhiyun }
4815*4882a593Smuzhiyun
4816*4882a593Smuzhiyun if (arg->type != TEP_PRINT_FIELD) {
4817*4882a593Smuzhiyun trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
4818*4882a593Smuzhiyun return rc;
4819*4882a593Smuzhiyun }
4820*4882a593Smuzhiyun
4821*4882a593Smuzhiyun if (!arg->field.field) {
4822*4882a593Smuzhiyun arg->field.field =
4823*4882a593Smuzhiyun tep_find_any_field(event, arg->field.name);
4824*4882a593Smuzhiyun if (!arg->field.field) {
4825*4882a593Smuzhiyun do_warning("%s: field %s not found",
4826*4882a593Smuzhiyun __func__, arg->field.name);
4827*4882a593Smuzhiyun return rc;
4828*4882a593Smuzhiyun }
4829*4882a593Smuzhiyun }
4830*4882a593Smuzhiyun
4831*4882a593Smuzhiyun buf = data + arg->field.field->offset;
4832*4882a593Smuzhiyun
4833*4882a593Smuzhiyun if (arg->field.field->size != 16) {
4834*4882a593Smuzhiyun trace_seq_printf(s, "INVALIDIPv6");
4835*4882a593Smuzhiyun return rc;
4836*4882a593Smuzhiyun }
4837*4882a593Smuzhiyun
4838*4882a593Smuzhiyun if (have_c)
4839*4882a593Smuzhiyun print_ip6c_addr(s, buf);
4840*4882a593Smuzhiyun else
4841*4882a593Smuzhiyun print_ip6_addr(s, i, buf);
4842*4882a593Smuzhiyun
4843*4882a593Smuzhiyun return rc;
4844*4882a593Smuzhiyun }
4845*4882a593Smuzhiyun
print_ipsa_arg(struct trace_seq * s,const char * ptr,char i,void * data,int size,struct tep_event * event,struct tep_print_arg * arg)4846*4882a593Smuzhiyun static int print_ipsa_arg(struct trace_seq *s, const char *ptr, char i,
4847*4882a593Smuzhiyun void *data, int size, struct tep_event *event,
4848*4882a593Smuzhiyun struct tep_print_arg *arg)
4849*4882a593Smuzhiyun {
4850*4882a593Smuzhiyun char have_c = 0, have_p = 0;
4851*4882a593Smuzhiyun unsigned char *buf;
4852*4882a593Smuzhiyun struct sockaddr_storage *sa;
4853*4882a593Smuzhiyun bool reverse = false;
4854*4882a593Smuzhiyun int rc = 0;
4855*4882a593Smuzhiyun int ret;
4856*4882a593Smuzhiyun
4857*4882a593Smuzhiyun /* pISpc */
4858*4882a593Smuzhiyun if (i == 'I') {
4859*4882a593Smuzhiyun if (*ptr == 'p') {
4860*4882a593Smuzhiyun have_p = 1;
4861*4882a593Smuzhiyun ptr++;
4862*4882a593Smuzhiyun rc++;
4863*4882a593Smuzhiyun }
4864*4882a593Smuzhiyun if (*ptr == 'c') {
4865*4882a593Smuzhiyun have_c = 1;
4866*4882a593Smuzhiyun ptr++;
4867*4882a593Smuzhiyun rc++;
4868*4882a593Smuzhiyun }
4869*4882a593Smuzhiyun }
4870*4882a593Smuzhiyun ret = parse_ip4_print_args(event->tep, ptr, &reverse);
4871*4882a593Smuzhiyun ptr += ret;
4872*4882a593Smuzhiyun rc += ret;
4873*4882a593Smuzhiyun
4874*4882a593Smuzhiyun if (arg->type == TEP_PRINT_FUNC) {
4875*4882a593Smuzhiyun process_defined_func(s, data, size, event, arg);
4876*4882a593Smuzhiyun return rc;
4877*4882a593Smuzhiyun }
4878*4882a593Smuzhiyun
4879*4882a593Smuzhiyun if (arg->type != TEP_PRINT_FIELD) {
4880*4882a593Smuzhiyun trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
4881*4882a593Smuzhiyun return rc;
4882*4882a593Smuzhiyun }
4883*4882a593Smuzhiyun
4884*4882a593Smuzhiyun if (!arg->field.field) {
4885*4882a593Smuzhiyun arg->field.field =
4886*4882a593Smuzhiyun tep_find_any_field(event, arg->field.name);
4887*4882a593Smuzhiyun if (!arg->field.field) {
4888*4882a593Smuzhiyun do_warning("%s: field %s not found",
4889*4882a593Smuzhiyun __func__, arg->field.name);
4890*4882a593Smuzhiyun return rc;
4891*4882a593Smuzhiyun }
4892*4882a593Smuzhiyun }
4893*4882a593Smuzhiyun
4894*4882a593Smuzhiyun sa = (struct sockaddr_storage *) (data + arg->field.field->offset);
4895*4882a593Smuzhiyun
4896*4882a593Smuzhiyun if (sa->ss_family == AF_INET) {
4897*4882a593Smuzhiyun struct sockaddr_in *sa4 = (struct sockaddr_in *) sa;
4898*4882a593Smuzhiyun
4899*4882a593Smuzhiyun if (arg->field.field->size < sizeof(struct sockaddr_in)) {
4900*4882a593Smuzhiyun trace_seq_printf(s, "INVALIDIPv4");
4901*4882a593Smuzhiyun return rc;
4902*4882a593Smuzhiyun }
4903*4882a593Smuzhiyun
4904*4882a593Smuzhiyun print_ip4_addr(s, i, reverse, (unsigned char *) &sa4->sin_addr);
4905*4882a593Smuzhiyun if (have_p)
4906*4882a593Smuzhiyun trace_seq_printf(s, ":%d", ntohs(sa4->sin_port));
4907*4882a593Smuzhiyun
4908*4882a593Smuzhiyun
4909*4882a593Smuzhiyun } else if (sa->ss_family == AF_INET6) {
4910*4882a593Smuzhiyun struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) sa;
4911*4882a593Smuzhiyun
4912*4882a593Smuzhiyun if (arg->field.field->size < sizeof(struct sockaddr_in6)) {
4913*4882a593Smuzhiyun trace_seq_printf(s, "INVALIDIPv6");
4914*4882a593Smuzhiyun return rc;
4915*4882a593Smuzhiyun }
4916*4882a593Smuzhiyun
4917*4882a593Smuzhiyun if (have_p)
4918*4882a593Smuzhiyun trace_seq_printf(s, "[");
4919*4882a593Smuzhiyun
4920*4882a593Smuzhiyun buf = (unsigned char *) &sa6->sin6_addr;
4921*4882a593Smuzhiyun if (have_c)
4922*4882a593Smuzhiyun print_ip6c_addr(s, buf);
4923*4882a593Smuzhiyun else
4924*4882a593Smuzhiyun print_ip6_addr(s, i, buf);
4925*4882a593Smuzhiyun
4926*4882a593Smuzhiyun if (have_p)
4927*4882a593Smuzhiyun trace_seq_printf(s, "]:%d", ntohs(sa6->sin6_port));
4928*4882a593Smuzhiyun }
4929*4882a593Smuzhiyun
4930*4882a593Smuzhiyun return rc;
4931*4882a593Smuzhiyun }
4932*4882a593Smuzhiyun
print_ip_arg(struct trace_seq * s,const char * ptr,void * data,int size,struct tep_event * event,struct tep_print_arg * arg)4933*4882a593Smuzhiyun static int print_ip_arg(struct trace_seq *s, const char *ptr,
4934*4882a593Smuzhiyun void *data, int size, struct tep_event *event,
4935*4882a593Smuzhiyun struct tep_print_arg *arg)
4936*4882a593Smuzhiyun {
4937*4882a593Smuzhiyun char i = *ptr; /* 'i' or 'I' */
4938*4882a593Smuzhiyun int rc = 1;
4939*4882a593Smuzhiyun
4940*4882a593Smuzhiyun /* IP version */
4941*4882a593Smuzhiyun ptr++;
4942*4882a593Smuzhiyun
4943*4882a593Smuzhiyun switch (*ptr) {
4944*4882a593Smuzhiyun case '4':
4945*4882a593Smuzhiyun rc += print_ipv4_arg(s, ptr + 1, i, data, size, event, arg);
4946*4882a593Smuzhiyun break;
4947*4882a593Smuzhiyun case '6':
4948*4882a593Smuzhiyun rc += print_ipv6_arg(s, ptr + 1, i, data, size, event, arg);
4949*4882a593Smuzhiyun break;
4950*4882a593Smuzhiyun case 'S':
4951*4882a593Smuzhiyun rc += print_ipsa_arg(s, ptr + 1, i, data, size, event, arg);
4952*4882a593Smuzhiyun break;
4953*4882a593Smuzhiyun default:
4954*4882a593Smuzhiyun return 0;
4955*4882a593Smuzhiyun }
4956*4882a593Smuzhiyun
4957*4882a593Smuzhiyun return rc;
4958*4882a593Smuzhiyun }
4959*4882a593Smuzhiyun
4960*4882a593Smuzhiyun static const int guid_index[16] = {3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15};
4961*4882a593Smuzhiyun static const int uuid_index[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
4962*4882a593Smuzhiyun
print_uuid_arg(struct trace_seq * s,const char * ptr,void * data,int size,struct tep_event * event,struct tep_print_arg * arg)4963*4882a593Smuzhiyun static int print_uuid_arg(struct trace_seq *s, const char *ptr,
4964*4882a593Smuzhiyun void *data, int size, struct tep_event *event,
4965*4882a593Smuzhiyun struct tep_print_arg *arg)
4966*4882a593Smuzhiyun {
4967*4882a593Smuzhiyun const int *index = uuid_index;
4968*4882a593Smuzhiyun char *format = "%02x";
4969*4882a593Smuzhiyun int ret = 0;
4970*4882a593Smuzhiyun char *buf;
4971*4882a593Smuzhiyun int i;
4972*4882a593Smuzhiyun
4973*4882a593Smuzhiyun switch (*(ptr + 1)) {
4974*4882a593Smuzhiyun case 'L':
4975*4882a593Smuzhiyun format = "%02X";
4976*4882a593Smuzhiyun /* fall through */
4977*4882a593Smuzhiyun case 'l':
4978*4882a593Smuzhiyun index = guid_index;
4979*4882a593Smuzhiyun ret++;
4980*4882a593Smuzhiyun break;
4981*4882a593Smuzhiyun case 'B':
4982*4882a593Smuzhiyun format = "%02X";
4983*4882a593Smuzhiyun /* fall through */
4984*4882a593Smuzhiyun case 'b':
4985*4882a593Smuzhiyun ret++;
4986*4882a593Smuzhiyun break;
4987*4882a593Smuzhiyun }
4988*4882a593Smuzhiyun
4989*4882a593Smuzhiyun if (arg->type == TEP_PRINT_FUNC) {
4990*4882a593Smuzhiyun process_defined_func(s, data, size, event, arg);
4991*4882a593Smuzhiyun return ret;
4992*4882a593Smuzhiyun }
4993*4882a593Smuzhiyun
4994*4882a593Smuzhiyun if (arg->type != TEP_PRINT_FIELD) {
4995*4882a593Smuzhiyun trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
4996*4882a593Smuzhiyun return ret;
4997*4882a593Smuzhiyun }
4998*4882a593Smuzhiyun
4999*4882a593Smuzhiyun if (!arg->field.field) {
5000*4882a593Smuzhiyun arg->field.field =
5001*4882a593Smuzhiyun tep_find_any_field(event, arg->field.name);
5002*4882a593Smuzhiyun if (!arg->field.field) {
5003*4882a593Smuzhiyun do_warning("%s: field %s not found",
5004*4882a593Smuzhiyun __func__, arg->field.name);
5005*4882a593Smuzhiyun return ret;
5006*4882a593Smuzhiyun }
5007*4882a593Smuzhiyun }
5008*4882a593Smuzhiyun
5009*4882a593Smuzhiyun if (arg->field.field->size != 16) {
5010*4882a593Smuzhiyun trace_seq_printf(s, "INVALIDUUID");
5011*4882a593Smuzhiyun return ret;
5012*4882a593Smuzhiyun }
5013*4882a593Smuzhiyun
5014*4882a593Smuzhiyun buf = data + arg->field.field->offset;
5015*4882a593Smuzhiyun
5016*4882a593Smuzhiyun for (i = 0; i < 16; i++) {
5017*4882a593Smuzhiyun trace_seq_printf(s, format, buf[index[i]] & 0xff);
5018*4882a593Smuzhiyun switch (i) {
5019*4882a593Smuzhiyun case 3:
5020*4882a593Smuzhiyun case 5:
5021*4882a593Smuzhiyun case 7:
5022*4882a593Smuzhiyun case 9:
5023*4882a593Smuzhiyun trace_seq_printf(s, "-");
5024*4882a593Smuzhiyun break;
5025*4882a593Smuzhiyun }
5026*4882a593Smuzhiyun }
5027*4882a593Smuzhiyun
5028*4882a593Smuzhiyun return ret;
5029*4882a593Smuzhiyun }
5030*4882a593Smuzhiyun
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)5031*4882a593Smuzhiyun static int print_raw_buff_arg(struct trace_seq *s, const char *ptr,
5032*4882a593Smuzhiyun void *data, int size, struct tep_event *event,
5033*4882a593Smuzhiyun struct tep_print_arg *arg, int print_len)
5034*4882a593Smuzhiyun {
5035*4882a593Smuzhiyun int plen = print_len;
5036*4882a593Smuzhiyun char *delim = " ";
5037*4882a593Smuzhiyun int ret = 0;
5038*4882a593Smuzhiyun char *buf;
5039*4882a593Smuzhiyun int i;
5040*4882a593Smuzhiyun unsigned long offset;
5041*4882a593Smuzhiyun int arr_len;
5042*4882a593Smuzhiyun
5043*4882a593Smuzhiyun switch (*(ptr + 1)) {
5044*4882a593Smuzhiyun case 'C':
5045*4882a593Smuzhiyun delim = ":";
5046*4882a593Smuzhiyun ret++;
5047*4882a593Smuzhiyun break;
5048*4882a593Smuzhiyun case 'D':
5049*4882a593Smuzhiyun delim = "-";
5050*4882a593Smuzhiyun ret++;
5051*4882a593Smuzhiyun break;
5052*4882a593Smuzhiyun case 'N':
5053*4882a593Smuzhiyun delim = "";
5054*4882a593Smuzhiyun ret++;
5055*4882a593Smuzhiyun break;
5056*4882a593Smuzhiyun }
5057*4882a593Smuzhiyun
5058*4882a593Smuzhiyun if (arg->type == TEP_PRINT_FUNC) {
5059*4882a593Smuzhiyun process_defined_func(s, data, size, event, arg);
5060*4882a593Smuzhiyun return ret;
5061*4882a593Smuzhiyun }
5062*4882a593Smuzhiyun
5063*4882a593Smuzhiyun if (arg->type != TEP_PRINT_DYNAMIC_ARRAY) {
5064*4882a593Smuzhiyun trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d", arg->type);
5065*4882a593Smuzhiyun return ret;
5066*4882a593Smuzhiyun }
5067*4882a593Smuzhiyun
5068*4882a593Smuzhiyun offset = tep_read_number(event->tep,
5069*4882a593Smuzhiyun data + arg->dynarray.field->offset,
5070*4882a593Smuzhiyun arg->dynarray.field->size);
5071*4882a593Smuzhiyun arr_len = (unsigned long long)(offset >> 16);
5072*4882a593Smuzhiyun buf = data + (offset & 0xffff);
5073*4882a593Smuzhiyun
5074*4882a593Smuzhiyun if (arr_len < plen)
5075*4882a593Smuzhiyun plen = arr_len;
5076*4882a593Smuzhiyun
5077*4882a593Smuzhiyun if (plen < 1)
5078*4882a593Smuzhiyun return ret;
5079*4882a593Smuzhiyun
5080*4882a593Smuzhiyun trace_seq_printf(s, "%02x", buf[0] & 0xff);
5081*4882a593Smuzhiyun for (i = 1; i < plen; i++)
5082*4882a593Smuzhiyun trace_seq_printf(s, "%s%02x", delim, buf[i] & 0xff);
5083*4882a593Smuzhiyun
5084*4882a593Smuzhiyun return ret;
5085*4882a593Smuzhiyun }
5086*4882a593Smuzhiyun
is_printable_array(char * p,unsigned int len)5087*4882a593Smuzhiyun static int is_printable_array(char *p, unsigned int len)
5088*4882a593Smuzhiyun {
5089*4882a593Smuzhiyun unsigned int i;
5090*4882a593Smuzhiyun
5091*4882a593Smuzhiyun for (i = 0; i < len && p[i]; i++)
5092*4882a593Smuzhiyun if (!isprint(p[i]) && !isspace(p[i]))
5093*4882a593Smuzhiyun return 0;
5094*4882a593Smuzhiyun return 1;
5095*4882a593Smuzhiyun }
5096*4882a593Smuzhiyun
tep_print_field(struct trace_seq * s,void * data,struct tep_format_field * field)5097*4882a593Smuzhiyun void tep_print_field(struct trace_seq *s, void *data,
5098*4882a593Smuzhiyun struct tep_format_field *field)
5099*4882a593Smuzhiyun {
5100*4882a593Smuzhiyun unsigned long long val;
5101*4882a593Smuzhiyun unsigned int offset, len, i;
5102*4882a593Smuzhiyun struct tep_handle *tep = field->event->tep;
5103*4882a593Smuzhiyun
5104*4882a593Smuzhiyun if (field->flags & TEP_FIELD_IS_ARRAY) {
5105*4882a593Smuzhiyun offset = field->offset;
5106*4882a593Smuzhiyun len = field->size;
5107*4882a593Smuzhiyun if (field->flags & TEP_FIELD_IS_DYNAMIC) {
5108*4882a593Smuzhiyun val = tep_read_number(tep, data + offset, len);
5109*4882a593Smuzhiyun offset = val;
5110*4882a593Smuzhiyun len = offset >> 16;
5111*4882a593Smuzhiyun offset &= 0xffff;
5112*4882a593Smuzhiyun }
5113*4882a593Smuzhiyun if (field->flags & TEP_FIELD_IS_STRING &&
5114*4882a593Smuzhiyun is_printable_array(data + offset, len)) {
5115*4882a593Smuzhiyun trace_seq_printf(s, "%s", (char *)data + offset);
5116*4882a593Smuzhiyun } else {
5117*4882a593Smuzhiyun trace_seq_puts(s, "ARRAY[");
5118*4882a593Smuzhiyun for (i = 0; i < len; i++) {
5119*4882a593Smuzhiyun if (i)
5120*4882a593Smuzhiyun trace_seq_puts(s, ", ");
5121*4882a593Smuzhiyun trace_seq_printf(s, "%02x",
5122*4882a593Smuzhiyun *((unsigned char *)data + offset + i));
5123*4882a593Smuzhiyun }
5124*4882a593Smuzhiyun trace_seq_putc(s, ']');
5125*4882a593Smuzhiyun field->flags &= ~TEP_FIELD_IS_STRING;
5126*4882a593Smuzhiyun }
5127*4882a593Smuzhiyun } else {
5128*4882a593Smuzhiyun val = tep_read_number(tep, data + field->offset,
5129*4882a593Smuzhiyun field->size);
5130*4882a593Smuzhiyun if (field->flags & TEP_FIELD_IS_POINTER) {
5131*4882a593Smuzhiyun trace_seq_printf(s, "0x%llx", val);
5132*4882a593Smuzhiyun } else if (field->flags & TEP_FIELD_IS_SIGNED) {
5133*4882a593Smuzhiyun switch (field->size) {
5134*4882a593Smuzhiyun case 4:
5135*4882a593Smuzhiyun /*
5136*4882a593Smuzhiyun * If field is long then print it in hex.
5137*4882a593Smuzhiyun * A long usually stores pointers.
5138*4882a593Smuzhiyun */
5139*4882a593Smuzhiyun if (field->flags & TEP_FIELD_IS_LONG)
5140*4882a593Smuzhiyun trace_seq_printf(s, "0x%x", (int)val);
5141*4882a593Smuzhiyun else
5142*4882a593Smuzhiyun trace_seq_printf(s, "%d", (int)val);
5143*4882a593Smuzhiyun break;
5144*4882a593Smuzhiyun case 2:
5145*4882a593Smuzhiyun trace_seq_printf(s, "%2d", (short)val);
5146*4882a593Smuzhiyun break;
5147*4882a593Smuzhiyun case 1:
5148*4882a593Smuzhiyun trace_seq_printf(s, "%1d", (char)val);
5149*4882a593Smuzhiyun break;
5150*4882a593Smuzhiyun default:
5151*4882a593Smuzhiyun trace_seq_printf(s, "%lld", val);
5152*4882a593Smuzhiyun }
5153*4882a593Smuzhiyun } else {
5154*4882a593Smuzhiyun if (field->flags & TEP_FIELD_IS_LONG)
5155*4882a593Smuzhiyun trace_seq_printf(s, "0x%llx", val);
5156*4882a593Smuzhiyun else
5157*4882a593Smuzhiyun trace_seq_printf(s, "%llu", val);
5158*4882a593Smuzhiyun }
5159*4882a593Smuzhiyun }
5160*4882a593Smuzhiyun }
5161*4882a593Smuzhiyun
tep_print_fields(struct trace_seq * s,void * data,int size __maybe_unused,struct tep_event * event)5162*4882a593Smuzhiyun void tep_print_fields(struct trace_seq *s, void *data,
5163*4882a593Smuzhiyun int size __maybe_unused, struct tep_event *event)
5164*4882a593Smuzhiyun {
5165*4882a593Smuzhiyun struct tep_format_field *field;
5166*4882a593Smuzhiyun
5167*4882a593Smuzhiyun field = event->format.fields;
5168*4882a593Smuzhiyun while (field) {
5169*4882a593Smuzhiyun trace_seq_printf(s, " %s=", field->name);
5170*4882a593Smuzhiyun tep_print_field(s, data, field);
5171*4882a593Smuzhiyun field = field->next;
5172*4882a593Smuzhiyun }
5173*4882a593Smuzhiyun }
5174*4882a593Smuzhiyun
print_function(struct trace_seq * s,const char * format,void * data,int size,struct tep_event * event,struct tep_print_arg * arg)5175*4882a593Smuzhiyun static int print_function(struct trace_seq *s, const char *format,
5176*4882a593Smuzhiyun void *data, int size, struct tep_event *event,
5177*4882a593Smuzhiyun struct tep_print_arg *arg)
5178*4882a593Smuzhiyun {
5179*4882a593Smuzhiyun struct func_map *func;
5180*4882a593Smuzhiyun unsigned long long val;
5181*4882a593Smuzhiyun
5182*4882a593Smuzhiyun val = eval_num_arg(data, size, event, arg);
5183*4882a593Smuzhiyun func = find_func(event->tep, val);
5184*4882a593Smuzhiyun if (func) {
5185*4882a593Smuzhiyun trace_seq_puts(s, func->func);
5186*4882a593Smuzhiyun if (*format == 'F' || *format == 'S')
5187*4882a593Smuzhiyun trace_seq_printf(s, "+0x%llx", val - func->addr);
5188*4882a593Smuzhiyun } else {
5189*4882a593Smuzhiyun if (event->tep->long_size == 4)
5190*4882a593Smuzhiyun trace_seq_printf(s, "0x%lx", (long)val);
5191*4882a593Smuzhiyun else
5192*4882a593Smuzhiyun trace_seq_printf(s, "0x%llx", (long long)val);
5193*4882a593Smuzhiyun }
5194*4882a593Smuzhiyun
5195*4882a593Smuzhiyun return 0;
5196*4882a593Smuzhiyun }
5197*4882a593Smuzhiyun
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)5198*4882a593Smuzhiyun static int print_arg_pointer(struct trace_seq *s, const char *format, int plen,
5199*4882a593Smuzhiyun void *data, int size,
5200*4882a593Smuzhiyun struct tep_event *event, struct tep_print_arg *arg)
5201*4882a593Smuzhiyun {
5202*4882a593Smuzhiyun unsigned long long val;
5203*4882a593Smuzhiyun int ret = 1;
5204*4882a593Smuzhiyun
5205*4882a593Smuzhiyun if (arg->type == TEP_PRINT_BSTRING) {
5206*4882a593Smuzhiyun trace_seq_puts(s, arg->string.string);
5207*4882a593Smuzhiyun return 0;
5208*4882a593Smuzhiyun }
5209*4882a593Smuzhiyun while (*format) {
5210*4882a593Smuzhiyun if (*format == 'p') {
5211*4882a593Smuzhiyun format++;
5212*4882a593Smuzhiyun break;
5213*4882a593Smuzhiyun }
5214*4882a593Smuzhiyun format++;
5215*4882a593Smuzhiyun }
5216*4882a593Smuzhiyun
5217*4882a593Smuzhiyun switch (*format) {
5218*4882a593Smuzhiyun case 'F':
5219*4882a593Smuzhiyun case 'f':
5220*4882a593Smuzhiyun case 'S':
5221*4882a593Smuzhiyun case 's':
5222*4882a593Smuzhiyun ret += print_function(s, format, data, size, event, arg);
5223*4882a593Smuzhiyun break;
5224*4882a593Smuzhiyun case 'M':
5225*4882a593Smuzhiyun case 'm':
5226*4882a593Smuzhiyun ret += print_mac_arg(s, format, data, size, event, arg);
5227*4882a593Smuzhiyun break;
5228*4882a593Smuzhiyun case 'I':
5229*4882a593Smuzhiyun case 'i':
5230*4882a593Smuzhiyun ret += print_ip_arg(s, format, data, size, event, arg);
5231*4882a593Smuzhiyun break;
5232*4882a593Smuzhiyun case 'U':
5233*4882a593Smuzhiyun ret += print_uuid_arg(s, format, data, size, event, arg);
5234*4882a593Smuzhiyun break;
5235*4882a593Smuzhiyun case 'h':
5236*4882a593Smuzhiyun ret += print_raw_buff_arg(s, format, data, size, event, arg, plen);
5237*4882a593Smuzhiyun break;
5238*4882a593Smuzhiyun default:
5239*4882a593Smuzhiyun ret = 0;
5240*4882a593Smuzhiyun val = eval_num_arg(data, size, event, arg);
5241*4882a593Smuzhiyun trace_seq_printf(s, "%p", (void *)(intptr_t)val);
5242*4882a593Smuzhiyun break;
5243*4882a593Smuzhiyun }
5244*4882a593Smuzhiyun
5245*4882a593Smuzhiyun return ret;
5246*4882a593Smuzhiyun
5247*4882a593Smuzhiyun }
5248*4882a593Smuzhiyun
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)5249*4882a593Smuzhiyun static int print_arg_number(struct trace_seq *s, const char *format, int plen,
5250*4882a593Smuzhiyun void *data, int size, int ls,
5251*4882a593Smuzhiyun struct tep_event *event, struct tep_print_arg *arg)
5252*4882a593Smuzhiyun {
5253*4882a593Smuzhiyun unsigned long long val;
5254*4882a593Smuzhiyun
5255*4882a593Smuzhiyun val = eval_num_arg(data, size, event, arg);
5256*4882a593Smuzhiyun
5257*4882a593Smuzhiyun switch (ls) {
5258*4882a593Smuzhiyun case -2:
5259*4882a593Smuzhiyun if (plen >= 0)
5260*4882a593Smuzhiyun trace_seq_printf(s, format, plen, (char)val);
5261*4882a593Smuzhiyun else
5262*4882a593Smuzhiyun trace_seq_printf(s, format, (char)val);
5263*4882a593Smuzhiyun break;
5264*4882a593Smuzhiyun case -1:
5265*4882a593Smuzhiyun if (plen >= 0)
5266*4882a593Smuzhiyun trace_seq_printf(s, format, plen, (short)val);
5267*4882a593Smuzhiyun else
5268*4882a593Smuzhiyun trace_seq_printf(s, format, (short)val);
5269*4882a593Smuzhiyun break;
5270*4882a593Smuzhiyun case 0:
5271*4882a593Smuzhiyun if (plen >= 0)
5272*4882a593Smuzhiyun trace_seq_printf(s, format, plen, (int)val);
5273*4882a593Smuzhiyun else
5274*4882a593Smuzhiyun trace_seq_printf(s, format, (int)val);
5275*4882a593Smuzhiyun break;
5276*4882a593Smuzhiyun case 1:
5277*4882a593Smuzhiyun if (plen >= 0)
5278*4882a593Smuzhiyun trace_seq_printf(s, format, plen, (long)val);
5279*4882a593Smuzhiyun else
5280*4882a593Smuzhiyun trace_seq_printf(s, format, (long)val);
5281*4882a593Smuzhiyun break;
5282*4882a593Smuzhiyun case 2:
5283*4882a593Smuzhiyun if (plen >= 0)
5284*4882a593Smuzhiyun trace_seq_printf(s, format, plen, (long long)val);
5285*4882a593Smuzhiyun else
5286*4882a593Smuzhiyun trace_seq_printf(s, format, (long long)val);
5287*4882a593Smuzhiyun break;
5288*4882a593Smuzhiyun default:
5289*4882a593Smuzhiyun do_warning_event(event, "bad count (%d)", ls);
5290*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_FAILED;
5291*4882a593Smuzhiyun }
5292*4882a593Smuzhiyun return 0;
5293*4882a593Smuzhiyun }
5294*4882a593Smuzhiyun
5295*4882a593Smuzhiyun
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)5296*4882a593Smuzhiyun static void print_arg_string(struct trace_seq *s, const char *format, int plen,
5297*4882a593Smuzhiyun void *data, int size,
5298*4882a593Smuzhiyun struct tep_event *event, struct tep_print_arg *arg)
5299*4882a593Smuzhiyun {
5300*4882a593Smuzhiyun struct trace_seq p;
5301*4882a593Smuzhiyun
5302*4882a593Smuzhiyun /* Use helper trace_seq */
5303*4882a593Smuzhiyun trace_seq_init(&p);
5304*4882a593Smuzhiyun print_str_arg(&p, data, size, event,
5305*4882a593Smuzhiyun format, plen, arg);
5306*4882a593Smuzhiyun trace_seq_terminate(&p);
5307*4882a593Smuzhiyun trace_seq_puts(s, p.buffer);
5308*4882a593Smuzhiyun trace_seq_destroy(&p);
5309*4882a593Smuzhiyun }
5310*4882a593Smuzhiyun
parse_arg_format_pointer(const char * format)5311*4882a593Smuzhiyun static int parse_arg_format_pointer(const char *format)
5312*4882a593Smuzhiyun {
5313*4882a593Smuzhiyun int ret = 0;
5314*4882a593Smuzhiyun int index;
5315*4882a593Smuzhiyun int loop;
5316*4882a593Smuzhiyun
5317*4882a593Smuzhiyun switch (*format) {
5318*4882a593Smuzhiyun case 'F':
5319*4882a593Smuzhiyun case 'S':
5320*4882a593Smuzhiyun case 'f':
5321*4882a593Smuzhiyun case 's':
5322*4882a593Smuzhiyun ret++;
5323*4882a593Smuzhiyun break;
5324*4882a593Smuzhiyun case 'M':
5325*4882a593Smuzhiyun case 'm':
5326*4882a593Smuzhiyun /* [mM]R , [mM]F */
5327*4882a593Smuzhiyun switch (format[1]) {
5328*4882a593Smuzhiyun case 'R':
5329*4882a593Smuzhiyun case 'F':
5330*4882a593Smuzhiyun ret++;
5331*4882a593Smuzhiyun break;
5332*4882a593Smuzhiyun }
5333*4882a593Smuzhiyun ret++;
5334*4882a593Smuzhiyun break;
5335*4882a593Smuzhiyun case 'I':
5336*4882a593Smuzhiyun case 'i':
5337*4882a593Smuzhiyun index = 2;
5338*4882a593Smuzhiyun loop = 1;
5339*4882a593Smuzhiyun switch (format[1]) {
5340*4882a593Smuzhiyun case 'S':
5341*4882a593Smuzhiyun /*[S][pfs]*/
5342*4882a593Smuzhiyun while (loop) {
5343*4882a593Smuzhiyun switch (format[index]) {
5344*4882a593Smuzhiyun case 'p':
5345*4882a593Smuzhiyun case 'f':
5346*4882a593Smuzhiyun case 's':
5347*4882a593Smuzhiyun ret++;
5348*4882a593Smuzhiyun index++;
5349*4882a593Smuzhiyun break;
5350*4882a593Smuzhiyun default:
5351*4882a593Smuzhiyun loop = 0;
5352*4882a593Smuzhiyun break;
5353*4882a593Smuzhiyun }
5354*4882a593Smuzhiyun }
5355*4882a593Smuzhiyun /* fall through */
5356*4882a593Smuzhiyun case '4':
5357*4882a593Smuzhiyun /* [4S][hnbl] */
5358*4882a593Smuzhiyun switch (format[index]) {
5359*4882a593Smuzhiyun case 'h':
5360*4882a593Smuzhiyun case 'n':
5361*4882a593Smuzhiyun case 'l':
5362*4882a593Smuzhiyun case 'b':
5363*4882a593Smuzhiyun ret++;
5364*4882a593Smuzhiyun index++;
5365*4882a593Smuzhiyun break;
5366*4882a593Smuzhiyun }
5367*4882a593Smuzhiyun if (format[1] == '4') {
5368*4882a593Smuzhiyun ret++;
5369*4882a593Smuzhiyun break;
5370*4882a593Smuzhiyun }
5371*4882a593Smuzhiyun /* fall through */
5372*4882a593Smuzhiyun case '6':
5373*4882a593Smuzhiyun /* [6S]c */
5374*4882a593Smuzhiyun if (format[index] == 'c')
5375*4882a593Smuzhiyun ret++;
5376*4882a593Smuzhiyun ret++;
5377*4882a593Smuzhiyun break;
5378*4882a593Smuzhiyun }
5379*4882a593Smuzhiyun ret++;
5380*4882a593Smuzhiyun break;
5381*4882a593Smuzhiyun case 'U':
5382*4882a593Smuzhiyun switch (format[1]) {
5383*4882a593Smuzhiyun case 'L':
5384*4882a593Smuzhiyun case 'l':
5385*4882a593Smuzhiyun case 'B':
5386*4882a593Smuzhiyun case 'b':
5387*4882a593Smuzhiyun ret++;
5388*4882a593Smuzhiyun break;
5389*4882a593Smuzhiyun }
5390*4882a593Smuzhiyun ret++;
5391*4882a593Smuzhiyun break;
5392*4882a593Smuzhiyun case 'h':
5393*4882a593Smuzhiyun switch (format[1]) {
5394*4882a593Smuzhiyun case 'C':
5395*4882a593Smuzhiyun case 'D':
5396*4882a593Smuzhiyun case 'N':
5397*4882a593Smuzhiyun ret++;
5398*4882a593Smuzhiyun break;
5399*4882a593Smuzhiyun }
5400*4882a593Smuzhiyun ret++;
5401*4882a593Smuzhiyun break;
5402*4882a593Smuzhiyun default:
5403*4882a593Smuzhiyun break;
5404*4882a593Smuzhiyun }
5405*4882a593Smuzhiyun
5406*4882a593Smuzhiyun return ret;
5407*4882a593Smuzhiyun }
5408*4882a593Smuzhiyun
free_parse_args(struct tep_print_parse * arg)5409*4882a593Smuzhiyun static void free_parse_args(struct tep_print_parse *arg)
5410*4882a593Smuzhiyun {
5411*4882a593Smuzhiyun struct tep_print_parse *del;
5412*4882a593Smuzhiyun
5413*4882a593Smuzhiyun while (arg) {
5414*4882a593Smuzhiyun del = arg;
5415*4882a593Smuzhiyun arg = del->next;
5416*4882a593Smuzhiyun free(del->format);
5417*4882a593Smuzhiyun free(del);
5418*4882a593Smuzhiyun }
5419*4882a593Smuzhiyun }
5420*4882a593Smuzhiyun
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)5421*4882a593Smuzhiyun static int parse_arg_add(struct tep_print_parse **parse, char *format,
5422*4882a593Smuzhiyun enum tep_print_parse_type type,
5423*4882a593Smuzhiyun struct tep_print_arg *arg,
5424*4882a593Smuzhiyun struct tep_print_arg *len_as_arg,
5425*4882a593Smuzhiyun int ls)
5426*4882a593Smuzhiyun {
5427*4882a593Smuzhiyun struct tep_print_parse *parg = NULL;
5428*4882a593Smuzhiyun
5429*4882a593Smuzhiyun parg = calloc(1, sizeof(*parg));
5430*4882a593Smuzhiyun if (!parg)
5431*4882a593Smuzhiyun goto error;
5432*4882a593Smuzhiyun parg->format = strdup(format);
5433*4882a593Smuzhiyun if (!parg->format)
5434*4882a593Smuzhiyun goto error;
5435*4882a593Smuzhiyun parg->type = type;
5436*4882a593Smuzhiyun parg->arg = arg;
5437*4882a593Smuzhiyun parg->len_as_arg = len_as_arg;
5438*4882a593Smuzhiyun parg->ls = ls;
5439*4882a593Smuzhiyun *parse = parg;
5440*4882a593Smuzhiyun return 0;
5441*4882a593Smuzhiyun error:
5442*4882a593Smuzhiyun if (parg) {
5443*4882a593Smuzhiyun free(parg->format);
5444*4882a593Smuzhiyun free(parg);
5445*4882a593Smuzhiyun }
5446*4882a593Smuzhiyun return -1;
5447*4882a593Smuzhiyun }
5448*4882a593Smuzhiyun
parse_arg_format(struct tep_print_parse ** parse,struct tep_event * event,const char * format,struct tep_print_arg ** arg)5449*4882a593Smuzhiyun static int parse_arg_format(struct tep_print_parse **parse,
5450*4882a593Smuzhiyun struct tep_event *event,
5451*4882a593Smuzhiyun const char *format, struct tep_print_arg **arg)
5452*4882a593Smuzhiyun {
5453*4882a593Smuzhiyun struct tep_print_arg *len_arg = NULL;
5454*4882a593Smuzhiyun char print_format[32];
5455*4882a593Smuzhiyun const char *start = format;
5456*4882a593Smuzhiyun int ret = 0;
5457*4882a593Smuzhiyun int ls = 0;
5458*4882a593Smuzhiyun int res;
5459*4882a593Smuzhiyun int len;
5460*4882a593Smuzhiyun
5461*4882a593Smuzhiyun format++;
5462*4882a593Smuzhiyun ret++;
5463*4882a593Smuzhiyun for (; *format; format++) {
5464*4882a593Smuzhiyun switch (*format) {
5465*4882a593Smuzhiyun case '#':
5466*4882a593Smuzhiyun /* FIXME: need to handle properly */
5467*4882a593Smuzhiyun break;
5468*4882a593Smuzhiyun case 'h':
5469*4882a593Smuzhiyun ls--;
5470*4882a593Smuzhiyun break;
5471*4882a593Smuzhiyun case 'l':
5472*4882a593Smuzhiyun ls++;
5473*4882a593Smuzhiyun break;
5474*4882a593Smuzhiyun case 'L':
5475*4882a593Smuzhiyun ls = 2;
5476*4882a593Smuzhiyun break;
5477*4882a593Smuzhiyun case '.':
5478*4882a593Smuzhiyun case 'z':
5479*4882a593Smuzhiyun case 'Z':
5480*4882a593Smuzhiyun case '0' ... '9':
5481*4882a593Smuzhiyun case '-':
5482*4882a593Smuzhiyun break;
5483*4882a593Smuzhiyun case '*':
5484*4882a593Smuzhiyun /* The argument is the length. */
5485*4882a593Smuzhiyun if (!*arg) {
5486*4882a593Smuzhiyun do_warning_event(event, "no argument match");
5487*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_FAILED;
5488*4882a593Smuzhiyun goto out_failed;
5489*4882a593Smuzhiyun }
5490*4882a593Smuzhiyun if (len_arg) {
5491*4882a593Smuzhiyun do_warning_event(event, "argument already matched");
5492*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_FAILED;
5493*4882a593Smuzhiyun goto out_failed;
5494*4882a593Smuzhiyun }
5495*4882a593Smuzhiyun len_arg = *arg;
5496*4882a593Smuzhiyun *arg = (*arg)->next;
5497*4882a593Smuzhiyun break;
5498*4882a593Smuzhiyun case 'p':
5499*4882a593Smuzhiyun if (!*arg) {
5500*4882a593Smuzhiyun do_warning_event(event, "no argument match");
5501*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_FAILED;
5502*4882a593Smuzhiyun goto out_failed;
5503*4882a593Smuzhiyun }
5504*4882a593Smuzhiyun res = parse_arg_format_pointer(format + 1);
5505*4882a593Smuzhiyun if (res > 0) {
5506*4882a593Smuzhiyun format += res;
5507*4882a593Smuzhiyun ret += res;
5508*4882a593Smuzhiyun }
5509*4882a593Smuzhiyun len = ((unsigned long)format + 1) -
5510*4882a593Smuzhiyun (unsigned long)start;
5511*4882a593Smuzhiyun /* should never happen */
5512*4882a593Smuzhiyun if (len > 31) {
5513*4882a593Smuzhiyun do_warning_event(event, "bad format!");
5514*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_FAILED;
5515*4882a593Smuzhiyun len = 31;
5516*4882a593Smuzhiyun }
5517*4882a593Smuzhiyun memcpy(print_format, start, len);
5518*4882a593Smuzhiyun print_format[len] = 0;
5519*4882a593Smuzhiyun
5520*4882a593Smuzhiyun parse_arg_add(parse, print_format,
5521*4882a593Smuzhiyun PRINT_FMT_ARG_POINTER, *arg, len_arg, ls);
5522*4882a593Smuzhiyun *arg = (*arg)->next;
5523*4882a593Smuzhiyun ret++;
5524*4882a593Smuzhiyun return ret;
5525*4882a593Smuzhiyun case 'd':
5526*4882a593Smuzhiyun case 'u':
5527*4882a593Smuzhiyun case 'i':
5528*4882a593Smuzhiyun case 'x':
5529*4882a593Smuzhiyun case 'X':
5530*4882a593Smuzhiyun case 'o':
5531*4882a593Smuzhiyun if (!*arg) {
5532*4882a593Smuzhiyun do_warning_event(event, "no argument match");
5533*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_FAILED;
5534*4882a593Smuzhiyun goto out_failed;
5535*4882a593Smuzhiyun }
5536*4882a593Smuzhiyun
5537*4882a593Smuzhiyun len = ((unsigned long)format + 1) -
5538*4882a593Smuzhiyun (unsigned long)start;
5539*4882a593Smuzhiyun
5540*4882a593Smuzhiyun /* should never happen */
5541*4882a593Smuzhiyun if (len > 30) {
5542*4882a593Smuzhiyun do_warning_event(event, "bad format!");
5543*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_FAILED;
5544*4882a593Smuzhiyun len = 31;
5545*4882a593Smuzhiyun }
5546*4882a593Smuzhiyun memcpy(print_format, start, len);
5547*4882a593Smuzhiyun print_format[len] = 0;
5548*4882a593Smuzhiyun
5549*4882a593Smuzhiyun if (event->tep->long_size == 8 && ls == 1 &&
5550*4882a593Smuzhiyun sizeof(long) != 8) {
5551*4882a593Smuzhiyun char *p;
5552*4882a593Smuzhiyun
5553*4882a593Smuzhiyun /* make %l into %ll */
5554*4882a593Smuzhiyun if (ls == 1 && (p = strchr(print_format, 'l')))
5555*4882a593Smuzhiyun memmove(p+1, p, strlen(p)+1);
5556*4882a593Smuzhiyun ls = 2;
5557*4882a593Smuzhiyun }
5558*4882a593Smuzhiyun if (ls < -2 || ls > 2) {
5559*4882a593Smuzhiyun do_warning_event(event, "bad count (%d)", ls);
5560*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_FAILED;
5561*4882a593Smuzhiyun }
5562*4882a593Smuzhiyun parse_arg_add(parse, print_format,
5563*4882a593Smuzhiyun PRINT_FMT_ARG_DIGIT, *arg, len_arg, ls);
5564*4882a593Smuzhiyun *arg = (*arg)->next;
5565*4882a593Smuzhiyun ret++;
5566*4882a593Smuzhiyun return ret;
5567*4882a593Smuzhiyun case 's':
5568*4882a593Smuzhiyun if (!*arg) {
5569*4882a593Smuzhiyun do_warning_event(event, "no matching argument");
5570*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_FAILED;
5571*4882a593Smuzhiyun goto out_failed;
5572*4882a593Smuzhiyun }
5573*4882a593Smuzhiyun
5574*4882a593Smuzhiyun len = ((unsigned long)format + 1) -
5575*4882a593Smuzhiyun (unsigned long)start;
5576*4882a593Smuzhiyun
5577*4882a593Smuzhiyun /* should never happen */
5578*4882a593Smuzhiyun if (len > 31) {
5579*4882a593Smuzhiyun do_warning_event(event, "bad format!");
5580*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_FAILED;
5581*4882a593Smuzhiyun len = 31;
5582*4882a593Smuzhiyun }
5583*4882a593Smuzhiyun
5584*4882a593Smuzhiyun memcpy(print_format, start, len);
5585*4882a593Smuzhiyun print_format[len] = 0;
5586*4882a593Smuzhiyun
5587*4882a593Smuzhiyun parse_arg_add(parse, print_format,
5588*4882a593Smuzhiyun PRINT_FMT_ARG_STRING, *arg, len_arg, 0);
5589*4882a593Smuzhiyun *arg = (*arg)->next;
5590*4882a593Smuzhiyun ret++;
5591*4882a593Smuzhiyun return ret;
5592*4882a593Smuzhiyun default:
5593*4882a593Smuzhiyun snprintf(print_format, 32, ">%c<", *format);
5594*4882a593Smuzhiyun parse_arg_add(parse, print_format,
5595*4882a593Smuzhiyun PRINT_FMT_STRING, NULL, NULL, 0);
5596*4882a593Smuzhiyun ret++;
5597*4882a593Smuzhiyun return ret;
5598*4882a593Smuzhiyun }
5599*4882a593Smuzhiyun ret++;
5600*4882a593Smuzhiyun }
5601*4882a593Smuzhiyun
5602*4882a593Smuzhiyun out_failed:
5603*4882a593Smuzhiyun return ret;
5604*4882a593Smuzhiyun
5605*4882a593Smuzhiyun }
5606*4882a593Smuzhiyun
parse_arg_string(struct tep_print_parse ** parse,const char * format)5607*4882a593Smuzhiyun static int parse_arg_string(struct tep_print_parse **parse, const char *format)
5608*4882a593Smuzhiyun {
5609*4882a593Smuzhiyun struct trace_seq s;
5610*4882a593Smuzhiyun int ret = 0;
5611*4882a593Smuzhiyun
5612*4882a593Smuzhiyun trace_seq_init(&s);
5613*4882a593Smuzhiyun for (; *format; format++) {
5614*4882a593Smuzhiyun if (*format == '\\') {
5615*4882a593Smuzhiyun format++;
5616*4882a593Smuzhiyun ret++;
5617*4882a593Smuzhiyun switch (*format) {
5618*4882a593Smuzhiyun case 'n':
5619*4882a593Smuzhiyun trace_seq_putc(&s, '\n');
5620*4882a593Smuzhiyun break;
5621*4882a593Smuzhiyun case 't':
5622*4882a593Smuzhiyun trace_seq_putc(&s, '\t');
5623*4882a593Smuzhiyun break;
5624*4882a593Smuzhiyun case 'r':
5625*4882a593Smuzhiyun trace_seq_putc(&s, '\r');
5626*4882a593Smuzhiyun break;
5627*4882a593Smuzhiyun case '\\':
5628*4882a593Smuzhiyun trace_seq_putc(&s, '\\');
5629*4882a593Smuzhiyun break;
5630*4882a593Smuzhiyun default:
5631*4882a593Smuzhiyun trace_seq_putc(&s, *format);
5632*4882a593Smuzhiyun break;
5633*4882a593Smuzhiyun }
5634*4882a593Smuzhiyun } else if (*format == '%') {
5635*4882a593Smuzhiyun if (*(format + 1) == '%') {
5636*4882a593Smuzhiyun trace_seq_putc(&s, '%');
5637*4882a593Smuzhiyun format++;
5638*4882a593Smuzhiyun ret++;
5639*4882a593Smuzhiyun } else
5640*4882a593Smuzhiyun break;
5641*4882a593Smuzhiyun } else
5642*4882a593Smuzhiyun trace_seq_putc(&s, *format);
5643*4882a593Smuzhiyun
5644*4882a593Smuzhiyun ret++;
5645*4882a593Smuzhiyun }
5646*4882a593Smuzhiyun trace_seq_terminate(&s);
5647*4882a593Smuzhiyun parse_arg_add(parse, s.buffer, PRINT_FMT_STRING, NULL, NULL, 0);
5648*4882a593Smuzhiyun trace_seq_destroy(&s);
5649*4882a593Smuzhiyun
5650*4882a593Smuzhiyun return ret;
5651*4882a593Smuzhiyun }
5652*4882a593Smuzhiyun
5653*4882a593Smuzhiyun static struct tep_print_parse *
parse_args(struct tep_event * event,const char * format,struct tep_print_arg * arg)5654*4882a593Smuzhiyun parse_args(struct tep_event *event, const char *format, struct tep_print_arg *arg)
5655*4882a593Smuzhiyun {
5656*4882a593Smuzhiyun struct tep_print_parse *parse_ret = NULL;
5657*4882a593Smuzhiyun struct tep_print_parse **parse = NULL;
5658*4882a593Smuzhiyun int ret;
5659*4882a593Smuzhiyun int len;
5660*4882a593Smuzhiyun
5661*4882a593Smuzhiyun len = strlen(format);
5662*4882a593Smuzhiyun while (*format) {
5663*4882a593Smuzhiyun if (!parse_ret)
5664*4882a593Smuzhiyun parse = &parse_ret;
5665*4882a593Smuzhiyun if (*format == '%' && *(format + 1) != '%')
5666*4882a593Smuzhiyun ret = parse_arg_format(parse, event, format, &arg);
5667*4882a593Smuzhiyun else
5668*4882a593Smuzhiyun ret = parse_arg_string(parse, format);
5669*4882a593Smuzhiyun if (*parse)
5670*4882a593Smuzhiyun parse = &((*parse)->next);
5671*4882a593Smuzhiyun
5672*4882a593Smuzhiyun len -= ret;
5673*4882a593Smuzhiyun if (len > 0)
5674*4882a593Smuzhiyun format += ret;
5675*4882a593Smuzhiyun else
5676*4882a593Smuzhiyun break;
5677*4882a593Smuzhiyun }
5678*4882a593Smuzhiyun return parse_ret;
5679*4882a593Smuzhiyun }
5680*4882a593Smuzhiyun
print_event_cache(struct tep_print_parse * parse,struct trace_seq * s,void * data,int size,struct tep_event * event)5681*4882a593Smuzhiyun static void print_event_cache(struct tep_print_parse *parse, struct trace_seq *s,
5682*4882a593Smuzhiyun void *data, int size, struct tep_event *event)
5683*4882a593Smuzhiyun {
5684*4882a593Smuzhiyun int len_arg;
5685*4882a593Smuzhiyun
5686*4882a593Smuzhiyun while (parse) {
5687*4882a593Smuzhiyun if (parse->len_as_arg)
5688*4882a593Smuzhiyun len_arg = eval_num_arg(data, size, event, parse->len_as_arg);
5689*4882a593Smuzhiyun switch (parse->type) {
5690*4882a593Smuzhiyun case PRINT_FMT_ARG_DIGIT:
5691*4882a593Smuzhiyun print_arg_number(s, parse->format,
5692*4882a593Smuzhiyun parse->len_as_arg ? len_arg : -1, data,
5693*4882a593Smuzhiyun size, parse->ls, event, parse->arg);
5694*4882a593Smuzhiyun break;
5695*4882a593Smuzhiyun case PRINT_FMT_ARG_POINTER:
5696*4882a593Smuzhiyun print_arg_pointer(s, parse->format,
5697*4882a593Smuzhiyun parse->len_as_arg ? len_arg : 1,
5698*4882a593Smuzhiyun data, size, event, parse->arg);
5699*4882a593Smuzhiyun break;
5700*4882a593Smuzhiyun case PRINT_FMT_ARG_STRING:
5701*4882a593Smuzhiyun print_arg_string(s, parse->format,
5702*4882a593Smuzhiyun parse->len_as_arg ? len_arg : -1,
5703*4882a593Smuzhiyun data, size, event, parse->arg);
5704*4882a593Smuzhiyun break;
5705*4882a593Smuzhiyun case PRINT_FMT_STRING:
5706*4882a593Smuzhiyun default:
5707*4882a593Smuzhiyun trace_seq_printf(s, "%s", parse->format);
5708*4882a593Smuzhiyun break;
5709*4882a593Smuzhiyun }
5710*4882a593Smuzhiyun parse = parse->next;
5711*4882a593Smuzhiyun }
5712*4882a593Smuzhiyun }
5713*4882a593Smuzhiyun
pretty_print(struct trace_seq * s,void * data,int size,struct tep_event * event)5714*4882a593Smuzhiyun static void pretty_print(struct trace_seq *s, void *data, int size, struct tep_event *event)
5715*4882a593Smuzhiyun {
5716*4882a593Smuzhiyun struct tep_print_parse *parse = event->print_fmt.print_cache;
5717*4882a593Smuzhiyun struct tep_print_arg *args = NULL;
5718*4882a593Smuzhiyun char *bprint_fmt = NULL;
5719*4882a593Smuzhiyun
5720*4882a593Smuzhiyun if (event->flags & TEP_EVENT_FL_FAILED) {
5721*4882a593Smuzhiyun trace_seq_printf(s, "[FAILED TO PARSE]");
5722*4882a593Smuzhiyun tep_print_fields(s, data, size, event);
5723*4882a593Smuzhiyun return;
5724*4882a593Smuzhiyun }
5725*4882a593Smuzhiyun
5726*4882a593Smuzhiyun if (event->flags & TEP_EVENT_FL_ISBPRINT) {
5727*4882a593Smuzhiyun bprint_fmt = get_bprint_format(data, size, event);
5728*4882a593Smuzhiyun args = make_bprint_args(bprint_fmt, data, size, event);
5729*4882a593Smuzhiyun parse = parse_args(event, bprint_fmt, args);
5730*4882a593Smuzhiyun }
5731*4882a593Smuzhiyun
5732*4882a593Smuzhiyun print_event_cache(parse, s, data, size, event);
5733*4882a593Smuzhiyun
5734*4882a593Smuzhiyun if (event->flags & TEP_EVENT_FL_ISBPRINT) {
5735*4882a593Smuzhiyun free_parse_args(parse);
5736*4882a593Smuzhiyun free_args(args);
5737*4882a593Smuzhiyun free(bprint_fmt);
5738*4882a593Smuzhiyun }
5739*4882a593Smuzhiyun }
5740*4882a593Smuzhiyun
5741*4882a593Smuzhiyun /*
5742*4882a593Smuzhiyun * This parses out the Latency format (interrupts disabled,
5743*4882a593Smuzhiyun * need rescheduling, in hard/soft interrupt, preempt count
5744*4882a593Smuzhiyun * and lock depth) and places it into the trace_seq.
5745*4882a593Smuzhiyun */
data_latency_format(struct tep_handle * tep,struct trace_seq * s,char * format,struct tep_record * record)5746*4882a593Smuzhiyun static void data_latency_format(struct tep_handle *tep, struct trace_seq *s,
5747*4882a593Smuzhiyun char *format, struct tep_record *record)
5748*4882a593Smuzhiyun {
5749*4882a593Smuzhiyun static int check_lock_depth = 1;
5750*4882a593Smuzhiyun static int check_migrate_disable = 1;
5751*4882a593Smuzhiyun static int lock_depth_exists;
5752*4882a593Smuzhiyun static int migrate_disable_exists;
5753*4882a593Smuzhiyun unsigned int lat_flags;
5754*4882a593Smuzhiyun struct trace_seq sq;
5755*4882a593Smuzhiyun unsigned int pc;
5756*4882a593Smuzhiyun int lock_depth = 0;
5757*4882a593Smuzhiyun int migrate_disable = 0;
5758*4882a593Smuzhiyun int hardirq;
5759*4882a593Smuzhiyun int softirq;
5760*4882a593Smuzhiyun void *data = record->data;
5761*4882a593Smuzhiyun
5762*4882a593Smuzhiyun trace_seq_init(&sq);
5763*4882a593Smuzhiyun lat_flags = parse_common_flags(tep, data);
5764*4882a593Smuzhiyun pc = parse_common_pc(tep, data);
5765*4882a593Smuzhiyun /* lock_depth may not always exist */
5766*4882a593Smuzhiyun if (lock_depth_exists)
5767*4882a593Smuzhiyun lock_depth = parse_common_lock_depth(tep, data);
5768*4882a593Smuzhiyun else if (check_lock_depth) {
5769*4882a593Smuzhiyun lock_depth = parse_common_lock_depth(tep, data);
5770*4882a593Smuzhiyun if (lock_depth < 0)
5771*4882a593Smuzhiyun check_lock_depth = 0;
5772*4882a593Smuzhiyun else
5773*4882a593Smuzhiyun lock_depth_exists = 1;
5774*4882a593Smuzhiyun }
5775*4882a593Smuzhiyun
5776*4882a593Smuzhiyun /* migrate_disable may not always exist */
5777*4882a593Smuzhiyun if (migrate_disable_exists)
5778*4882a593Smuzhiyun migrate_disable = parse_common_migrate_disable(tep, data);
5779*4882a593Smuzhiyun else if (check_migrate_disable) {
5780*4882a593Smuzhiyun migrate_disable = parse_common_migrate_disable(tep, data);
5781*4882a593Smuzhiyun if (migrate_disable < 0)
5782*4882a593Smuzhiyun check_migrate_disable = 0;
5783*4882a593Smuzhiyun else
5784*4882a593Smuzhiyun migrate_disable_exists = 1;
5785*4882a593Smuzhiyun }
5786*4882a593Smuzhiyun
5787*4882a593Smuzhiyun hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
5788*4882a593Smuzhiyun softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
5789*4882a593Smuzhiyun
5790*4882a593Smuzhiyun trace_seq_printf(&sq, "%c%c%c",
5791*4882a593Smuzhiyun (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
5792*4882a593Smuzhiyun (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
5793*4882a593Smuzhiyun 'X' : '.',
5794*4882a593Smuzhiyun (lat_flags & TRACE_FLAG_NEED_RESCHED) ?
5795*4882a593Smuzhiyun 'N' : '.',
5796*4882a593Smuzhiyun (hardirq && softirq) ? 'H' :
5797*4882a593Smuzhiyun hardirq ? 'h' : softirq ? 's' : '.');
5798*4882a593Smuzhiyun
5799*4882a593Smuzhiyun if (pc)
5800*4882a593Smuzhiyun trace_seq_printf(&sq, "%x", pc);
5801*4882a593Smuzhiyun else
5802*4882a593Smuzhiyun trace_seq_printf(&sq, ".");
5803*4882a593Smuzhiyun
5804*4882a593Smuzhiyun if (migrate_disable_exists) {
5805*4882a593Smuzhiyun if (migrate_disable < 0)
5806*4882a593Smuzhiyun trace_seq_printf(&sq, ".");
5807*4882a593Smuzhiyun else
5808*4882a593Smuzhiyun trace_seq_printf(&sq, "%d", migrate_disable);
5809*4882a593Smuzhiyun }
5810*4882a593Smuzhiyun
5811*4882a593Smuzhiyun if (lock_depth_exists) {
5812*4882a593Smuzhiyun if (lock_depth < 0)
5813*4882a593Smuzhiyun trace_seq_printf(&sq, ".");
5814*4882a593Smuzhiyun else
5815*4882a593Smuzhiyun trace_seq_printf(&sq, "%d", lock_depth);
5816*4882a593Smuzhiyun }
5817*4882a593Smuzhiyun
5818*4882a593Smuzhiyun if (sq.state == TRACE_SEQ__MEM_ALLOC_FAILED) {
5819*4882a593Smuzhiyun s->state = TRACE_SEQ__MEM_ALLOC_FAILED;
5820*4882a593Smuzhiyun return;
5821*4882a593Smuzhiyun }
5822*4882a593Smuzhiyun
5823*4882a593Smuzhiyun trace_seq_terminate(&sq);
5824*4882a593Smuzhiyun trace_seq_puts(s, sq.buffer);
5825*4882a593Smuzhiyun trace_seq_destroy(&sq);
5826*4882a593Smuzhiyun trace_seq_terminate(s);
5827*4882a593Smuzhiyun }
5828*4882a593Smuzhiyun
5829*4882a593Smuzhiyun /**
5830*4882a593Smuzhiyun * tep_data_type - parse out the given event type
5831*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
5832*4882a593Smuzhiyun * @rec: the record to read from
5833*4882a593Smuzhiyun *
5834*4882a593Smuzhiyun * This returns the event id from the @rec.
5835*4882a593Smuzhiyun */
tep_data_type(struct tep_handle * tep,struct tep_record * rec)5836*4882a593Smuzhiyun int tep_data_type(struct tep_handle *tep, struct tep_record *rec)
5837*4882a593Smuzhiyun {
5838*4882a593Smuzhiyun return trace_parse_common_type(tep, rec->data);
5839*4882a593Smuzhiyun }
5840*4882a593Smuzhiyun
5841*4882a593Smuzhiyun /**
5842*4882a593Smuzhiyun * tep_data_pid - parse the PID from record
5843*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
5844*4882a593Smuzhiyun * @rec: the record to parse
5845*4882a593Smuzhiyun *
5846*4882a593Smuzhiyun * This returns the PID from a record.
5847*4882a593Smuzhiyun */
tep_data_pid(struct tep_handle * tep,struct tep_record * rec)5848*4882a593Smuzhiyun int tep_data_pid(struct tep_handle *tep, struct tep_record *rec)
5849*4882a593Smuzhiyun {
5850*4882a593Smuzhiyun return parse_common_pid(tep, rec->data);
5851*4882a593Smuzhiyun }
5852*4882a593Smuzhiyun
5853*4882a593Smuzhiyun /**
5854*4882a593Smuzhiyun * tep_data_preempt_count - parse the preempt count from the record
5855*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
5856*4882a593Smuzhiyun * @rec: the record to parse
5857*4882a593Smuzhiyun *
5858*4882a593Smuzhiyun * This returns the preempt count from a record.
5859*4882a593Smuzhiyun */
tep_data_preempt_count(struct tep_handle * tep,struct tep_record * rec)5860*4882a593Smuzhiyun int tep_data_preempt_count(struct tep_handle *tep, struct tep_record *rec)
5861*4882a593Smuzhiyun {
5862*4882a593Smuzhiyun return parse_common_pc(tep, rec->data);
5863*4882a593Smuzhiyun }
5864*4882a593Smuzhiyun
5865*4882a593Smuzhiyun /**
5866*4882a593Smuzhiyun * tep_data_flags - parse the latency flags from the record
5867*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
5868*4882a593Smuzhiyun * @rec: the record to parse
5869*4882a593Smuzhiyun *
5870*4882a593Smuzhiyun * This returns the latency flags from a record.
5871*4882a593Smuzhiyun *
5872*4882a593Smuzhiyun * Use trace_flag_type enum for the flags (see event-parse.h).
5873*4882a593Smuzhiyun */
tep_data_flags(struct tep_handle * tep,struct tep_record * rec)5874*4882a593Smuzhiyun int tep_data_flags(struct tep_handle *tep, struct tep_record *rec)
5875*4882a593Smuzhiyun {
5876*4882a593Smuzhiyun return parse_common_flags(tep, rec->data);
5877*4882a593Smuzhiyun }
5878*4882a593Smuzhiyun
5879*4882a593Smuzhiyun /**
5880*4882a593Smuzhiyun * tep_data_comm_from_pid - return the command line from PID
5881*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
5882*4882a593Smuzhiyun * @pid: the PID of the task to search for
5883*4882a593Smuzhiyun *
5884*4882a593Smuzhiyun * This returns a pointer to the command line that has the given
5885*4882a593Smuzhiyun * @pid.
5886*4882a593Smuzhiyun */
tep_data_comm_from_pid(struct tep_handle * tep,int pid)5887*4882a593Smuzhiyun const char *tep_data_comm_from_pid(struct tep_handle *tep, int pid)
5888*4882a593Smuzhiyun {
5889*4882a593Smuzhiyun const char *comm;
5890*4882a593Smuzhiyun
5891*4882a593Smuzhiyun comm = find_cmdline(tep, pid);
5892*4882a593Smuzhiyun return comm;
5893*4882a593Smuzhiyun }
5894*4882a593Smuzhiyun
5895*4882a593Smuzhiyun static struct tep_cmdline *
pid_from_cmdlist(struct tep_handle * tep,const char * comm,struct tep_cmdline * next)5896*4882a593Smuzhiyun pid_from_cmdlist(struct tep_handle *tep, const char *comm, struct tep_cmdline *next)
5897*4882a593Smuzhiyun {
5898*4882a593Smuzhiyun struct cmdline_list *cmdlist = (struct cmdline_list *)next;
5899*4882a593Smuzhiyun
5900*4882a593Smuzhiyun if (cmdlist)
5901*4882a593Smuzhiyun cmdlist = cmdlist->next;
5902*4882a593Smuzhiyun else
5903*4882a593Smuzhiyun cmdlist = tep->cmdlist;
5904*4882a593Smuzhiyun
5905*4882a593Smuzhiyun while (cmdlist && strcmp(cmdlist->comm, comm) != 0)
5906*4882a593Smuzhiyun cmdlist = cmdlist->next;
5907*4882a593Smuzhiyun
5908*4882a593Smuzhiyun return (struct tep_cmdline *)cmdlist;
5909*4882a593Smuzhiyun }
5910*4882a593Smuzhiyun
5911*4882a593Smuzhiyun /**
5912*4882a593Smuzhiyun * tep_data_pid_from_comm - return the pid from a given comm
5913*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
5914*4882a593Smuzhiyun * @comm: the cmdline to find the pid from
5915*4882a593Smuzhiyun * @next: the cmdline structure to find the next comm
5916*4882a593Smuzhiyun *
5917*4882a593Smuzhiyun * This returns the cmdline structure that holds a pid for a given
5918*4882a593Smuzhiyun * comm, or NULL if none found. As there may be more than one pid for
5919*4882a593Smuzhiyun * a given comm, the result of this call can be passed back into
5920*4882a593Smuzhiyun * a recurring call in the @next parameter, and then it will find the
5921*4882a593Smuzhiyun * next pid.
5922*4882a593Smuzhiyun * Also, it does a linear search, so it may be slow.
5923*4882a593Smuzhiyun */
tep_data_pid_from_comm(struct tep_handle * tep,const char * comm,struct tep_cmdline * next)5924*4882a593Smuzhiyun struct tep_cmdline *tep_data_pid_from_comm(struct tep_handle *tep, const char *comm,
5925*4882a593Smuzhiyun struct tep_cmdline *next)
5926*4882a593Smuzhiyun {
5927*4882a593Smuzhiyun struct tep_cmdline *cmdline;
5928*4882a593Smuzhiyun
5929*4882a593Smuzhiyun /*
5930*4882a593Smuzhiyun * If the cmdlines have not been converted yet, then use
5931*4882a593Smuzhiyun * the list.
5932*4882a593Smuzhiyun */
5933*4882a593Smuzhiyun if (!tep->cmdlines)
5934*4882a593Smuzhiyun return pid_from_cmdlist(tep, comm, next);
5935*4882a593Smuzhiyun
5936*4882a593Smuzhiyun if (next) {
5937*4882a593Smuzhiyun /*
5938*4882a593Smuzhiyun * The next pointer could have been still from
5939*4882a593Smuzhiyun * a previous call before cmdlines were created
5940*4882a593Smuzhiyun */
5941*4882a593Smuzhiyun if (next < tep->cmdlines ||
5942*4882a593Smuzhiyun next >= tep->cmdlines + tep->cmdline_count)
5943*4882a593Smuzhiyun next = NULL;
5944*4882a593Smuzhiyun else
5945*4882a593Smuzhiyun cmdline = next++;
5946*4882a593Smuzhiyun }
5947*4882a593Smuzhiyun
5948*4882a593Smuzhiyun if (!next)
5949*4882a593Smuzhiyun cmdline = tep->cmdlines;
5950*4882a593Smuzhiyun
5951*4882a593Smuzhiyun while (cmdline < tep->cmdlines + tep->cmdline_count) {
5952*4882a593Smuzhiyun if (strcmp(cmdline->comm, comm) == 0)
5953*4882a593Smuzhiyun return cmdline;
5954*4882a593Smuzhiyun cmdline++;
5955*4882a593Smuzhiyun }
5956*4882a593Smuzhiyun return NULL;
5957*4882a593Smuzhiyun }
5958*4882a593Smuzhiyun
5959*4882a593Smuzhiyun /**
5960*4882a593Smuzhiyun * tep_cmdline_pid - return the pid associated to a given cmdline
5961*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
5962*4882a593Smuzhiyun * @cmdline: The cmdline structure to get the pid from
5963*4882a593Smuzhiyun *
5964*4882a593Smuzhiyun * Returns the pid for a give cmdline. If @cmdline is NULL, then
5965*4882a593Smuzhiyun * -1 is returned.
5966*4882a593Smuzhiyun */
tep_cmdline_pid(struct tep_handle * tep,struct tep_cmdline * cmdline)5967*4882a593Smuzhiyun int tep_cmdline_pid(struct tep_handle *tep, struct tep_cmdline *cmdline)
5968*4882a593Smuzhiyun {
5969*4882a593Smuzhiyun struct cmdline_list *cmdlist = (struct cmdline_list *)cmdline;
5970*4882a593Smuzhiyun
5971*4882a593Smuzhiyun if (!cmdline)
5972*4882a593Smuzhiyun return -1;
5973*4882a593Smuzhiyun
5974*4882a593Smuzhiyun /*
5975*4882a593Smuzhiyun * If cmdlines have not been created yet, or cmdline is
5976*4882a593Smuzhiyun * not part of the array, then treat it as a cmdlist instead.
5977*4882a593Smuzhiyun */
5978*4882a593Smuzhiyun if (!tep->cmdlines ||
5979*4882a593Smuzhiyun cmdline < tep->cmdlines ||
5980*4882a593Smuzhiyun cmdline >= tep->cmdlines + tep->cmdline_count)
5981*4882a593Smuzhiyun return cmdlist->pid;
5982*4882a593Smuzhiyun
5983*4882a593Smuzhiyun return cmdline->pid;
5984*4882a593Smuzhiyun }
5985*4882a593Smuzhiyun
5986*4882a593Smuzhiyun /*
5987*4882a593Smuzhiyun * This parses the raw @data using the given @event information and
5988*4882a593Smuzhiyun * writes the print format into the trace_seq.
5989*4882a593Smuzhiyun */
print_event_info(struct trace_seq * s,char * format,bool raw,struct tep_event * event,struct tep_record * record)5990*4882a593Smuzhiyun static void print_event_info(struct trace_seq *s, char *format, bool raw,
5991*4882a593Smuzhiyun struct tep_event *event, struct tep_record *record)
5992*4882a593Smuzhiyun {
5993*4882a593Smuzhiyun int print_pretty = 1;
5994*4882a593Smuzhiyun
5995*4882a593Smuzhiyun if (raw || (event->flags & TEP_EVENT_FL_PRINTRAW))
5996*4882a593Smuzhiyun tep_print_fields(s, record->data, record->size, event);
5997*4882a593Smuzhiyun else {
5998*4882a593Smuzhiyun
5999*4882a593Smuzhiyun if (event->handler && !(event->flags & TEP_EVENT_FL_NOHANDLE))
6000*4882a593Smuzhiyun print_pretty = event->handler(s, record, event,
6001*4882a593Smuzhiyun event->context);
6002*4882a593Smuzhiyun
6003*4882a593Smuzhiyun if (print_pretty)
6004*4882a593Smuzhiyun pretty_print(s, record->data, record->size, event);
6005*4882a593Smuzhiyun }
6006*4882a593Smuzhiyun
6007*4882a593Smuzhiyun trace_seq_terminate(s);
6008*4882a593Smuzhiyun }
6009*4882a593Smuzhiyun
6010*4882a593Smuzhiyun /**
6011*4882a593Smuzhiyun * tep_find_event_by_record - return the event from a given record
6012*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
6013*4882a593Smuzhiyun * @record: The record to get the event from
6014*4882a593Smuzhiyun *
6015*4882a593Smuzhiyun * Returns the associated event for a given record, or NULL if non is
6016*4882a593Smuzhiyun * is found.
6017*4882a593Smuzhiyun */
6018*4882a593Smuzhiyun struct tep_event *
tep_find_event_by_record(struct tep_handle * tep,struct tep_record * record)6019*4882a593Smuzhiyun tep_find_event_by_record(struct tep_handle *tep, struct tep_record *record)
6020*4882a593Smuzhiyun {
6021*4882a593Smuzhiyun int type;
6022*4882a593Smuzhiyun
6023*4882a593Smuzhiyun if (record->size < 0) {
6024*4882a593Smuzhiyun do_warning("ug! negative record size %d", record->size);
6025*4882a593Smuzhiyun return NULL;
6026*4882a593Smuzhiyun }
6027*4882a593Smuzhiyun
6028*4882a593Smuzhiyun type = trace_parse_common_type(tep, record->data);
6029*4882a593Smuzhiyun
6030*4882a593Smuzhiyun return tep_find_event(tep, type);
6031*4882a593Smuzhiyun }
6032*4882a593Smuzhiyun
6033*4882a593Smuzhiyun /*
6034*4882a593Smuzhiyun * Writes the timestamp of the record into @s. Time divisor and precision can be
6035*4882a593Smuzhiyun * specified as part of printf @format string. Example:
6036*4882a593Smuzhiyun * "%3.1000d" - divide the time by 1000 and print the first 3 digits
6037*4882a593Smuzhiyun * before the dot. Thus, the timestamp "123456000" will be printed as
6038*4882a593Smuzhiyun * "123.456"
6039*4882a593Smuzhiyun */
print_event_time(struct tep_handle * tep,struct trace_seq * s,char * format,struct tep_event * event,struct tep_record * record)6040*4882a593Smuzhiyun static void print_event_time(struct tep_handle *tep, struct trace_seq *s,
6041*4882a593Smuzhiyun char *format, struct tep_event *event,
6042*4882a593Smuzhiyun struct tep_record *record)
6043*4882a593Smuzhiyun {
6044*4882a593Smuzhiyun unsigned long long time;
6045*4882a593Smuzhiyun char *divstr;
6046*4882a593Smuzhiyun int prec = 0, pr;
6047*4882a593Smuzhiyun int div = 0;
6048*4882a593Smuzhiyun int p10 = 1;
6049*4882a593Smuzhiyun
6050*4882a593Smuzhiyun if (isdigit(*(format + 1)))
6051*4882a593Smuzhiyun prec = atoi(format + 1);
6052*4882a593Smuzhiyun divstr = strchr(format, '.');
6053*4882a593Smuzhiyun if (divstr && isdigit(*(divstr + 1)))
6054*4882a593Smuzhiyun div = atoi(divstr + 1);
6055*4882a593Smuzhiyun time = record->ts;
6056*4882a593Smuzhiyun if (div) {
6057*4882a593Smuzhiyun time += div / 2;
6058*4882a593Smuzhiyun time /= div;
6059*4882a593Smuzhiyun }
6060*4882a593Smuzhiyun pr = prec;
6061*4882a593Smuzhiyun while (pr--)
6062*4882a593Smuzhiyun p10 *= 10;
6063*4882a593Smuzhiyun
6064*4882a593Smuzhiyun if (p10 > 1 && p10 < time)
6065*4882a593Smuzhiyun trace_seq_printf(s, "%5llu.%0*llu", time / p10, prec, time % p10);
6066*4882a593Smuzhiyun else
6067*4882a593Smuzhiyun trace_seq_printf(s, "%12llu", time);
6068*4882a593Smuzhiyun }
6069*4882a593Smuzhiyun
6070*4882a593Smuzhiyun struct print_event_type {
6071*4882a593Smuzhiyun enum {
6072*4882a593Smuzhiyun EVENT_TYPE_INT = 1,
6073*4882a593Smuzhiyun EVENT_TYPE_STRING,
6074*4882a593Smuzhiyun EVENT_TYPE_UNKNOWN,
6075*4882a593Smuzhiyun } type;
6076*4882a593Smuzhiyun char format[32];
6077*4882a593Smuzhiyun };
6078*4882a593Smuzhiyun
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)6079*4882a593Smuzhiyun static void print_string(struct tep_handle *tep, struct trace_seq *s,
6080*4882a593Smuzhiyun struct tep_record *record, struct tep_event *event,
6081*4882a593Smuzhiyun const char *arg, struct print_event_type *type)
6082*4882a593Smuzhiyun {
6083*4882a593Smuzhiyun const char *comm;
6084*4882a593Smuzhiyun int pid;
6085*4882a593Smuzhiyun
6086*4882a593Smuzhiyun if (strncmp(arg, TEP_PRINT_LATENCY, strlen(TEP_PRINT_LATENCY)) == 0) {
6087*4882a593Smuzhiyun data_latency_format(tep, s, type->format, record);
6088*4882a593Smuzhiyun } else if (strncmp(arg, TEP_PRINT_COMM, strlen(TEP_PRINT_COMM)) == 0) {
6089*4882a593Smuzhiyun pid = parse_common_pid(tep, record->data);
6090*4882a593Smuzhiyun comm = find_cmdline(tep, pid);
6091*4882a593Smuzhiyun trace_seq_printf(s, type->format, comm);
6092*4882a593Smuzhiyun } else if (strncmp(arg, TEP_PRINT_INFO_RAW, strlen(TEP_PRINT_INFO_RAW)) == 0) {
6093*4882a593Smuzhiyun print_event_info(s, type->format, true, event, record);
6094*4882a593Smuzhiyun } else if (strncmp(arg, TEP_PRINT_INFO, strlen(TEP_PRINT_INFO)) == 0) {
6095*4882a593Smuzhiyun print_event_info(s, type->format, false, event, record);
6096*4882a593Smuzhiyun } else if (strncmp(arg, TEP_PRINT_NAME, strlen(TEP_PRINT_NAME)) == 0) {
6097*4882a593Smuzhiyun trace_seq_printf(s, type->format, event->name);
6098*4882a593Smuzhiyun } else {
6099*4882a593Smuzhiyun trace_seq_printf(s, "[UNKNOWN TEP TYPE %s]", arg);
6100*4882a593Smuzhiyun }
6101*4882a593Smuzhiyun
6102*4882a593Smuzhiyun }
6103*4882a593Smuzhiyun
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)6104*4882a593Smuzhiyun static void print_int(struct tep_handle *tep, struct trace_seq *s,
6105*4882a593Smuzhiyun struct tep_record *record, struct tep_event *event,
6106*4882a593Smuzhiyun int arg, struct print_event_type *type)
6107*4882a593Smuzhiyun {
6108*4882a593Smuzhiyun int param;
6109*4882a593Smuzhiyun
6110*4882a593Smuzhiyun switch (arg) {
6111*4882a593Smuzhiyun case TEP_PRINT_CPU:
6112*4882a593Smuzhiyun param = record->cpu;
6113*4882a593Smuzhiyun break;
6114*4882a593Smuzhiyun case TEP_PRINT_PID:
6115*4882a593Smuzhiyun param = parse_common_pid(tep, record->data);
6116*4882a593Smuzhiyun break;
6117*4882a593Smuzhiyun case TEP_PRINT_TIME:
6118*4882a593Smuzhiyun return print_event_time(tep, s, type->format, event, record);
6119*4882a593Smuzhiyun default:
6120*4882a593Smuzhiyun return;
6121*4882a593Smuzhiyun }
6122*4882a593Smuzhiyun trace_seq_printf(s, type->format, param);
6123*4882a593Smuzhiyun }
6124*4882a593Smuzhiyun
tep_print_event_param_type(char * format,struct print_event_type * type)6125*4882a593Smuzhiyun static int tep_print_event_param_type(char *format,
6126*4882a593Smuzhiyun struct print_event_type *type)
6127*4882a593Smuzhiyun {
6128*4882a593Smuzhiyun char *str = format + 1;
6129*4882a593Smuzhiyun int i = 1;
6130*4882a593Smuzhiyun
6131*4882a593Smuzhiyun type->type = EVENT_TYPE_UNKNOWN;
6132*4882a593Smuzhiyun while (*str) {
6133*4882a593Smuzhiyun switch (*str) {
6134*4882a593Smuzhiyun case 'd':
6135*4882a593Smuzhiyun case 'u':
6136*4882a593Smuzhiyun case 'i':
6137*4882a593Smuzhiyun case 'x':
6138*4882a593Smuzhiyun case 'X':
6139*4882a593Smuzhiyun case 'o':
6140*4882a593Smuzhiyun type->type = EVENT_TYPE_INT;
6141*4882a593Smuzhiyun break;
6142*4882a593Smuzhiyun case 's':
6143*4882a593Smuzhiyun type->type = EVENT_TYPE_STRING;
6144*4882a593Smuzhiyun break;
6145*4882a593Smuzhiyun }
6146*4882a593Smuzhiyun str++;
6147*4882a593Smuzhiyun i++;
6148*4882a593Smuzhiyun if (type->type != EVENT_TYPE_UNKNOWN)
6149*4882a593Smuzhiyun break;
6150*4882a593Smuzhiyun }
6151*4882a593Smuzhiyun memset(type->format, 0, 32);
6152*4882a593Smuzhiyun memcpy(type->format, format, i < 32 ? i : 31);
6153*4882a593Smuzhiyun return i;
6154*4882a593Smuzhiyun }
6155*4882a593Smuzhiyun
6156*4882a593Smuzhiyun /**
6157*4882a593Smuzhiyun * tep_print_event - Write various event information
6158*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
6159*4882a593Smuzhiyun * @s: the trace_seq to write to
6160*4882a593Smuzhiyun * @record: The record to get the event from
6161*4882a593Smuzhiyun * @format: a printf format string. Supported event fileds:
6162*4882a593Smuzhiyun * TEP_PRINT_PID, "%d" - event PID
6163*4882a593Smuzhiyun * TEP_PRINT_CPU, "%d" - event CPU
6164*4882a593Smuzhiyun * TEP_PRINT_COMM, "%s" - event command string
6165*4882a593Smuzhiyun * TEP_PRINT_NAME, "%s" - event name
6166*4882a593Smuzhiyun * TEP_PRINT_LATENCY, "%s" - event latency
6167*4882a593Smuzhiyun * TEP_PRINT_TIME, %d - event time stamp. A divisor and precision
6168*4882a593Smuzhiyun * can be specified as part of this format string:
6169*4882a593Smuzhiyun * "%precision.divisord". Example:
6170*4882a593Smuzhiyun * "%3.1000d" - divide the time by 1000 and print the first
6171*4882a593Smuzhiyun * 3 digits before the dot. Thus, the time stamp
6172*4882a593Smuzhiyun * "123456000" will be printed as "123.456"
6173*4882a593Smuzhiyun * TEP_PRINT_INFO, "%s" - event information. If any width is specified in
6174*4882a593Smuzhiyun * the format string, the event information will be printed
6175*4882a593Smuzhiyun * in raw format.
6176*4882a593Smuzhiyun * Writes the specified event information into @s.
6177*4882a593Smuzhiyun */
tep_print_event(struct tep_handle * tep,struct trace_seq * s,struct tep_record * record,const char * fmt,...)6178*4882a593Smuzhiyun void tep_print_event(struct tep_handle *tep, struct trace_seq *s,
6179*4882a593Smuzhiyun struct tep_record *record, const char *fmt, ...)
6180*4882a593Smuzhiyun {
6181*4882a593Smuzhiyun struct print_event_type type;
6182*4882a593Smuzhiyun char *format = strdup(fmt);
6183*4882a593Smuzhiyun char *current = format;
6184*4882a593Smuzhiyun char *str = format;
6185*4882a593Smuzhiyun int offset;
6186*4882a593Smuzhiyun va_list args;
6187*4882a593Smuzhiyun struct tep_event *event;
6188*4882a593Smuzhiyun
6189*4882a593Smuzhiyun if (!format)
6190*4882a593Smuzhiyun return;
6191*4882a593Smuzhiyun
6192*4882a593Smuzhiyun event = tep_find_event_by_record(tep, record);
6193*4882a593Smuzhiyun va_start(args, fmt);
6194*4882a593Smuzhiyun while (*current) {
6195*4882a593Smuzhiyun current = strchr(str, '%');
6196*4882a593Smuzhiyun if (!current) {
6197*4882a593Smuzhiyun trace_seq_puts(s, str);
6198*4882a593Smuzhiyun break;
6199*4882a593Smuzhiyun }
6200*4882a593Smuzhiyun memset(&type, 0, sizeof(type));
6201*4882a593Smuzhiyun offset = tep_print_event_param_type(current, &type);
6202*4882a593Smuzhiyun *current = '\0';
6203*4882a593Smuzhiyun trace_seq_puts(s, str);
6204*4882a593Smuzhiyun current += offset;
6205*4882a593Smuzhiyun switch (type.type) {
6206*4882a593Smuzhiyun case EVENT_TYPE_STRING:
6207*4882a593Smuzhiyun print_string(tep, s, record, event,
6208*4882a593Smuzhiyun va_arg(args, char*), &type);
6209*4882a593Smuzhiyun break;
6210*4882a593Smuzhiyun case EVENT_TYPE_INT:
6211*4882a593Smuzhiyun print_int(tep, s, record, event,
6212*4882a593Smuzhiyun va_arg(args, int), &type);
6213*4882a593Smuzhiyun break;
6214*4882a593Smuzhiyun case EVENT_TYPE_UNKNOWN:
6215*4882a593Smuzhiyun default:
6216*4882a593Smuzhiyun trace_seq_printf(s, "[UNKNOWN TYPE]");
6217*4882a593Smuzhiyun break;
6218*4882a593Smuzhiyun }
6219*4882a593Smuzhiyun str = current;
6220*4882a593Smuzhiyun
6221*4882a593Smuzhiyun }
6222*4882a593Smuzhiyun va_end(args);
6223*4882a593Smuzhiyun free(format);
6224*4882a593Smuzhiyun }
6225*4882a593Smuzhiyun
events_id_cmp(const void * a,const void * b)6226*4882a593Smuzhiyun static int events_id_cmp(const void *a, const void *b)
6227*4882a593Smuzhiyun {
6228*4882a593Smuzhiyun struct tep_event * const * ea = a;
6229*4882a593Smuzhiyun struct tep_event * const * eb = b;
6230*4882a593Smuzhiyun
6231*4882a593Smuzhiyun if ((*ea)->id < (*eb)->id)
6232*4882a593Smuzhiyun return -1;
6233*4882a593Smuzhiyun
6234*4882a593Smuzhiyun if ((*ea)->id > (*eb)->id)
6235*4882a593Smuzhiyun return 1;
6236*4882a593Smuzhiyun
6237*4882a593Smuzhiyun return 0;
6238*4882a593Smuzhiyun }
6239*4882a593Smuzhiyun
events_name_cmp(const void * a,const void * b)6240*4882a593Smuzhiyun static int events_name_cmp(const void *a, const void *b)
6241*4882a593Smuzhiyun {
6242*4882a593Smuzhiyun struct tep_event * const * ea = a;
6243*4882a593Smuzhiyun struct tep_event * const * eb = b;
6244*4882a593Smuzhiyun int res;
6245*4882a593Smuzhiyun
6246*4882a593Smuzhiyun res = strcmp((*ea)->name, (*eb)->name);
6247*4882a593Smuzhiyun if (res)
6248*4882a593Smuzhiyun return res;
6249*4882a593Smuzhiyun
6250*4882a593Smuzhiyun res = strcmp((*ea)->system, (*eb)->system);
6251*4882a593Smuzhiyun if (res)
6252*4882a593Smuzhiyun return res;
6253*4882a593Smuzhiyun
6254*4882a593Smuzhiyun return events_id_cmp(a, b);
6255*4882a593Smuzhiyun }
6256*4882a593Smuzhiyun
events_system_cmp(const void * a,const void * b)6257*4882a593Smuzhiyun static int events_system_cmp(const void *a, const void *b)
6258*4882a593Smuzhiyun {
6259*4882a593Smuzhiyun struct tep_event * const * ea = a;
6260*4882a593Smuzhiyun struct tep_event * const * eb = b;
6261*4882a593Smuzhiyun int res;
6262*4882a593Smuzhiyun
6263*4882a593Smuzhiyun res = strcmp((*ea)->system, (*eb)->system);
6264*4882a593Smuzhiyun if (res)
6265*4882a593Smuzhiyun return res;
6266*4882a593Smuzhiyun
6267*4882a593Smuzhiyun res = strcmp((*ea)->name, (*eb)->name);
6268*4882a593Smuzhiyun if (res)
6269*4882a593Smuzhiyun return res;
6270*4882a593Smuzhiyun
6271*4882a593Smuzhiyun return events_id_cmp(a, b);
6272*4882a593Smuzhiyun }
6273*4882a593Smuzhiyun
list_events_copy(struct tep_handle * tep)6274*4882a593Smuzhiyun static struct tep_event **list_events_copy(struct tep_handle *tep)
6275*4882a593Smuzhiyun {
6276*4882a593Smuzhiyun struct tep_event **events;
6277*4882a593Smuzhiyun
6278*4882a593Smuzhiyun if (!tep)
6279*4882a593Smuzhiyun return NULL;
6280*4882a593Smuzhiyun
6281*4882a593Smuzhiyun events = malloc(sizeof(*events) * (tep->nr_events + 1));
6282*4882a593Smuzhiyun if (!events)
6283*4882a593Smuzhiyun return NULL;
6284*4882a593Smuzhiyun
6285*4882a593Smuzhiyun memcpy(events, tep->events, sizeof(*events) * tep->nr_events);
6286*4882a593Smuzhiyun events[tep->nr_events] = NULL;
6287*4882a593Smuzhiyun return events;
6288*4882a593Smuzhiyun }
6289*4882a593Smuzhiyun
list_events_sort(struct tep_event ** events,int nr_events,enum tep_event_sort_type sort_type)6290*4882a593Smuzhiyun static void list_events_sort(struct tep_event **events, int nr_events,
6291*4882a593Smuzhiyun enum tep_event_sort_type sort_type)
6292*4882a593Smuzhiyun {
6293*4882a593Smuzhiyun int (*sort)(const void *a, const void *b);
6294*4882a593Smuzhiyun
6295*4882a593Smuzhiyun switch (sort_type) {
6296*4882a593Smuzhiyun case TEP_EVENT_SORT_ID:
6297*4882a593Smuzhiyun sort = events_id_cmp;
6298*4882a593Smuzhiyun break;
6299*4882a593Smuzhiyun case TEP_EVENT_SORT_NAME:
6300*4882a593Smuzhiyun sort = events_name_cmp;
6301*4882a593Smuzhiyun break;
6302*4882a593Smuzhiyun case TEP_EVENT_SORT_SYSTEM:
6303*4882a593Smuzhiyun sort = events_system_cmp;
6304*4882a593Smuzhiyun break;
6305*4882a593Smuzhiyun default:
6306*4882a593Smuzhiyun sort = NULL;
6307*4882a593Smuzhiyun }
6308*4882a593Smuzhiyun
6309*4882a593Smuzhiyun if (sort)
6310*4882a593Smuzhiyun qsort(events, nr_events, sizeof(*events), sort);
6311*4882a593Smuzhiyun }
6312*4882a593Smuzhiyun
6313*4882a593Smuzhiyun /**
6314*4882a593Smuzhiyun * tep_list_events - Get events, sorted by given criteria.
6315*4882a593Smuzhiyun * @tep: a handle to the tep context
6316*4882a593Smuzhiyun * @sort_type: desired sort order of the events in the array
6317*4882a593Smuzhiyun *
6318*4882a593Smuzhiyun * Returns an array of pointers to all events, sorted by the given
6319*4882a593Smuzhiyun * @sort_type criteria. The last element of the array is NULL. The returned
6320*4882a593Smuzhiyun * memory must not be freed, it is managed by the library.
6321*4882a593Smuzhiyun * The function is not thread safe.
6322*4882a593Smuzhiyun */
tep_list_events(struct tep_handle * tep,enum tep_event_sort_type sort_type)6323*4882a593Smuzhiyun struct tep_event **tep_list_events(struct tep_handle *tep,
6324*4882a593Smuzhiyun enum tep_event_sort_type sort_type)
6325*4882a593Smuzhiyun {
6326*4882a593Smuzhiyun struct tep_event **events;
6327*4882a593Smuzhiyun
6328*4882a593Smuzhiyun if (!tep)
6329*4882a593Smuzhiyun return NULL;
6330*4882a593Smuzhiyun
6331*4882a593Smuzhiyun events = tep->sort_events;
6332*4882a593Smuzhiyun if (events && tep->last_type == sort_type)
6333*4882a593Smuzhiyun return events;
6334*4882a593Smuzhiyun
6335*4882a593Smuzhiyun if (!events) {
6336*4882a593Smuzhiyun events = list_events_copy(tep);
6337*4882a593Smuzhiyun if (!events)
6338*4882a593Smuzhiyun return NULL;
6339*4882a593Smuzhiyun
6340*4882a593Smuzhiyun tep->sort_events = events;
6341*4882a593Smuzhiyun
6342*4882a593Smuzhiyun /* the internal events are sorted by id */
6343*4882a593Smuzhiyun if (sort_type == TEP_EVENT_SORT_ID) {
6344*4882a593Smuzhiyun tep->last_type = sort_type;
6345*4882a593Smuzhiyun return events;
6346*4882a593Smuzhiyun }
6347*4882a593Smuzhiyun }
6348*4882a593Smuzhiyun
6349*4882a593Smuzhiyun list_events_sort(events, tep->nr_events, sort_type);
6350*4882a593Smuzhiyun tep->last_type = sort_type;
6351*4882a593Smuzhiyun
6352*4882a593Smuzhiyun return events;
6353*4882a593Smuzhiyun }
6354*4882a593Smuzhiyun
6355*4882a593Smuzhiyun
6356*4882a593Smuzhiyun /**
6357*4882a593Smuzhiyun * tep_list_events_copy - Thread safe version of tep_list_events()
6358*4882a593Smuzhiyun * @tep: a handle to the tep context
6359*4882a593Smuzhiyun * @sort_type: desired sort order of the events in the array
6360*4882a593Smuzhiyun *
6361*4882a593Smuzhiyun * Returns an array of pointers to all events, sorted by the given
6362*4882a593Smuzhiyun * @sort_type criteria. The last element of the array is NULL. The returned
6363*4882a593Smuzhiyun * array is newly allocated inside the function and must be freed by the caller
6364*4882a593Smuzhiyun */
tep_list_events_copy(struct tep_handle * tep,enum tep_event_sort_type sort_type)6365*4882a593Smuzhiyun struct tep_event **tep_list_events_copy(struct tep_handle *tep,
6366*4882a593Smuzhiyun enum tep_event_sort_type sort_type)
6367*4882a593Smuzhiyun {
6368*4882a593Smuzhiyun struct tep_event **events;
6369*4882a593Smuzhiyun
6370*4882a593Smuzhiyun if (!tep)
6371*4882a593Smuzhiyun return NULL;
6372*4882a593Smuzhiyun
6373*4882a593Smuzhiyun events = list_events_copy(tep);
6374*4882a593Smuzhiyun if (!events)
6375*4882a593Smuzhiyun return NULL;
6376*4882a593Smuzhiyun
6377*4882a593Smuzhiyun /* the internal events are sorted by id */
6378*4882a593Smuzhiyun if (sort_type == TEP_EVENT_SORT_ID)
6379*4882a593Smuzhiyun return events;
6380*4882a593Smuzhiyun
6381*4882a593Smuzhiyun list_events_sort(events, tep->nr_events, sort_type);
6382*4882a593Smuzhiyun
6383*4882a593Smuzhiyun return events;
6384*4882a593Smuzhiyun }
6385*4882a593Smuzhiyun
6386*4882a593Smuzhiyun static struct tep_format_field **
get_event_fields(const char * type,const char * name,int count,struct tep_format_field * list)6387*4882a593Smuzhiyun get_event_fields(const char *type, const char *name,
6388*4882a593Smuzhiyun int count, struct tep_format_field *list)
6389*4882a593Smuzhiyun {
6390*4882a593Smuzhiyun struct tep_format_field **fields;
6391*4882a593Smuzhiyun struct tep_format_field *field;
6392*4882a593Smuzhiyun int i = 0;
6393*4882a593Smuzhiyun
6394*4882a593Smuzhiyun fields = malloc(sizeof(*fields) * (count + 1));
6395*4882a593Smuzhiyun if (!fields)
6396*4882a593Smuzhiyun return NULL;
6397*4882a593Smuzhiyun
6398*4882a593Smuzhiyun for (field = list; field; field = field->next) {
6399*4882a593Smuzhiyun fields[i++] = field;
6400*4882a593Smuzhiyun if (i == count + 1) {
6401*4882a593Smuzhiyun do_warning("event %s has more %s fields than specified",
6402*4882a593Smuzhiyun name, type);
6403*4882a593Smuzhiyun i--;
6404*4882a593Smuzhiyun break;
6405*4882a593Smuzhiyun }
6406*4882a593Smuzhiyun }
6407*4882a593Smuzhiyun
6408*4882a593Smuzhiyun if (i != count)
6409*4882a593Smuzhiyun do_warning("event %s has less %s fields than specified",
6410*4882a593Smuzhiyun name, type);
6411*4882a593Smuzhiyun
6412*4882a593Smuzhiyun fields[i] = NULL;
6413*4882a593Smuzhiyun
6414*4882a593Smuzhiyun return fields;
6415*4882a593Smuzhiyun }
6416*4882a593Smuzhiyun
6417*4882a593Smuzhiyun /**
6418*4882a593Smuzhiyun * tep_event_common_fields - return a list of common fields for an event
6419*4882a593Smuzhiyun * @event: the event to return the common fields of.
6420*4882a593Smuzhiyun *
6421*4882a593Smuzhiyun * Returns an allocated array of fields. The last item in the array is NULL.
6422*4882a593Smuzhiyun * The array must be freed with free().
6423*4882a593Smuzhiyun */
tep_event_common_fields(struct tep_event * event)6424*4882a593Smuzhiyun struct tep_format_field **tep_event_common_fields(struct tep_event *event)
6425*4882a593Smuzhiyun {
6426*4882a593Smuzhiyun return get_event_fields("common", event->name,
6427*4882a593Smuzhiyun event->format.nr_common,
6428*4882a593Smuzhiyun event->format.common_fields);
6429*4882a593Smuzhiyun }
6430*4882a593Smuzhiyun
6431*4882a593Smuzhiyun /**
6432*4882a593Smuzhiyun * tep_event_fields - return a list of event specific fields for an event
6433*4882a593Smuzhiyun * @event: the event to return the fields of.
6434*4882a593Smuzhiyun *
6435*4882a593Smuzhiyun * Returns an allocated array of fields. The last item in the array is NULL.
6436*4882a593Smuzhiyun * The array must be freed with free().
6437*4882a593Smuzhiyun */
tep_event_fields(struct tep_event * event)6438*4882a593Smuzhiyun struct tep_format_field **tep_event_fields(struct tep_event *event)
6439*4882a593Smuzhiyun {
6440*4882a593Smuzhiyun return get_event_fields("event", event->name,
6441*4882a593Smuzhiyun event->format.nr_fields,
6442*4882a593Smuzhiyun event->format.fields);
6443*4882a593Smuzhiyun }
6444*4882a593Smuzhiyun
print_fields(struct trace_seq * s,struct tep_print_flag_sym * field)6445*4882a593Smuzhiyun static void print_fields(struct trace_seq *s, struct tep_print_flag_sym *field)
6446*4882a593Smuzhiyun {
6447*4882a593Smuzhiyun trace_seq_printf(s, "{ %s, %s }", field->value, field->str);
6448*4882a593Smuzhiyun if (field->next) {
6449*4882a593Smuzhiyun trace_seq_puts(s, ", ");
6450*4882a593Smuzhiyun print_fields(s, field->next);
6451*4882a593Smuzhiyun }
6452*4882a593Smuzhiyun }
6453*4882a593Smuzhiyun
6454*4882a593Smuzhiyun /* for debugging */
print_args(struct tep_print_arg * args)6455*4882a593Smuzhiyun static void print_args(struct tep_print_arg *args)
6456*4882a593Smuzhiyun {
6457*4882a593Smuzhiyun int print_paren = 1;
6458*4882a593Smuzhiyun struct trace_seq s;
6459*4882a593Smuzhiyun
6460*4882a593Smuzhiyun switch (args->type) {
6461*4882a593Smuzhiyun case TEP_PRINT_NULL:
6462*4882a593Smuzhiyun printf("null");
6463*4882a593Smuzhiyun break;
6464*4882a593Smuzhiyun case TEP_PRINT_ATOM:
6465*4882a593Smuzhiyun printf("%s", args->atom.atom);
6466*4882a593Smuzhiyun break;
6467*4882a593Smuzhiyun case TEP_PRINT_FIELD:
6468*4882a593Smuzhiyun printf("REC->%s", args->field.name);
6469*4882a593Smuzhiyun break;
6470*4882a593Smuzhiyun case TEP_PRINT_FLAGS:
6471*4882a593Smuzhiyun printf("__print_flags(");
6472*4882a593Smuzhiyun print_args(args->flags.field);
6473*4882a593Smuzhiyun printf(", %s, ", args->flags.delim);
6474*4882a593Smuzhiyun trace_seq_init(&s);
6475*4882a593Smuzhiyun print_fields(&s, args->flags.flags);
6476*4882a593Smuzhiyun trace_seq_do_printf(&s);
6477*4882a593Smuzhiyun trace_seq_destroy(&s);
6478*4882a593Smuzhiyun printf(")");
6479*4882a593Smuzhiyun break;
6480*4882a593Smuzhiyun case TEP_PRINT_SYMBOL:
6481*4882a593Smuzhiyun printf("__print_symbolic(");
6482*4882a593Smuzhiyun print_args(args->symbol.field);
6483*4882a593Smuzhiyun printf(", ");
6484*4882a593Smuzhiyun trace_seq_init(&s);
6485*4882a593Smuzhiyun print_fields(&s, args->symbol.symbols);
6486*4882a593Smuzhiyun trace_seq_do_printf(&s);
6487*4882a593Smuzhiyun trace_seq_destroy(&s);
6488*4882a593Smuzhiyun printf(")");
6489*4882a593Smuzhiyun break;
6490*4882a593Smuzhiyun case TEP_PRINT_HEX:
6491*4882a593Smuzhiyun printf("__print_hex(");
6492*4882a593Smuzhiyun print_args(args->hex.field);
6493*4882a593Smuzhiyun printf(", ");
6494*4882a593Smuzhiyun print_args(args->hex.size);
6495*4882a593Smuzhiyun printf(")");
6496*4882a593Smuzhiyun break;
6497*4882a593Smuzhiyun case TEP_PRINT_HEX_STR:
6498*4882a593Smuzhiyun printf("__print_hex_str(");
6499*4882a593Smuzhiyun print_args(args->hex.field);
6500*4882a593Smuzhiyun printf(", ");
6501*4882a593Smuzhiyun print_args(args->hex.size);
6502*4882a593Smuzhiyun printf(")");
6503*4882a593Smuzhiyun break;
6504*4882a593Smuzhiyun case TEP_PRINT_INT_ARRAY:
6505*4882a593Smuzhiyun printf("__print_array(");
6506*4882a593Smuzhiyun print_args(args->int_array.field);
6507*4882a593Smuzhiyun printf(", ");
6508*4882a593Smuzhiyun print_args(args->int_array.count);
6509*4882a593Smuzhiyun printf(", ");
6510*4882a593Smuzhiyun print_args(args->int_array.el_size);
6511*4882a593Smuzhiyun printf(")");
6512*4882a593Smuzhiyun break;
6513*4882a593Smuzhiyun case TEP_PRINT_STRING:
6514*4882a593Smuzhiyun case TEP_PRINT_BSTRING:
6515*4882a593Smuzhiyun printf("__get_str(%s)", args->string.string);
6516*4882a593Smuzhiyun break;
6517*4882a593Smuzhiyun case TEP_PRINT_BITMASK:
6518*4882a593Smuzhiyun printf("__get_bitmask(%s)", args->bitmask.bitmask);
6519*4882a593Smuzhiyun break;
6520*4882a593Smuzhiyun case TEP_PRINT_TYPE:
6521*4882a593Smuzhiyun printf("(%s)", args->typecast.type);
6522*4882a593Smuzhiyun print_args(args->typecast.item);
6523*4882a593Smuzhiyun break;
6524*4882a593Smuzhiyun case TEP_PRINT_OP:
6525*4882a593Smuzhiyun if (strcmp(args->op.op, ":") == 0)
6526*4882a593Smuzhiyun print_paren = 0;
6527*4882a593Smuzhiyun if (print_paren)
6528*4882a593Smuzhiyun printf("(");
6529*4882a593Smuzhiyun print_args(args->op.left);
6530*4882a593Smuzhiyun printf(" %s ", args->op.op);
6531*4882a593Smuzhiyun print_args(args->op.right);
6532*4882a593Smuzhiyun if (print_paren)
6533*4882a593Smuzhiyun printf(")");
6534*4882a593Smuzhiyun break;
6535*4882a593Smuzhiyun default:
6536*4882a593Smuzhiyun /* we should warn... */
6537*4882a593Smuzhiyun return;
6538*4882a593Smuzhiyun }
6539*4882a593Smuzhiyun if (args->next) {
6540*4882a593Smuzhiyun printf("\n");
6541*4882a593Smuzhiyun print_args(args->next);
6542*4882a593Smuzhiyun }
6543*4882a593Smuzhiyun }
6544*4882a593Smuzhiyun
parse_header_field(const char * field,int * offset,int * size,int mandatory)6545*4882a593Smuzhiyun static void parse_header_field(const char *field,
6546*4882a593Smuzhiyun int *offset, int *size, int mandatory)
6547*4882a593Smuzhiyun {
6548*4882a593Smuzhiyun unsigned long long save_input_buf_ptr;
6549*4882a593Smuzhiyun unsigned long long save_input_buf_siz;
6550*4882a593Smuzhiyun char *token;
6551*4882a593Smuzhiyun int type;
6552*4882a593Smuzhiyun
6553*4882a593Smuzhiyun save_input_buf_ptr = input_buf_ptr;
6554*4882a593Smuzhiyun save_input_buf_siz = input_buf_siz;
6555*4882a593Smuzhiyun
6556*4882a593Smuzhiyun if (read_expected(TEP_EVENT_ITEM, "field") < 0)
6557*4882a593Smuzhiyun return;
6558*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ":") < 0)
6559*4882a593Smuzhiyun return;
6560*4882a593Smuzhiyun
6561*4882a593Smuzhiyun /* type */
6562*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
6563*4882a593Smuzhiyun goto fail;
6564*4882a593Smuzhiyun free_token(token);
6565*4882a593Smuzhiyun
6566*4882a593Smuzhiyun /*
6567*4882a593Smuzhiyun * If this is not a mandatory field, then test it first.
6568*4882a593Smuzhiyun */
6569*4882a593Smuzhiyun if (mandatory) {
6570*4882a593Smuzhiyun if (read_expected(TEP_EVENT_ITEM, field) < 0)
6571*4882a593Smuzhiyun return;
6572*4882a593Smuzhiyun } else {
6573*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
6574*4882a593Smuzhiyun goto fail;
6575*4882a593Smuzhiyun if (strcmp(token, field) != 0)
6576*4882a593Smuzhiyun goto discard;
6577*4882a593Smuzhiyun free_token(token);
6578*4882a593Smuzhiyun }
6579*4882a593Smuzhiyun
6580*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ";") < 0)
6581*4882a593Smuzhiyun return;
6582*4882a593Smuzhiyun if (read_expected(TEP_EVENT_ITEM, "offset") < 0)
6583*4882a593Smuzhiyun return;
6584*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ":") < 0)
6585*4882a593Smuzhiyun return;
6586*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
6587*4882a593Smuzhiyun goto fail;
6588*4882a593Smuzhiyun *offset = atoi(token);
6589*4882a593Smuzhiyun free_token(token);
6590*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ";") < 0)
6591*4882a593Smuzhiyun return;
6592*4882a593Smuzhiyun if (read_expected(TEP_EVENT_ITEM, "size") < 0)
6593*4882a593Smuzhiyun return;
6594*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ":") < 0)
6595*4882a593Smuzhiyun return;
6596*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_ITEM, &token) < 0)
6597*4882a593Smuzhiyun goto fail;
6598*4882a593Smuzhiyun *size = atoi(token);
6599*4882a593Smuzhiyun free_token(token);
6600*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ";") < 0)
6601*4882a593Smuzhiyun return;
6602*4882a593Smuzhiyun type = read_token(&token);
6603*4882a593Smuzhiyun if (type != TEP_EVENT_NEWLINE) {
6604*4882a593Smuzhiyun /* newer versions of the kernel have a "signed" type */
6605*4882a593Smuzhiyun if (type != TEP_EVENT_ITEM)
6606*4882a593Smuzhiyun goto fail;
6607*4882a593Smuzhiyun
6608*4882a593Smuzhiyun if (strcmp(token, "signed") != 0)
6609*4882a593Smuzhiyun goto fail;
6610*4882a593Smuzhiyun
6611*4882a593Smuzhiyun free_token(token);
6612*4882a593Smuzhiyun
6613*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ":") < 0)
6614*4882a593Smuzhiyun return;
6615*4882a593Smuzhiyun
6616*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_ITEM, &token))
6617*4882a593Smuzhiyun goto fail;
6618*4882a593Smuzhiyun
6619*4882a593Smuzhiyun free_token(token);
6620*4882a593Smuzhiyun if (read_expected(TEP_EVENT_OP, ";") < 0)
6621*4882a593Smuzhiyun return;
6622*4882a593Smuzhiyun
6623*4882a593Smuzhiyun if (read_expect_type(TEP_EVENT_NEWLINE, &token))
6624*4882a593Smuzhiyun goto fail;
6625*4882a593Smuzhiyun }
6626*4882a593Smuzhiyun fail:
6627*4882a593Smuzhiyun free_token(token);
6628*4882a593Smuzhiyun return;
6629*4882a593Smuzhiyun
6630*4882a593Smuzhiyun discard:
6631*4882a593Smuzhiyun input_buf_ptr = save_input_buf_ptr;
6632*4882a593Smuzhiyun input_buf_siz = save_input_buf_siz;
6633*4882a593Smuzhiyun *offset = 0;
6634*4882a593Smuzhiyun *size = 0;
6635*4882a593Smuzhiyun free_token(token);
6636*4882a593Smuzhiyun }
6637*4882a593Smuzhiyun
6638*4882a593Smuzhiyun /**
6639*4882a593Smuzhiyun * tep_parse_header_page - parse the data stored in the header page
6640*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
6641*4882a593Smuzhiyun * @buf: the buffer storing the header page format string
6642*4882a593Smuzhiyun * @size: the size of @buf
6643*4882a593Smuzhiyun * @long_size: the long size to use if there is no header
6644*4882a593Smuzhiyun *
6645*4882a593Smuzhiyun * This parses the header page format for information on the
6646*4882a593Smuzhiyun * ring buffer used. The @buf should be copied from
6647*4882a593Smuzhiyun *
6648*4882a593Smuzhiyun * /sys/kernel/debug/tracing/events/header_page
6649*4882a593Smuzhiyun */
tep_parse_header_page(struct tep_handle * tep,char * buf,unsigned long size,int long_size)6650*4882a593Smuzhiyun int tep_parse_header_page(struct tep_handle *tep, char *buf, unsigned long size,
6651*4882a593Smuzhiyun int long_size)
6652*4882a593Smuzhiyun {
6653*4882a593Smuzhiyun int ignore;
6654*4882a593Smuzhiyun
6655*4882a593Smuzhiyun if (!size) {
6656*4882a593Smuzhiyun /*
6657*4882a593Smuzhiyun * Old kernels did not have header page info.
6658*4882a593Smuzhiyun * Sorry but we just use what we find here in user space.
6659*4882a593Smuzhiyun */
6660*4882a593Smuzhiyun tep->header_page_ts_size = sizeof(long long);
6661*4882a593Smuzhiyun tep->header_page_size_size = long_size;
6662*4882a593Smuzhiyun tep->header_page_data_offset = sizeof(long long) + long_size;
6663*4882a593Smuzhiyun tep->old_format = 1;
6664*4882a593Smuzhiyun return -1;
6665*4882a593Smuzhiyun }
6666*4882a593Smuzhiyun init_input_buf(buf, size);
6667*4882a593Smuzhiyun
6668*4882a593Smuzhiyun parse_header_field("timestamp", &tep->header_page_ts_offset,
6669*4882a593Smuzhiyun &tep->header_page_ts_size, 1);
6670*4882a593Smuzhiyun parse_header_field("commit", &tep->header_page_size_offset,
6671*4882a593Smuzhiyun &tep->header_page_size_size, 1);
6672*4882a593Smuzhiyun parse_header_field("overwrite", &tep->header_page_overwrite,
6673*4882a593Smuzhiyun &ignore, 0);
6674*4882a593Smuzhiyun parse_header_field("data", &tep->header_page_data_offset,
6675*4882a593Smuzhiyun &tep->header_page_data_size, 1);
6676*4882a593Smuzhiyun
6677*4882a593Smuzhiyun return 0;
6678*4882a593Smuzhiyun }
6679*4882a593Smuzhiyun
event_matches(struct tep_event * event,int id,const char * sys_name,const char * event_name)6680*4882a593Smuzhiyun static int event_matches(struct tep_event *event,
6681*4882a593Smuzhiyun int id, const char *sys_name,
6682*4882a593Smuzhiyun const char *event_name)
6683*4882a593Smuzhiyun {
6684*4882a593Smuzhiyun if (id >= 0 && id != event->id)
6685*4882a593Smuzhiyun return 0;
6686*4882a593Smuzhiyun
6687*4882a593Smuzhiyun if (event_name && (strcmp(event_name, event->name) != 0))
6688*4882a593Smuzhiyun return 0;
6689*4882a593Smuzhiyun
6690*4882a593Smuzhiyun if (sys_name && (strcmp(sys_name, event->system) != 0))
6691*4882a593Smuzhiyun return 0;
6692*4882a593Smuzhiyun
6693*4882a593Smuzhiyun return 1;
6694*4882a593Smuzhiyun }
6695*4882a593Smuzhiyun
free_handler(struct event_handler * handle)6696*4882a593Smuzhiyun static void free_handler(struct event_handler *handle)
6697*4882a593Smuzhiyun {
6698*4882a593Smuzhiyun free((void *)handle->sys_name);
6699*4882a593Smuzhiyun free((void *)handle->event_name);
6700*4882a593Smuzhiyun free(handle);
6701*4882a593Smuzhiyun }
6702*4882a593Smuzhiyun
find_event_handle(struct tep_handle * tep,struct tep_event * event)6703*4882a593Smuzhiyun static int find_event_handle(struct tep_handle *tep, struct tep_event *event)
6704*4882a593Smuzhiyun {
6705*4882a593Smuzhiyun struct event_handler *handle, **next;
6706*4882a593Smuzhiyun
6707*4882a593Smuzhiyun for (next = &tep->handlers; *next;
6708*4882a593Smuzhiyun next = &(*next)->next) {
6709*4882a593Smuzhiyun handle = *next;
6710*4882a593Smuzhiyun if (event_matches(event, handle->id,
6711*4882a593Smuzhiyun handle->sys_name,
6712*4882a593Smuzhiyun handle->event_name))
6713*4882a593Smuzhiyun break;
6714*4882a593Smuzhiyun }
6715*4882a593Smuzhiyun
6716*4882a593Smuzhiyun if (!(*next))
6717*4882a593Smuzhiyun return 0;
6718*4882a593Smuzhiyun
6719*4882a593Smuzhiyun pr_stat("overriding event (%d) %s:%s with new print handler",
6720*4882a593Smuzhiyun event->id, event->system, event->name);
6721*4882a593Smuzhiyun
6722*4882a593Smuzhiyun event->handler = handle->func;
6723*4882a593Smuzhiyun event->context = handle->context;
6724*4882a593Smuzhiyun
6725*4882a593Smuzhiyun *next = handle->next;
6726*4882a593Smuzhiyun free_handler(handle);
6727*4882a593Smuzhiyun
6728*4882a593Smuzhiyun return 1;
6729*4882a593Smuzhiyun }
6730*4882a593Smuzhiyun
6731*4882a593Smuzhiyun /**
6732*4882a593Smuzhiyun * parse_format - parse the event format
6733*4882a593Smuzhiyun * @buf: the buffer storing the event format string
6734*4882a593Smuzhiyun * @size: the size of @buf
6735*4882a593Smuzhiyun * @sys: the system the event belongs to
6736*4882a593Smuzhiyun *
6737*4882a593Smuzhiyun * This parses the event format and creates an event structure
6738*4882a593Smuzhiyun * to quickly parse raw data for a given event.
6739*4882a593Smuzhiyun *
6740*4882a593Smuzhiyun * These files currently come from:
6741*4882a593Smuzhiyun *
6742*4882a593Smuzhiyun * /sys/kernel/debug/tracing/events/.../.../format
6743*4882a593Smuzhiyun */
parse_format(struct tep_event ** eventp,struct tep_handle * tep,const char * buf,unsigned long size,const char * sys)6744*4882a593Smuzhiyun static enum tep_errno parse_format(struct tep_event **eventp,
6745*4882a593Smuzhiyun struct tep_handle *tep, const char *buf,
6746*4882a593Smuzhiyun unsigned long size, const char *sys)
6747*4882a593Smuzhiyun {
6748*4882a593Smuzhiyun struct tep_event *event;
6749*4882a593Smuzhiyun int ret;
6750*4882a593Smuzhiyun
6751*4882a593Smuzhiyun init_input_buf(buf, size);
6752*4882a593Smuzhiyun
6753*4882a593Smuzhiyun *eventp = event = alloc_event();
6754*4882a593Smuzhiyun if (!event)
6755*4882a593Smuzhiyun return TEP_ERRNO__MEM_ALLOC_FAILED;
6756*4882a593Smuzhiyun
6757*4882a593Smuzhiyun event->name = event_read_name();
6758*4882a593Smuzhiyun if (!event->name) {
6759*4882a593Smuzhiyun /* Bad event? */
6760*4882a593Smuzhiyun ret = TEP_ERRNO__MEM_ALLOC_FAILED;
6761*4882a593Smuzhiyun goto event_alloc_failed;
6762*4882a593Smuzhiyun }
6763*4882a593Smuzhiyun
6764*4882a593Smuzhiyun if (strcmp(sys, "ftrace") == 0) {
6765*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_ISFTRACE;
6766*4882a593Smuzhiyun
6767*4882a593Smuzhiyun if (strcmp(event->name, "bprint") == 0)
6768*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_ISBPRINT;
6769*4882a593Smuzhiyun }
6770*4882a593Smuzhiyun
6771*4882a593Smuzhiyun event->id = event_read_id();
6772*4882a593Smuzhiyun if (event->id < 0) {
6773*4882a593Smuzhiyun ret = TEP_ERRNO__READ_ID_FAILED;
6774*4882a593Smuzhiyun /*
6775*4882a593Smuzhiyun * This isn't an allocation error actually.
6776*4882a593Smuzhiyun * But as the ID is critical, just bail out.
6777*4882a593Smuzhiyun */
6778*4882a593Smuzhiyun goto event_alloc_failed;
6779*4882a593Smuzhiyun }
6780*4882a593Smuzhiyun
6781*4882a593Smuzhiyun event->system = strdup(sys);
6782*4882a593Smuzhiyun if (!event->system) {
6783*4882a593Smuzhiyun ret = TEP_ERRNO__MEM_ALLOC_FAILED;
6784*4882a593Smuzhiyun goto event_alloc_failed;
6785*4882a593Smuzhiyun }
6786*4882a593Smuzhiyun
6787*4882a593Smuzhiyun /* Add tep to event so that it can be referenced */
6788*4882a593Smuzhiyun event->tep = tep;
6789*4882a593Smuzhiyun
6790*4882a593Smuzhiyun ret = event_read_format(event);
6791*4882a593Smuzhiyun if (ret < 0) {
6792*4882a593Smuzhiyun ret = TEP_ERRNO__READ_FORMAT_FAILED;
6793*4882a593Smuzhiyun goto event_parse_failed;
6794*4882a593Smuzhiyun }
6795*4882a593Smuzhiyun
6796*4882a593Smuzhiyun /*
6797*4882a593Smuzhiyun * If the event has an override, don't print warnings if the event
6798*4882a593Smuzhiyun * print format fails to parse.
6799*4882a593Smuzhiyun */
6800*4882a593Smuzhiyun if (tep && find_event_handle(tep, event))
6801*4882a593Smuzhiyun show_warning = 0;
6802*4882a593Smuzhiyun
6803*4882a593Smuzhiyun ret = event_read_print(event);
6804*4882a593Smuzhiyun show_warning = 1;
6805*4882a593Smuzhiyun
6806*4882a593Smuzhiyun if (ret < 0) {
6807*4882a593Smuzhiyun ret = TEP_ERRNO__READ_PRINT_FAILED;
6808*4882a593Smuzhiyun goto event_parse_failed;
6809*4882a593Smuzhiyun }
6810*4882a593Smuzhiyun
6811*4882a593Smuzhiyun if (!ret && (event->flags & TEP_EVENT_FL_ISFTRACE)) {
6812*4882a593Smuzhiyun struct tep_format_field *field;
6813*4882a593Smuzhiyun struct tep_print_arg *arg, **list;
6814*4882a593Smuzhiyun
6815*4882a593Smuzhiyun /* old ftrace had no args */
6816*4882a593Smuzhiyun list = &event->print_fmt.args;
6817*4882a593Smuzhiyun for (field = event->format.fields; field; field = field->next) {
6818*4882a593Smuzhiyun arg = alloc_arg();
6819*4882a593Smuzhiyun if (!arg) {
6820*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_FAILED;
6821*4882a593Smuzhiyun return TEP_ERRNO__OLD_FTRACE_ARG_FAILED;
6822*4882a593Smuzhiyun }
6823*4882a593Smuzhiyun arg->type = TEP_PRINT_FIELD;
6824*4882a593Smuzhiyun arg->field.name = strdup(field->name);
6825*4882a593Smuzhiyun if (!arg->field.name) {
6826*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_FAILED;
6827*4882a593Smuzhiyun free_arg(arg);
6828*4882a593Smuzhiyun return TEP_ERRNO__OLD_FTRACE_ARG_FAILED;
6829*4882a593Smuzhiyun }
6830*4882a593Smuzhiyun arg->field.field = field;
6831*4882a593Smuzhiyun *list = arg;
6832*4882a593Smuzhiyun list = &arg->next;
6833*4882a593Smuzhiyun }
6834*4882a593Smuzhiyun }
6835*4882a593Smuzhiyun
6836*4882a593Smuzhiyun if (!(event->flags & TEP_EVENT_FL_ISBPRINT))
6837*4882a593Smuzhiyun event->print_fmt.print_cache = parse_args(event,
6838*4882a593Smuzhiyun event->print_fmt.format,
6839*4882a593Smuzhiyun event->print_fmt.args);
6840*4882a593Smuzhiyun
6841*4882a593Smuzhiyun return 0;
6842*4882a593Smuzhiyun
6843*4882a593Smuzhiyun event_parse_failed:
6844*4882a593Smuzhiyun event->flags |= TEP_EVENT_FL_FAILED;
6845*4882a593Smuzhiyun return ret;
6846*4882a593Smuzhiyun
6847*4882a593Smuzhiyun event_alloc_failed:
6848*4882a593Smuzhiyun free(event->system);
6849*4882a593Smuzhiyun free(event->name);
6850*4882a593Smuzhiyun free(event);
6851*4882a593Smuzhiyun *eventp = NULL;
6852*4882a593Smuzhiyun return ret;
6853*4882a593Smuzhiyun }
6854*4882a593Smuzhiyun
6855*4882a593Smuzhiyun static enum tep_errno
__parse_event(struct tep_handle * tep,struct tep_event ** eventp,const char * buf,unsigned long size,const char * sys)6856*4882a593Smuzhiyun __parse_event(struct tep_handle *tep,
6857*4882a593Smuzhiyun struct tep_event **eventp,
6858*4882a593Smuzhiyun const char *buf, unsigned long size,
6859*4882a593Smuzhiyun const char *sys)
6860*4882a593Smuzhiyun {
6861*4882a593Smuzhiyun int ret = parse_format(eventp, tep, buf, size, sys);
6862*4882a593Smuzhiyun struct tep_event *event = *eventp;
6863*4882a593Smuzhiyun
6864*4882a593Smuzhiyun if (event == NULL)
6865*4882a593Smuzhiyun return ret;
6866*4882a593Smuzhiyun
6867*4882a593Smuzhiyun if (tep && add_event(tep, event)) {
6868*4882a593Smuzhiyun ret = TEP_ERRNO__MEM_ALLOC_FAILED;
6869*4882a593Smuzhiyun goto event_add_failed;
6870*4882a593Smuzhiyun }
6871*4882a593Smuzhiyun
6872*4882a593Smuzhiyun #define PRINT_ARGS 0
6873*4882a593Smuzhiyun if (PRINT_ARGS && event->print_fmt.args)
6874*4882a593Smuzhiyun print_args(event->print_fmt.args);
6875*4882a593Smuzhiyun
6876*4882a593Smuzhiyun return 0;
6877*4882a593Smuzhiyun
6878*4882a593Smuzhiyun event_add_failed:
6879*4882a593Smuzhiyun free_tep_event(event);
6880*4882a593Smuzhiyun return ret;
6881*4882a593Smuzhiyun }
6882*4882a593Smuzhiyun
6883*4882a593Smuzhiyun /**
6884*4882a593Smuzhiyun * tep_parse_format - parse the event format
6885*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
6886*4882a593Smuzhiyun * @eventp: returned format
6887*4882a593Smuzhiyun * @buf: the buffer storing the event format string
6888*4882a593Smuzhiyun * @size: the size of @buf
6889*4882a593Smuzhiyun * @sys: the system the event belongs to
6890*4882a593Smuzhiyun *
6891*4882a593Smuzhiyun * This parses the event format and creates an event structure
6892*4882a593Smuzhiyun * to quickly parse raw data for a given event.
6893*4882a593Smuzhiyun *
6894*4882a593Smuzhiyun * These files currently come from:
6895*4882a593Smuzhiyun *
6896*4882a593Smuzhiyun * /sys/kernel/debug/tracing/events/.../.../format
6897*4882a593Smuzhiyun */
tep_parse_format(struct tep_handle * tep,struct tep_event ** eventp,const char * buf,unsigned long size,const char * sys)6898*4882a593Smuzhiyun enum tep_errno tep_parse_format(struct tep_handle *tep,
6899*4882a593Smuzhiyun struct tep_event **eventp,
6900*4882a593Smuzhiyun const char *buf,
6901*4882a593Smuzhiyun unsigned long size, const char *sys)
6902*4882a593Smuzhiyun {
6903*4882a593Smuzhiyun return __parse_event(tep, eventp, buf, size, sys);
6904*4882a593Smuzhiyun }
6905*4882a593Smuzhiyun
6906*4882a593Smuzhiyun /**
6907*4882a593Smuzhiyun * tep_parse_event - parse the event format
6908*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
6909*4882a593Smuzhiyun * @buf: the buffer storing the event format string
6910*4882a593Smuzhiyun * @size: the size of @buf
6911*4882a593Smuzhiyun * @sys: the system the event belongs to
6912*4882a593Smuzhiyun *
6913*4882a593Smuzhiyun * This parses the event format and creates an event structure
6914*4882a593Smuzhiyun * to quickly parse raw data for a given event.
6915*4882a593Smuzhiyun *
6916*4882a593Smuzhiyun * These files currently come from:
6917*4882a593Smuzhiyun *
6918*4882a593Smuzhiyun * /sys/kernel/debug/tracing/events/.../.../format
6919*4882a593Smuzhiyun */
tep_parse_event(struct tep_handle * tep,const char * buf,unsigned long size,const char * sys)6920*4882a593Smuzhiyun enum tep_errno tep_parse_event(struct tep_handle *tep, const char *buf,
6921*4882a593Smuzhiyun unsigned long size, const char *sys)
6922*4882a593Smuzhiyun {
6923*4882a593Smuzhiyun struct tep_event *event = NULL;
6924*4882a593Smuzhiyun return __parse_event(tep, &event, buf, size, sys);
6925*4882a593Smuzhiyun }
6926*4882a593Smuzhiyun
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)6927*4882a593Smuzhiyun int get_field_val(struct trace_seq *s, struct tep_format_field *field,
6928*4882a593Smuzhiyun const char *name, struct tep_record *record,
6929*4882a593Smuzhiyun unsigned long long *val, int err)
6930*4882a593Smuzhiyun {
6931*4882a593Smuzhiyun if (!field) {
6932*4882a593Smuzhiyun if (err)
6933*4882a593Smuzhiyun trace_seq_printf(s, "<CANT FIND FIELD %s>", name);
6934*4882a593Smuzhiyun return -1;
6935*4882a593Smuzhiyun }
6936*4882a593Smuzhiyun
6937*4882a593Smuzhiyun if (tep_read_number_field(field, record->data, val)) {
6938*4882a593Smuzhiyun if (err)
6939*4882a593Smuzhiyun trace_seq_printf(s, " %s=INVALID", name);
6940*4882a593Smuzhiyun return -1;
6941*4882a593Smuzhiyun }
6942*4882a593Smuzhiyun
6943*4882a593Smuzhiyun return 0;
6944*4882a593Smuzhiyun }
6945*4882a593Smuzhiyun
6946*4882a593Smuzhiyun /**
6947*4882a593Smuzhiyun * tep_get_field_raw - return the raw pointer into the data field
6948*4882a593Smuzhiyun * @s: The seq to print to on error
6949*4882a593Smuzhiyun * @event: the event that the field is for
6950*4882a593Smuzhiyun * @name: The name of the field
6951*4882a593Smuzhiyun * @record: The record with the field name.
6952*4882a593Smuzhiyun * @len: place to store the field length.
6953*4882a593Smuzhiyun * @err: print default error if failed.
6954*4882a593Smuzhiyun *
6955*4882a593Smuzhiyun * Returns a pointer into record->data of the field and places
6956*4882a593Smuzhiyun * the length of the field in @len.
6957*4882a593Smuzhiyun *
6958*4882a593Smuzhiyun * On failure, it returns NULL.
6959*4882a593Smuzhiyun */
tep_get_field_raw(struct trace_seq * s,struct tep_event * event,const char * name,struct tep_record * record,int * len,int err)6960*4882a593Smuzhiyun void *tep_get_field_raw(struct trace_seq *s, struct tep_event *event,
6961*4882a593Smuzhiyun const char *name, struct tep_record *record,
6962*4882a593Smuzhiyun int *len, int err)
6963*4882a593Smuzhiyun {
6964*4882a593Smuzhiyun struct tep_format_field *field;
6965*4882a593Smuzhiyun void *data = record->data;
6966*4882a593Smuzhiyun unsigned offset;
6967*4882a593Smuzhiyun int dummy;
6968*4882a593Smuzhiyun
6969*4882a593Smuzhiyun if (!event)
6970*4882a593Smuzhiyun return NULL;
6971*4882a593Smuzhiyun
6972*4882a593Smuzhiyun field = tep_find_field(event, name);
6973*4882a593Smuzhiyun
6974*4882a593Smuzhiyun if (!field) {
6975*4882a593Smuzhiyun if (err)
6976*4882a593Smuzhiyun trace_seq_printf(s, "<CANT FIND FIELD %s>", name);
6977*4882a593Smuzhiyun return NULL;
6978*4882a593Smuzhiyun }
6979*4882a593Smuzhiyun
6980*4882a593Smuzhiyun /* Allow @len to be NULL */
6981*4882a593Smuzhiyun if (!len)
6982*4882a593Smuzhiyun len = &dummy;
6983*4882a593Smuzhiyun
6984*4882a593Smuzhiyun offset = field->offset;
6985*4882a593Smuzhiyun if (field->flags & TEP_FIELD_IS_DYNAMIC) {
6986*4882a593Smuzhiyun offset = tep_read_number(event->tep,
6987*4882a593Smuzhiyun data + offset, field->size);
6988*4882a593Smuzhiyun *len = offset >> 16;
6989*4882a593Smuzhiyun offset &= 0xffff;
6990*4882a593Smuzhiyun } else
6991*4882a593Smuzhiyun *len = field->size;
6992*4882a593Smuzhiyun
6993*4882a593Smuzhiyun return data + offset;
6994*4882a593Smuzhiyun }
6995*4882a593Smuzhiyun
6996*4882a593Smuzhiyun /**
6997*4882a593Smuzhiyun * tep_get_field_val - find a field and return its value
6998*4882a593Smuzhiyun * @s: The seq to print to on error
6999*4882a593Smuzhiyun * @event: the event that the field is for
7000*4882a593Smuzhiyun * @name: The name of the field
7001*4882a593Smuzhiyun * @record: The record with the field name.
7002*4882a593Smuzhiyun * @val: place to store the value of the field.
7003*4882a593Smuzhiyun * @err: print default error if failed.
7004*4882a593Smuzhiyun *
7005*4882a593Smuzhiyun * Returns 0 on success -1 on field not found.
7006*4882a593Smuzhiyun */
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)7007*4882a593Smuzhiyun int tep_get_field_val(struct trace_seq *s, struct tep_event *event,
7008*4882a593Smuzhiyun const char *name, struct tep_record *record,
7009*4882a593Smuzhiyun unsigned long long *val, int err)
7010*4882a593Smuzhiyun {
7011*4882a593Smuzhiyun struct tep_format_field *field;
7012*4882a593Smuzhiyun
7013*4882a593Smuzhiyun if (!event)
7014*4882a593Smuzhiyun return -1;
7015*4882a593Smuzhiyun
7016*4882a593Smuzhiyun field = tep_find_field(event, name);
7017*4882a593Smuzhiyun
7018*4882a593Smuzhiyun return get_field_val(s, field, name, record, val, err);
7019*4882a593Smuzhiyun }
7020*4882a593Smuzhiyun
7021*4882a593Smuzhiyun /**
7022*4882a593Smuzhiyun * tep_get_common_field_val - find a common field and return its value
7023*4882a593Smuzhiyun * @s: The seq to print to on error
7024*4882a593Smuzhiyun * @event: the event that the field is for
7025*4882a593Smuzhiyun * @name: The name of the field
7026*4882a593Smuzhiyun * @record: The record with the field name.
7027*4882a593Smuzhiyun * @val: place to store the value of the field.
7028*4882a593Smuzhiyun * @err: print default error if failed.
7029*4882a593Smuzhiyun *
7030*4882a593Smuzhiyun * Returns 0 on success -1 on field not found.
7031*4882a593Smuzhiyun */
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)7032*4882a593Smuzhiyun int tep_get_common_field_val(struct trace_seq *s, struct tep_event *event,
7033*4882a593Smuzhiyun const char *name, struct tep_record *record,
7034*4882a593Smuzhiyun unsigned long long *val, int err)
7035*4882a593Smuzhiyun {
7036*4882a593Smuzhiyun struct tep_format_field *field;
7037*4882a593Smuzhiyun
7038*4882a593Smuzhiyun if (!event)
7039*4882a593Smuzhiyun return -1;
7040*4882a593Smuzhiyun
7041*4882a593Smuzhiyun field = tep_find_common_field(event, name);
7042*4882a593Smuzhiyun
7043*4882a593Smuzhiyun return get_field_val(s, field, name, record, val, err);
7044*4882a593Smuzhiyun }
7045*4882a593Smuzhiyun
7046*4882a593Smuzhiyun /**
7047*4882a593Smuzhiyun * tep_get_any_field_val - find a any field and return its value
7048*4882a593Smuzhiyun * @s: The seq to print to on error
7049*4882a593Smuzhiyun * @event: the event that the field is for
7050*4882a593Smuzhiyun * @name: The name of the field
7051*4882a593Smuzhiyun * @record: The record with the field name.
7052*4882a593Smuzhiyun * @val: place to store the value of the field.
7053*4882a593Smuzhiyun * @err: print default error if failed.
7054*4882a593Smuzhiyun *
7055*4882a593Smuzhiyun * Returns 0 on success -1 on field not found.
7056*4882a593Smuzhiyun */
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)7057*4882a593Smuzhiyun int tep_get_any_field_val(struct trace_seq *s, struct tep_event *event,
7058*4882a593Smuzhiyun const char *name, struct tep_record *record,
7059*4882a593Smuzhiyun unsigned long long *val, int err)
7060*4882a593Smuzhiyun {
7061*4882a593Smuzhiyun struct tep_format_field *field;
7062*4882a593Smuzhiyun
7063*4882a593Smuzhiyun if (!event)
7064*4882a593Smuzhiyun return -1;
7065*4882a593Smuzhiyun
7066*4882a593Smuzhiyun field = tep_find_any_field(event, name);
7067*4882a593Smuzhiyun
7068*4882a593Smuzhiyun return get_field_val(s, field, name, record, val, err);
7069*4882a593Smuzhiyun }
7070*4882a593Smuzhiyun
7071*4882a593Smuzhiyun /**
7072*4882a593Smuzhiyun * tep_print_num_field - print a field and a format
7073*4882a593Smuzhiyun * @s: The seq to print to
7074*4882a593Smuzhiyun * @fmt: The printf format to print the field with.
7075*4882a593Smuzhiyun * @event: the event that the field is for
7076*4882a593Smuzhiyun * @name: The name of the field
7077*4882a593Smuzhiyun * @record: The record with the field name.
7078*4882a593Smuzhiyun * @err: print default error if failed.
7079*4882a593Smuzhiyun *
7080*4882a593Smuzhiyun * Returns positive value on success, negative in case of an error,
7081*4882a593Smuzhiyun * or 0 if buffer is full.
7082*4882a593Smuzhiyun */
tep_print_num_field(struct trace_seq * s,const char * fmt,struct tep_event * event,const char * name,struct tep_record * record,int err)7083*4882a593Smuzhiyun int tep_print_num_field(struct trace_seq *s, const char *fmt,
7084*4882a593Smuzhiyun struct tep_event *event, const char *name,
7085*4882a593Smuzhiyun struct tep_record *record, int err)
7086*4882a593Smuzhiyun {
7087*4882a593Smuzhiyun struct tep_format_field *field = tep_find_field(event, name);
7088*4882a593Smuzhiyun unsigned long long val;
7089*4882a593Smuzhiyun
7090*4882a593Smuzhiyun if (!field)
7091*4882a593Smuzhiyun goto failed;
7092*4882a593Smuzhiyun
7093*4882a593Smuzhiyun if (tep_read_number_field(field, record->data, &val))
7094*4882a593Smuzhiyun goto failed;
7095*4882a593Smuzhiyun
7096*4882a593Smuzhiyun return trace_seq_printf(s, fmt, val);
7097*4882a593Smuzhiyun
7098*4882a593Smuzhiyun failed:
7099*4882a593Smuzhiyun if (err)
7100*4882a593Smuzhiyun trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
7101*4882a593Smuzhiyun return -1;
7102*4882a593Smuzhiyun }
7103*4882a593Smuzhiyun
7104*4882a593Smuzhiyun /**
7105*4882a593Smuzhiyun * tep_print_func_field - print a field and a format for function pointers
7106*4882a593Smuzhiyun * @s: The seq to print to
7107*4882a593Smuzhiyun * @fmt: The printf format to print the field with.
7108*4882a593Smuzhiyun * @event: the event that the field is for
7109*4882a593Smuzhiyun * @name: The name of the field
7110*4882a593Smuzhiyun * @record: The record with the field name.
7111*4882a593Smuzhiyun * @err: print default error if failed.
7112*4882a593Smuzhiyun *
7113*4882a593Smuzhiyun * Returns positive value on success, negative in case of an error,
7114*4882a593Smuzhiyun * or 0 if buffer is full.
7115*4882a593Smuzhiyun */
tep_print_func_field(struct trace_seq * s,const char * fmt,struct tep_event * event,const char * name,struct tep_record * record,int err)7116*4882a593Smuzhiyun int tep_print_func_field(struct trace_seq *s, const char *fmt,
7117*4882a593Smuzhiyun struct tep_event *event, const char *name,
7118*4882a593Smuzhiyun struct tep_record *record, int err)
7119*4882a593Smuzhiyun {
7120*4882a593Smuzhiyun struct tep_format_field *field = tep_find_field(event, name);
7121*4882a593Smuzhiyun struct tep_handle *tep = event->tep;
7122*4882a593Smuzhiyun unsigned long long val;
7123*4882a593Smuzhiyun struct func_map *func;
7124*4882a593Smuzhiyun char tmp[128];
7125*4882a593Smuzhiyun
7126*4882a593Smuzhiyun if (!field)
7127*4882a593Smuzhiyun goto failed;
7128*4882a593Smuzhiyun
7129*4882a593Smuzhiyun if (tep_read_number_field(field, record->data, &val))
7130*4882a593Smuzhiyun goto failed;
7131*4882a593Smuzhiyun
7132*4882a593Smuzhiyun func = find_func(tep, val);
7133*4882a593Smuzhiyun
7134*4882a593Smuzhiyun if (func)
7135*4882a593Smuzhiyun snprintf(tmp, 128, "%s/0x%llx", func->func, func->addr - val);
7136*4882a593Smuzhiyun else
7137*4882a593Smuzhiyun sprintf(tmp, "0x%08llx", val);
7138*4882a593Smuzhiyun
7139*4882a593Smuzhiyun return trace_seq_printf(s, fmt, tmp);
7140*4882a593Smuzhiyun
7141*4882a593Smuzhiyun failed:
7142*4882a593Smuzhiyun if (err)
7143*4882a593Smuzhiyun trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
7144*4882a593Smuzhiyun return -1;
7145*4882a593Smuzhiyun }
7146*4882a593Smuzhiyun
free_func_handle(struct tep_function_handler * func)7147*4882a593Smuzhiyun static void free_func_handle(struct tep_function_handler *func)
7148*4882a593Smuzhiyun {
7149*4882a593Smuzhiyun struct func_params *params;
7150*4882a593Smuzhiyun
7151*4882a593Smuzhiyun free(func->name);
7152*4882a593Smuzhiyun
7153*4882a593Smuzhiyun while (func->params) {
7154*4882a593Smuzhiyun params = func->params;
7155*4882a593Smuzhiyun func->params = params->next;
7156*4882a593Smuzhiyun free(params);
7157*4882a593Smuzhiyun }
7158*4882a593Smuzhiyun
7159*4882a593Smuzhiyun free(func);
7160*4882a593Smuzhiyun }
7161*4882a593Smuzhiyun
7162*4882a593Smuzhiyun /**
7163*4882a593Smuzhiyun * tep_register_print_function - register a helper function
7164*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
7165*4882a593Smuzhiyun * @func: the function to process the helper function
7166*4882a593Smuzhiyun * @ret_type: the return type of the helper function
7167*4882a593Smuzhiyun * @name: the name of the helper function
7168*4882a593Smuzhiyun * @parameters: A list of enum tep_func_arg_type
7169*4882a593Smuzhiyun *
7170*4882a593Smuzhiyun * Some events may have helper functions in the print format arguments.
7171*4882a593Smuzhiyun * This allows a plugin to dynamically create a way to process one
7172*4882a593Smuzhiyun * of these functions.
7173*4882a593Smuzhiyun *
7174*4882a593Smuzhiyun * The @parameters is a variable list of tep_func_arg_type enums that
7175*4882a593Smuzhiyun * must end with TEP_FUNC_ARG_VOID.
7176*4882a593Smuzhiyun */
tep_register_print_function(struct tep_handle * tep,tep_func_handler func,enum tep_func_arg_type ret_type,char * name,...)7177*4882a593Smuzhiyun int tep_register_print_function(struct tep_handle *tep,
7178*4882a593Smuzhiyun tep_func_handler func,
7179*4882a593Smuzhiyun enum tep_func_arg_type ret_type,
7180*4882a593Smuzhiyun char *name, ...)
7181*4882a593Smuzhiyun {
7182*4882a593Smuzhiyun struct tep_function_handler *func_handle;
7183*4882a593Smuzhiyun struct func_params **next_param;
7184*4882a593Smuzhiyun struct func_params *param;
7185*4882a593Smuzhiyun enum tep_func_arg_type type;
7186*4882a593Smuzhiyun va_list ap;
7187*4882a593Smuzhiyun int ret;
7188*4882a593Smuzhiyun
7189*4882a593Smuzhiyun func_handle = find_func_handler(tep, name);
7190*4882a593Smuzhiyun if (func_handle) {
7191*4882a593Smuzhiyun /*
7192*4882a593Smuzhiyun * This is most like caused by the users own
7193*4882a593Smuzhiyun * plugins updating the function. This overrides the
7194*4882a593Smuzhiyun * system defaults.
7195*4882a593Smuzhiyun */
7196*4882a593Smuzhiyun pr_stat("override of function helper '%s'", name);
7197*4882a593Smuzhiyun remove_func_handler(tep, name);
7198*4882a593Smuzhiyun }
7199*4882a593Smuzhiyun
7200*4882a593Smuzhiyun func_handle = calloc(1, sizeof(*func_handle));
7201*4882a593Smuzhiyun if (!func_handle) {
7202*4882a593Smuzhiyun do_warning("Failed to allocate function handler");
7203*4882a593Smuzhiyun return TEP_ERRNO__MEM_ALLOC_FAILED;
7204*4882a593Smuzhiyun }
7205*4882a593Smuzhiyun
7206*4882a593Smuzhiyun func_handle->ret_type = ret_type;
7207*4882a593Smuzhiyun func_handle->name = strdup(name);
7208*4882a593Smuzhiyun func_handle->func = func;
7209*4882a593Smuzhiyun if (!func_handle->name) {
7210*4882a593Smuzhiyun do_warning("Failed to allocate function name");
7211*4882a593Smuzhiyun free(func_handle);
7212*4882a593Smuzhiyun return TEP_ERRNO__MEM_ALLOC_FAILED;
7213*4882a593Smuzhiyun }
7214*4882a593Smuzhiyun
7215*4882a593Smuzhiyun next_param = &(func_handle->params);
7216*4882a593Smuzhiyun va_start(ap, name);
7217*4882a593Smuzhiyun for (;;) {
7218*4882a593Smuzhiyun type = va_arg(ap, enum tep_func_arg_type);
7219*4882a593Smuzhiyun if (type == TEP_FUNC_ARG_VOID)
7220*4882a593Smuzhiyun break;
7221*4882a593Smuzhiyun
7222*4882a593Smuzhiyun if (type >= TEP_FUNC_ARG_MAX_TYPES) {
7223*4882a593Smuzhiyun do_warning("Invalid argument type %d", type);
7224*4882a593Smuzhiyun ret = TEP_ERRNO__INVALID_ARG_TYPE;
7225*4882a593Smuzhiyun goto out_free;
7226*4882a593Smuzhiyun }
7227*4882a593Smuzhiyun
7228*4882a593Smuzhiyun param = malloc(sizeof(*param));
7229*4882a593Smuzhiyun if (!param) {
7230*4882a593Smuzhiyun do_warning("Failed to allocate function param");
7231*4882a593Smuzhiyun ret = TEP_ERRNO__MEM_ALLOC_FAILED;
7232*4882a593Smuzhiyun goto out_free;
7233*4882a593Smuzhiyun }
7234*4882a593Smuzhiyun param->type = type;
7235*4882a593Smuzhiyun param->next = NULL;
7236*4882a593Smuzhiyun
7237*4882a593Smuzhiyun *next_param = param;
7238*4882a593Smuzhiyun next_param = &(param->next);
7239*4882a593Smuzhiyun
7240*4882a593Smuzhiyun func_handle->nr_args++;
7241*4882a593Smuzhiyun }
7242*4882a593Smuzhiyun va_end(ap);
7243*4882a593Smuzhiyun
7244*4882a593Smuzhiyun func_handle->next = tep->func_handlers;
7245*4882a593Smuzhiyun tep->func_handlers = func_handle;
7246*4882a593Smuzhiyun
7247*4882a593Smuzhiyun return 0;
7248*4882a593Smuzhiyun out_free:
7249*4882a593Smuzhiyun va_end(ap);
7250*4882a593Smuzhiyun free_func_handle(func_handle);
7251*4882a593Smuzhiyun return ret;
7252*4882a593Smuzhiyun }
7253*4882a593Smuzhiyun
7254*4882a593Smuzhiyun /**
7255*4882a593Smuzhiyun * tep_unregister_print_function - unregister a helper function
7256*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
7257*4882a593Smuzhiyun * @func: the function to process the helper function
7258*4882a593Smuzhiyun * @name: the name of the helper function
7259*4882a593Smuzhiyun *
7260*4882a593Smuzhiyun * This function removes existing print handler for function @name.
7261*4882a593Smuzhiyun *
7262*4882a593Smuzhiyun * Returns 0 if the handler was removed successully, -1 otherwise.
7263*4882a593Smuzhiyun */
tep_unregister_print_function(struct tep_handle * tep,tep_func_handler func,char * name)7264*4882a593Smuzhiyun int tep_unregister_print_function(struct tep_handle *tep,
7265*4882a593Smuzhiyun tep_func_handler func, char *name)
7266*4882a593Smuzhiyun {
7267*4882a593Smuzhiyun struct tep_function_handler *func_handle;
7268*4882a593Smuzhiyun
7269*4882a593Smuzhiyun func_handle = find_func_handler(tep, name);
7270*4882a593Smuzhiyun if (func_handle && func_handle->func == func) {
7271*4882a593Smuzhiyun remove_func_handler(tep, name);
7272*4882a593Smuzhiyun return 0;
7273*4882a593Smuzhiyun }
7274*4882a593Smuzhiyun return -1;
7275*4882a593Smuzhiyun }
7276*4882a593Smuzhiyun
search_event(struct tep_handle * tep,int id,const char * sys_name,const char * event_name)7277*4882a593Smuzhiyun static struct tep_event *search_event(struct tep_handle *tep, int id,
7278*4882a593Smuzhiyun const char *sys_name,
7279*4882a593Smuzhiyun const char *event_name)
7280*4882a593Smuzhiyun {
7281*4882a593Smuzhiyun struct tep_event *event;
7282*4882a593Smuzhiyun
7283*4882a593Smuzhiyun if (id >= 0) {
7284*4882a593Smuzhiyun /* search by id */
7285*4882a593Smuzhiyun event = tep_find_event(tep, id);
7286*4882a593Smuzhiyun if (!event)
7287*4882a593Smuzhiyun return NULL;
7288*4882a593Smuzhiyun if (event_name && (strcmp(event_name, event->name) != 0))
7289*4882a593Smuzhiyun return NULL;
7290*4882a593Smuzhiyun if (sys_name && (strcmp(sys_name, event->system) != 0))
7291*4882a593Smuzhiyun return NULL;
7292*4882a593Smuzhiyun } else {
7293*4882a593Smuzhiyun event = tep_find_event_by_name(tep, sys_name, event_name);
7294*4882a593Smuzhiyun if (!event)
7295*4882a593Smuzhiyun return NULL;
7296*4882a593Smuzhiyun }
7297*4882a593Smuzhiyun return event;
7298*4882a593Smuzhiyun }
7299*4882a593Smuzhiyun
7300*4882a593Smuzhiyun /**
7301*4882a593Smuzhiyun * tep_register_event_handler - register a way to parse an event
7302*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
7303*4882a593Smuzhiyun * @id: the id of the event to register
7304*4882a593Smuzhiyun * @sys_name: the system name the event belongs to
7305*4882a593Smuzhiyun * @event_name: the name of the event
7306*4882a593Smuzhiyun * @func: the function to call to parse the event information
7307*4882a593Smuzhiyun * @context: the data to be passed to @func
7308*4882a593Smuzhiyun *
7309*4882a593Smuzhiyun * This function allows a developer to override the parsing of
7310*4882a593Smuzhiyun * a given event. If for some reason the default print format
7311*4882a593Smuzhiyun * is not sufficient, this function will register a function
7312*4882a593Smuzhiyun * for an event to be used to parse the data instead.
7313*4882a593Smuzhiyun *
7314*4882a593Smuzhiyun * If @id is >= 0, then it is used to find the event.
7315*4882a593Smuzhiyun * else @sys_name and @event_name are used.
7316*4882a593Smuzhiyun *
7317*4882a593Smuzhiyun * Returns:
7318*4882a593Smuzhiyun * TEP_REGISTER_SUCCESS_OVERWRITE if an existing handler is overwritten
7319*4882a593Smuzhiyun * TEP_REGISTER_SUCCESS if a new handler is registered successfully
7320*4882a593Smuzhiyun * negative TEP_ERRNO_... in case of an error
7321*4882a593Smuzhiyun *
7322*4882a593Smuzhiyun */
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)7323*4882a593Smuzhiyun int tep_register_event_handler(struct tep_handle *tep, int id,
7324*4882a593Smuzhiyun const char *sys_name, const char *event_name,
7325*4882a593Smuzhiyun tep_event_handler_func func, void *context)
7326*4882a593Smuzhiyun {
7327*4882a593Smuzhiyun struct tep_event *event;
7328*4882a593Smuzhiyun struct event_handler *handle;
7329*4882a593Smuzhiyun
7330*4882a593Smuzhiyun event = search_event(tep, id, sys_name, event_name);
7331*4882a593Smuzhiyun if (event == NULL)
7332*4882a593Smuzhiyun goto not_found;
7333*4882a593Smuzhiyun
7334*4882a593Smuzhiyun pr_stat("overriding event (%d) %s:%s with new print handler",
7335*4882a593Smuzhiyun event->id, event->system, event->name);
7336*4882a593Smuzhiyun
7337*4882a593Smuzhiyun event->handler = func;
7338*4882a593Smuzhiyun event->context = context;
7339*4882a593Smuzhiyun return TEP_REGISTER_SUCCESS_OVERWRITE;
7340*4882a593Smuzhiyun
7341*4882a593Smuzhiyun not_found:
7342*4882a593Smuzhiyun /* Save for later use. */
7343*4882a593Smuzhiyun handle = calloc(1, sizeof(*handle));
7344*4882a593Smuzhiyun if (!handle) {
7345*4882a593Smuzhiyun do_warning("Failed to allocate event handler");
7346*4882a593Smuzhiyun return TEP_ERRNO__MEM_ALLOC_FAILED;
7347*4882a593Smuzhiyun }
7348*4882a593Smuzhiyun
7349*4882a593Smuzhiyun handle->id = id;
7350*4882a593Smuzhiyun if (event_name)
7351*4882a593Smuzhiyun handle->event_name = strdup(event_name);
7352*4882a593Smuzhiyun if (sys_name)
7353*4882a593Smuzhiyun handle->sys_name = strdup(sys_name);
7354*4882a593Smuzhiyun
7355*4882a593Smuzhiyun if ((event_name && !handle->event_name) ||
7356*4882a593Smuzhiyun (sys_name && !handle->sys_name)) {
7357*4882a593Smuzhiyun do_warning("Failed to allocate event/sys name");
7358*4882a593Smuzhiyun free((void *)handle->event_name);
7359*4882a593Smuzhiyun free((void *)handle->sys_name);
7360*4882a593Smuzhiyun free(handle);
7361*4882a593Smuzhiyun return TEP_ERRNO__MEM_ALLOC_FAILED;
7362*4882a593Smuzhiyun }
7363*4882a593Smuzhiyun
7364*4882a593Smuzhiyun handle->func = func;
7365*4882a593Smuzhiyun handle->next = tep->handlers;
7366*4882a593Smuzhiyun tep->handlers = handle;
7367*4882a593Smuzhiyun handle->context = context;
7368*4882a593Smuzhiyun
7369*4882a593Smuzhiyun return TEP_REGISTER_SUCCESS;
7370*4882a593Smuzhiyun }
7371*4882a593Smuzhiyun
handle_matches(struct event_handler * handler,int id,const char * sys_name,const char * event_name,tep_event_handler_func func,void * context)7372*4882a593Smuzhiyun static int handle_matches(struct event_handler *handler, int id,
7373*4882a593Smuzhiyun const char *sys_name, const char *event_name,
7374*4882a593Smuzhiyun tep_event_handler_func func, void *context)
7375*4882a593Smuzhiyun {
7376*4882a593Smuzhiyun if (id >= 0 && id != handler->id)
7377*4882a593Smuzhiyun return 0;
7378*4882a593Smuzhiyun
7379*4882a593Smuzhiyun if (event_name && (strcmp(event_name, handler->event_name) != 0))
7380*4882a593Smuzhiyun return 0;
7381*4882a593Smuzhiyun
7382*4882a593Smuzhiyun if (sys_name && (strcmp(sys_name, handler->sys_name) != 0))
7383*4882a593Smuzhiyun return 0;
7384*4882a593Smuzhiyun
7385*4882a593Smuzhiyun if (func != handler->func || context != handler->context)
7386*4882a593Smuzhiyun return 0;
7387*4882a593Smuzhiyun
7388*4882a593Smuzhiyun return 1;
7389*4882a593Smuzhiyun }
7390*4882a593Smuzhiyun
7391*4882a593Smuzhiyun /**
7392*4882a593Smuzhiyun * tep_unregister_event_handler - unregister an existing event handler
7393*4882a593Smuzhiyun * @tep: a handle to the trace event parser context
7394*4882a593Smuzhiyun * @id: the id of the event to unregister
7395*4882a593Smuzhiyun * @sys_name: the system name the handler belongs to
7396*4882a593Smuzhiyun * @event_name: the name of the event handler
7397*4882a593Smuzhiyun * @func: the function to call to parse the event information
7398*4882a593Smuzhiyun * @context: the data to be passed to @func
7399*4882a593Smuzhiyun *
7400*4882a593Smuzhiyun * This function removes existing event handler (parser).
7401*4882a593Smuzhiyun *
7402*4882a593Smuzhiyun * If @id is >= 0, then it is used to find the event.
7403*4882a593Smuzhiyun * else @sys_name and @event_name are used.
7404*4882a593Smuzhiyun *
7405*4882a593Smuzhiyun * Returns 0 if handler was removed successfully, -1 if event was not found.
7406*4882a593Smuzhiyun */
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)7407*4882a593Smuzhiyun int tep_unregister_event_handler(struct tep_handle *tep, int id,
7408*4882a593Smuzhiyun const char *sys_name, const char *event_name,
7409*4882a593Smuzhiyun tep_event_handler_func func, void *context)
7410*4882a593Smuzhiyun {
7411*4882a593Smuzhiyun struct tep_event *event;
7412*4882a593Smuzhiyun struct event_handler *handle;
7413*4882a593Smuzhiyun struct event_handler **next;
7414*4882a593Smuzhiyun
7415*4882a593Smuzhiyun event = search_event(tep, id, sys_name, event_name);
7416*4882a593Smuzhiyun if (event == NULL)
7417*4882a593Smuzhiyun goto not_found;
7418*4882a593Smuzhiyun
7419*4882a593Smuzhiyun if (event->handler == func && event->context == context) {
7420*4882a593Smuzhiyun pr_stat("removing override handler for event (%d) %s:%s. Going back to default handler.",
7421*4882a593Smuzhiyun event->id, event->system, event->name);
7422*4882a593Smuzhiyun
7423*4882a593Smuzhiyun event->handler = NULL;
7424*4882a593Smuzhiyun event->context = NULL;
7425*4882a593Smuzhiyun return 0;
7426*4882a593Smuzhiyun }
7427*4882a593Smuzhiyun
7428*4882a593Smuzhiyun not_found:
7429*4882a593Smuzhiyun for (next = &tep->handlers; *next; next = &(*next)->next) {
7430*4882a593Smuzhiyun handle = *next;
7431*4882a593Smuzhiyun if (handle_matches(handle, id, sys_name, event_name,
7432*4882a593Smuzhiyun func, context))
7433*4882a593Smuzhiyun break;
7434*4882a593Smuzhiyun }
7435*4882a593Smuzhiyun
7436*4882a593Smuzhiyun if (!(*next))
7437*4882a593Smuzhiyun return -1;
7438*4882a593Smuzhiyun
7439*4882a593Smuzhiyun *next = handle->next;
7440*4882a593Smuzhiyun free_handler(handle);
7441*4882a593Smuzhiyun
7442*4882a593Smuzhiyun return 0;
7443*4882a593Smuzhiyun }
7444*4882a593Smuzhiyun
7445*4882a593Smuzhiyun /**
7446*4882a593Smuzhiyun * tep_alloc - create a tep handle
7447*4882a593Smuzhiyun */
tep_alloc(void)7448*4882a593Smuzhiyun struct tep_handle *tep_alloc(void)
7449*4882a593Smuzhiyun {
7450*4882a593Smuzhiyun struct tep_handle *tep = calloc(1, sizeof(*tep));
7451*4882a593Smuzhiyun
7452*4882a593Smuzhiyun if (tep) {
7453*4882a593Smuzhiyun tep->ref_count = 1;
7454*4882a593Smuzhiyun tep->host_bigendian = tep_is_bigendian();
7455*4882a593Smuzhiyun }
7456*4882a593Smuzhiyun
7457*4882a593Smuzhiyun return tep;
7458*4882a593Smuzhiyun }
7459*4882a593Smuzhiyun
tep_ref(struct tep_handle * tep)7460*4882a593Smuzhiyun void tep_ref(struct tep_handle *tep)
7461*4882a593Smuzhiyun {
7462*4882a593Smuzhiyun tep->ref_count++;
7463*4882a593Smuzhiyun }
7464*4882a593Smuzhiyun
tep_get_ref(struct tep_handle * tep)7465*4882a593Smuzhiyun int tep_get_ref(struct tep_handle *tep)
7466*4882a593Smuzhiyun {
7467*4882a593Smuzhiyun if (tep)
7468*4882a593Smuzhiyun return tep->ref_count;
7469*4882a593Smuzhiyun return 0;
7470*4882a593Smuzhiyun }
7471*4882a593Smuzhiyun
free_tep_format_field(struct tep_format_field * field)7472*4882a593Smuzhiyun __hidden void free_tep_format_field(struct tep_format_field *field)
7473*4882a593Smuzhiyun {
7474*4882a593Smuzhiyun free(field->type);
7475*4882a593Smuzhiyun if (field->alias != field->name)
7476*4882a593Smuzhiyun free(field->alias);
7477*4882a593Smuzhiyun free(field->name);
7478*4882a593Smuzhiyun free(field);
7479*4882a593Smuzhiyun }
7480*4882a593Smuzhiyun
free_format_fields(struct tep_format_field * field)7481*4882a593Smuzhiyun static void free_format_fields(struct tep_format_field *field)
7482*4882a593Smuzhiyun {
7483*4882a593Smuzhiyun struct tep_format_field *next;
7484*4882a593Smuzhiyun
7485*4882a593Smuzhiyun while (field) {
7486*4882a593Smuzhiyun next = field->next;
7487*4882a593Smuzhiyun free_tep_format_field(field);
7488*4882a593Smuzhiyun field = next;
7489*4882a593Smuzhiyun }
7490*4882a593Smuzhiyun }
7491*4882a593Smuzhiyun
free_formats(struct tep_format * format)7492*4882a593Smuzhiyun static void free_formats(struct tep_format *format)
7493*4882a593Smuzhiyun {
7494*4882a593Smuzhiyun free_format_fields(format->common_fields);
7495*4882a593Smuzhiyun free_format_fields(format->fields);
7496*4882a593Smuzhiyun }
7497*4882a593Smuzhiyun
free_tep_event(struct tep_event * event)7498*4882a593Smuzhiyun __hidden void free_tep_event(struct tep_event *event)
7499*4882a593Smuzhiyun {
7500*4882a593Smuzhiyun free(event->name);
7501*4882a593Smuzhiyun free(event->system);
7502*4882a593Smuzhiyun
7503*4882a593Smuzhiyun free_formats(&event->format);
7504*4882a593Smuzhiyun
7505*4882a593Smuzhiyun free(event->print_fmt.format);
7506*4882a593Smuzhiyun free_args(event->print_fmt.args);
7507*4882a593Smuzhiyun free_parse_args(event->print_fmt.print_cache);
7508*4882a593Smuzhiyun free(event);
7509*4882a593Smuzhiyun }
7510*4882a593Smuzhiyun
7511*4882a593Smuzhiyun /**
7512*4882a593Smuzhiyun * tep_free - free a tep handle
7513*4882a593Smuzhiyun * @tep: the tep handle to free
7514*4882a593Smuzhiyun */
tep_free(struct tep_handle * tep)7515*4882a593Smuzhiyun void tep_free(struct tep_handle *tep)
7516*4882a593Smuzhiyun {
7517*4882a593Smuzhiyun struct cmdline_list *cmdlist, *cmdnext;
7518*4882a593Smuzhiyun struct func_list *funclist, *funcnext;
7519*4882a593Smuzhiyun struct printk_list *printklist, *printknext;
7520*4882a593Smuzhiyun struct tep_function_handler *func_handler;
7521*4882a593Smuzhiyun struct event_handler *handle;
7522*4882a593Smuzhiyun int i;
7523*4882a593Smuzhiyun
7524*4882a593Smuzhiyun if (!tep)
7525*4882a593Smuzhiyun return;
7526*4882a593Smuzhiyun
7527*4882a593Smuzhiyun cmdlist = tep->cmdlist;
7528*4882a593Smuzhiyun funclist = tep->funclist;
7529*4882a593Smuzhiyun printklist = tep->printklist;
7530*4882a593Smuzhiyun
7531*4882a593Smuzhiyun tep->ref_count--;
7532*4882a593Smuzhiyun if (tep->ref_count)
7533*4882a593Smuzhiyun return;
7534*4882a593Smuzhiyun
7535*4882a593Smuzhiyun if (tep->cmdlines) {
7536*4882a593Smuzhiyun for (i = 0; i < tep->cmdline_count; i++)
7537*4882a593Smuzhiyun free(tep->cmdlines[i].comm);
7538*4882a593Smuzhiyun free(tep->cmdlines);
7539*4882a593Smuzhiyun }
7540*4882a593Smuzhiyun
7541*4882a593Smuzhiyun while (cmdlist) {
7542*4882a593Smuzhiyun cmdnext = cmdlist->next;
7543*4882a593Smuzhiyun free(cmdlist->comm);
7544*4882a593Smuzhiyun free(cmdlist);
7545*4882a593Smuzhiyun cmdlist = cmdnext;
7546*4882a593Smuzhiyun }
7547*4882a593Smuzhiyun
7548*4882a593Smuzhiyun if (tep->func_map) {
7549*4882a593Smuzhiyun for (i = 0; i < (int)tep->func_count; i++) {
7550*4882a593Smuzhiyun free(tep->func_map[i].func);
7551*4882a593Smuzhiyun free(tep->func_map[i].mod);
7552*4882a593Smuzhiyun }
7553*4882a593Smuzhiyun free(tep->func_map);
7554*4882a593Smuzhiyun }
7555*4882a593Smuzhiyun
7556*4882a593Smuzhiyun while (funclist) {
7557*4882a593Smuzhiyun funcnext = funclist->next;
7558*4882a593Smuzhiyun free(funclist->func);
7559*4882a593Smuzhiyun free(funclist->mod);
7560*4882a593Smuzhiyun free(funclist);
7561*4882a593Smuzhiyun funclist = funcnext;
7562*4882a593Smuzhiyun }
7563*4882a593Smuzhiyun
7564*4882a593Smuzhiyun while (tep->func_handlers) {
7565*4882a593Smuzhiyun func_handler = tep->func_handlers;
7566*4882a593Smuzhiyun tep->func_handlers = func_handler->next;
7567*4882a593Smuzhiyun free_func_handle(func_handler);
7568*4882a593Smuzhiyun }
7569*4882a593Smuzhiyun
7570*4882a593Smuzhiyun if (tep->printk_map) {
7571*4882a593Smuzhiyun for (i = 0; i < (int)tep->printk_count; i++)
7572*4882a593Smuzhiyun free(tep->printk_map[i].printk);
7573*4882a593Smuzhiyun free(tep->printk_map);
7574*4882a593Smuzhiyun }
7575*4882a593Smuzhiyun
7576*4882a593Smuzhiyun while (printklist) {
7577*4882a593Smuzhiyun printknext = printklist->next;
7578*4882a593Smuzhiyun free(printklist->printk);
7579*4882a593Smuzhiyun free(printklist);
7580*4882a593Smuzhiyun printklist = printknext;
7581*4882a593Smuzhiyun }
7582*4882a593Smuzhiyun
7583*4882a593Smuzhiyun for (i = 0; i < tep->nr_events; i++)
7584*4882a593Smuzhiyun free_tep_event(tep->events[i]);
7585*4882a593Smuzhiyun
7586*4882a593Smuzhiyun while (tep->handlers) {
7587*4882a593Smuzhiyun handle = tep->handlers;
7588*4882a593Smuzhiyun tep->handlers = handle->next;
7589*4882a593Smuzhiyun free_handler(handle);
7590*4882a593Smuzhiyun }
7591*4882a593Smuzhiyun
7592*4882a593Smuzhiyun free(tep->events);
7593*4882a593Smuzhiyun free(tep->sort_events);
7594*4882a593Smuzhiyun free(tep->func_resolver);
7595*4882a593Smuzhiyun free_tep_plugin_paths(tep);
7596*4882a593Smuzhiyun
7597*4882a593Smuzhiyun free(tep);
7598*4882a593Smuzhiyun }
7599*4882a593Smuzhiyun
tep_unref(struct tep_handle * tep)7600*4882a593Smuzhiyun void tep_unref(struct tep_handle *tep)
7601*4882a593Smuzhiyun {
7602*4882a593Smuzhiyun tep_free(tep);
7603*4882a593Smuzhiyun }
7604