aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/lib/traceevent/Makefile303
-rw-r--r--tools/lib/traceevent/event-parse.c4971
-rw-r--r--tools/lib/traceevent/event-parse.h806
-rw-r--r--tools/lib/traceevent/event-utils.h64
-rw-r--r--tools/lib/traceevent/parse-filter.c2262
-rw-r--r--tools/lib/traceevent/parse-utils.c110
-rw-r--r--tools/lib/traceevent/trace-seq.c199
7 files changed, 8715 insertions, 0 deletions
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
new file mode 100644
index 00000000000..3d69aa9ff51
--- /dev/null
+++ b/tools/lib/traceevent/Makefile
@@ -0,0 +1,303 @@
1# trace-cmd version
2EP_VERSION = 1
3EP_PATCHLEVEL = 1
4EP_EXTRAVERSION = 0
5
6# file format version
7FILE_VERSION = 6
8
9MAKEFLAGS += --no-print-directory
10
11
12# Makefiles suck: This macro sets a default value of $(2) for the
13# variable named by $(1), unless the variable has been set by
14# environment or command line. This is necessary for CC and AR
15# because make sets default values, so the simpler ?= approach
16# won't work as expected.
17define allow-override
18 $(if $(or $(findstring environment,$(origin $(1))),\
19 $(findstring command line,$(origin $(1)))),,\
20 $(eval $(1) = $(2)))
21endef
22
23# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix.
24$(call allow-override,CC,$(CROSS_COMPILE)gcc)
25$(call allow-override,AR,$(CROSS_COMPILE)ar)
26
27EXT = -std=gnu99
28INSTALL = install
29
30# Use DESTDIR for installing into a different root directory.
31# This is useful for building a package. The program will be
32# installed in this directory as if it was the root directory.
33# Then the build tool can move it later.
34DESTDIR ?=
35DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
36
37prefix ?= /usr/local
38bindir_relative = bin
39bindir = $(prefix)/$(bindir_relative)
40man_dir = $(prefix)/share/man
41man_dir_SQ = '$(subst ','\'',$(man_dir))'
42html_install = $(prefix)/share/kernelshark/html
43html_install_SQ = '$(subst ','\'',$(html_install))'
44img_install = $(prefix)/share/kernelshark/html/images
45img_install_SQ = '$(subst ','\'',$(img_install))'
46
47export man_dir man_dir_SQ html_install html_install_SQ INSTALL
48export img_install img_install_SQ
49export DESTDIR DESTDIR_SQ
50
51# copy a bit from Linux kbuild
52
53ifeq ("$(origin V)", "command line")
54 VERBOSE = $(V)
55endif
56ifndef VERBOSE
57 VERBOSE = 0
58endif
59
60ifeq ("$(origin O)", "command line")
61 BUILD_OUTPUT := $(O)
62endif
63
64ifeq ($(BUILD_SRC),)
65ifneq ($(BUILD_OUTPUT),)
66
67define build_output
68 $(if $(VERBOSE:1=),@)$(MAKE) -C $(BUILD_OUTPUT) \
69 BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1
70endef
71
72saved-output := $(BUILD_OUTPUT)
73BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd)
74$(if $(BUILD_OUTPUT),, \
75 $(error output directory "$(saved-output)" does not exist))
76
77all: sub-make
78
79gui: force
80 $(call build_output, all_cmd)
81
82$(filter-out gui,$(MAKECMDGOALS)): sub-make
83
84sub-make: force
85 $(call build_output, $(MAKECMDGOALS))
86
87
88# Leave processing to above invocation of make
89skip-makefile := 1
90
91endif # BUILD_OUTPUT
92endif # BUILD_SRC
93
94# We process the rest of the Makefile if this is the final invocation of make
95ifeq ($(skip-makefile),)
96
97srctree := $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR))
98objtree := $(CURDIR)
99src := $(srctree)
100obj := $(objtree)
101
102export prefix bindir src obj
103
104# Shell quotes
105bindir_SQ = $(subst ','\'',$(bindir))
106bindir_relative_SQ = $(subst ','\'',$(bindir_relative))
107
108LIB_FILE = libtraceevent.a libtraceevent.so
109
110CONFIG_INCLUDES =
111CONFIG_LIBS =
112CONFIG_FLAGS =
113
114VERSION = $(EP_VERSION)
115PATCHLEVEL = $(EP_PATCHLEVEL)
116EXTRAVERSION = $(EP_EXTRAVERSION)
117
118OBJ = $@
119N =
120
121export Q VERBOSE
122
123EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
124
125INCLUDES = -I. -I/usr/local/include $(CONFIG_INCLUDES)
126
127# Set compile option CFLAGS if not set elsewhere
128CFLAGS ?= -g -Wall
129
130# Append required CFLAGS
131override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
132override CFLAGS += $(udis86-flags)
133
134ifeq ($(VERBOSE),1)
135 Q =
136 print_compile =
137 print_app_build =
138 print_fpic_compile =
139 print_shared_lib_compile =
140 print_plugin_obj_compile =
141 print_plugin_build =
142 print_install =
143else
144 Q = @
145 print_compile = echo ' CC '$(OBJ);
146 print_app_build = echo ' BUILD '$(OBJ);
147 print_fpic_compile = echo ' CC FPIC '$(OBJ);
148 print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ);
149 print_plugin_obj_compile = echo ' CC PLUGIN OBJ '$(OBJ);
150 print_plugin_build = echo ' CC PLUGI '$(OBJ);
151 print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ);
152 print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
153endif
154
155do_fpic_compile = \
156 ($(print_fpic_compile) \
157 $(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@)
158
159do_app_build = \
160 ($(print_app_build) \
161 $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS))
162
163do_compile_shared_library = \
164 ($(print_shared_lib_compile) \
165 $(CC) --shared $^ -o $@)
166
167do_compile_plugin_obj = \
168 ($(print_plugin_obj_compile) \
169 $(CC) -c $(CFLAGS) -fPIC -o $@ $<)
170
171do_plugin_build = \
172 ($(print_plugin_build) \
173 $(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<)
174
175do_build_static_lib = \
176 ($(print_static_lib_build) \
177 $(RM) $@; $(AR) rcs $@ $^)
178
179
180define do_compile
181 $(print_compile) \
182 $(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
183endef
184
185$(obj)/%.o: $(src)/%.c
186 $(Q)$(call do_compile)
187
188%.o: $(src)/%.c
189 $(Q)$(call do_compile)
190
191PEVENT_LIB_OBJS = event-parse.o trace-seq.o parse-filter.o parse-utils.o
192
193ALL_OBJS = $(PEVENT_LIB_OBJS)
194
195CMD_TARGETS = $(LIB_FILE)
196
197TARGETS = $(CMD_TARGETS)
198
199
200all: all_cmd
201
202all_cmd: $(CMD_TARGETS)
203
204libtraceevent.so: $(PEVENT_LIB_OBJS)
205 $(Q)$(do_compile_shared_library)
206
207libtraceevent.a: $(PEVENT_LIB_OBJS)
208 $(Q)$(do_build_static_lib)
209
210$(PEVENT_LIB_OBJS): %.o: $(src)/%.c
211 $(Q)$(do_fpic_compile)
212
213define make_version.h
214 (echo '/* This file is automatically generated. Do not modify. */'; \
215 echo \#define VERSION_CODE $(shell \
216 expr $(VERSION) \* 256 + $(PATCHLEVEL)); \
217 echo '#define EXTRAVERSION ' $(EXTRAVERSION); \
218 echo '#define VERSION_STRING "'$(VERSION).$(PATCHLEVEL).$(EXTRAVERSION)'"'; \
219 echo '#define FILE_VERSION '$(FILE_VERSION); \
220 ) > $1
221endef
222
223define update_version.h
224 ($(call make_version.h, $@.tmp); \
225 if [ -r $@ ] && cmp -s $@ $@.tmp; then \
226 rm -f $@.tmp; \
227 else \
228 echo ' UPDATE $@'; \
229 mv -f $@.tmp $@; \
230 fi);
231endef
232
233ep_version.h: force
234 $(Q)$(N)$(call update_version.h)
235
236VERSION_FILES = ep_version.h
237
238define update_dir
239 (echo $1 > $@.tmp; \
240 if [ -r $@ ] && cmp -s $@ $@.tmp; then \
241 rm -f $@.tmp; \
242 else \
243 echo ' UPDATE $@'; \
244 mv -f $@.tmp $@; \
245 fi);
246endef
247
248## make deps
249
250all_objs := $(sort $(ALL_OBJS))
251all_deps := $(all_objs:%.o=.%.d)
252
253define check_deps
254 $(CC) -M $(CFLAGS) $< > $@;
255endef
256
257$(gui_deps): ks_version.h
258$(non_gui_deps): tc_version.h
259
260$(all_deps): .%.d: $(src)/%.c
261 $(Q)$(call check_deps)
262
263$(all_objs) : %.o : .%.d
264
265dep_includes := $(wildcard $(all_deps))
266
267ifneq ($(dep_includes),)
268 include $(dep_includes)
269endif
270
271tags: force
272 $(RM) tags
273 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px
274
275TAGS: force
276 $(RM) TAGS
277 find . -name '*.[ch]' | xargs etags
278
279define do_install
280 $(print_install) \
281 if [ ! -d '$(DESTDIR_SQ)$2' ]; then \
282 $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \
283 fi; \
284 $(INSTALL) $1 '$(DESTDIR_SQ)$2'
285endef
286
287install_lib: all_cmd install_plugins install_python
288 $(Q)$(call do_install,$(LIB_FILE),$(bindir_SQ))
289
290install: install_lib
291
292clean:
293 $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES).*.d
294 $(RM) tags TAGS
295
296endif # skip-makefile
297
298PHONY += force
299force:
300
301# Declare the contents of the .PHONY variable as phony. We keep that
302# information in a variable so we can use it in if_changed and friends.
303.PHONY: $(PHONY)
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
new file mode 100644
index 00000000000..47a3227e98b
--- /dev/null
+++ b/tools/lib/traceevent/event-parse.c
@@ -0,0 +1,4971 @@
1/*
2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 *
21 * The parts for function graph printing was taken and modified from the
22 * Linux Kernel that were written by
23 * - Copyright (C) 2009 Frederic Weisbecker,
24 * Frederic Weisbecker gave his permission to relicense the code to
25 * the Lesser General Public License.
26 */
27#define _GNU_SOURCE
28#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
31#include <stdarg.h>
32#include <ctype.h>
33#include <errno.h>
34
35#include "event-parse.h"
36
37static const char *input_buf;
38static unsigned long long input_buf_ptr;
39static unsigned long long input_buf_siz;
40
41static int show_warning = 1;
42
43#define do_warning(fmt, ...) \
44 do { \
45 if (show_warning) \
46 warning(fmt, ##__VA_ARGS__); \
47 } while (0)
48
49static void init_input_buf(const char *buf, unsigned long long size)
50{
51 input_buf = buf;
52 input_buf_siz = size;
53 input_buf_ptr = 0;
54}
55
56const char *pevent_get_input_buf(void)
57{
58 return input_buf;
59}
60
61unsigned long long pevent_get_input_buf_ptr(void)
62{
63 return input_buf_ptr;
64}
65
66struct event_handler {
67 struct event_handler *next;
68 int id;
69 const char *sys_name;
70 const char *event_name;
71 pevent_event_handler_func func;
72 void *context;
73};
74
75struct pevent_func_params {
76 struct pevent_func_params *next;
77 enum pevent_func_arg_type type;
78};
79
80struct pevent_function_handler {
81 struct pevent_function_handler *next;
82 enum pevent_func_arg_type ret_type;
83 char *name;
84 pevent_func_handler func;
85 struct pevent_func_params *params;
86 int nr_args;
87};
88
89static unsigned long long
90process_defined_func(struct trace_seq *s, void *data, int size,
91 struct event_format *event, struct print_arg *arg);
92
93static void free_func_handle(struct pevent_function_handler *func);
94
95/**
96 * pevent_buffer_init - init buffer for parsing
97 * @buf: buffer to parse
98 * @size: the size of the buffer
99 *
100 * For use with pevent_read_token(), this initializes the internal
101 * buffer that pevent_read_token() will parse.
102 */
103void pevent_buffer_init(const char *buf, unsigned long long size)
104{
105 init_input_buf(buf, size);
106}
107
108void breakpoint(void)
109{
110 static int x;
111 x++;
112}
113
114struct print_arg *alloc_arg(void)
115{
116 struct print_arg *arg;
117
118 arg = malloc_or_die(sizeof(*arg));
119 if (!arg)
120 return NULL;
121 memset(arg, 0, sizeof(*arg));
122
123 return arg;
124}
125
126struct cmdline {
127 char *comm;
128 int pid;
129};
130
131static int cmdline_cmp(const void *a, const void *b)
132{
133 const struct cmdline *ca = a;
134 const struct cmdline *cb = b;
135
136 if (ca->pid < cb->pid)
137 return -1;
138 if (ca->pid > cb->pid)
139 return 1;
140
141 return 0;
142}
143
144struct cmdline_list {
145 struct cmdline_list *next;
146 char *comm;
147 int pid;
148};
149
150static int cmdline_init(struct pevent *pevent)
151{
152 struct cmdline_list *cmdlist = pevent->cmdlist;
153 struct cmdline_list *item;
154 struct cmdline *cmdlines;
155 int i;
156
157 cmdlines = malloc_or_die(sizeof(*cmdlines) * pevent->cmdline_count);
158
159 i = 0;
160 while (cmdlist) {
161 cmdlines[i].pid = cmdlist->pid;
162 cmdlines[i].comm = cmdlist->comm;
163 i++;
164 item = cmdlist;
165 cmdlist = cmdlist->next;
166 free(item);
167 }
168
169 qsort(cmdlines, pevent->cmdline_count, sizeof(*cmdlines), cmdline_cmp);
170
171 pevent->cmdlines = cmdlines;
172 pevent->cmdlist = NULL;
173
174 return 0;
175}
176
177static char *find_cmdline(struct pevent *pevent, int pid)
178{
179 const struct cmdline *comm;
180 struct cmdline key;
181
182 if (!pid)
183 return "<idle>";
184
185 if (!pevent->cmdlines)
186 cmdline_init(pevent);
187
188 key.pid = pid;
189
190 comm = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
191 sizeof(*pevent->cmdlines), cmdline_cmp);
192
193 if (comm)
194 return comm->comm;
195 return "<...>";
196}
197
198/**
199 * pevent_pid_is_registered - return if a pid has a cmdline registered
200 * @pevent: handle for the pevent
201 * @pid: The pid to check if it has a cmdline registered with.
202 *
203 * Returns 1 if the pid has a cmdline mapped to it
204 * 0 otherwise.
205 */
206int pevent_pid_is_registered(struct pevent *pevent, int pid)
207{
208 const struct cmdline *comm;
209 struct cmdline key;
210
211 if (!pid)
212 return 1;
213
214 if (!pevent->cmdlines)
215 cmdline_init(pevent);
216
217 key.pid = pid;
218
219 comm = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
220 sizeof(*pevent->cmdlines), cmdline_cmp);
221
222 if (comm)
223 return 1;
224 return 0;
225}
226
227/*
228 * If the command lines have been converted to an array, then
229 * we must add this pid. This is much slower than when cmdlines
230 * are added before the array is initialized.
231 */
232static int add_new_comm(struct pevent *pevent, const char *comm, int pid)
233{
234 struct cmdline *cmdlines = pevent->cmdlines;
235 const struct cmdline *cmdline;
236 struct cmdline key;
237
238 if (!pid)
239 return 0;
240
241 /* avoid duplicates */
242 key.pid = pid;
243
244 cmdline = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
245 sizeof(*pevent->cmdlines), cmdline_cmp);
246 if (cmdline) {
247 errno = EEXIST;
248 return -1;
249 }
250
251 cmdlines = realloc(cmdlines, sizeof(*cmdlines) * (pevent->cmdline_count + 1));
252 if (!cmdlines) {
253 errno = ENOMEM;
254 return -1;
255 }
256
257 cmdlines[pevent->cmdline_count].pid = pid;
258 cmdlines[pevent->cmdline_count].comm = strdup(comm);
259 if (!cmdlines[pevent->cmdline_count].comm)
260 die("malloc comm");
261
262 if (cmdlines[pevent->cmdline_count].comm)
263 pevent->cmdline_count++;
264
265 qsort(cmdlines, pevent->cmdline_count, sizeof(*cmdlines), cmdline_cmp);
266 pevent->cmdlines = cmdlines;
267
268 return 0;
269}
270
271/**
272 * pevent_register_comm - register a pid / comm mapping
273 * @pevent: handle for the pevent
274 * @comm: the command line to register
275 * @pid: the pid to map the command line to
276 *
277 * This adds a mapping to search for command line names with
278 * a given pid. The comm is duplicated.
279 */
280int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
281{
282 struct cmdline_list *item;
283
284 if (pevent->cmdlines)
285 return add_new_comm(pevent, comm, pid);
286
287 item = malloc_or_die(sizeof(*item));
288 item->comm = strdup(comm);
289 if (!item->comm)
290 die("malloc comm");
291 item->pid = pid;
292 item->next = pevent->cmdlist;
293
294 pevent->cmdlist = item;
295 pevent->cmdline_count++;
296
297 return 0;
298}
299
300struct func_map {
301 unsigned long long addr;
302 char *func;
303 char *mod;
304};
305
306struct func_list {
307 struct func_list *next;
308 unsigned long long addr;
309 char *func;
310 char *mod;
311};
312
313static int func_cmp(const void *a, const void *b)
314{
315 const struct func_map *fa = a;
316 const struct func_map *fb = b;
317
318 if (fa->addr < fb->addr)
319 return -1;
320 if (fa->addr > fb->addr)
321 return 1;
322
323 return 0;
324}
325
326/*
327 * We are searching for a record in between, not an exact
328 * match.
329 */
330static int func_bcmp(const void *a, const void *b)
331{
332 const struct func_map *fa = a;
333 const struct func_map *fb = b;
334
335 if ((fa->addr == fb->addr) ||
336
337 (fa->addr > fb->addr &&
338 fa->addr < (fb+1)->addr))
339 return 0;
340
341 if (fa->addr < fb->addr)
342 return -1;
343
344 return 1;
345}
346
347static int func_map_init(struct pevent *pevent)
348{
349 struct func_list *funclist;
350 struct func_list *item;
351 struct func_map *func_map;
352 int i;
353
354 func_map = malloc_or_die(sizeof(*func_map) * (pevent->func_count + 1));
355 funclist = pevent->funclist;
356
357 i = 0;
358 while (funclist) {
359 func_map[i].func = funclist->func;
360 func_map[i].addr = funclist->addr;
361 func_map[i].mod = funclist->mod;
362 i++;
363 item = funclist;
364 funclist = funclist->next;
365 free(item);
366 }
367
368 qsort(func_map, pevent->func_count, sizeof(*func_map), func_cmp);
369
370 /*
371 * Add a special record at the end.
372 */
373 func_map[pevent->func_count].func = NULL;
374 func_map[pevent->func_count].addr = 0;
375 func_map[pevent->func_count].mod = NULL;
376
377 pevent->func_map = func_map;
378 pevent->funclist = NULL;
379
380 return 0;
381}
382
383static struct func_map *
384find_func(struct pevent *pevent, unsigned long long addr)
385{
386 struct func_map *func;
387 struct func_map key;
388
389 if (!pevent->func_map)
390 func_map_init(pevent);
391
392 key.addr = addr;
393
394 func = bsearch(&key, pevent->func_map, pevent->func_count,
395 sizeof(*pevent->func_map), func_bcmp);
396
397 return func;
398}
399
400/**
401 * pevent_find_function - find a function by a given address
402 * @pevent: handle for the pevent
403 * @addr: the address to find the function with
404 *
405 * Returns a pointer to the function stored that has the given
406 * address. Note, the address does not have to be exact, it
407 * will select the function that would contain the address.
408 */
409const char *pevent_find_function(struct pevent *pevent, unsigned long long addr)
410{
411 struct func_map *map;
412
413 map = find_func(pevent, addr);
414 if (!map)
415 return NULL;
416
417 return map->func;
418}
419
420/**
421 * pevent_find_function_address - find a function address by a given address
422 * @pevent: handle for the pevent
423 * @addr: the address to find the function with
424 *
425 * Returns the address the function starts at. This can be used in
426 * conjunction with pevent_find_function to print both the function
427 * name and the function offset.
428 */
429unsigned long long
430pevent_find_function_address(struct pevent *pevent, unsigned long long addr)
431{
432 struct func_map *map;
433
434 map = find_func(pevent, addr);
435 if (!map)
436 return 0;
437
438 return map->addr;
439}
440
441/**
442 * pevent_register_function - register a function with a given address
443 * @pevent: handle for the pevent
444 * @function: the function name to register
445 * @addr: the address the function starts at
446 * @mod: the kernel module the function may be in (NULL for none)
447 *
448 * This registers a function name with an address and module.
449 * The @func passed in is duplicated.
450 */
451int pevent_register_function(struct pevent *pevent, char *func,
452 unsigned long long addr, char *mod)
453{
454 struct func_list *item;
455
456 item = malloc_or_die(sizeof(*item));
457
458 item->next = pevent->funclist;
459 item->func = strdup(func);
460 if (mod)
461 item->mod = strdup(mod);
462 else
463 item->mod = NULL;
464 item->addr = addr;
465
466 pevent->funclist = item;
467
468 pevent->func_count++;
469
470 return 0;
471}
472
473/**
474 * pevent_print_funcs - print out the stored functions
475 * @pevent: handle for the pevent
476 *
477 * This prints out the stored functions.
478 */
479void pevent_print_funcs(struct pevent *pevent)
480{
481 int i;
482
483 if (!pevent->func_map)
484 func_map_init(pevent);
485
486 for (i = 0; i < (int)pevent->func_count; i++) {
487 printf("%016llx %s",
488 pevent->func_map[i].addr,
489 pevent->func_map[i].func);
490 if (pevent->func_map[i].mod)
491 printf(" [%s]\n", pevent->func_map[i].mod);
492 else
493 printf("\n");
494 }
495}
496
497struct printk_map {
498 unsigned long long addr;
499 char *printk;
500};
501
502struct printk_list {
503 struct printk_list *next;
504 unsigned long long addr;
505 char *printk;
506};
507
508static int printk_cmp(const void *a, const void *b)
509{
510 const struct func_map *fa = a;
511 const struct func_map *fb = b;
512
513 if (fa->addr < fb->addr)
514 return -1;
515 if (fa->addr > fb->addr)
516 return 1;
517
518 return 0;
519}
520
521static void printk_map_init(struct pevent *pevent)
522{
523 struct printk_list *printklist;
524 struct printk_list *item;
525 struct printk_map *printk_map;
526 int i;
527
528 printk_map = malloc_or_die(sizeof(*printk_map) * (pevent->printk_count + 1));
529
530 printklist = pevent->printklist;
531
532 i = 0;
533 while (printklist) {
534 printk_map[i].printk = printklist->printk;
535 printk_map[i].addr = printklist->addr;
536 i++;
537 item = printklist;
538 printklist = printklist->next;
539 free(item);
540 }
541
542 qsort(printk_map, pevent->printk_count, sizeof(*printk_map), printk_cmp);
543
544 pevent->printk_map = printk_map;
545 pevent->printklist = NULL;
546}
547
548static struct printk_map *
549find_printk(struct pevent *pevent, unsigned long long addr)
550{
551 struct printk_map *printk;
552 struct printk_map key;
553
554 if (!pevent->printk_map)
555 printk_map_init(pevent);
556
557 key.addr = addr;
558
559 printk = bsearch(&key, pevent->printk_map, pevent->printk_count,
560 sizeof(*pevent->printk_map), printk_cmp);
561
562 return printk;
563}
564
565/**
566 * pevent_register_print_string - register a string by its address
567 * @pevent: handle for the pevent
568 * @fmt: the string format to register
569 * @addr: the address the string was located at
570 *
571 * This registers a string by the address it was stored in the kernel.
572 * The @fmt passed in is duplicated.
573 */
574int pevent_register_print_string(struct pevent *pevent, char *fmt,
575 unsigned long long addr)
576{
577 struct printk_list *item;
578
579 item = malloc_or_die(sizeof(*item));
580
581 item->next = pevent->printklist;
582 pevent->printklist = item;
583 item->printk = strdup(fmt);
584 item->addr = addr;
585
586 pevent->printk_count++;
587
588 return 0;
589}
590
591/**
592 * pevent_print_printk - print out the stored strings
593 * @pevent: handle for the pevent
594 *
595 * This prints the string formats that were stored.
596 */
597void pevent_print_printk(struct pevent *pevent)
598{
599 int i;
600
601 if (!pevent->printk_map)
602 printk_map_init(pevent);
603
604 for (i = 0; i < (int)pevent->printk_count; i++) {
605 printf("%016llx %s\n",
606 pevent->printk_map[i].addr,
607 pevent->printk_map[i].printk);
608 }
609}
610
611static struct event_format *alloc_event(void)
612{
613 struct event_format *event;
614
615 event = malloc_or_die(sizeof(*event));
616 memset(event, 0, sizeof(*event));
617
618 return event;
619}
620
621static void add_event(struct pevent *pevent, struct event_format *event)
622{
623 int i;
624
625 if (!pevent->events)
626 pevent->events = malloc_or_die(sizeof(event));
627 else
628 pevent->events =
629 realloc(pevent->events, sizeof(event) *
630 (pevent->nr_events + 1));
631 if (!pevent->events)
632 die("Can not allocate events");
633
634 for (i = 0; i < pevent->nr_events; i++) {
635 if (pevent->events[i]->id > event->id)
636 break;
637 }
638 if (i < pevent->nr_events)
639 memmove(&pevent->events[i + 1],
640 &pevent->events[i],
641 sizeof(event) * (pevent->nr_events - i));
642
643 pevent->events[i] = event;
644 pevent->nr_events++;
645
646 event->pevent = pevent;
647}
648
649static int event_item_type(enum event_type type)
650{
651 switch (type) {
652 case EVENT_ITEM ... EVENT_SQUOTE:
653 return 1;
654 case EVENT_ERROR ... EVENT_DELIM:
655 default:
656 return 0;
657 }
658}
659
660static void free_flag_sym(struct print_flag_sym *fsym)
661{
662 struct print_flag_sym *next;
663
664 while (fsym) {
665 next = fsym->next;
666 free(fsym->value);
667 free(fsym->str);
668 free(fsym);
669 fsym = next;
670 }
671}
672
673static void free_arg(struct print_arg *arg)
674{
675 struct print_arg *farg;
676
677 if (!arg)
678 return;
679
680 switch (arg->type) {
681 case PRINT_ATOM:
682 free(arg->atom.atom);
683 break;
684 case PRINT_FIELD:
685 free(arg->field.name);
686 break;
687 case PRINT_FLAGS:
688 free_arg(arg->flags.field);
689 free(arg->flags.delim);
690 free_flag_sym(arg->flags.flags);
691 break;
692 case PRINT_SYMBOL:
693 free_arg(arg->symbol.field);
694 free_flag_sym(arg->symbol.symbols);
695 break;
696 case PRINT_TYPE:
697 free(arg->typecast.type);
698 free_arg(arg->typecast.item);
699 break;
700 case PRINT_STRING:
701 case PRINT_BSTRING:
702 free(arg->string.string);
703 break;
704 case PRINT_DYNAMIC_ARRAY:
705 free(arg->dynarray.index);
706 break;
707 case PRINT_OP:
708 free(arg->op.op);
709 free_arg(arg->op.left);
710 free_arg(arg->op.right);
711 break;
712 case PRINT_FUNC:
713 while (arg->func.args) {
714 farg = arg->func.args;
715 arg->func.args = farg->next;
716 free_arg(farg);
717 }
718 break;
719
720 case PRINT_NULL:
721 default:
722 break;
723 }
724
725 free(arg);
726}
727
728static enum event_type get_type(int ch)
729{
730 if (ch == '\n')
731 return EVENT_NEWLINE;
732 if (isspace(ch))
733 return EVENT_SPACE;
734 if (isalnum(ch) || ch == '_')
735 return EVENT_ITEM;
736 if (ch == '\'')
737 return EVENT_SQUOTE;
738 if (ch == '"')
739 return EVENT_DQUOTE;
740 if (!isprint(ch))
741 return EVENT_NONE;
742 if (ch == '(' || ch == ')' || ch == ',')
743 return EVENT_DELIM;
744
745 return EVENT_OP;
746}
747
748static int __read_char(void)
749{
750 if (input_buf_ptr >= input_buf_siz)
751 return -1;
752
753 return input_buf[input_buf_ptr++];
754}
755
756static int __peek_char(void)
757{
758 if (input_buf_ptr >= input_buf_siz)
759 return -1;
760
761 return input_buf[input_buf_ptr];
762}
763
764/**
765 * pevent_peek_char - peek at the next character that will be read
766 *
767 * Returns the next character read, or -1 if end of buffer.
768 */
769int pevent_peek_char(void)
770{
771 return __peek_char();
772}
773
774static enum event_type force_token(const char *str, char **tok);
775
776static enum event_type __read_token(char **tok)
777{
778 char buf[BUFSIZ];
779 int ch, last_ch, quote_ch, next_ch;
780 int i = 0;
781 int tok_size = 0;
782 enum event_type type;
783
784 *tok = NULL;
785
786
787 ch = __read_char();
788 if (ch < 0)
789 return EVENT_NONE;
790
791 type = get_type(ch);
792 if (type == EVENT_NONE)
793 return type;
794
795 buf[i++] = ch;
796
797 switch (type) {
798 case EVENT_NEWLINE:
799 case EVENT_DELIM:
800 *tok = malloc_or_die(2);
801 (*tok)[0] = ch;
802 (*tok)[1] = 0;
803 return type;
804
805 case EVENT_OP:
806 switch (ch) {
807 case '-':
808 next_ch = __peek_char();
809 if (next_ch == '>') {
810 buf[i++] = __read_char();
811 break;
812 }
813 /* fall through */
814 case '+':
815 case '|':
816 case '&':
817 case '>':
818 case '<':
819 last_ch = ch;
820 ch = __peek_char();
821 if (ch != last_ch)
822 goto test_equal;
823 buf[i++] = __read_char();
824 switch (last_ch) {
825 case '>':
826 case '<':
827 goto test_equal;
828 default:
829 break;
830 }
831 break;
832 case '!':
833 case '=':
834 goto test_equal;
835 default: /* what should we do instead? */
836 break;
837 }
838 buf[i] = 0;
839 *tok = strdup(buf);
840 return type;
841
842 test_equal:
843 ch = __peek_char();
844 if (ch == '=')
845 buf[i++] = __read_char();
846 goto out;
847
848 case EVENT_DQUOTE:
849 case EVENT_SQUOTE:
850 /* don't keep quotes */
851 i--;
852 quote_ch = ch;
853 last_ch = 0;
854 concat:
855 do {
856 if (i == (BUFSIZ - 1)) {
857 buf[i] = 0;
858 if (*tok) {
859 *tok = realloc(*tok, tok_size + BUFSIZ);
860 if (!*tok)
861 return EVENT_NONE;
862 strcat(*tok, buf);
863 } else
864 *tok = strdup(buf);
865
866 if (!*tok)
867 return EVENT_NONE;
868 tok_size += BUFSIZ;
869 i = 0;
870 }
871 last_ch = ch;
872 ch = __read_char();
873 buf[i++] = ch;
874 /* the '\' '\' will cancel itself */
875 if (ch == '\\' && last_ch == '\\')
876 last_ch = 0;
877 } while (ch != quote_ch || last_ch == '\\');
878 /* remove the last quote */
879 i--;
880
881 /*
882 * For strings (double quotes) check the next token.
883 * If it is another string, concatinate the two.
884 */
885 if (type == EVENT_DQUOTE) {
886 unsigned long long save_input_buf_ptr = input_buf_ptr;
887
888 do {
889 ch = __read_char();
890 } while (isspace(ch));
891 if (ch == '"')
892 goto concat;
893 input_buf_ptr = save_input_buf_ptr;
894 }
895
896 goto out;
897
898 case EVENT_ERROR ... EVENT_SPACE:
899 case EVENT_ITEM:
900 default:
901 break;
902 }
903
904 while (get_type(__peek_char()) == type) {
905 if (i == (BUFSIZ - 1)) {
906 buf[i] = 0;
907 if (*tok) {
908 *tok = realloc(*tok, tok_size + BUFSIZ);
909 if (!*tok)
910 return EVENT_NONE;
911 strcat(*tok, buf);
912 } else
913 *tok = strdup(buf);
914
915 if (!*tok)
916 return EVENT_NONE;
917 tok_size += BUFSIZ;
918 i = 0;
919 }
920 ch = __read_char();
921 buf[i++] = ch;
922 }
923
924 out:
925 buf[i] = 0;
926 if (*tok) {
927 *tok = realloc(*tok, tok_size + i);
928 if (!*tok)
929 return EVENT_NONE;
930 strcat(*tok, buf);
931 } else
932 *tok = strdup(buf);
933 if (!*tok)
934 return EVENT_NONE;
935
936 if (type == EVENT_ITEM) {
937 /*
938 * Older versions of the kernel has a bug that
939 * creates invalid symbols and will break the mac80211
940 * parsing. This is a work around to that bug.
941 *
942 * See Linux kernel commit:
943 * 811cb50baf63461ce0bdb234927046131fc7fa8b
944 */
945 if (strcmp(*tok, "LOCAL_PR_FMT") == 0) {
946 free(*tok);
947 *tok = NULL;
948 return force_token("\"\%s\" ", tok);
949 } else if (strcmp(*tok, "STA_PR_FMT") == 0) {
950 free(*tok);
951 *tok = NULL;
952 return force_token("\" sta:%pM\" ", tok);
953 } else if (strcmp(*tok, "VIF_PR_FMT") == 0) {
954 free(*tok);
955 *tok = NULL;
956 return force_token("\" vif:%p(%d)\" ", tok);
957 }
958 }
959
960 return type;
961}
962
963static enum event_type force_token(const char *str, char **tok)
964{
965 const char *save_input_buf;
966 unsigned long long save_input_buf_ptr;
967 unsigned long long save_input_buf_siz;
968 enum event_type type;
969
970 /* save off the current input pointers */
971 save_input_buf = input_buf;
972 save_input_buf_ptr = input_buf_ptr;
973 save_input_buf_siz = input_buf_siz;
974
975 init_input_buf(str, strlen(str));
976
977 type = __read_token(tok);
978
979 /* reset back to original token */
980 input_buf = save_input_buf;
981 input_buf_ptr = save_input_buf_ptr;
982 input_buf_siz = save_input_buf_siz;
983
984 return type;
985}
986
987static void free_token(char *tok)
988{
989 if (tok)
990 free(tok);
991}
992
993static enum event_type read_token(char **tok)
994{
995 enum event_type type;
996
997 for (;;) {
998 type = __read_token(tok);
999 if (type != EVENT_SPACE)
1000 return type;
1001
1002 free_token(*tok);
1003 }
1004
1005 /* not reached */
1006 *tok = NULL;
1007 return EVENT_NONE;
1008}
1009
1010/**
1011 * pevent_read_token - access to utilites to use the pevent parser
1012 * @tok: The token to return
1013 *
1014 * This will parse tokens from the string given by
1015 * pevent_init_data().
1016 *
1017 * Returns the token type.
1018 */
1019enum event_type pevent_read_token(char **tok)
1020{
1021 return read_token(tok);
1022}
1023
1024/**
1025 * pevent_free_token - free a token returned by pevent_read_token
1026 * @token: the token to free
1027 */
1028void pevent_free_token(char *token)
1029{
1030 free_token(token);
1031}
1032
1033/* no newline */
1034static enum event_type read_token_item(char **tok)
1035{
1036 enum event_type type;
1037
1038 for (;;) {
1039 type = __read_token(tok);
1040 if (type != EVENT_SPACE && type != EVENT_NEWLINE)
1041 return type;
1042 free_token(*tok);
1043 *tok = NULL;
1044 }
1045
1046 /* not reached */
1047 *tok = NULL;
1048 return EVENT_NONE;
1049}
1050
1051static int test_type(enum event_type type, enum event_type expect)
1052{
1053 if (type != expect) {
1054 do_warning("Error: expected type %d but read %d",
1055 expect, type);
1056 return -1;
1057 }
1058 return 0;
1059}
1060
1061static int test_type_token(enum event_type type, const char *token,
1062 enum event_type expect, const char *expect_tok)
1063{
1064 if (type != expect) {
1065 do_warning("Error: expected type %d but read %d",
1066 expect, type);
1067 return -1;
1068 }
1069
1070 if (strcmp(token, expect_tok) != 0) {
1071 do_warning("Error: expected '%s' but read '%s'",
1072 expect_tok, token);
1073 return -1;
1074 }
1075 return 0;
1076}
1077
1078static int __read_expect_type(enum event_type expect, char **tok, int newline_ok)
1079{
1080 enum event_type type;
1081
1082 if (newline_ok)
1083 type = read_token(tok);
1084 else
1085 type = read_token_item(tok);
1086 return test_type(type, expect);
1087}
1088
1089static int read_expect_type(enum event_type expect, char **tok)
1090{
1091 return __read_expect_type(expect, tok, 1);
1092}
1093
1094static int __read_expected(enum event_type expect, const char *str,
1095 int newline_ok)
1096{
1097 enum event_type type;
1098 char *token;
1099 int ret;
1100
1101 if (newline_ok)
1102 type = read_token(&token);
1103 else
1104 type = read_token_item(&token);
1105
1106 ret = test_type_token(type, token, expect, str);
1107
1108 free_token(token);
1109
1110 return ret;
1111}
1112
1113static int read_expected(enum event_type expect, const char *str)
1114{
1115 return __read_expected(expect, str, 1);
1116}
1117
1118static int read_expected_item(enum event_type expect, const char *str)
1119{
1120 return __read_expected(expect, str, 0);
1121}
1122
1123static char *event_read_name(void)
1124{
1125 char *token;
1126
1127 if (read_expected(EVENT_ITEM, "name") < 0)
1128 return NULL;
1129
1130 if (read_expected(EVENT_OP, ":") < 0)
1131 return NULL;
1132
1133 if (read_expect_type(EVENT_ITEM, &token) < 0)
1134 goto fail;
1135
1136 return token;
1137
1138 fail:
1139 free_token(token);
1140 return NULL;
1141}
1142
1143static int event_read_id(void)
1144{
1145 char *token;
1146 int id;
1147
1148 if (read_expected_item(EVENT_ITEM, "ID") < 0)
1149 return -1;
1150
1151 if (read_expected(EVENT_OP, ":") < 0)
1152 return -1;
1153
1154 if (read_expect_type(EVENT_ITEM, &token) < 0)
1155 goto fail;
1156
1157 id = strtoul(token, NULL, 0);
1158 free_token(token);
1159 return id;
1160
1161 fail:
1162 free_token(token);
1163 return -1;
1164}
1165
1166static int field_is_string(struct format_field *field)
1167{
1168 if ((field->flags & FIELD_IS_ARRAY) &&
1169 (strstr(field->type, "char") || strstr(field->type, "u8") ||
1170 strstr(field->type, "s8")))
1171 return 1;
1172
1173 return 0;
1174}
1175
1176static int field_is_dynamic(struct format_field *field)
1177{
1178 if (strncmp(field->type, "__data_loc", 10) == 0)
1179 return 1;
1180
1181 return 0;
1182}
1183
1184static int field_is_long(struct format_field *field)
1185{
1186 /* includes long long */
1187 if (strstr(field->type, "long"))
1188 return 1;
1189
1190 return 0;
1191}
1192
1193static int event_read_fields(struct event_format *event, struct format_field **fields)
1194{
1195 struct format_field *field = NULL;
1196 enum event_type type;
1197 char *token;
1198 char *last_token;
1199 int count = 0;
1200
1201 do {
1202 type = read_token(&token);
1203 if (type == EVENT_NEWLINE) {
1204 free_token(token);
1205 return count;
1206 }
1207
1208 count++;
1209
1210 if (test_type_token(type, token, EVENT_ITEM, "field"))
1211 goto fail;
1212 free_token(token);
1213
1214 type = read_token(&token);
1215 /*
1216 * The ftrace fields may still use the "special" name.
1217 * Just ignore it.
1218 */
1219 if (event->flags & EVENT_FL_ISFTRACE &&
1220 type == EVENT_ITEM && strcmp(token, "special") == 0) {
1221 free_token(token);
1222 type = read_token(&token);
1223 }
1224
1225 if (test_type_token(type, token, EVENT_OP, ":") < 0)
1226 goto fail;
1227
1228 free_token(token);
1229 if (read_expect_type(EVENT_ITEM, &token) < 0)
1230 goto fail;
1231
1232 last_token = token;
1233
1234 field = malloc_or_die(sizeof(*field));
1235 memset(field, 0, sizeof(*field));
1236 field->event = event;
1237
1238 /* read the rest of the type */
1239 for (;;) {
1240 type = read_token(&token);
1241 if (type == EVENT_ITEM ||
1242 (type == EVENT_OP && strcmp(token, "*") == 0) ||
1243 /*
1244 * Some of the ftrace fields are broken and have
1245 * an illegal "." in them.
1246 */
1247 (event->flags & EVENT_FL_ISFTRACE &&
1248 type == EVENT_OP && strcmp(token, ".") == 0)) {
1249
1250 if (strcmp(token, "*") == 0)
1251 field->flags |= FIELD_IS_POINTER;
1252
1253 if (field->type) {
1254 field->type = realloc(field->type,
1255 strlen(field->type) +
1256 strlen(last_token) + 2);
1257 strcat(field->type, " ");
1258 strcat(field->type, last_token);
1259 free(last_token);
1260 } else
1261 field->type = last_token;
1262 last_token = token;
1263 continue;
1264 }
1265
1266 break;
1267 }
1268
1269 if (!field->type) {
1270 die("no type found");
1271 goto fail;
1272 }
1273 field->name = last_token;
1274
1275 if (test_type(type, EVENT_OP))
1276 goto fail;
1277
1278 if (strcmp(token, "[") == 0) {
1279 enum event_type last_type = type;
1280 char *brackets = token;
1281 int len;
1282
1283 field->flags |= FIELD_IS_ARRAY;
1284
1285 type = read_token(&token);
1286
1287 if (type == EVENT_ITEM)
1288 field->arraylen = strtoul(token, NULL, 0);
1289 else
1290 field->arraylen = 0;
1291
1292 while (strcmp(token, "]") != 0) {
1293 if (last_type == EVENT_ITEM &&
1294 type == EVENT_ITEM)
1295 len = 2;
1296 else
1297 len = 1;
1298 last_type = type;
1299
1300 brackets = realloc(brackets,
1301 strlen(brackets) +
1302 strlen(token) + len);
1303 if (len == 2)
1304 strcat(brackets, " ");
1305 strcat(brackets, token);
1306 /* We only care about the last token */
1307 field->arraylen = strtoul(token, NULL, 0);
1308 free_token(token);
1309 type = read_token(&token);
1310 if (type == EVENT_NONE) {
1311 die("failed to find token");
1312 goto fail;
1313 }
1314 }
1315
1316 free_token(token);
1317
1318 brackets = realloc(brackets, strlen(brackets) + 2);
1319 strcat(brackets, "]");
1320
1321 /* add brackets to type */
1322
1323 type = read_token(&token);
1324 /*
1325 * If the next token is not an OP, then it is of
1326 * the format: type [] item;
1327 */
1328 if (type == EVENT_ITEM) {
1329 field->type = realloc(field->type,
1330 strlen(field->type) +
1331 strlen(field->name) +
1332 strlen(brackets) + 2);
1333 strcat(field->type, " ");
1334 strcat(field->type, field->name);
1335 free_token(field->name);
1336 strcat(field->type, brackets);
1337 field->name = token;
1338 type = read_token(&token);
1339 } else {
1340 field->type = realloc(field->type,
1341 strlen(field->type) +
1342 strlen(brackets) + 1);
1343 strcat(field->type, brackets);
1344 }
1345 free(brackets);
1346 }
1347
1348 if (field_is_string(field))
1349 field->flags |= FIELD_IS_STRING;
1350 if (field_is_dynamic(field))
1351 field->flags |= FIELD_IS_DYNAMIC;
1352 if (field_is_long(field))
1353 field->flags |= FIELD_IS_LONG;
1354
1355 if (test_type_token(type, token, EVENT_OP, ";"))
1356 goto fail;
1357 free_token(token);
1358
1359 if (read_expected(EVENT_ITEM, "offset") < 0)
1360 goto fail_expect;
1361
1362 if (read_expected(EVENT_OP, ":") < 0)
1363 goto fail_expect;
1364
1365 if (read_expect_type(EVENT_ITEM, &token))
1366 goto fail;
1367 field->offset = strtoul(token, NULL, 0);
1368 free_token(token);
1369
1370 if (read_expected(EVENT_OP, ";") < 0)
1371 goto fail_expect;
1372
1373 if (read_expected(EVENT_ITEM, "size") < 0)
1374 goto fail_expect;
1375
1376 if (read_expected(EVENT_OP, ":") < 0)
1377 goto fail_expect;
1378
1379 if (read_expect_type(EVENT_ITEM, &token))
1380 goto fail;
1381 field->size = strtoul(token, NULL, 0);
1382 free_token(token);
1383
1384 if (read_expected(EVENT_OP, ";") < 0)
1385 goto fail_expect;
1386
1387 type = read_token(&token);
1388 if (type != EVENT_NEWLINE) {
1389 /* newer versions of the kernel have a "signed" type */
1390 if (test_type_token(type, token, EVENT_ITEM, "signed"))
1391 goto fail;
1392
1393 free_token(token);
1394
1395 if (read_expected(EVENT_OP, ":") < 0)
1396 goto fail_expect;
1397
1398 if (read_expect_type(EVENT_ITEM, &token))
1399 goto fail;
1400
1401 /* add signed type */
1402
1403 free_token(token);
1404 if (read_expected(EVENT_OP, ";") < 0)
1405 goto fail_expect;
1406
1407 if (read_expect_type(EVENT_NEWLINE, &token))
1408 goto fail;
1409 }
1410
1411 free_token(token);
1412
1413 if (field->flags & FIELD_IS_ARRAY) {
1414 if (field->arraylen)
1415 field->elementsize = field->size / field->arraylen;
1416 else if (field->flags & FIELD_IS_STRING)
1417 field->elementsize = 1;
1418 else
1419 field->elementsize = event->pevent->long_size;
1420 } else
1421 field->elementsize = field->size;
1422
1423 *fields = field;
1424 fields = &field->next;
1425
1426 } while (1);
1427
1428 return 0;
1429
1430fail:
1431 free_token(token);
1432fail_expect:
1433 if (field)
1434 free(field);
1435 return -1;
1436}
1437
1438static int event_read_format(struct event_format *event)
1439{
1440 char *token;
1441 int ret;
1442
1443 if (read_expected_item(EVENT_ITEM, "format") < 0)
1444 return -1;
1445
1446 if (read_expected(EVENT_OP, ":") < 0)
1447 return -1;
1448
1449 if (read_expect_type(EVENT_NEWLINE, &token))
1450 goto fail;
1451 free_token(token);
1452
1453 ret = event_read_fields(event, &event->format.common_fields);
1454 if (ret < 0)
1455 return ret;
1456 event->format.nr_common = ret;
1457
1458 ret = event_read_fields(event, &event->format.fields);
1459 if (ret < 0)
1460 return ret;
1461 event->format.nr_fields = ret;
1462
1463 return 0;
1464
1465 fail:
1466 free_token(token);
1467 return -1;
1468}
1469
1470static enum event_type
1471process_arg_token(struct event_format *event, struct print_arg *arg,
1472 char **tok, enum event_type type);
1473
1474static enum event_type
1475process_arg(struct event_format *event, struct print_arg *arg, char **tok)
1476{
1477 enum event_type type;
1478 char *token;
1479
1480 type = read_token(&token);
1481 *tok = token;
1482
1483 return process_arg_token(event, arg, tok, type);
1484}
1485
1486static enum event_type
1487process_op(struct event_format *event, struct print_arg *arg, char **tok);
1488
1489static enum event_type
1490process_cond(struct event_format *event, struct print_arg *top, char **tok)
1491{
1492 struct print_arg *arg, *left, *right;
1493 enum event_type type;
1494 char *token = NULL;
1495
1496 arg = alloc_arg();
1497 left = alloc_arg();
1498 right = alloc_arg();
1499
1500 arg->type = PRINT_OP;
1501 arg->op.left = left;
1502 arg->op.right = right;
1503
1504 *tok = NULL;
1505 type = process_arg(event, left, &token);
1506
1507 again:
1508 /* Handle other operations in the arguments */
1509 if (type == EVENT_OP && strcmp(token, ":") != 0) {
1510 type = process_op(event, left, &token);
1511 goto again;
1512 }
1513
1514 if (test_type_token(type, token, EVENT_OP, ":"))
1515 goto out_free;
1516
1517 arg->op.op = token;
1518
1519 type = process_arg(event, right, &token);
1520
1521 top->op.right = arg;
1522
1523 *tok = token;
1524 return type;
1525
1526out_free:
1527 /* Top may point to itself */
1528 top->op.right = NULL;
1529 free_token(token);
1530 free_arg(arg);
1531 return EVENT_ERROR;
1532}
1533
1534static enum event_type
1535process_array(struct event_format *event, struct print_arg *top, char **tok)
1536{
1537 struct print_arg *arg;
1538 enum event_type type;
1539 char *token = NULL;
1540
1541 arg = alloc_arg();
1542
1543 *tok = NULL;
1544 type = process_arg(event, arg, &token);
1545 if (test_type_token(type, token, EVENT_OP, "]"))
1546 goto out_free;
1547
1548 top->op.right = arg;
1549
1550 free_token(token);
1551 type = read_token_item(&token);
1552 *tok = token;
1553
1554 return type;
1555
1556out_free:
1557 free_token(*tok);
1558 *tok = NULL;
1559 free_arg(arg);
1560 return EVENT_ERROR;
1561}
1562
1563static int get_op_prio(char *op)
1564{
1565 if (!op[1]) {
1566 switch (op[0]) {
1567 case '~':
1568 case '!':
1569 return 4;
1570 case '*':
1571 case '/':
1572 case '%':
1573 return 6;
1574 case '+':
1575 case '-':
1576 return 7;
1577 /* '>>' and '<<' are 8 */
1578 case '<':
1579 case '>':
1580 return 9;
1581 /* '==' and '!=' are 10 */
1582 case '&':
1583 return 11;
1584 case '^':
1585 return 12;
1586 case '|':
1587 return 13;
1588 case '?':
1589 return 16;
1590 default:
1591 die("unknown op '%c'", op[0]);
1592 return -1;
1593 }
1594 } else {
1595 if (strcmp(op, "++") == 0 ||
1596 strcmp(op, "--") == 0) {
1597 return 3;
1598 } else if (strcmp(op, ">>") == 0 ||
1599 strcmp(op, "<<") == 0) {
1600 return 8;
1601 } else if (strcmp(op, ">=") == 0 ||
1602 strcmp(op, "<=") == 0) {
1603 return 9;
1604 } else if (strcmp(op, "==") == 0 ||
1605 strcmp(op, "!=") == 0) {
1606 return 10;
1607 } else if (strcmp(op, "&&") == 0) {
1608 return 14;
1609 } else if (strcmp(op, "||") == 0) {
1610 return 15;
1611 } else {
1612 die("unknown op '%s'", op);
1613 return -1;
1614 }
1615 }
1616}
1617
1618static void set_op_prio(struct print_arg *arg)
1619{
1620
1621 /* single ops are the greatest */
1622 if (!arg->op.left || arg->op.left->type == PRINT_NULL) {
1623 arg->op.prio = 0;
1624 return;
1625 }
1626
1627 arg->op.prio = get_op_prio(arg->op.op);
1628}
1629
1630/* Note, *tok does not get freed, but will most likely be saved */
1631static enum event_type
1632process_op(struct event_format *event, struct print_arg *arg, char **tok)
1633{
1634 struct print_arg *left, *right = NULL;
1635 enum event_type type;
1636 char *token;
1637
1638 /* the op is passed in via tok */
1639 token = *tok;
1640
1641 if (arg->type == PRINT_OP && !arg->op.left) {
1642 /* handle single op */
1643 if (token[1]) {
1644 die("bad op token %s", token);
1645 goto out_free;
1646 }
1647 switch (token[0]) {
1648 case '~':
1649 case '!':
1650 case '+':
1651 case '-':
1652 break;
1653 default:
1654 do_warning("bad op token %s", token);
1655 goto out_free;
1656
1657 }
1658
1659 /* make an empty left */
1660 left = alloc_arg();
1661 left->type = PRINT_NULL;
1662 arg->op.left = left;
1663
1664 right = alloc_arg();
1665 arg->op.right = right;
1666
1667 /* do not free the token, it belongs to an op */
1668 *tok = NULL;
1669 type = process_arg(event, right, tok);
1670
1671 } else if (strcmp(token, "?") == 0) {
1672
1673 left = alloc_arg();
1674 /* copy the top arg to the left */
1675 *left = *arg;
1676
1677 arg->type = PRINT_OP;
1678 arg->op.op = token;
1679 arg->op.left = left;
1680 arg->op.prio = 0;
1681
1682 type = process_cond(event, arg, tok);
1683
1684 } else if (strcmp(token, ">>") == 0 ||
1685 strcmp(token, "<<") == 0 ||
1686 strcmp(token, "&") == 0 ||
1687 strcmp(token, "|") == 0 ||
1688 strcmp(token, "&&") == 0 ||
1689 strcmp(token, "||") == 0 ||
1690 strcmp(token, "-") == 0 ||
1691 strcmp(token, "+") == 0 ||
1692 strcmp(token, "*") == 0 ||
1693 strcmp(token, "^") == 0 ||
1694 strcmp(token, "/") == 0 ||
1695 strcmp(token, "<") == 0 ||
1696 strcmp(token, ">") == 0 ||
1697 strcmp(token, "==") == 0 ||
1698 strcmp(token, "!=") == 0) {
1699
1700 left = alloc_arg();
1701
1702 /* copy the top arg to the left */
1703 *left = *arg;
1704
1705 arg->type = PRINT_OP;
1706 arg->op.op = token;
1707 arg->op.left = left;
1708
1709 set_op_prio(arg);
1710
1711 type = read_token_item(&token);
1712 *tok = token;
1713
1714 /* could just be a type pointer */
1715 if ((strcmp(arg->op.op, "*") == 0) &&
1716 type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
1717 if (left->type != PRINT_ATOM)
1718 die("bad pointer type");
1719 left->atom.atom = realloc(left->atom.atom,
1720 strlen(left->atom.atom) + 3);
1721 strcat(left->atom.atom, " *");
1722 free(arg->op.op);
1723 *arg = *left;
1724 free(left);
1725
1726 return type;
1727 }
1728
1729 right = alloc_arg();
1730 type = process_arg_token(event, right, tok, type);
1731 arg->op.right = right;
1732
1733 } else if (strcmp(token, "[") == 0) {
1734
1735 left = alloc_arg();
1736 *left = *arg;
1737
1738 arg->type = PRINT_OP;
1739 arg->op.op = token;
1740 arg->op.left = left;
1741
1742 arg->op.prio = 0;
1743
1744 type = process_array(event, arg, tok);
1745
1746 } else {
1747 do_warning("unknown op '%s'", token);
1748 event->flags |= EVENT_FL_FAILED;
1749 /* the arg is now the left side */
1750 goto out_free;
1751 }
1752
1753 if (type == EVENT_OP && strcmp(*tok, ":") != 0) {
1754 int prio;
1755
1756 /* higher prios need to be closer to the root */
1757 prio = get_op_prio(*tok);
1758
1759 if (prio > arg->op.prio)
1760 return process_op(event, arg, tok);
1761
1762 return process_op(event, right, tok);
1763 }
1764
1765 return type;
1766
1767 out_free:
1768 free_token(token);
1769 *tok = NULL;
1770 return EVENT_ERROR;
1771}
1772
1773static enum event_type
1774process_entry(struct event_format *event __unused, struct print_arg *arg,
1775 char **tok)
1776{
1777 enum event_type type;
1778 char *field;
1779 char *token;
1780
1781 if (read_expected(EVENT_OP, "->") < 0)
1782 goto out_err;
1783
1784 if (read_expect_type(EVENT_ITEM, &token) < 0)
1785 goto out_free;
1786 field = token;
1787
1788 arg->type = PRINT_FIELD;
1789 arg->field.name = field;
1790
1791 type = read_token(&token);
1792 *tok = token;
1793
1794 return type;
1795
1796 out_free:
1797 free_token(token);
1798 out_err:
1799 *tok = NULL;
1800 return EVENT_ERROR;
1801}
1802
1803static char *arg_eval (struct print_arg *arg);
1804
1805static unsigned long long
1806eval_type_str(unsigned long long val, const char *type, int pointer)
1807{
1808 int sign = 0;
1809 char *ref;
1810 int len;
1811
1812 len = strlen(type);
1813
1814 if (pointer) {
1815
1816 if (type[len-1] != '*') {
1817 do_warning("pointer expected with non pointer type");
1818 return val;
1819 }
1820
1821 ref = malloc_or_die(len);
1822 memcpy(ref, type, len);
1823
1824 /* chop off the " *" */
1825 ref[len - 2] = 0;
1826
1827 val = eval_type_str(val, ref, 0);
1828 free(ref);
1829 return val;
1830 }
1831
1832 /* check if this is a pointer */
1833 if (type[len - 1] == '*')
1834 return val;
1835
1836 /* Try to figure out the arg size*/
1837 if (strncmp(type, "struct", 6) == 0)
1838 /* all bets off */
1839 return val;
1840
1841 if (strcmp(type, "u8") == 0)
1842 return val & 0xff;
1843
1844 if (strcmp(type, "u16") == 0)
1845 return val & 0xffff;
1846
1847 if (strcmp(type, "u32") == 0)
1848 return val & 0xffffffff;
1849
1850 if (strcmp(type, "u64") == 0 ||
1851 strcmp(type, "s64"))
1852 return val;
1853
1854 if (strcmp(type, "s8") == 0)
1855 return (unsigned long long)(char)val & 0xff;
1856
1857 if (strcmp(type, "s16") == 0)
1858 return (unsigned long long)(short)val & 0xffff;
1859
1860 if (strcmp(type, "s32") == 0)
1861 return (unsigned long long)(int)val & 0xffffffff;
1862
1863 if (strncmp(type, "unsigned ", 9) == 0) {
1864 sign = 0;
1865 type += 9;
1866 }
1867
1868 if (strcmp(type, "char") == 0) {
1869 if (sign)
1870 return (unsigned long long)(char)val & 0xff;
1871 else
1872 return val & 0xff;
1873 }
1874
1875 if (strcmp(type, "short") == 0) {
1876 if (sign)
1877 return (unsigned long long)(short)val & 0xffff;
1878 else
1879 return val & 0xffff;
1880 }
1881
1882 if (strcmp(type, "int") == 0) {
1883 if (sign)
1884 return (unsigned long long)(int)val & 0xffffffff;
1885 else
1886 return val & 0xffffffff;
1887 }
1888
1889 return val;
1890}
1891
1892/*
1893 * Try to figure out the type.
1894 */
1895static unsigned long long
1896eval_type(unsigned long long val, struct print_arg *arg, int pointer)
1897{
1898 if (arg->type != PRINT_TYPE)
1899 die("expected type argument");
1900
1901 return eval_type_str(val, arg->typecast.type, pointer);
1902}
1903
1904static long long arg_num_eval(struct print_arg *arg)
1905{
1906 long long left, right;
1907 long long val = 0;
1908
1909 switch (arg->type) {
1910 case PRINT_ATOM:
1911 val = strtoll(arg->atom.atom, NULL, 0);
1912 break;
1913 case PRINT_TYPE:
1914 val = arg_num_eval(arg->typecast.item);
1915 val = eval_type(val, arg, 0);
1916 break;
1917 case PRINT_OP:
1918 switch (arg->op.op[0]) {
1919 case '|':
1920 left = arg_num_eval(arg->op.left);
1921 right = arg_num_eval(arg->op.right);
1922 if (arg->op.op[1])
1923 val = left || right;
1924 else
1925 val = left | right;
1926 break;
1927 case '&':
1928 left = arg_num_eval(arg->op.left);
1929 right = arg_num_eval(arg->op.right);
1930 if (arg->op.op[1])
1931 val = left && right;
1932 else
1933 val = left & right;
1934 break;
1935 case '<':
1936 left = arg_num_eval(arg->op.left);
1937 right = arg_num_eval(arg->op.right);
1938 switch (arg->op.op[1]) {
1939 case 0:
1940 val = left < right;
1941 break;
1942 case '<':
1943 val = left << right;
1944 break;
1945 case '=':
1946 val = left <= right;
1947 break;
1948 default:
1949 die("unknown op '%s'", arg->op.op);
1950 }
1951 break;
1952 case '>':
1953 left = arg_num_eval(arg->op.left);
1954 right = arg_num_eval(arg->op.right);
1955 switch (arg->op.op[1]) {
1956 case 0:
1957 val = left > right;
1958 break;
1959 case '>':
1960 val = left >> right;
1961 break;
1962 case '=':
1963 val = left >= right;
1964 break;
1965 default:
1966 die("unknown op '%s'", arg->op.op);
1967 }
1968 break;
1969 case '=':
1970 left = arg_num_eval(arg->op.left);
1971 right = arg_num_eval(arg->op.right);
1972
1973 if (arg->op.op[1] != '=')
1974 die("unknown op '%s'", arg->op.op);
1975
1976 val = left == right;
1977 break;
1978 case '!':
1979 left = arg_num_eval(arg->op.left);
1980 right = arg_num_eval(arg->op.right);
1981
1982 switch (arg->op.op[1]) {
1983 case '=':
1984 val = left != right;
1985 break;
1986 default:
1987 die("unknown op '%s'", arg->op.op);
1988 }
1989 break;
1990 case '-':
1991 /* check for negative */
1992 if (arg->op.left->type == PRINT_NULL)
1993 left = 0;
1994 else
1995 left = arg_num_eval(arg->op.left);
1996 right = arg_num_eval(arg->op.right);
1997 val = left - right;
1998 break;
1999 default:
2000 die("unknown op '%s'", arg->op.op);
2001 }
2002 break;
2003
2004 case PRINT_NULL:
2005 case PRINT_FIELD ... PRINT_SYMBOL:
2006 case PRINT_STRING:
2007 case PRINT_BSTRING:
2008 default:
2009 die("invalid eval type %d", arg->type);
2010
2011 }
2012 return val;
2013}
2014
2015static char *arg_eval (struct print_arg *arg)
2016{
2017 long long val;
2018 static char buf[20];
2019
2020 switch (arg->type) {
2021 case PRINT_ATOM:
2022 return arg->atom.atom;
2023 case PRINT_TYPE:
2024 return arg_eval(arg->typecast.item);
2025 case PRINT_OP:
2026 val = arg_num_eval(arg);
2027 sprintf(buf, "%lld", val);
2028 return buf;
2029
2030 case PRINT_NULL:
2031 case PRINT_FIELD ... PRINT_SYMBOL:
2032 case PRINT_STRING:
2033 case PRINT_BSTRING:
2034 default:
2035 die("invalid eval type %d", arg->type);
2036 break;
2037 }
2038
2039 return NULL;
2040}
2041
2042static enum event_type
2043process_fields(struct event_format *event, struct print_flag_sym **list, char **tok)
2044{
2045 enum event_type type;
2046 struct print_arg *arg = NULL;
2047 struct print_flag_sym *field;
2048 char *token = *tok;
2049 char *value;
2050
2051 do {
2052 free_token(token);
2053 type = read_token_item(&token);
2054 if (test_type_token(type, token, EVENT_OP, "{"))
2055 break;
2056
2057 arg = alloc_arg();
2058
2059 free_token(token);
2060 type = process_arg(event, arg, &token);
2061 if (test_type_token(type, token, EVENT_DELIM, ","))
2062 goto out_free;
2063
2064 field = malloc_or_die(sizeof(*field));
2065 memset(field, 0, sizeof(field));
2066
2067 value = arg_eval(arg);
2068 field->value = strdup(value);
2069
2070 free_arg(arg);
2071 arg = alloc_arg();
2072
2073 free_token(token);
2074 type = process_arg(event, arg, &token);
2075 if (test_type_token(type, token, EVENT_OP, "}"))
2076 goto out_free;
2077
2078 value = arg_eval(arg);
2079 field->str = strdup(value);
2080 free_arg(arg);
2081 arg = NULL;
2082
2083 *list = field;
2084 list = &field->next;
2085
2086 free_token(token);
2087 type = read_token_item(&token);
2088 } while (type == EVENT_DELIM && strcmp(token, ",") == 0);
2089
2090 *tok = token;
2091 return type;
2092
2093out_free:
2094 free_arg(arg);
2095 free_token(token);
2096 *tok = NULL;
2097
2098 return EVENT_ERROR;
2099}
2100
2101static enum event_type
2102process_flags(struct event_format *event, struct print_arg *arg, char **tok)
2103{
2104 struct print_arg *field;
2105 enum event_type type;
2106 char *token;
2107
2108 memset(arg, 0, sizeof(*arg));
2109 arg->type = PRINT_FLAGS;
2110
2111 field = alloc_arg();
2112
2113 type = process_arg(event, field, &token);
2114
2115 /* Handle operations in the first argument */
2116 while (type == EVENT_OP)
2117 type = process_op(event, field, &token);
2118
2119 if (test_type_token(type, token, EVENT_DELIM, ","))
2120 goto out_free;
2121 free_token(token);
2122
2123 arg->flags.field = field;
2124
2125 type = read_token_item(&token);
2126 if (event_item_type(type)) {
2127 arg->flags.delim = token;
2128 type = read_token_item(&token);
2129 }
2130
2131 if (test_type_token(type, token, EVENT_DELIM, ","))
2132 goto out_free;
2133
2134 type = process_fields(event, &arg->flags.flags, &token);
2135 if (test_type_token(type, token, EVENT_DELIM, ")"))
2136 goto out_free;
2137
2138 free_token(token);
2139 type = read_token_item(tok);
2140 return type;
2141
2142 out_free:
2143 free_token(token);
2144 *tok = NULL;
2145 return EVENT_ERROR;
2146}
2147
2148static enum event_type
2149process_symbols(struct event_format *event, struct print_arg *arg, char **tok)
2150{
2151 struct print_arg *field;
2152 enum event_type type;
2153 char *token;
2154
2155 memset(arg, 0, sizeof(*arg));
2156 arg->type = PRINT_SYMBOL;
2157
2158 field = alloc_arg();
2159
2160 type = process_arg(event, field, &token);
2161 if (test_type_token(type, token, EVENT_DELIM, ","))
2162 goto out_free;
2163
2164 arg->symbol.field = field;
2165
2166 type = process_fields(event, &arg->symbol.symbols, &token);
2167 if (test_type_token(type, token, EVENT_DELIM, ")"))
2168 goto out_free;
2169
2170 free_token(token);
2171 type = read_token_item(tok);
2172 return type;
2173
2174 out_free:
2175 free_token(token);
2176 *tok = NULL;
2177 return EVENT_ERROR;
2178}
2179
2180static enum event_type
2181process_dynamic_array(struct event_format *event, struct print_arg *arg, char **tok)
2182{
2183 struct format_field *field;
2184 enum event_type type;
2185 char *token;
2186
2187 memset(arg, 0, sizeof(*arg));
2188 arg->type = PRINT_DYNAMIC_ARRAY;
2189
2190 /*
2191 * The item within the parenthesis is another field that holds
2192 * the index into where the array starts.
2193 */
2194 type = read_token(&token);
2195 *tok = token;
2196 if (type != EVENT_ITEM)
2197 goto out_free;
2198
2199 /* Find the field */
2200
2201 field = pevent_find_field(event, token);
2202 if (!field)
2203 goto out_free;
2204
2205 arg->dynarray.field = field;
2206 arg->dynarray.index = 0;
2207
2208 if (read_expected(EVENT_DELIM, ")") < 0)
2209 goto out_free;
2210
2211 free_token(token);
2212 type = read_token_item(&token);
2213 *tok = token;
2214 if (type != EVENT_OP || strcmp(token, "[") != 0)
2215 return type;
2216
2217 free_token(token);
2218 arg = alloc_arg();
2219 type = process_arg(event, arg, &token);
2220 if (type == EVENT_ERROR)
2221 goto out_free;
2222
2223 if (!test_type_token(type, token, EVENT_OP, "]"))
2224 goto out_free;
2225
2226 free_token(token);
2227 type = read_token_item(tok);
2228 return type;
2229
2230 out_free:
2231 free(arg);
2232 free_token(token);
2233 *tok = NULL;
2234 return EVENT_ERROR;
2235}
2236
2237static enum event_type
2238process_paren(struct event_format *event, struct print_arg *arg, char **tok)
2239{
2240 struct print_arg *item_arg;
2241 enum event_type type;
2242 char *token;
2243
2244 type = process_arg(event, arg, &token);
2245
2246 if (type == EVENT_ERROR)
2247 goto out_free;
2248
2249 if (type == EVENT_OP)
2250 type = process_op(event, arg, &token);
2251
2252 if (type == EVENT_ERROR)
2253 goto out_free;
2254
2255 if (test_type_token(type, token, EVENT_DELIM, ")"))
2256 goto out_free;
2257
2258 free_token(token);
2259 type = read_token_item(&token);
2260
2261 /*
2262 * If the next token is an item or another open paren, then
2263 * this was a typecast.
2264 */
2265 if (event_item_type(type) ||
2266 (type == EVENT_DELIM && strcmp(token, "(") == 0)) {
2267
2268 /* make this a typecast and contine */
2269
2270 /* prevous must be an atom */
2271 if (arg->type != PRINT_ATOM)
2272 die("previous needed to be PRINT_ATOM");
2273
2274 item_arg = alloc_arg();
2275
2276 arg->type = PRINT_TYPE;
2277 arg->typecast.type = arg->atom.atom;
2278 arg->typecast.item = item_arg;
2279 type = process_arg_token(event, item_arg, &token, type);
2280
2281 }
2282
2283 *tok = token;
2284 return type;
2285
2286 out_free:
2287 free_token(token);
2288 *tok = NULL;
2289 return EVENT_ERROR;
2290}
2291
2292
2293static enum event_type
2294process_str(struct event_format *event __unused, struct print_arg *arg, char **tok)
2295{
2296 enum event_type type;
2297 char *token;
2298
2299 if (read_expect_type(EVENT_ITEM, &token) < 0)
2300 goto out_free;
2301
2302 arg->type = PRINT_STRING;
2303 arg->string.string = token;
2304 arg->string.offset = -1;
2305
2306 if (read_expected(EVENT_DELIM, ")") < 0)
2307 goto out_err;
2308
2309 type = read_token(&token);
2310 *tok = token;
2311
2312 return type;
2313
2314 out_free:
2315 free_token(token);
2316 out_err:
2317 *tok = NULL;
2318 return EVENT_ERROR;
2319}
2320
2321static struct pevent_function_handler *
2322find_func_handler(struct pevent *pevent, char *func_name)
2323{
2324 struct pevent_function_handler *func;
2325
2326 for (func = pevent->func_handlers; func; func = func->next) {
2327 if (strcmp(func->name, func_name) == 0)
2328 break;
2329 }
2330
2331 return func;
2332}
2333
2334static void remove_func_handler(struct pevent *pevent, char *func_name)
2335{
2336 struct pevent_function_handler *func;
2337 struct pevent_function_handler **next;
2338
2339 next = &pevent->func_handlers;
2340 while ((func = *next)) {
2341 if (strcmp(func->name, func_name) == 0) {
2342 *next = func->next;
2343 free_func_handle(func);
2344 break;
2345 }
2346 next = &func->next;
2347 }
2348}
2349
2350static enum event_type
2351process_func_handler(struct event_format *event, struct pevent_function_handler *func,
2352 struct print_arg *arg, char **tok)
2353{
2354 struct print_arg **next_arg;
2355 struct print_arg *farg;
2356 enum event_type type;
2357 char *token;
2358 char *test;
2359 int i;
2360
2361 arg->type = PRINT_FUNC;
2362 arg->func.func = func;
2363
2364 *tok = NULL;
2365
2366 next_arg = &(arg->func.args);
2367 for (i = 0; i < func->nr_args; i++) {
2368 farg = alloc_arg();
2369 type = process_arg(event, farg, &token);
2370 if (i < (func->nr_args - 1))
2371 test = ",";
2372 else
2373 test = ")";
2374
2375 if (test_type_token(type, token, EVENT_DELIM, test)) {
2376 free_arg(farg);
2377 free_token(token);
2378 return EVENT_ERROR;
2379 }
2380
2381 *next_arg = farg;
2382 next_arg = &(farg->next);
2383 free_token(token);
2384 }
2385
2386 type = read_token(&token);
2387 *tok = token;
2388
2389 return type;
2390}
2391
2392static enum event_type
2393process_function(struct event_format *event, struct print_arg *arg,
2394 char *token, char **tok)
2395{
2396 struct pevent_function_handler *func;
2397
2398 if (strcmp(token, "__print_flags") == 0) {
2399 free_token(token);
2400 return process_flags(event, arg, tok);
2401 }
2402 if (strcmp(token, "__print_symbolic") == 0) {
2403 free_token(token);
2404 return process_symbols(event, arg, tok);
2405 }
2406 if (strcmp(token, "__get_str") == 0) {
2407 free_token(token);
2408 return process_str(event, arg, tok);
2409 }
2410 if (strcmp(token, "__get_dynamic_array") == 0) {
2411 free_token(token);
2412 return process_dynamic_array(event, arg, tok);
2413 }
2414
2415 func = find_func_handler(event->pevent, token);
2416 if (func) {
2417 free_token(token);
2418 return process_func_handler(event, func, arg, tok);
2419 }
2420
2421 do_warning("function %s not defined", token);
2422 free_token(token);
2423 return EVENT_ERROR;
2424}
2425
2426static enum event_type
2427process_arg_token(struct event_format *event, struct print_arg *arg,
2428 char **tok, enum event_type type)
2429{
2430 char *token;
2431 char *atom;
2432
2433 token = *tok;
2434
2435 switch (type) {
2436 case EVENT_ITEM:
2437 if (strcmp(token, "REC") == 0) {
2438 free_token(token);
2439 type = process_entry(event, arg, &token);
2440 break;
2441 }
2442 atom = token;
2443 /* test the next token */
2444 type = read_token_item(&token);
2445
2446 /*
2447 * If the next token is a parenthesis, then this
2448 * is a function.
2449 */
2450 if (type == EVENT_DELIM && strcmp(token, "(") == 0) {
2451 free_token(token);
2452 token = NULL;
2453 /* this will free atom. */
2454 type = process_function(event, arg, atom, &token);
2455 break;
2456 }
2457 /* atoms can be more than one token long */
2458 while (type == EVENT_ITEM) {
2459 atom = realloc(atom, strlen(atom) + strlen(token) + 2);
2460 strcat(atom, " ");
2461 strcat(atom, token);
2462 free_token(token);
2463 type = read_token_item(&token);
2464 }
2465
2466 arg->type = PRINT_ATOM;
2467 arg->atom.atom = atom;
2468 break;
2469
2470 case EVENT_DQUOTE:
2471 case EVENT_SQUOTE:
2472 arg->type = PRINT_ATOM;
2473 arg->atom.atom = token;
2474 type = read_token_item(&token);
2475 break;
2476 case EVENT_DELIM:
2477 if (strcmp(token, "(") == 0) {
2478 free_token(token);
2479 type = process_paren(event, arg, &token);
2480 break;
2481 }
2482 case EVENT_OP:
2483 /* handle single ops */
2484 arg->type = PRINT_OP;
2485 arg->op.op = token;
2486 arg->op.left = NULL;
2487 type = process_op(event, arg, &token);
2488
2489 /* On error, the op is freed */
2490 if (type == EVENT_ERROR)
2491 arg->op.op = NULL;
2492
2493 /* return error type if errored */
2494 break;
2495
2496 case EVENT_ERROR ... EVENT_NEWLINE:
2497 default:
2498 die("unexpected type %d", type);
2499 }
2500 *tok = token;
2501
2502 return type;
2503}
2504
2505static int event_read_print_args(struct event_format *event, struct print_arg **list)
2506{
2507 enum event_type type = EVENT_ERROR;
2508 struct print_arg *arg;
2509 char *token;
2510 int args = 0;
2511
2512 do {
2513 if (type == EVENT_NEWLINE) {
2514 type = read_token_item(&token);
2515 continue;
2516 }
2517
2518 arg = alloc_arg();
2519
2520 type = process_arg(event, arg, &token);
2521
2522 if (type == EVENT_ERROR) {
2523 free_token(token);
2524 free_arg(arg);
2525 return -1;
2526 }
2527
2528 *list = arg;
2529 args++;
2530
2531 if (type == EVENT_OP) {
2532 type = process_op(event, arg, &token);
2533 free_token(token);
2534 if (type == EVENT_ERROR) {
2535 *list = NULL;
2536 free_arg(arg);
2537 return -1;
2538 }
2539 list = &arg->next;
2540 continue;
2541 }
2542
2543 if (type == EVENT_DELIM && strcmp(token, ",") == 0) {
2544 free_token(token);
2545 *list = arg;
2546 list = &arg->next;
2547 continue;
2548 }
2549 break;
2550 } while (type != EVENT_NONE);
2551
2552 if (type != EVENT_NONE && type != EVENT_ERROR)
2553 free_token(token);
2554
2555 return args;
2556}
2557
2558static int event_read_print(struct event_format *event)
2559{
2560 enum event_type type;
2561 char *token;
2562 int ret;
2563
2564 if (read_expected_item(EVENT_ITEM, "print") < 0)
2565 return -1;
2566
2567 if (read_expected(EVENT_ITEM, "fmt") < 0)
2568 return -1;
2569
2570 if (read_expected(EVENT_OP, ":") < 0)
2571 return -1;
2572
2573 if (read_expect_type(EVENT_DQUOTE, &token) < 0)
2574 goto fail;
2575
2576 concat:
2577 event->print_fmt.format = token;
2578 event->print_fmt.args = NULL;
2579
2580 /* ok to have no arg */
2581 type = read_token_item(&token);
2582
2583 if (type == EVENT_NONE)
2584 return 0;
2585
2586 /* Handle concatenation of print lines */
2587 if (type == EVENT_DQUOTE) {
2588 char *cat;
2589
2590 cat = malloc_or_die(strlen(event->print_fmt.format) +
2591 strlen(token) + 1);
2592 strcpy(cat, event->print_fmt.format);
2593 strcat(cat, token);
2594 free_token(token);
2595 free_token(event->print_fmt.format);
2596 event->print_fmt.format = NULL;
2597 token = cat;
2598 goto concat;
2599 }
2600
2601 if (test_type_token(type, token, EVENT_DELIM, ","))
2602 goto fail;
2603
2604 free_token(token);
2605
2606 ret = event_read_print_args(event, &event->print_fmt.args);
2607 if (ret < 0)
2608 return -1;
2609
2610 return ret;
2611
2612 fail:
2613 free_token(token);
2614 return -1;
2615}
2616
2617/**
2618 * pevent_find_common_field - return a common field by event
2619 * @event: handle for the event
2620 * @name: the name of the common field to return
2621 *
2622 * Returns a common field from the event by the given @name.
2623 * This only searchs the common fields and not all field.
2624 */
2625struct format_field *
2626pevent_find_common_field(struct event_format *event, const char *name)
2627{
2628 struct format_field *format;
2629
2630 for (format = event->format.common_fields;
2631 format; format = format->next) {
2632 if (strcmp(format->name, name) == 0)
2633 break;
2634 }
2635
2636 return format;
2637}
2638
2639/**
2640 * pevent_find_field - find a non-common field
2641 * @event: handle for the event
2642 * @name: the name of the non-common field
2643 *
2644 * Returns a non-common field by the given @name.
2645 * This does not search common fields.
2646 */
2647struct format_field *
2648pevent_find_field(struct event_format *event, const char *name)
2649{
2650 struct format_field *format;
2651
2652 for (format = event->format.fields;
2653 format; format = format->next) {
2654 if (strcmp(format->name, name) == 0)
2655 break;
2656 }
2657
2658 return format;
2659}
2660
2661/**
2662 * pevent_find_any_field - find any field by name
2663 * @event: handle for the event
2664 * @name: the name of the field
2665 *
2666 * Returns a field by the given @name.
2667 * This searchs the common field names first, then
2668 * the non-common ones if a common one was not found.
2669 */
2670struct format_field *
2671pevent_find_any_field(struct event_format *event, const char *name)
2672{
2673 struct format_field *format;
2674
2675 format = pevent_find_common_field(event, name);
2676 if (format)
2677 return format;
2678 return pevent_find_field(event, name);
2679}
2680
2681/**
2682 * pevent_read_number - read a number from data
2683 * @pevent: handle for the pevent
2684 * @ptr: the raw data
2685 * @size: the size of the data that holds the number
2686 *
2687 * Returns the number (converted to host) from the
2688 * raw data.
2689 */
2690unsigned long long pevent_read_number(struct pevent *pevent,
2691 const void *ptr, int size)
2692{
2693 switch (size) {
2694 case 1:
2695 return *(unsigned char *)ptr;
2696 case 2:
2697 return data2host2(pevent, ptr);
2698 case 4:
2699 return data2host4(pevent, ptr);
2700 case 8:
2701 return data2host8(pevent, ptr);
2702 default:
2703 /* BUG! */
2704 return 0;
2705 }
2706}
2707
2708/**
2709 * pevent_read_number_field - read a number from data
2710 * @field: a handle to the field
2711 * @data: the raw data to read
2712 * @value: the value to place the number in
2713 *
2714 * Reads raw data according to a field offset and size,
2715 * and translates it into @value.
2716 *
2717 * Returns 0 on success, -1 otherwise.
2718 */
2719int pevent_read_number_field(struct format_field *field, const void *data,
2720 unsigned long long *value)
2721{
2722 if (!field)
2723 return -1;
2724 switch (field->size) {
2725 case 1:
2726 case 2:
2727 case 4:
2728 case 8:
2729 *value = pevent_read_number(field->event->pevent,
2730 data + field->offset, field->size);
2731 return 0;
2732 default:
2733 return -1;
2734 }
2735}
2736
2737static int get_common_info(struct pevent *pevent,
2738 const char *type, int *offset, int *size)
2739{
2740 struct event_format *event;
2741 struct format_field *field;
2742
2743 /*
2744 * All events should have the same common elements.
2745 * Pick any event to find where the type is;
2746 */
2747 if (!pevent->events)
2748 die("no event_list!");
2749
2750 event = pevent->events[0];
2751 field = pevent_find_common_field(event, type);
2752 if (!field)
2753 die("field '%s' not found", type);
2754
2755 *offset = field->offset;
2756 *size = field->size;
2757
2758 return 0;
2759}
2760
2761static int __parse_common(struct pevent *pevent, void *data,
2762 int *size, int *offset, const char *name)
2763{
2764 int ret;
2765
2766 if (!*size) {
2767 ret = get_common_info(pevent, name, offset, size);
2768 if (ret < 0)
2769 return ret;
2770 }
2771 return pevent_read_number(pevent, data + *offset, *size);
2772}
2773
2774static int trace_parse_common_type(struct pevent *pevent, void *data)
2775{
2776 return __parse_common(pevent, data,
2777 &pevent->type_size, &pevent->type_offset,
2778 "common_type");
2779}
2780
2781static int parse_common_pid(struct pevent *pevent, void *data)
2782{
2783 return __parse_common(pevent, data,
2784 &pevent->pid_size, &pevent->pid_offset,
2785 "common_pid");
2786}
2787
2788static int parse_common_pc(struct pevent *pevent, void *data)
2789{
2790 return __parse_common(pevent, data,
2791 &pevent->pc_size, &pevent->pc_offset,
2792 "common_preempt_count");
2793}
2794
2795static int parse_common_flags(struct pevent *pevent, void *data)
2796{
2797 return __parse_common(pevent, data,
2798 &pevent->flags_size, &pevent->flags_offset,
2799 "common_flags");
2800}
2801
2802static int parse_common_lock_depth(struct pevent *pevent, void *data)
2803{
2804 int ret;
2805
2806 ret = __parse_common(pevent, data,
2807 &pevent->ld_size, &pevent->ld_offset,
2808 "common_lock_depth");
2809 if (ret < 0)
2810 return -1;
2811
2812 return ret;
2813}
2814
2815static int events_id_cmp(const void *a, const void *b);
2816
2817/**
2818 * pevent_find_event - find an event by given id
2819 * @pevent: a handle to the pevent
2820 * @id: the id of the event
2821 *
2822 * Returns an event that has a given @id.
2823 */
2824struct event_format *pevent_find_event(struct pevent *pevent, int id)
2825{
2826 struct event_format **eventptr;
2827 struct event_format key;
2828 struct event_format *pkey = &key;
2829
2830 /* Check cache first */
2831 if (pevent->last_event && pevent->last_event->id == id)
2832 return pevent->last_event;
2833
2834 key.id = id;
2835
2836 eventptr = bsearch(&pkey, pevent->events, pevent->nr_events,
2837 sizeof(*pevent->events), events_id_cmp);
2838
2839 if (eventptr) {
2840 pevent->last_event = *eventptr;
2841 return *eventptr;
2842 }
2843
2844 return NULL;
2845}
2846
2847/**
2848 * pevent_find_event_by_name - find an event by given name
2849 * @pevent: a handle to the pevent
2850 * @sys: the system name to search for
2851 * @name: the name of the event to search for
2852 *
2853 * This returns an event with a given @name and under the system
2854 * @sys. If @sys is NULL the first event with @name is returned.
2855 */
2856struct event_format *
2857pevent_find_event_by_name(struct pevent *pevent,
2858 const char *sys, const char *name)
2859{
2860 struct event_format *event;
2861 int i;
2862
2863 if (pevent->last_event &&
2864 strcmp(pevent->last_event->name, name) == 0 &&
2865 (!sys || strcmp(pevent->last_event->system, sys) == 0))
2866 return pevent->last_event;
2867
2868 for (i = 0; i < pevent->nr_events; i++) {
2869 event = pevent->events[i];
2870 if (strcmp(event->name, name) == 0) {
2871 if (!sys)
2872 break;
2873 if (strcmp(event->system, sys) == 0)
2874 break;
2875 }
2876 }
2877 if (i == pevent->nr_events)
2878 event = NULL;
2879
2880 pevent->last_event = event;
2881 return event;
2882}
2883
2884static unsigned long long
2885eval_num_arg(void *data, int size, struct event_format *event, struct print_arg *arg)
2886{
2887 struct pevent *pevent = event->pevent;
2888 unsigned long long val = 0;
2889 unsigned long long left, right;
2890 struct print_arg *typearg = NULL;
2891 struct print_arg *larg;
2892 unsigned long offset;
2893 unsigned int field_size;
2894
2895 switch (arg->type) {
2896 case PRINT_NULL:
2897 /* ?? */
2898 return 0;
2899 case PRINT_ATOM:
2900 return strtoull(arg->atom.atom, NULL, 0);
2901 case PRINT_FIELD:
2902 if (!arg->field.field) {
2903 arg->field.field = pevent_find_any_field(event, arg->field.name);
2904 if (!arg->field.field)
2905 die("field %s not found", arg->field.name);
2906 }
2907 /* must be a number */
2908 val = pevent_read_number(pevent, data + arg->field.field->offset,
2909 arg->field.field->size);
2910 break;
2911 case PRINT_FLAGS:
2912 case PRINT_SYMBOL:
2913 break;
2914 case PRINT_TYPE:
2915 val = eval_num_arg(data, size, event, arg->typecast.item);
2916 return eval_type(val, arg, 0);
2917 case PRINT_STRING:
2918 case PRINT_BSTRING:
2919 return 0;
2920 case PRINT_FUNC: {
2921 struct trace_seq s;
2922 trace_seq_init(&s);
2923 val = process_defined_func(&s, data, size, event, arg);
2924 trace_seq_destroy(&s);
2925 return val;
2926 }
2927 case PRINT_OP:
2928 if (strcmp(arg->op.op, "[") == 0) {
2929 /*
2930 * Arrays are special, since we don't want
2931 * to read the arg as is.
2932 */
2933 right = eval_num_arg(data, size, event, arg->op.right);
2934
2935 /* handle typecasts */
2936 larg = arg->op.left;
2937 while (larg->type == PRINT_TYPE) {
2938 if (!typearg)
2939 typearg = larg;
2940 larg = larg->typecast.item;
2941 }
2942
2943 /* Default to long size */
2944 field_size = pevent->long_size;
2945
2946 switch (larg->type) {
2947 case PRINT_DYNAMIC_ARRAY:
2948 offset = pevent_read_number(pevent,
2949 data + larg->dynarray.field->offset,
2950 larg->dynarray.field->size);
2951 if (larg->dynarray.field->elementsize)
2952 field_size = larg->dynarray.field->elementsize;
2953 /*
2954 * The actual length of the dynamic array is stored
2955 * in the top half of the field, and the offset
2956 * is in the bottom half of the 32 bit field.
2957 */
2958 offset &= 0xffff;
2959 offset += right;
2960 break;
2961 case PRINT_FIELD:
2962 if (!larg->field.field) {
2963 larg->field.field =
2964 pevent_find_any_field(event, larg->field.name);
2965 if (!larg->field.field)
2966 die("field %s not found", larg->field.name);
2967 }
2968 field_size = larg->field.field->elementsize;
2969 offset = larg->field.field->offset +
2970 right * larg->field.field->elementsize;
2971 break;
2972 default:
2973 goto default_op; /* oops, all bets off */
2974 }
2975 val = pevent_read_number(pevent,
2976 data + offset, field_size);
2977 if (typearg)
2978 val = eval_type(val, typearg, 1);
2979 break;
2980 } else if (strcmp(arg->op.op, "?") == 0) {
2981 left = eval_num_arg(data, size, event, arg->op.left);
2982 arg = arg->op.right;
2983 if (left)
2984 val = eval_num_arg(data, size, event, arg->op.left);
2985 else
2986 val = eval_num_arg(data, size, event, arg->op.right);
2987 break;
2988 }
2989 default_op:
2990 left = eval_num_arg(data, size, event, arg->op.left);
2991 right = eval_num_arg(data, size, event, arg->op.right);
2992 switch (arg->op.op[0]) {
2993 case '!':
2994 switch (arg->op.op[1]) {
2995 case 0:
2996 val = !right;
2997 break;
2998 case '=':
2999 val = left != right;
3000 break;
3001 default:
3002 die("unknown op '%s'", arg->op.op);
3003 }
3004 break;
3005 case '~':
3006 val = ~right;
3007 break;
3008 case '|':
3009 if (arg->op.op[1])
3010 val = left || right;
3011 else
3012 val = left | right;
3013 break;
3014 case '&':
3015 if (arg->op.op[1])
3016 val = left && right;
3017 else
3018 val = left & right;
3019 break;
3020 case '<':
3021 switch (arg->op.op[1]) {
3022 case 0:
3023 val = left < right;
3024 break;
3025 case '<':
3026 val = left << right;
3027 break;
3028 case '=':
3029 val = left <= right;
3030 break;
3031 default:
3032 die("unknown op '%s'", arg->op.op);
3033 }
3034 break;
3035 case '>':
3036 switch (arg->op.op[1]) {
3037 case 0:
3038 val = left > right;
3039 break;
3040 case '>':
3041 val = left >> right;
3042 break;
3043 case '=':
3044 val = left >= right;
3045 break;
3046 default:
3047 die("unknown op '%s'", arg->op.op);
3048 }
3049 break;
3050 case '=':
3051 if (arg->op.op[1] != '=')
3052 die("unknown op '%s'", arg->op.op);
3053 val = left == right;
3054 break;
3055 case '-':
3056 val = left - right;
3057 break;
3058 case '+':
3059 val = left + right;
3060 break;
3061 default:
3062 die("unknown op '%s'", arg->op.op);
3063 }
3064 break;
3065 default: /* not sure what to do there */
3066 return 0;
3067 }
3068 return val;
3069}
3070
3071struct flag {
3072 const char *name;
3073 unsigned long long value;
3074};
3075
3076static const struct flag flags[] = {
3077 { "HI_SOFTIRQ", 0 },
3078 { "TIMER_SOFTIRQ", 1 },
3079 { "NET_TX_SOFTIRQ", 2 },
3080 { "NET_RX_SOFTIRQ", 3 },
3081 { "BLOCK_SOFTIRQ", 4 },
3082 { "BLOCK_IOPOLL_SOFTIRQ", 5 },
3083 { "TASKLET_SOFTIRQ", 6 },
3084 { "SCHED_SOFTIRQ", 7 },
3085 { "HRTIMER_SOFTIRQ", 8 },
3086 { "RCU_SOFTIRQ", 9 },
3087
3088 { "HRTIMER_NORESTART", 0 },
3089 { "HRTIMER_RESTART", 1 },
3090};
3091
3092static unsigned long long eval_flag(const char *flag)
3093{
3094 int i;
3095
3096 /*
3097 * Some flags in the format files do not get converted.
3098 * If the flag is not numeric, see if it is something that
3099 * we already know about.
3100 */
3101 if (isdigit(flag[0]))
3102 return strtoull(flag, NULL, 0);
3103
3104 for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++)
3105 if (strcmp(flags[i].name, flag) == 0)
3106 return flags[i].value;
3107
3108 return 0;
3109}
3110
3111static void print_str_to_seq(struct trace_seq *s, const char *format,
3112 int len_arg, const char *str)
3113{
3114 if (len_arg >= 0)
3115 trace_seq_printf(s, format, len_arg, str);
3116 else
3117 trace_seq_printf(s, format, str);
3118}
3119
3120static void print_str_arg(struct trace_seq *s, void *data, int size,
3121 struct event_format *event, const char *format,
3122 int len_arg, struct print_arg *arg)
3123{
3124 struct pevent *pevent = event->pevent;
3125 struct print_flag_sym *flag;
3126 unsigned long long val, fval;
3127 unsigned long addr;
3128 char *str;
3129 int print;
3130 int len;
3131
3132 switch (arg->type) {
3133 case PRINT_NULL:
3134 /* ?? */
3135 return;
3136 case PRINT_ATOM:
3137 print_str_to_seq(s, format, len_arg, arg->atom.atom);
3138 return;
3139 case PRINT_FIELD:
3140 if (!arg->field.field) {
3141 arg->field.field = pevent_find_any_field(event, arg->field.name);
3142 if (!arg->field.field)
3143 die("field %s not found", arg->field.name);
3144 }
3145 /* Zero sized fields, mean the rest of the data */
3146 len = arg->field.field->size ? : size - arg->field.field->offset;
3147
3148 /*
3149 * Some events pass in pointers. If this is not an array
3150 * and the size is the same as long_size, assume that it
3151 * is a pointer.
3152 */
3153 if (!(arg->field.field->flags & FIELD_IS_ARRAY) &&
3154 arg->field.field->size == pevent->long_size) {
3155 addr = *(unsigned long *)(data + arg->field.field->offset);
3156 trace_seq_printf(s, "%lx", addr);
3157 break;
3158 }
3159 str = malloc_or_die(len + 1);
3160 memcpy(str, data + arg->field.field->offset, len);
3161 str[len] = 0;
3162 print_str_to_seq(s, format, len_arg, str);
3163 free(str);
3164 break;
3165 case PRINT_FLAGS:
3166 val = eval_num_arg(data, size, event, arg->flags.field);
3167 print = 0;
3168 for (flag = arg->flags.flags; flag; flag = flag->next) {
3169 fval = eval_flag(flag->value);
3170 if (!val && !fval) {
3171 print_str_to_seq(s, format, len_arg, flag->str);
3172 break;
3173 }
3174 if (fval && (val & fval) == fval) {
3175 if (print && arg->flags.delim)
3176 trace_seq_puts(s, arg->flags.delim);
3177 print_str_to_seq(s, format, len_arg, flag->str);
3178 print = 1;
3179 val &= ~fval;
3180 }
3181 }
3182 break;
3183 case PRINT_SYMBOL:
3184 val = eval_num_arg(data, size, event, arg->symbol.field);
3185 for (flag = arg->symbol.symbols; flag; flag = flag->next) {
3186 fval = eval_flag(flag->value);
3187 if (val == fval) {
3188 print_str_to_seq(s, format, len_arg, flag->str);
3189 break;
3190 }
3191 }
3192 break;
3193
3194 case PRINT_TYPE:
3195 break;
3196 case PRINT_STRING: {
3197 int str_offset;
3198
3199 if (arg->string.offset == -1) {
3200 struct format_field *f;
3201
3202 f = pevent_find_any_field(event, arg->string.string);
3203 arg->string.offset = f->offset;
3204 }
3205 str_offset = data2host4(pevent, data + arg->string.offset);
3206 str_offset &= 0xffff;
3207 print_str_to_seq(s, format, len_arg, ((char *)data) + str_offset);
3208 break;
3209 }
3210 case PRINT_BSTRING:
3211 trace_seq_printf(s, format, arg->string.string);
3212 break;
3213 case PRINT_OP:
3214 /*
3215 * The only op for string should be ? :
3216 */
3217 if (arg->op.op[0] != '?')
3218 return;
3219 val = eval_num_arg(data, size, event, arg->op.left);
3220 if (val)
3221 print_str_arg(s, data, size, event,
3222 format, len_arg, arg->op.right->op.left);
3223 else
3224 print_str_arg(s, data, size, event,
3225 format, len_arg, arg->op.right->op.right);
3226 break;
3227 case PRINT_FUNC:
3228 process_defined_func(s, data, size, event, arg);
3229 break;
3230 default:
3231 /* well... */
3232 break;
3233 }
3234}
3235
3236static unsigned long long
3237process_defined_func(struct trace_seq *s, void *data, int size,
3238 struct event_format *event, struct print_arg *arg)
3239{
3240 struct pevent_function_handler *func_handle = arg->func.func;
3241 struct pevent_func_params *param;
3242 unsigned long long *args;
3243 unsigned long long ret;
3244 struct print_arg *farg;
3245 struct trace_seq str;
3246 struct save_str {
3247 struct save_str *next;
3248 char *str;
3249 } *strings = NULL, *string;
3250 int i;
3251
3252 if (!func_handle->nr_args) {
3253 ret = (*func_handle->func)(s, NULL);
3254 goto out;
3255 }
3256
3257 farg = arg->func.args;
3258 param = func_handle->params;
3259
3260 args = malloc_or_die(sizeof(*args) * func_handle->nr_args);
3261 for (i = 0; i < func_handle->nr_args; i++) {
3262 switch (param->type) {
3263 case PEVENT_FUNC_ARG_INT:
3264 case PEVENT_FUNC_ARG_LONG:
3265 case PEVENT_FUNC_ARG_PTR:
3266 args[i] = eval_num_arg(data, size, event, farg);
3267 break;
3268 case PEVENT_FUNC_ARG_STRING:
3269 trace_seq_init(&str);
3270 print_str_arg(&str, data, size, event, "%s", -1, farg);
3271 trace_seq_terminate(&str);
3272 string = malloc_or_die(sizeof(*string));
3273 string->next = strings;
3274 string->str = strdup(str.buffer);
3275 strings = string;
3276 trace_seq_destroy(&str);
3277 break;
3278 default:
3279 /*
3280 * Something went totally wrong, this is not
3281 * an input error, something in this code broke.
3282 */
3283 die("Unexpected end of arguments\n");
3284 break;
3285 }
3286 farg = farg->next;
3287 }
3288
3289 ret = (*func_handle->func)(s, args);
3290 free(args);
3291 while (strings) {
3292 string = strings;
3293 strings = string->next;
3294 free(string->str);
3295 free(string);
3296 }
3297
3298 out:
3299 /* TBD : handle return type here */
3300 return ret;
3301}
3302
3303static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event_format *event)
3304{
3305 struct pevent *pevent = event->pevent;
3306 struct format_field *field, *ip_field;
3307 struct print_arg *args, *arg, **next;
3308 unsigned long long ip, val;
3309 char *ptr;
3310 void *bptr;
3311
3312 field = pevent->bprint_buf_field;
3313 ip_field = pevent->bprint_ip_field;
3314
3315 if (!field) {
3316 field = pevent_find_field(event, "buf");
3317 if (!field)
3318 die("can't find buffer field for binary printk");
3319 ip_field = pevent_find_field(event, "ip");
3320 if (!ip_field)
3321 die("can't find ip field for binary printk");
3322 pevent->bprint_buf_field = field;
3323 pevent->bprint_ip_field = ip_field;
3324 }
3325
3326 ip = pevent_read_number(pevent, data + ip_field->offset, ip_field->size);
3327
3328 /*
3329 * The first arg is the IP pointer.
3330 */
3331 args = alloc_arg();
3332 arg = args;
3333 arg->next = NULL;
3334 next = &arg->next;
3335
3336 arg->type = PRINT_ATOM;
3337 arg->atom.atom = malloc_or_die(32);
3338 sprintf(arg->atom.atom, "%lld", ip);
3339
3340 /* skip the first "%pf : " */
3341 for (ptr = fmt + 6, bptr = data + field->offset;
3342 bptr < data + size && *ptr; ptr++) {
3343 int ls = 0;
3344
3345 if (*ptr == '%') {
3346 process_again:
3347 ptr++;
3348 switch (*ptr) {
3349 case '%':
3350 break;
3351 case 'l':
3352 ls++;
3353 goto process_again;
3354 case 'L':
3355 ls = 2;
3356 goto process_again;
3357 case '0' ... '9':
3358 goto process_again;
3359 case 'p':
3360 ls = 1;
3361 /* fall through */
3362 case 'd':
3363 case 'u':
3364 case 'x':
3365 case 'i':
3366 /* the pointers are always 4 bytes aligned */
3367 bptr = (void *)(((unsigned long)bptr + 3) &
3368 ~3);
3369 switch (ls) {
3370 case 0:
3371 ls = 4;
3372 break;
3373 case 1:
3374 ls = pevent->long_size;
3375 break;
3376 case 2:
3377 ls = 8;
3378 default:
3379 break;
3380 }
3381 val = pevent_read_number(pevent, bptr, ls);
3382 bptr += ls;
3383 arg = alloc_arg();
3384 arg->next = NULL;
3385 arg->type = PRINT_ATOM;
3386 arg->atom.atom = malloc_or_die(32);
3387 sprintf(arg->atom.atom, "%lld", val);
3388 *next = arg;
3389 next = &arg->next;
3390 break;
3391 case 's':
3392 arg = alloc_arg();
3393 arg->next = NULL;
3394 arg->type = PRINT_BSTRING;
3395 arg->string.string = strdup(bptr);
3396 bptr += strlen(bptr) + 1;
3397 *next = arg;
3398 next = &arg->next;
3399 default:
3400 break;
3401 }
3402 }
3403 }
3404
3405 return args;
3406}
3407
3408static void free_args(struct print_arg *args)
3409{
3410 struct print_arg *next;
3411
3412 while (args) {
3413 next = args->next;
3414
3415 free_arg(args);
3416 args = next;
3417 }
3418}
3419
3420static char *
3421get_bprint_format(void *data, int size __unused, struct event_format *event)
3422{
3423 struct pevent *pevent = event->pevent;
3424 unsigned long long addr;
3425 struct format_field *field;
3426 struct printk_map *printk;
3427 char *format;
3428 char *p;
3429
3430 field = pevent->bprint_fmt_field;
3431
3432 if (!field) {
3433 field = pevent_find_field(event, "fmt");
3434 if (!field)
3435 die("can't find format field for binary printk");
3436 pevent->bprint_fmt_field = field;
3437 }
3438
3439 addr = pevent_read_number(pevent, data + field->offset, field->size);
3440
3441 printk = find_printk(pevent, addr);
3442 if (!printk) {
3443 format = malloc_or_die(45);
3444 sprintf(format, "%%pf : (NO FORMAT FOUND at %llx)\n",
3445 addr);
3446 return format;
3447 }
3448
3449 p = printk->printk;
3450 /* Remove any quotes. */
3451 if (*p == '"')
3452 p++;
3453 format = malloc_or_die(strlen(p) + 10);
3454 sprintf(format, "%s : %s", "%pf", p);
3455 /* remove ending quotes and new line since we will add one too */
3456 p = format + strlen(format) - 1;
3457 if (*p == '"')
3458 *p = 0;
3459
3460 p -= 2;
3461 if (strcmp(p, "\\n") == 0)
3462 *p = 0;
3463
3464 return format;
3465}
3466
3467static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,
3468 struct event_format *event, struct print_arg *arg)
3469{
3470 unsigned char *buf;
3471 char *fmt = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x";
3472
3473 if (arg->type == PRINT_FUNC) {
3474 process_defined_func(s, data, size, event, arg);
3475 return;
3476 }
3477
3478 if (arg->type != PRINT_FIELD) {
3479 trace_seq_printf(s, "ARG TYPE NOT FIELD BUT %d",
3480 arg->type);
3481 return;
3482 }
3483
3484 if (mac == 'm')
3485 fmt = "%.2x%.2x%.2x%.2x%.2x%.2x";
3486 if (!arg->field.field) {
3487 arg->field.field =
3488 pevent_find_any_field(event, arg->field.name);
3489 if (!arg->field.field)
3490 die("field %s not found", arg->field.name);
3491 }
3492 if (arg->field.field->size != 6) {
3493 trace_seq_printf(s, "INVALIDMAC");
3494 return;
3495 }
3496 buf = data + arg->field.field->offset;
3497 trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
3498}
3499
3500static void print_event_fields(struct trace_seq *s, void *data, int size,
3501 struct event_format *event)
3502{
3503 struct format_field *field;
3504 unsigned long long val;
3505 unsigned int offset, len, i;
3506
3507 field = event->format.fields;
3508 while (field) {
3509 trace_seq_printf(s, " %s=", field->name);
3510 if (field->flags & FIELD_IS_ARRAY) {
3511 offset = field->offset;
3512 len = field->size;
3513 if (field->flags & FIELD_IS_DYNAMIC) {
3514 val = pevent_read_number(event->pevent, data + offset, len);
3515 offset = val;
3516 len = offset >> 16;
3517 offset &= 0xffff;
3518 }
3519 if (field->flags & FIELD_IS_STRING) {
3520 trace_seq_printf(s, "%s", (char *)data + offset);
3521 } else {
3522 trace_seq_puts(s, "ARRAY[");
3523 for (i = 0; i < len; i++) {
3524 if (i)
3525 trace_seq_puts(s, ", ");
3526 trace_seq_printf(s, "%02x",
3527 *((unsigned char *)data + offset + i));
3528 }
3529 trace_seq_putc(s, ']');
3530 }
3531 } else {
3532 val = pevent_read_number(event->pevent, data + field->offset,
3533 field->size);
3534 if (field->flags & FIELD_IS_POINTER) {
3535 trace_seq_printf(s, "0x%llx", val);
3536 } else if (field->flags & FIELD_IS_SIGNED) {
3537 switch (field->size) {
3538 case 4:
3539 /*
3540 * If field is long then print it in hex.
3541 * A long usually stores pointers.
3542 */
3543 if (field->flags & FIELD_IS_LONG)
3544 trace_seq_printf(s, "0x%x", (int)val);
3545 else
3546 trace_seq_printf(s, "%d", (int)val);
3547 break;
3548 case 2:
3549 trace_seq_printf(s, "%2d", (short)val);
3550 break;
3551 case 1:
3552 trace_seq_printf(s, "%1d", (char)val);
3553 break;
3554 default:
3555 trace_seq_printf(s, "%lld", val);
3556 }
3557 } else {
3558 if (field->flags & FIELD_IS_LONG)
3559 trace_seq_printf(s, "0x%llx", val);
3560 else
3561 trace_seq_printf(s, "%llu", val);
3562 }
3563 }
3564 field = field->next;
3565 }
3566}
3567
3568static void pretty_print(struct trace_seq *s, void *data, int size, struct event_format *event)
3569{
3570 struct pevent *pevent = event->pevent;
3571 struct print_fmt *print_fmt = &event->print_fmt;
3572 struct print_arg *arg = print_fmt->args;
3573 struct print_arg *args = NULL;
3574 const char *ptr = print_fmt->format;
3575 unsigned long long val;
3576 struct func_map *func;
3577 const char *saveptr;
3578 char *bprint_fmt = NULL;
3579 char format[32];
3580 int show_func;
3581 int len_as_arg;
3582 int len_arg;
3583 int len;
3584 int ls;
3585
3586 if (event->flags & EVENT_FL_FAILED) {
3587 trace_seq_printf(s, "[FAILED TO PARSE]");
3588 print_event_fields(s, data, size, event);
3589 return;
3590 }
3591
3592 if (event->flags & EVENT_FL_ISBPRINT) {
3593 bprint_fmt = get_bprint_format(data, size, event);
3594 args = make_bprint_args(bprint_fmt, data, size, event);
3595 arg = args;
3596 ptr = bprint_fmt;
3597 }
3598
3599 for (; *ptr; ptr++) {
3600 ls = 0;
3601 if (*ptr == '\\') {
3602 ptr++;
3603 switch (*ptr) {
3604 case 'n':
3605 trace_seq_putc(s, '\n');
3606 break;
3607 case 't':
3608 trace_seq_putc(s, '\t');
3609 break;
3610 case 'r':
3611 trace_seq_putc(s, '\r');
3612 break;
3613 case '\\':
3614 trace_seq_putc(s, '\\');
3615 break;
3616 default:
3617 trace_seq_putc(s, *ptr);
3618 break;
3619 }
3620
3621 } else if (*ptr == '%') {
3622 saveptr = ptr;
3623 show_func = 0;
3624 len_as_arg = 0;
3625 cont_process:
3626 ptr++;
3627 switch (*ptr) {
3628 case '%':
3629 trace_seq_putc(s, '%');
3630 break;
3631 case '#':
3632 /* FIXME: need to handle properly */
3633 goto cont_process;
3634 case 'h':
3635 ls--;
3636 goto cont_process;
3637 case 'l':
3638 ls++;
3639 goto cont_process;
3640 case 'L':
3641 ls = 2;
3642 goto cont_process;
3643 case '*':
3644 /* The argument is the length. */
3645 if (!arg)
3646 die("no argument match");
3647 len_arg = eval_num_arg(data, size, event, arg);
3648 len_as_arg = 1;
3649 arg = arg->next;
3650 goto cont_process;
3651 case '.':
3652 case 'z':
3653 case 'Z':
3654 case '0' ... '9':
3655 goto cont_process;
3656 case 'p':
3657 if (pevent->long_size == 4)
3658 ls = 1;
3659 else
3660 ls = 2;
3661
3662 if (*(ptr+1) == 'F' ||
3663 *(ptr+1) == 'f') {
3664 ptr++;
3665 show_func = *ptr;
3666 } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') {
3667 print_mac_arg(s, *(ptr+1), data, size, event, arg);
3668 ptr++;
3669 break;
3670 }
3671
3672 /* fall through */
3673 case 'd':
3674 case 'i':
3675 case 'x':
3676 case 'X':
3677 case 'u':
3678 if (!arg)
3679 die("no argument match");
3680
3681 len = ((unsigned long)ptr + 1) -
3682 (unsigned long)saveptr;
3683
3684 /* should never happen */
3685 if (len > 31)
3686 die("bad format!");
3687
3688 memcpy(format, saveptr, len);
3689 format[len] = 0;
3690
3691 val = eval_num_arg(data, size, event, arg);
3692 arg = arg->next;
3693
3694 if (show_func) {
3695 func = find_func(pevent, val);
3696 if (func) {
3697 trace_seq_puts(s, func->func);
3698 if (show_func == 'F')
3699 trace_seq_printf(s,
3700 "+0x%llx",
3701 val - func->addr);
3702 break;
3703 }
3704 }
3705 if (pevent->long_size == 8 && ls) {
3706 char *p;
3707
3708 ls = 2;
3709 /* make %l into %ll */
3710 p = strchr(format, 'l');
3711 if (p)
3712 memmove(p, p+1, strlen(p)+1);
3713 else if (strcmp(format, "%p") == 0)
3714 strcpy(format, "0x%llx");
3715 }
3716 switch (ls) {
3717 case -2:
3718 if (len_as_arg)
3719 trace_seq_printf(s, format, len_arg, (char)val);
3720 else
3721 trace_seq_printf(s, format, (char)val);
3722 break;
3723 case -1:
3724 if (len_as_arg)
3725 trace_seq_printf(s, format, len_arg, (short)val);
3726 else
3727 trace_seq_printf(s, format, (short)val);
3728 break;
3729 case 0:
3730 if (len_as_arg)
3731 trace_seq_printf(s, format, len_arg, (int)val);
3732 else
3733 trace_seq_printf(s, format, (int)val);
3734 break;
3735 case 1:
3736 if (len_as_arg)
3737 trace_seq_printf(s, format, len_arg, (long)val);
3738 else
3739 trace_seq_printf(s, format, (long)val);
3740 break;
3741 case 2:
3742 if (len_as_arg)
3743 trace_seq_printf(s, format, len_arg,
3744 (long long)val);
3745 else
3746 trace_seq_printf(s, format, (long long)val);
3747 break;
3748 default:
3749 die("bad count (%d)", ls);
3750 }
3751 break;
3752 case 's':
3753 if (!arg)
3754 die("no matching argument");
3755
3756 len = ((unsigned long)ptr + 1) -
3757 (unsigned long)saveptr;
3758
3759 /* should never happen */
3760 if (len > 31)
3761 die("bad format!");
3762
3763 memcpy(format, saveptr, len);
3764 format[len] = 0;
3765 if (!len_as_arg)
3766 len_arg = -1;
3767 print_str_arg(s, data, size, event,
3768 format, len_arg, arg);
3769 arg = arg->next;
3770 break;
3771 default:
3772 trace_seq_printf(s, ">%c<", *ptr);
3773
3774 }
3775 } else
3776 trace_seq_putc(s, *ptr);
3777 }
3778
3779 if (args) {
3780 free_args(args);
3781 free(bprint_fmt);
3782 }
3783}
3784
3785/**
3786 * pevent_data_lat_fmt - parse the data for the latency format
3787 * @pevent: a handle to the pevent
3788 * @s: the trace_seq to write to
3789 * @data: the raw data to read from
3790 * @size: currently unused.
3791 *
3792 * This parses out the Latency format (interrupts disabled,
3793 * need rescheduling, in hard/soft interrupt, preempt count
3794 * and lock depth) and places it into the trace_seq.
3795 */
3796void pevent_data_lat_fmt(struct pevent *pevent,
3797 struct trace_seq *s, struct record *record)
3798{
3799 static int check_lock_depth = 1;
3800 static int lock_depth_exists;
3801 unsigned int lat_flags;
3802 unsigned int pc;
3803 int lock_depth;
3804 int hardirq;
3805 int softirq;
3806 void *data = record->data;
3807
3808 lat_flags = parse_common_flags(pevent, data);
3809 pc = parse_common_pc(pevent, data);
3810 /* lock_depth may not always exist */
3811 if (check_lock_depth) {
3812 struct format_field *field;
3813 struct event_format *event;
3814
3815 check_lock_depth = 0;
3816 event = pevent->events[0];
3817 field = pevent_find_common_field(event, "common_lock_depth");
3818 if (field)
3819 lock_depth_exists = 1;
3820 }
3821 if (lock_depth_exists)
3822 lock_depth = parse_common_lock_depth(pevent, data);
3823
3824 hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
3825 softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
3826
3827 trace_seq_printf(s, "%c%c%c",
3828 (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
3829 (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
3830 'X' : '.',
3831 (lat_flags & TRACE_FLAG_NEED_RESCHED) ?
3832 'N' : '.',
3833 (hardirq && softirq) ? 'H' :
3834 hardirq ? 'h' : softirq ? 's' : '.');
3835
3836 if (pc)
3837 trace_seq_printf(s, "%x", pc);
3838 else
3839 trace_seq_putc(s, '.');
3840
3841 if (lock_depth_exists) {
3842 if (lock_depth < 0)
3843 trace_seq_putc(s, '.');
3844 else
3845 trace_seq_printf(s, "%d", lock_depth);
3846 }
3847
3848 trace_seq_terminate(s);
3849}
3850
3851/**
3852 * pevent_data_type - parse out the given event type
3853 * @pevent: a handle to the pevent
3854 * @rec: the record to read from
3855 *
3856 * This returns the event id from the @rec.
3857 */
3858int pevent_data_type(struct pevent *pevent, struct record *rec)
3859{
3860 return trace_parse_common_type(pevent, rec->data);
3861}
3862
3863/**
3864 * pevent_data_event_from_type - find the event by a given type
3865 * @pevent: a handle to the pevent
3866 * @type: the type of the event.
3867 *
3868 * This returns the event form a given @type;
3869 */
3870struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type)
3871{
3872 return pevent_find_event(pevent, type);
3873}
3874
3875/**
3876 * pevent_data_pid - parse the PID from raw data
3877 * @pevent: a handle to the pevent
3878 * @rec: the record to parse
3879 *
3880 * This returns the PID from a raw data.
3881 */
3882int pevent_data_pid(struct pevent *pevent, struct record *rec)
3883{
3884 return parse_common_pid(pevent, rec->data);
3885}
3886
3887/**
3888 * pevent_data_comm_from_pid - return the command line from PID
3889 * @pevent: a handle to the pevent
3890 * @pid: the PID of the task to search for
3891 *
3892 * This returns a pointer to the command line that has the given
3893 * @pid.
3894 */
3895const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid)
3896{
3897 const char *comm;
3898
3899 comm = find_cmdline(pevent, pid);
3900 return comm;
3901}
3902
3903/**
3904 * pevent_data_comm_from_pid - parse the data into the print format
3905 * @s: the trace_seq to write to
3906 * @event: the handle to the event
3907 * @cpu: the cpu the event was recorded on
3908 * @data: the raw data
3909 * @size: the size of the raw data
3910 * @nsecs: the timestamp of the event
3911 *
3912 * This parses the raw @data using the given @event information and
3913 * writes the print format into the trace_seq.
3914 */
3915void pevent_event_info(struct trace_seq *s, struct event_format *event,
3916 struct record *record)
3917{
3918 int print_pretty = 1;
3919
3920 if (event->pevent->print_raw)
3921 print_event_fields(s, record->data, record->size, event);
3922 else {
3923
3924 if (event->handler)
3925 print_pretty = event->handler(s, record, event,
3926 event->context);
3927
3928 if (print_pretty)
3929 pretty_print(s, record->data, record->size, event);
3930 }
3931
3932 trace_seq_terminate(s);
3933}
3934
3935void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
3936 struct record *record)
3937{
3938 static char *spaces = " "; /* 20 spaces */
3939 struct event_format *event;
3940 unsigned long secs;
3941 unsigned long usecs;
3942 const char *comm;
3943 void *data = record->data;
3944 int type;
3945 int pid;
3946 int len;
3947
3948 secs = record->ts / NSECS_PER_SEC;
3949 usecs = record->ts - secs * NSECS_PER_SEC;
3950 usecs = (usecs + 500) / NSECS_PER_USEC;
3951
3952 if (record->size < 0) {
3953 do_warning("ug! negative record size %d", record->size);
3954 return;
3955 }
3956
3957 type = trace_parse_common_type(pevent, data);
3958
3959 event = pevent_find_event(pevent, type);
3960 if (!event) {
3961 do_warning("ug! no event found for type %d", type);
3962 return;
3963 }
3964
3965 pid = parse_common_pid(pevent, data);
3966 comm = find_cmdline(pevent, pid);
3967
3968 if (pevent->latency_format) {
3969 trace_seq_printf(s, "%8.8s-%-5d %3d",
3970 comm, pid, record->cpu);
3971 pevent_data_lat_fmt(pevent, s, record);
3972 } else
3973 trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu);
3974
3975 trace_seq_printf(s, " %5lu.%06lu: %s: ", secs, usecs, event->name);
3976
3977 /* Space out the event names evenly. */
3978 len = strlen(event->name);
3979 if (len < 20)
3980 trace_seq_printf(s, "%.*s", 20 - len, spaces);
3981
3982 pevent_event_info(s, event, record);
3983}
3984
3985static int events_id_cmp(const void *a, const void *b)
3986{
3987 struct event_format * const * ea = a;
3988 struct event_format * const * eb = b;
3989
3990 if ((*ea)->id < (*eb)->id)
3991 return -1;
3992
3993 if ((*ea)->id > (*eb)->id)
3994 return 1;
3995
3996 return 0;
3997}
3998
3999static int events_name_cmp(const void *a, const void *b)
4000{
4001 struct event_format * const * ea = a;
4002 struct event_format * const * eb = b;
4003 int res;
4004
4005 res = strcmp((*ea)->name, (*eb)->name);
4006 if (res)
4007 return res;
4008
4009 res = strcmp((*ea)->system, (*eb)->system);
4010 if (res)
4011 return res;
4012
4013 return events_id_cmp(a, b);
4014}
4015
4016static int events_system_cmp(const void *a, const void *b)
4017{
4018 struct event_format * const * ea = a;
4019 struct event_format * const * eb = b;
4020 int res;
4021
4022 res = strcmp((*ea)->system, (*eb)->system);
4023 if (res)
4024 return res;
4025
4026 res = strcmp((*ea)->name, (*eb)->name);
4027 if (res)
4028 return res;
4029
4030 return events_id_cmp(a, b);
4031}
4032
4033struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type sort_type)
4034{
4035 struct event_format **events;
4036 int (*sort)(const void *a, const void *b);
4037
4038 events = pevent->sort_events;
4039
4040 if (events && pevent->last_type == sort_type)
4041 return events;
4042
4043 if (!events) {
4044 events = malloc(sizeof(*events) * (pevent->nr_events + 1));
4045 if (!events)
4046 return NULL;
4047
4048 memcpy(events, pevent->events, sizeof(*events) * pevent->nr_events);
4049 events[pevent->nr_events] = NULL;
4050
4051 pevent->sort_events = events;
4052
4053 /* the internal events are sorted by id */
4054 if (sort_type == EVENT_SORT_ID) {
4055 pevent->last_type = sort_type;
4056 return events;
4057 }
4058 }
4059
4060 switch (sort_type) {
4061 case EVENT_SORT_ID:
4062 sort = events_id_cmp;
4063 break;
4064 case EVENT_SORT_NAME:
4065 sort = events_name_cmp;
4066 break;
4067 case EVENT_SORT_SYSTEM:
4068 sort = events_system_cmp;
4069 break;
4070 default:
4071 return events;
4072 }
4073
4074 qsort(events, pevent->nr_events, sizeof(*events), sort);
4075 pevent->last_type = sort_type;
4076
4077 return events;
4078}
4079
4080static struct format_field **
4081get_event_fields(const char *type, const char *name,
4082 int count, struct format_field *list)
4083{
4084 struct format_field **fields;
4085 struct format_field *field;
4086 int i = 0;
4087
4088 fields = malloc_or_die(sizeof(*fields) * (count + 1));
4089 for (field = list; field; field = field->next) {
4090 fields[i++] = field;
4091 if (i == count + 1) {
4092 do_warning("event %s has more %s fields than specified",
4093 name, type);
4094 i--;
4095 break;
4096 }
4097 }
4098
4099 if (i != count)
4100 do_warning("event %s has less %s fields than specified",
4101 name, type);
4102
4103 fields[i] = NULL;
4104
4105 return fields;
4106}
4107
4108/**
4109 * pevent_event_common_fields - return a list of common fields for an event
4110 * @event: the event to return the common fields of.
4111 *
4112 * Returns an allocated array of fields. The last item in the array is NULL.
4113 * The array must be freed with free().
4114 */
4115struct format_field **pevent_event_common_fields(struct event_format *event)
4116{
4117 return get_event_fields("common", event->name,
4118 event->format.nr_common,
4119 event->format.common_fields);
4120}
4121
4122/**
4123 * pevent_event_fields - return a list of event specific fields for an event
4124 * @event: the event to return the fields of.
4125 *
4126 * Returns an allocated array of fields. The last item in the array is NULL.
4127 * The array must be freed with free().
4128 */
4129struct format_field **pevent_event_fields(struct event_format *event)
4130{
4131 return get_event_fields("event", event->name,
4132 event->format.nr_fields,
4133 event->format.fields);
4134}
4135
4136static void print_fields(struct trace_seq *s, struct print_flag_sym *field)
4137{
4138 trace_seq_printf(s, "{ %s, %s }", field->value, field->str);
4139 if (field->next) {
4140 trace_seq_puts(s, ", ");
4141 print_fields(s, field->next);
4142 }
4143}
4144
4145/* for debugging */
4146static void print_args(struct print_arg *args)
4147{
4148 int print_paren = 1;
4149 struct trace_seq s;
4150
4151 switch (args->type) {
4152 case PRINT_NULL:
4153 printf("null");
4154 break;
4155 case PRINT_ATOM:
4156 printf("%s", args->atom.atom);
4157 break;
4158 case PRINT_FIELD:
4159 printf("REC->%s", args->field.name);
4160 break;
4161 case PRINT_FLAGS:
4162 printf("__print_flags(");
4163 print_args(args->flags.field);
4164 printf(", %s, ", args->flags.delim);
4165 trace_seq_init(&s);
4166 print_fields(&s, args->flags.flags);
4167 trace_seq_do_printf(&s);
4168 trace_seq_destroy(&s);
4169 printf(")");
4170 break;
4171 case PRINT_SYMBOL:
4172 printf("__print_symbolic(");
4173 print_args(args->symbol.field);
4174 printf(", ");
4175 trace_seq_init(&s);
4176 print_fields(&s, args->symbol.symbols);
4177 trace_seq_do_printf(&s);
4178 trace_seq_destroy(&s);
4179 printf(")");
4180 break;
4181 case PRINT_STRING:
4182 case PRINT_BSTRING:
4183 printf("__get_str(%s)", args->string.string);
4184 break;
4185 case PRINT_TYPE:
4186 printf("(%s)", args->typecast.type);
4187 print_args(args->typecast.item);
4188 break;
4189 case PRINT_OP:
4190 if (strcmp(args->op.op, ":") == 0)
4191 print_paren = 0;
4192 if (print_paren)
4193 printf("(");
4194 print_args(args->op.left);
4195 printf(" %s ", args->op.op);
4196 print_args(args->op.right);
4197 if (print_paren)
4198 printf(")");
4199 break;
4200 default:
4201 /* we should warn... */
4202 return;
4203 }
4204 if (args->next) {
4205 printf("\n");
4206 print_args(args->next);
4207 }
4208}
4209
4210static void parse_header_field(const char *field,
4211 int *offset, int *size, int mandatory)
4212{
4213 unsigned long long save_input_buf_ptr;
4214 unsigned long long save_input_buf_siz;
4215 char *token;
4216 int type;
4217
4218 save_input_buf_ptr = input_buf_ptr;
4219 save_input_buf_siz = input_buf_siz;
4220
4221 if (read_expected(EVENT_ITEM, "field") < 0)
4222 return;
4223 if (read_expected(EVENT_OP, ":") < 0)
4224 return;
4225
4226 /* type */
4227 if (read_expect_type(EVENT_ITEM, &token) < 0)
4228 goto fail;
4229 free_token(token);
4230
4231 /*
4232 * If this is not a mandatory field, then test it first.
4233 */
4234 if (mandatory) {
4235 if (read_expected(EVENT_ITEM, field) < 0)
4236 return;
4237 } else {
4238 if (read_expect_type(EVENT_ITEM, &token) < 0)
4239 goto fail;
4240 if (strcmp(token, field) != 0)
4241 goto discard;
4242 free_token(token);
4243 }
4244
4245 if (read_expected(EVENT_OP, ";") < 0)
4246 return;
4247 if (read_expected(EVENT_ITEM, "offset") < 0)
4248 return;
4249 if (read_expected(EVENT_OP, ":") < 0)
4250 return;
4251 if (read_expect_type(EVENT_ITEM, &token) < 0)
4252 goto fail;
4253 *offset = atoi(token);
4254 free_token(token);
4255 if (read_expected(EVENT_OP, ";") < 0)
4256 return;
4257 if (read_expected(EVENT_ITEM, "size") < 0)
4258 return;
4259 if (read_expected(EVENT_OP, ":") < 0)
4260 return;
4261 if (read_expect_type(EVENT_ITEM, &token) < 0)
4262 goto fail;
4263 *size = atoi(token);
4264 free_token(token);
4265 if (read_expected(EVENT_OP, ";") < 0)
4266 return;
4267 type = read_token(&token);
4268 if (type != EVENT_NEWLINE) {
4269 /* newer versions of the kernel have a "signed" type */
4270 if (type != EVENT_ITEM)
4271 goto fail;
4272
4273 if (strcmp(token, "signed") != 0)
4274 goto fail;
4275
4276 free_token(token);
4277
4278 if (read_expected(EVENT_OP, ":") < 0)
4279 return;
4280
4281 if (read_expect_type(EVENT_ITEM, &token))
4282 goto fail;
4283
4284 free_token(token);
4285 if (read_expected(EVENT_OP, ";") < 0)
4286 return;
4287
4288 if (read_expect_type(EVENT_NEWLINE, &token))
4289 goto fail;
4290 }
4291 fail:
4292 free_token(token);
4293 return;
4294
4295 discard:
4296 input_buf_ptr = save_input_buf_ptr;
4297 input_buf_siz = save_input_buf_siz;
4298 *offset = 0;
4299 *size = 0;
4300 free_token(token);
4301}
4302
4303/**
4304 * pevent_parse_header_page - parse the data stored in the header page
4305 * @pevent: the handle to the pevent
4306 * @buf: the buffer storing the header page format string
4307 * @size: the size of @buf
4308 * @long_size: the long size to use if there is no header
4309 *
4310 * This parses the header page format for information on the
4311 * ring buffer used. The @buf should be copied from
4312 *
4313 * /sys/kernel/debug/tracing/events/header_page
4314 */
4315int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size,
4316 int long_size)
4317{
4318 int ignore;
4319
4320 if (!size) {
4321 /*
4322 * Old kernels did not have header page info.
4323 * Sorry but we just use what we find here in user space.
4324 */
4325 pevent->header_page_ts_size = sizeof(long long);
4326 pevent->header_page_size_size = long_size;
4327 pevent->header_page_data_offset = sizeof(long long) + long_size;
4328 pevent->old_format = 1;
4329 return -1;
4330 }
4331 init_input_buf(buf, size);
4332
4333 parse_header_field("timestamp", &pevent->header_page_ts_offset,
4334 &pevent->header_page_ts_size, 1);
4335 parse_header_field("commit", &pevent->header_page_size_offset,
4336 &pevent->header_page_size_size, 1);
4337 parse_header_field("overwrite", &pevent->header_page_overwrite,
4338 &ignore, 0);
4339 parse_header_field("data", &pevent->header_page_data_offset,
4340 &pevent->header_page_data_size, 1);
4341
4342 return 0;
4343}
4344
4345static int event_matches(struct event_format *event,
4346 int id, const char *sys_name,
4347 const char *event_name)
4348{
4349 if (id >= 0 && id != event->id)
4350 return 0;
4351
4352 if (event_name && (strcmp(event_name, event->name) != 0))
4353 return 0;
4354
4355 if (sys_name && (strcmp(sys_name, event->system) != 0))
4356 return 0;
4357
4358 return 1;
4359}
4360
4361static void free_handler(struct event_handler *handle)
4362{
4363 free((void *)handle->sys_name);
4364 free((void *)handle->event_name);
4365 free(handle);
4366}
4367
4368static int find_event_handle(struct pevent *pevent, struct event_format *event)
4369{
4370 struct event_handler *handle, **next;
4371
4372 for (next = &pevent->handlers; *next;
4373 next = &(*next)->next) {
4374 handle = *next;
4375 if (event_matches(event, handle->id,
4376 handle->sys_name,
4377 handle->event_name))
4378 break;
4379 }
4380
4381 if (!(*next))
4382 return 0;
4383
4384 pr_stat("overriding event (%d) %s:%s with new print handler",
4385 event->id, event->system, event->name);
4386
4387 event->handler = handle->func;
4388 event->context = handle->context;
4389
4390 *next = handle->next;
4391 free_handler(handle);
4392
4393 return 1;
4394}
4395
4396/**
4397 * pevent_parse_event - parse the event format
4398 * @pevent: the handle to the pevent
4399 * @buf: the buffer storing the event format string
4400 * @size: the size of @buf
4401 * @sys: the system the event belongs to
4402 *
4403 * This parses the event format and creates an event structure
4404 * to quickly parse raw data for a given event.
4405 *
4406 * These files currently come from:
4407 *
4408 * /sys/kernel/debug/tracing/events/.../.../format
4409 */
4410int pevent_parse_event(struct pevent *pevent,
4411 const char *buf, unsigned long size,
4412 const char *sys)
4413{
4414 struct event_format *event;
4415 int ret;
4416
4417 init_input_buf(buf, size);
4418
4419 event = alloc_event();
4420 if (!event)
4421 return -ENOMEM;
4422
4423 event->name = event_read_name();
4424 if (!event->name) {
4425 /* Bad event? */
4426 free(event);
4427 return -1;
4428 }
4429
4430 if (strcmp(sys, "ftrace") == 0) {
4431
4432 event->flags |= EVENT_FL_ISFTRACE;
4433
4434 if (strcmp(event->name, "bprint") == 0)
4435 event->flags |= EVENT_FL_ISBPRINT;
4436 }
4437
4438 event->id = event_read_id();
4439 if (event->id < 0)
4440 die("failed to read event id");
4441
4442 event->system = strdup(sys);
4443
4444 /* Add pevent to event so that it can be referenced */
4445 event->pevent = pevent;
4446
4447 ret = event_read_format(event);
4448 if (ret < 0) {
4449 do_warning("failed to read event format for %s", event->name);
4450 goto event_failed;
4451 }
4452
4453 /*
4454 * If the event has an override, don't print warnings if the event
4455 * print format fails to parse.
4456 */
4457 if (find_event_handle(pevent, event))
4458 show_warning = 0;
4459
4460 ret = event_read_print(event);
4461 if (ret < 0) {
4462 do_warning("failed to read event print fmt for %s",
4463 event->name);
4464 show_warning = 1;
4465 goto event_failed;
4466 }
4467 show_warning = 1;
4468
4469 add_event(pevent, event);
4470
4471 if (!ret && (event->flags & EVENT_FL_ISFTRACE)) {
4472 struct format_field *field;
4473 struct print_arg *arg, **list;
4474
4475 /* old ftrace had no args */
4476
4477 list = &event->print_fmt.args;
4478 for (field = event->format.fields; field; field = field->next) {
4479 arg = alloc_arg();
4480 *list = arg;
4481 list = &arg->next;
4482 arg->type = PRINT_FIELD;
4483 arg->field.name = strdup(field->name);
4484 arg->field.field = field;
4485 }
4486 return 0;
4487 }
4488
4489#define PRINT_ARGS 0
4490 if (PRINT_ARGS && event->print_fmt.args)
4491 print_args(event->print_fmt.args);
4492
4493 return 0;
4494
4495 event_failed:
4496 event->flags |= EVENT_FL_FAILED;
4497 /* still add it even if it failed */
4498 add_event(pevent, event);
4499 return -1;
4500}
4501
4502int get_field_val(struct trace_seq *s, struct format_field *field,
4503 const char *name, struct record *record,
4504 unsigned long long *val, int err)
4505{
4506 if (!field) {
4507 if (err)
4508 trace_seq_printf(s, "<CANT FIND FIELD %s>", name);
4509 return -1;
4510 }
4511
4512 if (pevent_read_number_field(field, record->data, val)) {
4513 if (err)
4514 trace_seq_printf(s, " %s=INVALID", name);
4515 return -1;
4516 }
4517
4518 return 0;
4519}
4520
4521/**
4522 * pevent_get_field_raw - return the raw pointer into the data field
4523 * @s: The seq to print to on error
4524 * @event: the event that the field is for
4525 * @name: The name of the field
4526 * @record: The record with the field name.
4527 * @len: place to store the field length.
4528 * @err: print default error if failed.
4529 *
4530 * Returns a pointer into record->data of the field and places
4531 * the length of the field in @len.
4532 *
4533 * On failure, it returns NULL.
4534 */
4535void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
4536 const char *name, struct record *record,
4537 int *len, int err)
4538{
4539 struct format_field *field;
4540 void *data = record->data;
4541 unsigned offset;
4542 int dummy;
4543
4544 if (!event)
4545 return NULL;
4546
4547 field = pevent_find_field(event, name);
4548
4549 if (!field) {
4550 if (err)
4551 trace_seq_printf(s, "<CANT FIND FIELD %s>", name);
4552 return NULL;
4553 }
4554
4555 /* Allow @len to be NULL */
4556 if (!len)
4557 len = &dummy;
4558
4559 offset = field->offset;
4560 if (field->flags & FIELD_IS_DYNAMIC) {
4561 offset = pevent_read_number(event->pevent,
4562 data + offset, field->size);
4563 *len = offset >> 16;
4564 offset &= 0xffff;
4565 } else
4566 *len = field->size;
4567
4568 return data + offset;
4569}
4570
4571/**
4572 * pevent_get_field_val - find a field and return its value
4573 * @s: The seq to print to on error
4574 * @event: the event that the field is for
4575 * @name: The name of the field
4576 * @record: The record with the field name.
4577 * @val: place to store the value of the field.
4578 * @err: print default error if failed.
4579 *
4580 * Returns 0 on success -1 on field not found.
4581 */
4582int pevent_get_field_val(struct trace_seq *s, struct event_format *event,
4583 const char *name, struct record *record,
4584 unsigned long long *val, int err)
4585{
4586 struct format_field *field;
4587
4588 if (!event)
4589 return -1;
4590
4591 field = pevent_find_field(event, name);
4592
4593 return get_field_val(s, field, name, record, val, err);
4594}
4595
4596/**
4597 * pevent_get_common_field_val - find a common field and return its value
4598 * @s: The seq to print to on error
4599 * @event: the event that the field is for
4600 * @name: The name of the field
4601 * @record: The record with the field name.
4602 * @val: place to store the value of the field.
4603 * @err: print default error if failed.
4604 *
4605 * Returns 0 on success -1 on field not found.
4606 */
4607int pevent_get_common_field_val(struct trace_seq *s, struct event_format *event,
4608 const char *name, struct record *record,
4609 unsigned long long *val, int err)
4610{
4611 struct format_field *field;
4612
4613 if (!event)
4614 return -1;
4615
4616 field = pevent_find_common_field(event, name);
4617
4618 return get_field_val(s, field, name, record, val, err);
4619}
4620
4621/**
4622 * pevent_get_any_field_val - find a any field and return its value
4623 * @s: The seq to print to on error
4624 * @event: the event that the field is for
4625 * @name: The name of the field
4626 * @record: The record with the field name.
4627 * @val: place to store the value of the field.
4628 * @err: print default error if failed.
4629 *
4630 * Returns 0 on success -1 on field not found.
4631 */
4632int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
4633 const char *name, struct record *record,
4634 unsigned long long *val, int err)
4635{
4636 struct format_field *field;
4637
4638 if (!event)
4639 return -1;
4640
4641 field = pevent_find_any_field(event, name);
4642
4643 return get_field_val(s, field, name, record, val, err);
4644}
4645
4646/**
4647 * pevent_print_num_field - print a field and a format
4648 * @s: The seq to print to
4649 * @fmt: The printf format to print the field with.
4650 * @event: the event that the field is for
4651 * @name: The name of the field
4652 * @record: The record with the field name.
4653 * @err: print default error if failed.
4654 *
4655 * Returns: 0 on success, -1 field not fould, or 1 if buffer is full.
4656 */
4657int pevent_print_num_field(struct trace_seq *s, const char *fmt,
4658 struct event_format *event, const char *name,
4659 struct record *record, int err)
4660{
4661 struct format_field *field = pevent_find_field(event, name);
4662 unsigned long long val;
4663
4664 if (!field)
4665 goto failed;
4666
4667 if (pevent_read_number_field(field, record->data, &val))
4668 goto failed;
4669
4670 return trace_seq_printf(s, fmt, val);
4671
4672 failed:
4673 if (err)
4674 trace_seq_printf(s, "CAN'T FIND FIELD \"%s\"", name);
4675 return -1;
4676}
4677
4678static void free_func_handle(struct pevent_function_handler *func)
4679{
4680 struct pevent_func_params *params;
4681
4682 free(func->name);
4683
4684 while (func->params) {
4685 params = func->params;
4686 func->params = params->next;
4687 free(params);
4688 }
4689
4690 free(func);
4691}
4692
4693/**
4694 * pevent_register_print_function - register a helper function
4695 * @pevent: the handle to the pevent
4696 * @func: the function to process the helper function
4697 * @name: the name of the helper function
4698 * @parameters: A list of enum pevent_func_arg_type
4699 *
4700 * Some events may have helper functions in the print format arguments.
4701 * This allows a plugin to dynmically create a way to process one
4702 * of these functions.
4703 *
4704 * The @parameters is a variable list of pevent_func_arg_type enums that
4705 * must end with PEVENT_FUNC_ARG_VOID.
4706 */
4707int pevent_register_print_function(struct pevent *pevent,
4708 pevent_func_handler func,
4709 enum pevent_func_arg_type ret_type,
4710 char *name, ...)
4711{
4712 struct pevent_function_handler *func_handle;
4713 struct pevent_func_params **next_param;
4714 struct pevent_func_params *param;
4715 enum pevent_func_arg_type type;
4716 va_list ap;
4717
4718 func_handle = find_func_handler(pevent, name);
4719 if (func_handle) {
4720 /*
4721 * This is most like caused by the users own
4722 * plugins updating the function. This overrides the
4723 * system defaults.
4724 */
4725 pr_stat("override of function helper '%s'", name);
4726 remove_func_handler(pevent, name);
4727 }
4728
4729 func_handle = malloc_or_die(sizeof(*func_handle));
4730 memset(func_handle, 0, sizeof(*func_handle));
4731
4732 func_handle->ret_type = ret_type;
4733 func_handle->name = strdup(name);
4734 func_handle->func = func;
4735 if (!func_handle->name)
4736 die("Failed to allocate function name");
4737
4738 next_param = &(func_handle->params);
4739 va_start(ap, name);
4740 for (;;) {
4741 type = va_arg(ap, enum pevent_func_arg_type);
4742 if (type == PEVENT_FUNC_ARG_VOID)
4743 break;
4744
4745 if (type < 0 || type >= PEVENT_FUNC_ARG_MAX_TYPES) {
4746 warning("Invalid argument type %d", type);
4747 goto out_free;
4748 }
4749
4750 param = malloc_or_die(sizeof(*param));
4751 param->type = type;
4752 param->next = NULL;
4753
4754 *next_param = param;
4755 next_param = &(param->next);
4756
4757 func_handle->nr_args++;
4758 }
4759 va_end(ap);
4760
4761 func_handle->next = pevent->func_handlers;
4762 pevent->func_handlers = func_handle;
4763
4764 return 0;
4765 out_free:
4766 va_end(ap);
4767 free_func_handle(func_handle);
4768 return -1;
4769}
4770
4771/**
4772 * pevent_register_event_handle - register a way to parse an event
4773 * @pevent: the handle to the pevent
4774 * @id: the id of the event to register
4775 * @sys_name: the system name the event belongs to
4776 * @event_name: the name of the event
4777 * @func: the function to call to parse the event information
4778 *
4779 * This function allows a developer to override the parsing of
4780 * a given event. If for some reason the default print format
4781 * is not sufficient, this function will register a function
4782 * for an event to be used to parse the data instead.
4783 *
4784 * If @id is >= 0, then it is used to find the event.
4785 * else @sys_name and @event_name are used.
4786 */
4787int pevent_register_event_handler(struct pevent *pevent,
4788 int id, char *sys_name, char *event_name,
4789 pevent_event_handler_func func,
4790 void *context)
4791{
4792 struct event_format *event;
4793 struct event_handler *handle;
4794
4795 if (id >= 0) {
4796 /* search by id */
4797 event = pevent_find_event(pevent, id);
4798 if (!event)
4799 goto not_found;
4800 if (event_name && (strcmp(event_name, event->name) != 0))
4801 goto not_found;
4802 if (sys_name && (strcmp(sys_name, event->system) != 0))
4803 goto not_found;
4804 } else {
4805 event = pevent_find_event_by_name(pevent, sys_name, event_name);
4806 if (!event)
4807 goto not_found;
4808 }
4809
4810 pr_stat("overriding event (%d) %s:%s with new print handler",
4811 event->id, event->system, event->name);
4812
4813 event->handler = func;
4814 event->context = context;
4815 return 0;
4816
4817 not_found:
4818 /* Save for later use. */
4819 handle = malloc_or_die(sizeof(*handle));
4820 memset(handle, 0, sizeof(handle));
4821 handle->id = id;
4822 if (event_name)
4823 handle->event_name = strdup(event_name);
4824 if (sys_name)
4825 handle->sys_name = strdup(sys_name);
4826
4827 handle->func = func;
4828 handle->next = pevent->handlers;
4829 pevent->handlers = handle;
4830 handle->context = context;
4831
4832 return -1;
4833}
4834
4835/**
4836 * pevent_alloc - create a pevent handle
4837 */
4838struct pevent *pevent_alloc(void)
4839{
4840 struct pevent *pevent;
4841
4842 pevent = malloc(sizeof(*pevent));
4843 if (!pevent)
4844 return NULL;
4845 memset(pevent, 0, sizeof(*pevent));
4846 pevent->ref_count = 1;
4847
4848 return pevent;
4849}
4850
4851void pevent_ref(struct pevent *pevent)
4852{
4853 pevent->ref_count++;
4854}
4855
4856static void free_format_fields(struct format_field *field)
4857{
4858 struct format_field *next;
4859
4860 while (field) {
4861 next = field->next;
4862 free(field->type);
4863 free(field->name);
4864 free(field);
4865 field = next;
4866 }
4867}
4868
4869static void free_formats(struct format *format)
4870{
4871 free_format_fields(format->common_fields);
4872 free_format_fields(format->fields);
4873}
4874
4875static void free_event(struct event_format *event)
4876{
4877 free(event->name);
4878 free(event->system);
4879
4880 free_formats(&event->format);
4881
4882 free(event->print_fmt.format);
4883 free_args(event->print_fmt.args);
4884
4885 free(event);
4886}
4887
4888/**
4889 * pevent_free - free a pevent handle
4890 * @pevent: the pevent handle to free
4891 */
4892void pevent_free(struct pevent *pevent)
4893{
4894 struct cmdline_list *cmdlist = pevent->cmdlist, *cmdnext;
4895 struct func_list *funclist = pevent->funclist, *funcnext;
4896 struct printk_list *printklist = pevent->printklist, *printknext;
4897 struct pevent_function_handler *func_handler;
4898 struct event_handler *handle;
4899 int i;
4900
4901 pevent->ref_count--;
4902 if (pevent->ref_count)
4903 return;
4904
4905 if (pevent->cmdlines) {
4906 for (i = 0; i < pevent->cmdline_count; i++)
4907 free(pevent->cmdlines[i].comm);
4908 free(pevent->cmdlines);
4909 }
4910
4911 while (cmdlist) {
4912 cmdnext = cmdlist->next;
4913 free(cmdlist->comm);
4914 free(cmdlist);
4915 cmdlist = cmdnext;
4916 }
4917
4918 if (pevent->func_map) {
4919 for (i = 0; i < pevent->func_count; i++) {
4920 free(pevent->func_map[i].func);
4921 free(pevent->func_map[i].mod);
4922 }
4923 free(pevent->func_map);
4924 }
4925
4926 while (funclist) {
4927 funcnext = funclist->next;
4928 free(funclist->func);
4929 free(funclist->mod);
4930 free(funclist);
4931 funclist = funcnext;
4932 }
4933
4934 while (pevent->func_handlers) {
4935 func_handler = pevent->func_handlers;
4936 pevent->func_handlers = func_handler->next;
4937 free_func_handle(func_handler);
4938 }
4939
4940 if (pevent->printk_map) {
4941 for (i = 0; i < pevent->printk_count; i++)
4942 free(pevent->printk_map[i].printk);
4943 free(pevent->printk_map);
4944 }
4945
4946 while (printklist) {
4947 printknext = printklist->next;
4948 free(printklist->printk);
4949 free(printklist);
4950 printklist = printknext;
4951 }
4952
4953 for (i = 0; i < pevent->nr_events; i++)
4954 free_event(pevent->events[i]);
4955
4956 while (pevent->handlers) {
4957 handle = pevent->handlers;
4958 pevent->handlers = handle->next;
4959 free_handler(handle);
4960 }
4961
4962 free(pevent->events);
4963 free(pevent->sort_events);
4964
4965 free(pevent);
4966}
4967
4968void pevent_unref(struct pevent *pevent)
4969{
4970 pevent_free(pevent);
4971}
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
new file mode 100644
index 00000000000..c32d7153a8d
--- /dev/null
+++ b/tools/lib/traceevent/event-parse.h
@@ -0,0 +1,806 @@
1/*
2 * Copyright (C) 2009, 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */
21#ifndef _PARSE_EVENTS_H
22#define _PARSE_EVENTS_H
23
24#include <stdarg.h>
25#include <regex.h>
26
27#ifndef __unused
28#define __unused __attribute__ ((unused))
29#endif
30
31/* ----------------------- trace_seq ----------------------- */
32
33
34#ifndef TRACE_SEQ_BUF_SIZE
35#define TRACE_SEQ_BUF_SIZE 4096
36#endif
37
38#ifndef DEBUG_RECORD
39#define DEBUG_RECORD 0
40#endif
41
42struct record {
43 unsigned long long ts;
44 unsigned long long offset;
45 long long missed_events; /* buffer dropped events before */
46 int record_size; /* size of binary record */
47 int size; /* size of data */
48 void *data;
49 int cpu;
50 int ref_count;
51 int locked; /* Do not free, even if ref_count is zero */
52 void *private;
53#if DEBUG_RECORD
54 struct record *prev;
55 struct record *next;
56 long alloc_addr;
57#endif
58};
59
60/*
61 * Trace sequences are used to allow a function to call several other functions
62 * to create a string of data to use (up to a max of PAGE_SIZE).
63 */
64
65struct trace_seq {
66 char *buffer;
67 unsigned int buffer_size;
68 unsigned int len;
69 unsigned int readpos;
70};
71
72void trace_seq_init(struct trace_seq *s);
73void trace_seq_destroy(struct trace_seq *s);
74
75extern int trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
76 __attribute__ ((format (printf, 2, 3)));
77extern int trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
78 __attribute__ ((format (printf, 2, 0)));
79
80extern int trace_seq_puts(struct trace_seq *s, const char *str);
81extern int trace_seq_putc(struct trace_seq *s, unsigned char c);
82
83extern void trace_seq_terminate(struct trace_seq *s);
84
85extern int trace_seq_do_printf(struct trace_seq *s);
86
87
88/* ----------------------- pevent ----------------------- */
89
90struct pevent;
91struct event_format;
92
93typedef int (*pevent_event_handler_func)(struct trace_seq *s,
94 struct record *record,
95 struct event_format *event,
96 void *context);
97
98typedef int (*pevent_plugin_load_func)(struct pevent *pevent);
99typedef int (*pevent_plugin_unload_func)(void);
100
101struct plugin_option {
102 struct plugin_option *next;
103 void *handle;
104 char *file;
105 char *name;
106 char *plugin_alias;
107 char *description;
108 char *value;
109 void *private;
110 int set;
111};
112
113/*
114 * Plugin hooks that can be called:
115 *
116 * PEVENT_PLUGIN_LOADER: (required)
117 * The function name to initialized the plugin.
118 *
119 * int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
120 *
121 * PEVENT_PLUGIN_UNLOADER: (optional)
122 * The function called just before unloading
123 *
124 * int PEVENT_PLUGIN_UNLOADER(void)
125 *
126 * PEVENT_PLUGIN_OPTIONS: (optional)
127 * Plugin options that can be set before loading
128 *
129 * struct plugin_option PEVENT_PLUGIN_OPTIONS[] = {
130 * {
131 * .name = "option-name",
132 * .plugin_alias = "overide-file-name", (optional)
133 * .description = "description of option to show users",
134 * },
135 * {
136 * .name = NULL,
137 * },
138 * };
139 *
140 * Array must end with .name = NULL;
141 *
142 *
143 * .plugin_alias is used to give a shorter name to access
144 * the vairable. Useful if a plugin handles more than one event.
145 *
146 * PEVENT_PLUGIN_ALIAS: (optional)
147 * The name to use for finding options (uses filename if not defined)
148 */
149#define PEVENT_PLUGIN_LOADER pevent_plugin_loader
150#define PEVENT_PLUGIN_UNLOADER pevent_plugin_unloader
151#define PEVENT_PLUGIN_OPTIONS pevent_plugin_options
152#define PEVENT_PLUGIN_ALIAS pevent_plugin_alias
153#define _MAKE_STR(x) #x
154#define MAKE_STR(x) _MAKE_STR(x)
155#define PEVENT_PLUGIN_LOADER_NAME MAKE_STR(PEVENT_PLUGIN_LOADER)
156#define PEVENT_PLUGIN_UNLOADER_NAME MAKE_STR(PEVENT_PLUGIN_UNLOADER)
157#define PEVENT_PLUGIN_OPTIONS_NAME MAKE_STR(PEVENT_PLUGIN_OPTIONS)
158#define PEVENT_PLUGIN_ALIAS_NAME MAKE_STR(PEVENT_PLUGIN_ALIAS)
159
160#define NSECS_PER_SEC 1000000000ULL
161#define NSECS_PER_USEC 1000ULL
162
163enum format_flags {
164 FIELD_IS_ARRAY = 1,
165 FIELD_IS_POINTER = 2,
166 FIELD_IS_SIGNED = 4,
167 FIELD_IS_STRING = 8,
168 FIELD_IS_DYNAMIC = 16,
169 FIELD_IS_LONG = 32,
170};
171
172struct format_field {
173 struct format_field *next;
174 struct event_format *event;
175 char *type;
176 char *name;
177 int offset;
178 int size;
179 unsigned int arraylen;
180 unsigned int elementsize;
181 unsigned long flags;
182};
183
184struct format {
185 int nr_common;
186 int nr_fields;
187 struct format_field *common_fields;
188 struct format_field *fields;
189};
190
191struct print_arg_atom {
192 char *atom;
193};
194
195struct print_arg_string {
196 char *string;
197 int offset;
198};
199
200struct print_arg_field {
201 char *name;
202 struct format_field *field;
203};
204
205struct print_flag_sym {
206 struct print_flag_sym *next;
207 char *value;
208 char *str;
209};
210
211struct print_arg_typecast {
212 char *type;
213 struct print_arg *item;
214};
215
216struct print_arg_flags {
217 struct print_arg *field;
218 char *delim;
219 struct print_flag_sym *flags;
220};
221
222struct print_arg_symbol {
223 struct print_arg *field;
224 struct print_flag_sym *symbols;
225};
226
227struct print_arg_dynarray {
228 struct format_field *field;
229 struct print_arg *index;
230};
231
232struct print_arg;
233
234struct print_arg_op {
235 char *op;
236 int prio;
237 struct print_arg *left;
238 struct print_arg *right;
239};
240
241struct pevent_function_handler;
242
243struct print_arg_func {
244 struct pevent_function_handler *func;
245 struct print_arg *args;
246};
247
248enum print_arg_type {
249 PRINT_NULL,
250 PRINT_ATOM,
251 PRINT_FIELD,
252 PRINT_FLAGS,
253 PRINT_SYMBOL,
254 PRINT_TYPE,
255 PRINT_STRING,
256 PRINT_BSTRING,
257 PRINT_DYNAMIC_ARRAY,
258 PRINT_OP,
259 PRINT_FUNC,
260};
261
262struct print_arg {
263 struct print_arg *next;
264 enum print_arg_type type;
265 union {
266 struct print_arg_atom atom;
267 struct print_arg_field field;
268 struct print_arg_typecast typecast;
269 struct print_arg_flags flags;
270 struct print_arg_symbol symbol;
271 struct print_arg_func func;
272 struct print_arg_string string;
273 struct print_arg_op op;
274 struct print_arg_dynarray dynarray;
275 };
276};
277
278struct print_fmt {
279 char *format;
280 struct print_arg *args;
281};
282
283struct event_format {
284 struct pevent *pevent;
285 char *name;
286 int id;
287 int flags;
288 struct format format;
289 struct print_fmt print_fmt;
290 char *system;
291 pevent_event_handler_func handler;
292 void *context;
293};
294
295enum {
296 EVENT_FL_ISFTRACE = 0x01,
297 EVENT_FL_ISPRINT = 0x02,
298 EVENT_FL_ISBPRINT = 0x04,
299 EVENT_FL_ISFUNCENT = 0x10,
300 EVENT_FL_ISFUNCRET = 0x20,
301
302 EVENT_FL_FAILED = 0x80000000
303};
304
305enum event_sort_type {
306 EVENT_SORT_ID,
307 EVENT_SORT_NAME,
308 EVENT_SORT_SYSTEM,
309};
310
311enum event_type {
312 EVENT_ERROR,
313 EVENT_NONE,
314 EVENT_SPACE,
315 EVENT_NEWLINE,
316 EVENT_OP,
317 EVENT_DELIM,
318 EVENT_ITEM,
319 EVENT_DQUOTE,
320 EVENT_SQUOTE,
321};
322
323typedef unsigned long long (*pevent_func_handler)(struct trace_seq *s,
324 unsigned long long *args);
325
326enum pevent_func_arg_type {
327 PEVENT_FUNC_ARG_VOID,
328 PEVENT_FUNC_ARG_INT,
329 PEVENT_FUNC_ARG_LONG,
330 PEVENT_FUNC_ARG_STRING,
331 PEVENT_FUNC_ARG_PTR,
332 PEVENT_FUNC_ARG_MAX_TYPES
333};
334
335struct cmdline;
336struct cmdline_list;
337struct func_map;
338struct func_list;
339struct event_handler;
340
341struct pevent {
342 int ref_count;
343
344 int header_page_ts_offset;
345 int header_page_ts_size;
346 int header_page_size_offset;
347 int header_page_size_size;
348 int header_page_data_offset;
349 int header_page_data_size;
350 int header_page_overwrite;
351
352 int file_bigendian;
353 int host_bigendian;
354
355 int latency_format;
356
357 int old_format;
358
359 int cpus;
360 int long_size;
361
362 struct cmdline *cmdlines;
363 struct cmdline_list *cmdlist;
364 int cmdline_count;
365
366 struct func_map *func_map;
367 struct func_list *funclist;
368 unsigned int func_count;
369
370 struct printk_map *printk_map;
371 struct printk_list *printklist;
372 unsigned int printk_count;
373
374 struct event_format **events;
375 int nr_events;
376 struct event_format **sort_events;
377 enum event_sort_type last_type;
378
379 int type_offset;
380 int type_size;
381
382 int pid_offset;
383 int pid_size;
384
385 int pc_offset;
386 int pc_size;
387
388 int flags_offset;
389 int flags_size;
390
391 int ld_offset;
392 int ld_size;
393
394 int print_raw;
395
396 int test_filters;
397
398 struct format_field *bprint_ip_field;
399 struct format_field *bprint_fmt_field;
400 struct format_field *bprint_buf_field;
401
402 struct event_handler *handlers;
403 struct pevent_function_handler *func_handlers;
404
405 /* cache */
406 struct event_format *last_event;
407};
408
409/* Can be overridden */
410void die(const char *fmt, ...);
411void *malloc_or_die(unsigned int size);
412void warning(const char *fmt, ...);
413void pr_stat(const char *fmt, ...);
414void vpr_stat(const char *fmt, va_list ap);
415
416/* Always available */
417void __die(const char *fmt, ...);
418void __warning(const char *fmt, ...);
419void __pr_stat(const char *fmt, ...);
420
421void __vdie(const char *fmt, ...);
422void __vwarning(const char *fmt, ...);
423void __vpr_stat(const char *fmt, ...);
424
425static inline unsigned short
426__data2host2(struct pevent *pevent, unsigned short data)
427{
428 unsigned short swap;
429
430 if (pevent->host_bigendian == pevent->file_bigendian)
431 return data;
432
433 swap = ((data & 0xffULL) << 8) |
434 ((data & (0xffULL << 8)) >> 8);
435
436 return swap;
437}
438
439static inline unsigned int
440__data2host4(struct pevent *pevent, unsigned int data)
441{
442 unsigned int swap;
443
444 if (pevent->host_bigendian == pevent->file_bigendian)
445 return data;
446
447 swap = ((data & 0xffULL) << 24) |
448 ((data & (0xffULL << 8)) << 8) |
449 ((data & (0xffULL << 16)) >> 8) |
450 ((data & (0xffULL << 24)) >> 24);
451
452 return swap;
453}
454
455static inline unsigned long long
456__data2host8(struct pevent *pevent, unsigned long long data)
457{
458 unsigned long long swap;
459
460 if (pevent->host_bigendian == pevent->file_bigendian)
461 return data;
462
463 swap = ((data & 0xffULL) << 56) |
464 ((data & (0xffULL << 8)) << 40) |
465 ((data & (0xffULL << 16)) << 24) |
466 ((data & (0xffULL << 24)) << 8) |
467 ((data & (0xffULL << 32)) >> 8) |
468 ((data & (0xffULL << 40)) >> 24) |
469 ((data & (0xffULL << 48)) >> 40) |
470 ((data & (0xffULL << 56)) >> 56);
471
472 return swap;
473}
474
475#define data2host2(pevent, ptr) __data2host2(pevent, *(unsigned short *)(ptr))
476#define data2host4(pevent, ptr) __data2host4(pevent, *(unsigned int *)(ptr))
477#define data2host8(pevent, ptr) \
478({ \
479 unsigned long long __val; \
480 \
481 memcpy(&__val, (ptr), sizeof(unsigned long long)); \
482 __data2host8(pevent, __val); \
483})
484
485/* taken from kernel/trace/trace.h */
486enum trace_flag_type {
487 TRACE_FLAG_IRQS_OFF = 0x01,
488 TRACE_FLAG_IRQS_NOSUPPORT = 0x02,
489 TRACE_FLAG_NEED_RESCHED = 0x04,
490 TRACE_FLAG_HARDIRQ = 0x08,
491 TRACE_FLAG_SOFTIRQ = 0x10,
492};
493
494int pevent_register_comm(struct pevent *pevent, const char *comm, int pid);
495int pevent_register_function(struct pevent *pevent, char *name,
496 unsigned long long addr, char *mod);
497int pevent_register_print_string(struct pevent *pevent, char *fmt,
498 unsigned long long addr);
499int pevent_pid_is_registered(struct pevent *pevent, int pid);
500
501void pevent_print_event(struct pevent *pevent, struct trace_seq *s,
502 struct record *record);
503
504int pevent_parse_header_page(struct pevent *pevent, char *buf, unsigned long size,
505 int long_size);
506
507int pevent_parse_event(struct pevent *pevent, const char *buf,
508 unsigned long size, const char *sys);
509
510void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
511 const char *name, struct record *record,
512 int *len, int err);
513
514int pevent_get_field_val(struct trace_seq *s, struct event_format *event,
515 const char *name, struct record *record,
516 unsigned long long *val, int err);
517int pevent_get_common_field_val(struct trace_seq *s, struct event_format *event,
518 const char *name, struct record *record,
519 unsigned long long *val, int err);
520int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
521 const char *name, struct record *record,
522 unsigned long long *val, int err);
523
524int pevent_print_num_field(struct trace_seq *s, const char *fmt,
525 struct event_format *event, const char *name,
526 struct record *record, int err);
527
528int pevent_register_event_handler(struct pevent *pevent, int id, char *sys_name, char *event_name,
529 pevent_event_handler_func func, void *context);
530int pevent_register_print_function(struct pevent *pevent,
531 pevent_func_handler func,
532 enum pevent_func_arg_type ret_type,
533 char *name, ...);
534
535struct format_field *pevent_find_common_field(struct event_format *event, const char *name);
536struct format_field *pevent_find_field(struct event_format *event, const char *name);
537struct format_field *pevent_find_any_field(struct event_format *event, const char *name);
538
539const char *pevent_find_function(struct pevent *pevent, unsigned long long addr);
540unsigned long long
541pevent_find_function_address(struct pevent *pevent, unsigned long long addr);
542unsigned long long pevent_read_number(struct pevent *pevent, const void *ptr, int size);
543int pevent_read_number_field(struct format_field *field, const void *data,
544 unsigned long long *value);
545
546struct event_format *pevent_find_event(struct pevent *pevent, int id);
547
548struct event_format *
549pevent_find_event_by_name(struct pevent *pevent, const char *sys, const char *name);
550
551void pevent_data_lat_fmt(struct pevent *pevent,
552 struct trace_seq *s, struct record *record);
553int pevent_data_type(struct pevent *pevent, struct record *rec);
554struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type);
555int pevent_data_pid(struct pevent *pevent, struct record *rec);
556const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid);
557void pevent_event_info(struct trace_seq *s, struct event_format *event,
558 struct record *record);
559
560struct event_format **pevent_list_events(struct pevent *pevent, enum event_sort_type);
561struct format_field **pevent_event_common_fields(struct event_format *event);
562struct format_field **pevent_event_fields(struct event_format *event);
563
564static inline int pevent_get_cpus(struct pevent *pevent)
565{
566 return pevent->cpus;
567}
568
569static inline void pevent_set_cpus(struct pevent *pevent, int cpus)
570{
571 pevent->cpus = cpus;
572}
573
574static inline int pevent_get_long_size(struct pevent *pevent)
575{
576 return pevent->long_size;
577}
578
579static inline void pevent_set_long_size(struct pevent *pevent, int long_size)
580{
581 pevent->long_size = long_size;
582}
583
584static inline int pevent_is_file_bigendian(struct pevent *pevent)
585{
586 return pevent->file_bigendian;
587}
588
589static inline void pevent_set_file_bigendian(struct pevent *pevent, int endian)
590{
591 pevent->file_bigendian = endian;
592}
593
594static inline int pevent_is_host_bigendian(struct pevent *pevent)
595{
596 return pevent->host_bigendian;
597}
598
599static inline void pevent_set_host_bigendian(struct pevent *pevent, int endian)
600{
601 pevent->host_bigendian = endian;
602}
603
604static inline int pevent_is_latency_format(struct pevent *pevent)
605{
606 return pevent->latency_format;
607}
608
609static inline void pevent_set_latency_format(struct pevent *pevent, int lat)
610{
611 pevent->latency_format = lat;
612}
613
614struct pevent *pevent_alloc(void);
615void pevent_free(struct pevent *pevent);
616void pevent_ref(struct pevent *pevent);
617void pevent_unref(struct pevent *pevent);
618
619/* access to the internal parser */
620void pevent_buffer_init(const char *buf, unsigned long long size);
621enum event_type pevent_read_token(char **tok);
622void pevent_free_token(char *token);
623int pevent_peek_char(void);
624const char *pevent_get_input_buf(void);
625unsigned long long pevent_get_input_buf_ptr(void);
626
627/* for debugging */
628void pevent_print_funcs(struct pevent *pevent);
629void pevent_print_printk(struct pevent *pevent);
630
631/* ----------------------- filtering ----------------------- */
632
633enum filter_boolean_type {
634 FILTER_FALSE,
635 FILTER_TRUE,
636};
637
638enum filter_op_type {
639 FILTER_OP_AND = 1,
640 FILTER_OP_OR,
641 FILTER_OP_NOT,
642};
643
644enum filter_cmp_type {
645 FILTER_CMP_NONE,
646 FILTER_CMP_EQ,
647 FILTER_CMP_NE,
648 FILTER_CMP_GT,
649 FILTER_CMP_LT,
650 FILTER_CMP_GE,
651 FILTER_CMP_LE,
652 FILTER_CMP_MATCH,
653 FILTER_CMP_NOT_MATCH,
654 FILTER_CMP_REGEX,
655 FILTER_CMP_NOT_REGEX,
656};
657
658enum filter_exp_type {
659 FILTER_EXP_NONE,
660 FILTER_EXP_ADD,
661 FILTER_EXP_SUB,
662 FILTER_EXP_MUL,
663 FILTER_EXP_DIV,
664 FILTER_EXP_MOD,
665 FILTER_EXP_RSHIFT,
666 FILTER_EXP_LSHIFT,
667 FILTER_EXP_AND,
668 FILTER_EXP_OR,
669 FILTER_EXP_XOR,
670 FILTER_EXP_NOT,
671};
672
673enum filter_arg_type {
674 FILTER_ARG_NONE,
675 FILTER_ARG_BOOLEAN,
676 FILTER_ARG_VALUE,
677 FILTER_ARG_FIELD,
678 FILTER_ARG_EXP,
679 FILTER_ARG_OP,
680 FILTER_ARG_NUM,
681 FILTER_ARG_STR,
682};
683
684enum filter_value_type {
685 FILTER_NUMBER,
686 FILTER_STRING,
687 FILTER_CHAR
688};
689
690struct fliter_arg;
691
692struct filter_arg_boolean {
693 enum filter_boolean_type value;
694};
695
696struct filter_arg_field {
697 struct format_field *field;
698};
699
700struct filter_arg_value {
701 enum filter_value_type type;
702 union {
703 char *str;
704 unsigned long long val;
705 };
706};
707
708struct filter_arg_op {
709 enum filter_op_type type;
710 struct filter_arg *left;
711 struct filter_arg *right;
712};
713
714struct filter_arg_exp {
715 enum filter_exp_type type;
716 struct filter_arg *left;
717 struct filter_arg *right;
718};
719
720struct filter_arg_num {
721 enum filter_cmp_type type;
722 struct filter_arg *left;
723 struct filter_arg *right;
724};
725
726struct filter_arg_str {
727 enum filter_cmp_type type;
728 struct format_field *field;
729 char *val;
730 char *buffer;
731 regex_t reg;
732};
733
734struct filter_arg {
735 enum filter_arg_type type;
736 union {
737 struct filter_arg_boolean bool;
738 struct filter_arg_field field;
739 struct filter_arg_value value;
740 struct filter_arg_op op;
741 struct filter_arg_exp exp;
742 struct filter_arg_num num;
743 struct filter_arg_str str;
744 };
745};
746
747struct filter_type {
748 int event_id;
749 struct event_format *event;
750 struct filter_arg *filter;
751};
752
753struct event_filter {
754 struct pevent *pevent;
755 int filters;
756 struct filter_type *event_filters;
757};
758
759struct event_filter *pevent_filter_alloc(struct pevent *pevent);
760
761#define FILTER_NONE -2
762#define FILTER_NOEXIST -1
763#define FILTER_MISS 0
764#define FILTER_MATCH 1
765
766enum filter_trivial_type {
767 FILTER_TRIVIAL_FALSE,
768 FILTER_TRIVIAL_TRUE,
769 FILTER_TRIVIAL_BOTH,
770};
771
772int pevent_filter_add_filter_str(struct event_filter *filter,
773 const char *filter_str,
774 char **error_str);
775
776
777int pevent_filter_match(struct event_filter *filter,
778 struct record *record);
779
780int pevent_event_filtered(struct event_filter *filter,
781 int event_id);
782
783void pevent_filter_reset(struct event_filter *filter);
784
785void pevent_filter_clear_trivial(struct event_filter *filter,
786 enum filter_trivial_type type);
787
788void pevent_filter_free(struct event_filter *filter);
789
790char *pevent_filter_make_string(struct event_filter *filter, int event_id);
791
792int pevent_filter_remove_event(struct event_filter *filter,
793 int event_id);
794
795int pevent_filter_event_has_trivial(struct event_filter *filter,
796 int event_id,
797 enum filter_trivial_type type);
798
799int pevent_filter_copy(struct event_filter *dest, struct event_filter *source);
800
801int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
802 enum filter_trivial_type type);
803
804int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2);
805
806#endif /* _PARSE_EVENTS_H */
diff --git a/tools/lib/traceevent/event-utils.h b/tools/lib/traceevent/event-utils.h
new file mode 100644
index 00000000000..a8fb48f1922
--- /dev/null
+++ b/tools/lib/traceevent/event-utils.h
@@ -0,0 +1,64 @@
1/*
2 * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */
21#ifndef __UTIL_H
22#define __UTIL_H
23
24#include <ctype.h>
25
26static inline char *strim(char *string)
27{
28 char *ret;
29
30 if (!string)
31 return NULL;
32 while (*string) {
33 if (!isspace(*string))
34 break;
35 string++;
36 }
37 ret = string;
38
39 string = ret + strlen(ret) - 1;
40 while (string > ret) {
41 if (!isspace(*string))
42 break;
43 string--;
44 }
45 string[1] = 0;
46
47 return ret;
48}
49
50static inline int has_text(const char *text)
51{
52 if (!text)
53 return 0;
54
55 while (*text) {
56 if (!isspace(*text))
57 return 1;
58 text++;
59 }
60
61 return 0;
62}
63
64#endif
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
new file mode 100644
index 00000000000..1df9966dff6
--- /dev/null
+++ b/tools/lib/traceevent/parse-filter.c
@@ -0,0 +1,2262 @@
1/*
2 * Copyright (C) 2010 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <stdarg.h>
25#include <errno.h>
26#include <sys/types.h>
27
28#include "event-parse.h"
29#include "event-utils.h"
30
31#define COMM "COMM"
32
33static struct format_field comm = {
34 .name = "COMM",
35};
36
37struct event_list {
38 struct event_list *next;
39 struct event_format *event;
40};
41
42#define MAX_ERR_STR_SIZE 256
43
44static void show_error(char **error_str, const char *fmt, ...)
45{
46 unsigned long long index;
47 const char *input;
48 char *error;
49 va_list ap;
50 int len;
51 int i;
52
53 if (!error_str)
54 return;
55
56 input = pevent_get_input_buf();
57 index = pevent_get_input_buf_ptr();
58 len = input ? strlen(input) : 0;
59
60 error = malloc_or_die(MAX_ERR_STR_SIZE + (len*2) + 3);
61
62 if (len) {
63 strcpy(error, input);
64 error[len] = '\n';
65 for (i = 1; i < len && i < index; i++)
66 error[len+i] = ' ';
67 error[len + i] = '^';
68 error[len + i + 1] = '\n';
69 len += i+2;
70 }
71
72 va_start(ap, fmt);
73 vsnprintf(error + len, MAX_ERR_STR_SIZE, fmt, ap);
74 va_end(ap);
75
76 *error_str = error;
77}
78
79static void free_token(char *token)
80{
81 pevent_free_token(token);
82}
83
84static enum event_type read_token(char **tok)
85{
86 enum event_type type;
87 char *token = NULL;
88
89 do {
90 free_token(token);
91 type = pevent_read_token(&token);
92 } while (type == EVENT_NEWLINE || type == EVENT_SPACE);
93
94 /* If token is = or ! check to see if the next char is ~ */
95 if (token &&
96 (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
97 pevent_peek_char() == '~') {
98 /* append it */
99 *tok = malloc(3);
100 sprintf(*tok, "%c%c", *token, '~');
101 free_token(token);
102 /* Now remove the '~' from the buffer */
103 pevent_read_token(&token);
104 free_token(token);
105 } else
106 *tok = token;
107
108 return type;
109}
110
111static int filter_cmp(const void *a, const void *b)
112{
113 const struct filter_type *ea = a;
114 const struct filter_type *eb = b;
115
116 if (ea->event_id < eb->event_id)
117 return -1;
118
119 if (ea->event_id > eb->event_id)
120 return 1;
121
122 return 0;
123}
124
125static struct filter_type *
126find_filter_type(struct event_filter *filter, int id)
127{
128 struct filter_type *filter_type;
129 struct filter_type key;
130
131 key.event_id = id;
132
133 filter_type = bsearch(&key, filter->event_filters,
134 filter->filters,
135 sizeof(*filter->event_filters),
136 filter_cmp);
137
138 return filter_type;
139}
140
141static struct filter_type *
142add_filter_type(struct event_filter *filter, int id)
143{
144 struct filter_type *filter_type;
145 int i;
146
147 filter_type = find_filter_type(filter, id);
148 if (filter_type)
149 return filter_type;
150
151 if (!filter->filters)
152 filter->event_filters =
153 malloc_or_die(sizeof(*filter->event_filters));
154 else {
155 filter->event_filters =
156 realloc(filter->event_filters,
157 sizeof(*filter->event_filters) *
158 (filter->filters + 1));
159 if (!filter->event_filters)
160 die("Could not allocate filter");
161 }
162
163 for (i = 0; i < filter->filters; i++) {
164 if (filter->event_filters[i].event_id > id)
165 break;
166 }
167
168 if (i < filter->filters)
169 memmove(&filter->event_filters[i+1],
170 &filter->event_filters[i],
171 sizeof(*filter->event_filters) *
172 (filter->filters - i));
173
174 filter_type = &filter->event_filters[i];
175 filter_type->event_id = id;
176 filter_type->event = pevent_find_event(filter->pevent, id);
177 filter_type->filter = NULL;
178
179 filter->filters++;
180
181 return filter_type;
182}
183
184/**
185 * pevent_filter_alloc - create a new event filter
186 * @pevent: The pevent that this filter is associated with
187 */
188struct event_filter *pevent_filter_alloc(struct pevent *pevent)
189{
190 struct event_filter *filter;
191
192 filter = malloc_or_die(sizeof(*filter));
193 memset(filter, 0, sizeof(*filter));
194 filter->pevent = pevent;
195 pevent_ref(pevent);
196
197 return filter;
198}
199
200static struct filter_arg *allocate_arg(void)
201{
202 struct filter_arg *arg;
203
204 arg = malloc_or_die(sizeof(*arg));
205 memset(arg, 0, sizeof(*arg));
206
207 return arg;
208}
209
210static void free_arg(struct filter_arg *arg)
211{
212 if (!arg)
213 return;
214
215 switch (arg->type) {
216 case FILTER_ARG_NONE:
217 case FILTER_ARG_BOOLEAN:
218 case FILTER_ARG_NUM:
219 break;
220
221 case FILTER_ARG_STR:
222 free(arg->str.val);
223 regfree(&arg->str.reg);
224 free(arg->str.buffer);
225 break;
226
227 case FILTER_ARG_OP:
228 free_arg(arg->op.left);
229 free_arg(arg->op.right);
230 default:
231 break;
232 }
233
234 free(arg);
235}
236
237static void add_event(struct event_list **events,
238 struct event_format *event)
239{
240 struct event_list *list;
241
242 list = malloc_or_die(sizeof(*list));
243 list->next = *events;
244 *events = list;
245 list->event = event;
246}
247
248static int event_match(struct event_format *event,
249 regex_t *sreg, regex_t *ereg)
250{
251 if (sreg) {
252 return !regexec(sreg, event->system, 0, NULL, 0) &&
253 !regexec(ereg, event->name, 0, NULL, 0);
254 }
255
256 return !regexec(ereg, event->system, 0, NULL, 0) ||
257 !regexec(ereg, event->name, 0, NULL, 0);
258}
259
260static int
261find_event(struct pevent *pevent, struct event_list **events,
262 char *sys_name, char *event_name)
263{
264 struct event_format *event;
265 regex_t ereg;
266 regex_t sreg;
267 int match = 0;
268 char *reg;
269 int ret;
270 int i;
271
272 if (!event_name) {
273 /* if no name is given, then swap sys and name */
274 event_name = sys_name;
275 sys_name = NULL;
276 }
277
278 reg = malloc_or_die(strlen(event_name) + 3);
279 sprintf(reg, "^%s$", event_name);
280
281 ret = regcomp(&ereg, reg, REG_ICASE|REG_NOSUB);
282 free(reg);
283
284 if (ret)
285 return -1;
286
287 if (sys_name) {
288 reg = malloc_or_die(strlen(sys_name) + 3);
289 sprintf(reg, "^%s$", sys_name);
290 ret = regcomp(&sreg, reg, REG_ICASE|REG_NOSUB);
291 free(reg);
292 if (ret) {
293 regfree(&ereg);
294 return -1;
295 }
296 }
297
298 for (i = 0; i < pevent->nr_events; i++) {
299 event = pevent->events[i];
300 if (event_match(event, sys_name ? &sreg : NULL, &ereg)) {
301 match = 1;
302 add_event(events, event);
303 }
304 }
305
306 regfree(&ereg);
307 if (sys_name)
308 regfree(&sreg);
309
310 if (!match)
311 return -1;
312
313 return 0;
314}
315
316static void free_events(struct event_list *events)
317{
318 struct event_list *event;
319
320 while (events) {
321 event = events;
322 events = events->next;
323 free(event);
324 }
325}
326
327static struct filter_arg *
328create_arg_item(struct event_format *event,
329 const char *token, enum filter_arg_type type,
330 char **error_str)
331{
332 struct format_field *field;
333 struct filter_arg *arg;
334
335 arg = allocate_arg();
336
337 switch (type) {
338
339 case EVENT_SQUOTE:
340 case EVENT_DQUOTE:
341 arg->type = FILTER_ARG_VALUE;
342 arg->value.type =
343 type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR;
344 arg->value.str = strdup(token);
345 if (!arg->value.str)
346 die("malloc string");
347 break;
348 case EVENT_ITEM:
349 /* if it is a number, then convert it */
350 if (isdigit(token[0])) {
351 arg->type = FILTER_ARG_VALUE;
352 arg->value.type = FILTER_NUMBER;
353 arg->value.val = strtoull(token, NULL, 0);
354 break;
355 }
356 /* Consider this a field */
357 field = pevent_find_any_field(event, token);
358 if (!field) {
359 if (strcmp(token, COMM) != 0) {
360 /* not a field, Make it false */
361 arg->type = FILTER_ARG_BOOLEAN;
362 arg->bool.value = FILTER_FALSE;
363 break;
364 }
365 /* If token is 'COMM' then it is special */
366 field = &comm;
367 }
368 arg->type = FILTER_ARG_FIELD;
369 arg->field.field = field;
370 break;
371 default:
372 free_arg(arg);
373 show_error(error_str, "expected a value but found %s",
374 token);
375 return NULL;
376 }
377 return arg;
378}
379
380static struct filter_arg *
381create_arg_op(enum filter_op_type btype)
382{
383 struct filter_arg *arg;
384
385 arg = allocate_arg();
386 arg->type = FILTER_ARG_OP;
387 arg->op.type = btype;
388
389 return arg;
390}
391
392static struct filter_arg *
393create_arg_exp(enum filter_exp_type etype)
394{
395 struct filter_arg *arg;
396
397 arg = allocate_arg();
398 arg->type = FILTER_ARG_EXP;
399 arg->op.type = etype;
400
401 return arg;
402}
403
404static struct filter_arg *
405create_arg_cmp(enum filter_exp_type etype)
406{
407 struct filter_arg *arg;
408
409 arg = allocate_arg();
410 /* Use NUM and change if necessary */
411 arg->type = FILTER_ARG_NUM;
412 arg->op.type = etype;
413
414 return arg;
415}
416
417static int add_right(struct filter_arg *op, struct filter_arg *arg,
418 char **error_str)
419{
420 struct filter_arg *left;
421 char *str;
422 int op_type;
423 int ret;
424
425 switch (op->type) {
426 case FILTER_ARG_EXP:
427 if (op->exp.right)
428 goto out_fail;
429 op->exp.right = arg;
430 break;
431
432 case FILTER_ARG_OP:
433 if (op->op.right)
434 goto out_fail;
435 op->op.right = arg;
436 break;
437
438 case FILTER_ARG_NUM:
439 if (op->op.right)
440 goto out_fail;
441 /*
442 * The arg must be num, str, or field
443 */
444 switch (arg->type) {
445 case FILTER_ARG_VALUE:
446 case FILTER_ARG_FIELD:
447 break;
448 default:
449 show_error(error_str,
450 "Illegal rvalue");
451 return -1;
452 }
453
454 /*
455 * Depending on the type, we may need to
456 * convert this to a string or regex.
457 */
458 switch (arg->value.type) {
459 case FILTER_CHAR:
460 /*
461 * A char should be converted to number if
462 * the string is 1 byte, and the compare
463 * is not a REGEX.
464 */
465 if (strlen(arg->value.str) == 1 &&
466 op->num.type != FILTER_CMP_REGEX &&
467 op->num.type != FILTER_CMP_NOT_REGEX) {
468 arg->value.type = FILTER_NUMBER;
469 goto do_int;
470 }
471 /* fall through */
472 case FILTER_STRING:
473
474 /* convert op to a string arg */
475 op_type = op->num.type;
476 left = op->num.left;
477 str = arg->value.str;
478
479 /* reset the op for the new field */
480 memset(op, 0, sizeof(*op));
481
482 /*
483 * If left arg was a field not found then
484 * NULL the entire op.
485 */
486 if (left->type == FILTER_ARG_BOOLEAN) {
487 free_arg(left);
488 free_arg(arg);
489 op->type = FILTER_ARG_BOOLEAN;
490 op->bool.value = FILTER_FALSE;
491 break;
492 }
493
494 /* Left arg must be a field */
495 if (left->type != FILTER_ARG_FIELD) {
496 show_error(error_str,
497 "Illegal lvalue for string comparison");
498 return -1;
499 }
500
501 /* Make sure this is a valid string compare */
502 switch (op_type) {
503 case FILTER_CMP_EQ:
504 op_type = FILTER_CMP_MATCH;
505 break;
506 case FILTER_CMP_NE:
507 op_type = FILTER_CMP_NOT_MATCH;
508 break;
509
510 case FILTER_CMP_REGEX:
511 case FILTER_CMP_NOT_REGEX:
512 ret = regcomp(&op->str.reg, str, REG_ICASE|REG_NOSUB);
513 if (ret) {
514 show_error(error_str,
515 "RegEx '%s' did not compute",
516 str);
517 return -1;
518 }
519 break;
520 default:
521 show_error(error_str,
522 "Illegal comparison for string");
523 return -1;
524 }
525
526 op->type = FILTER_ARG_STR;
527 op->str.type = op_type;
528 op->str.field = left->field.field;
529 op->str.val = strdup(str);
530 if (!op->str.val)
531 die("malloc string");
532 /*
533 * Need a buffer to copy data for tests
534 */
535 op->str.buffer = malloc_or_die(op->str.field->size + 1);
536 /* Null terminate this buffer */
537 op->str.buffer[op->str.field->size] = 0;
538
539 /* We no longer have left or right args */
540 free_arg(arg);
541 free_arg(left);
542
543 break;
544
545 case FILTER_NUMBER:
546
547 do_int:
548 switch (op->num.type) {
549 case FILTER_CMP_REGEX:
550 case FILTER_CMP_NOT_REGEX:
551 show_error(error_str,
552 "Op not allowed with integers");
553 return -1;
554
555 default:
556 break;
557 }
558
559 /* numeric compare */
560 op->num.right = arg;
561 break;
562 default:
563 goto out_fail;
564 }
565 break;
566 default:
567 goto out_fail;
568 }
569
570 return 0;
571
572 out_fail:
573 show_error(error_str,
574 "Syntax error");
575 return -1;
576}
577
578static struct filter_arg *
579rotate_op_right(struct filter_arg *a, struct filter_arg *b)
580{
581 struct filter_arg *arg;
582
583 arg = a->op.right;
584 a->op.right = b;
585 return arg;
586}
587
588static int add_left(struct filter_arg *op, struct filter_arg *arg)
589{
590 switch (op->type) {
591 case FILTER_ARG_EXP:
592 if (arg->type == FILTER_ARG_OP)
593 arg = rotate_op_right(arg, op);
594 op->exp.left = arg;
595 break;
596
597 case FILTER_ARG_OP:
598 op->op.left = arg;
599 break;
600 case FILTER_ARG_NUM:
601 if (arg->type == FILTER_ARG_OP)
602 arg = rotate_op_right(arg, op);
603
604 /* left arg of compares must be a field */
605 if (arg->type != FILTER_ARG_FIELD &&
606 arg->type != FILTER_ARG_BOOLEAN)
607 return -1;
608 op->num.left = arg;
609 break;
610 default:
611 return -1;
612 }
613 return 0;
614}
615
616enum op_type {
617 OP_NONE,
618 OP_BOOL,
619 OP_NOT,
620 OP_EXP,
621 OP_CMP,
622};
623
624static enum op_type process_op(const char *token,
625 enum filter_op_type *btype,
626 enum filter_cmp_type *ctype,
627 enum filter_exp_type *etype)
628{
629 *btype = FILTER_OP_NOT;
630 *etype = FILTER_EXP_NONE;
631 *ctype = FILTER_CMP_NONE;
632
633 if (strcmp(token, "&&") == 0)
634 *btype = FILTER_OP_AND;
635 else if (strcmp(token, "||") == 0)
636 *btype = FILTER_OP_OR;
637 else if (strcmp(token, "!") == 0)
638 return OP_NOT;
639
640 if (*btype != FILTER_OP_NOT)
641 return OP_BOOL;
642
643 /* Check for value expressions */
644 if (strcmp(token, "+") == 0) {
645 *etype = FILTER_EXP_ADD;
646 } else if (strcmp(token, "-") == 0) {
647 *etype = FILTER_EXP_SUB;
648 } else if (strcmp(token, "*") == 0) {
649 *etype = FILTER_EXP_MUL;
650 } else if (strcmp(token, "/") == 0) {
651 *etype = FILTER_EXP_DIV;
652 } else if (strcmp(token, "%") == 0) {
653 *etype = FILTER_EXP_MOD;
654 } else if (strcmp(token, ">>") == 0) {
655 *etype = FILTER_EXP_RSHIFT;
656 } else if (strcmp(token, "<<") == 0) {
657 *etype = FILTER_EXP_LSHIFT;
658 } else if (strcmp(token, "&") == 0) {
659 *etype = FILTER_EXP_AND;
660 } else if (strcmp(token, "|") == 0) {
661 *etype = FILTER_EXP_OR;
662 } else if (strcmp(token, "^") == 0) {
663 *etype = FILTER_EXP_XOR;
664 } else if (strcmp(token, "~") == 0)
665 *etype = FILTER_EXP_NOT;
666
667 if (*etype != FILTER_EXP_NONE)
668 return OP_EXP;
669
670 /* Check for compares */
671 if (strcmp(token, "==") == 0)
672 *ctype = FILTER_CMP_EQ;
673 else if (strcmp(token, "!=") == 0)
674 *ctype = FILTER_CMP_NE;
675 else if (strcmp(token, "<") == 0)
676 *ctype = FILTER_CMP_LT;
677 else if (strcmp(token, ">") == 0)
678 *ctype = FILTER_CMP_GT;
679 else if (strcmp(token, "<=") == 0)
680 *ctype = FILTER_CMP_LE;
681 else if (strcmp(token, ">=") == 0)
682 *ctype = FILTER_CMP_GE;
683 else if (strcmp(token, "=~") == 0)
684 *ctype = FILTER_CMP_REGEX;
685 else if (strcmp(token, "!~") == 0)
686 *ctype = FILTER_CMP_NOT_REGEX;
687 else
688 return OP_NONE;
689
690 return OP_CMP;
691}
692
693static int check_op_done(struct filter_arg *arg)
694{
695 switch (arg->type) {
696 case FILTER_ARG_EXP:
697 return arg->exp.right != NULL;
698
699 case FILTER_ARG_OP:
700 return arg->op.right != NULL;
701
702 case FILTER_ARG_NUM:
703 return arg->num.right != NULL;
704
705 case FILTER_ARG_STR:
706 /* A string conversion is always done */
707 return 1;
708
709 case FILTER_ARG_BOOLEAN:
710 /* field not found, is ok */
711 return 1;
712
713 default:
714 return 0;
715 }
716}
717
718enum filter_vals {
719 FILTER_VAL_NORM,
720 FILTER_VAL_FALSE,
721 FILTER_VAL_TRUE,
722};
723
724void reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
725 struct filter_arg *arg)
726{
727 struct filter_arg *other_child;
728 struct filter_arg **ptr;
729
730 if (parent->type != FILTER_ARG_OP &&
731 arg->type != FILTER_ARG_OP)
732 die("can not reparent other than OP");
733
734 /* Get the sibling */
735 if (old_child->op.right == arg) {
736 ptr = &old_child->op.right;
737 other_child = old_child->op.left;
738 } else if (old_child->op.left == arg) {
739 ptr = &old_child->op.left;
740 other_child = old_child->op.right;
741 } else
742 die("Error in reparent op, find other child");
743
744 /* Detach arg from old_child */
745 *ptr = NULL;
746
747 /* Check for root */
748 if (parent == old_child) {
749 free_arg(other_child);
750 *parent = *arg;
751 /* Free arg without recussion */
752 free(arg);
753 return;
754 }
755
756 if (parent->op.right == old_child)
757 ptr = &parent->op.right;
758 else if (parent->op.left == old_child)
759 ptr = &parent->op.left;
760 else
761 die("Error in reparent op");
762 *ptr = arg;
763
764 free_arg(old_child);
765}
766
767enum filter_vals test_arg(struct filter_arg *parent, struct filter_arg *arg)
768{
769 enum filter_vals lval, rval;
770
771 switch (arg->type) {
772
773 /* bad case */
774 case FILTER_ARG_BOOLEAN:
775 return FILTER_VAL_FALSE + arg->bool.value;
776
777 /* good cases: */
778 case FILTER_ARG_STR:
779 case FILTER_ARG_VALUE:
780 case FILTER_ARG_FIELD:
781 return FILTER_VAL_NORM;
782
783 case FILTER_ARG_EXP:
784 lval = test_arg(arg, arg->exp.left);
785 if (lval != FILTER_VAL_NORM)
786 return lval;
787 rval = test_arg(arg, arg->exp.right);
788 if (rval != FILTER_VAL_NORM)
789 return rval;
790 return FILTER_VAL_NORM;
791
792 case FILTER_ARG_NUM:
793 lval = test_arg(arg, arg->num.left);
794 if (lval != FILTER_VAL_NORM)
795 return lval;
796 rval = test_arg(arg, arg->num.right);
797 if (rval != FILTER_VAL_NORM)
798 return rval;
799 return FILTER_VAL_NORM;
800
801 case FILTER_ARG_OP:
802 if (arg->op.type != FILTER_OP_NOT) {
803 lval = test_arg(arg, arg->op.left);
804 switch (lval) {
805 case FILTER_VAL_NORM:
806 break;
807 case FILTER_VAL_TRUE:
808 if (arg->op.type == FILTER_OP_OR)
809 return FILTER_VAL_TRUE;
810 rval = test_arg(arg, arg->op.right);
811 if (rval != FILTER_VAL_NORM)
812 return rval;
813
814 reparent_op_arg(parent, arg, arg->op.right);
815 return FILTER_VAL_NORM;
816
817 case FILTER_VAL_FALSE:
818 if (arg->op.type == FILTER_OP_AND)
819 return FILTER_VAL_FALSE;
820 rval = test_arg(arg, arg->op.right);
821 if (rval != FILTER_VAL_NORM)
822 return rval;
823
824 reparent_op_arg(parent, arg, arg->op.right);
825 return FILTER_VAL_NORM;
826 }
827 }
828
829 rval = test_arg(arg, arg->op.right);
830 switch (rval) {
831 case FILTER_VAL_NORM:
832 break;
833 case FILTER_VAL_TRUE:
834 if (arg->op.type == FILTER_OP_OR)
835 return FILTER_VAL_TRUE;
836 if (arg->op.type == FILTER_OP_NOT)
837 return FILTER_VAL_FALSE;
838
839 reparent_op_arg(parent, arg, arg->op.left);
840 return FILTER_VAL_NORM;
841
842 case FILTER_VAL_FALSE:
843 if (arg->op.type == FILTER_OP_AND)
844 return FILTER_VAL_FALSE;
845 if (arg->op.type == FILTER_OP_NOT)
846 return FILTER_VAL_TRUE;
847
848 reparent_op_arg(parent, arg, arg->op.left);
849 return FILTER_VAL_NORM;
850 }
851
852 return FILTER_VAL_NORM;
853 default:
854 die("bad arg in filter tree");
855 }
856 return FILTER_VAL_NORM;
857}
858
859/* Remove any unknown event fields */
860static struct filter_arg *collapse_tree(struct filter_arg *arg)
861{
862 enum filter_vals ret;
863
864 ret = test_arg(arg, arg);
865 switch (ret) {
866 case FILTER_VAL_NORM:
867 return arg;
868
869 case FILTER_VAL_TRUE:
870 case FILTER_VAL_FALSE:
871 free_arg(arg);
872 arg = allocate_arg();
873 arg->type = FILTER_ARG_BOOLEAN;
874 arg->bool.value = ret == FILTER_VAL_TRUE;
875 }
876
877 return arg;
878}
879
880static int
881process_filter(struct event_format *event, struct filter_arg **parg,
882 char **error_str, int not)
883{
884 enum event_type type;
885 char *token = NULL;
886 struct filter_arg *current_op = NULL;
887 struct filter_arg *current_exp = NULL;
888 struct filter_arg *left_item = NULL;
889 struct filter_arg *arg = NULL;
890 enum op_type op_type;
891 enum filter_op_type btype;
892 enum filter_exp_type etype;
893 enum filter_cmp_type ctype;
894 int ret;
895
896 *parg = NULL;
897
898 do {
899 free(token);
900 type = read_token(&token);
901 switch (type) {
902 case EVENT_SQUOTE:
903 case EVENT_DQUOTE:
904 case EVENT_ITEM:
905 arg = create_arg_item(event, token, type, error_str);
906 if (!arg)
907 goto fail;
908 if (!left_item)
909 left_item = arg;
910 else if (current_exp) {
911 ret = add_right(current_exp, arg, error_str);
912 if (ret < 0)
913 goto fail;
914 left_item = NULL;
915 /* Not's only one one expression */
916 if (not) {
917 arg = NULL;
918 if (current_op)
919 goto fail_print;
920 free(token);
921 *parg = current_exp;
922 return 0;
923 }
924 } else
925 goto fail_print;
926 arg = NULL;
927 break;
928
929 case EVENT_DELIM:
930 if (*token == ',') {
931 show_error(error_str,
932 "Illegal token ','");
933 goto fail;
934 }
935
936 if (*token == '(') {
937 if (left_item) {
938 show_error(error_str,
939 "Open paren can not come after item");
940 goto fail;
941 }
942 if (current_exp) {
943 show_error(error_str,
944 "Open paren can not come after expression");
945 goto fail;
946 }
947
948 ret = process_filter(event, &arg, error_str, 0);
949 if (ret != 1) {
950 if (ret == 0)
951 show_error(error_str,
952 "Unbalanced number of '('");
953 goto fail;
954 }
955 ret = 0;
956
957 /* A not wants just one expression */
958 if (not) {
959 if (current_op)
960 goto fail_print;
961 *parg = arg;
962 return 0;
963 }
964
965 if (current_op)
966 ret = add_right(current_op, arg, error_str);
967 else
968 current_exp = arg;
969
970 if (ret < 0)
971 goto fail;
972
973 } else { /* ')' */
974 if (!current_op && !current_exp)
975 goto fail_print;
976
977 /* Make sure everything is finished at this level */
978 if (current_exp && !check_op_done(current_exp))
979 goto fail_print;
980 if (current_op && !check_op_done(current_op))
981 goto fail_print;
982
983 if (current_op)
984 *parg = current_op;
985 else
986 *parg = current_exp;
987 return 1;
988 }
989 break;
990
991 case EVENT_OP:
992 op_type = process_op(token, &btype, &ctype, &etype);
993
994 /* All expect a left arg except for NOT */
995 switch (op_type) {
996 case OP_BOOL:
997 /* Logic ops need a left expression */
998 if (!current_exp && !current_op)
999 goto fail_print;
1000 /* fall through */
1001 case OP_NOT:
1002 /* logic only processes ops and exp */
1003 if (left_item)
1004 goto fail_print;
1005 break;
1006 case OP_EXP:
1007 case OP_CMP:
1008 if (!left_item)
1009 goto fail_print;
1010 break;
1011 case OP_NONE:
1012 show_error(error_str,
1013 "Unknown op token %s", token);
1014 goto fail;
1015 }
1016
1017 ret = 0;
1018 switch (op_type) {
1019 case OP_BOOL:
1020 arg = create_arg_op(btype);
1021 if (current_op)
1022 ret = add_left(arg, current_op);
1023 else
1024 ret = add_left(arg, current_exp);
1025 current_op = arg;
1026 current_exp = NULL;
1027 break;
1028
1029 case OP_NOT:
1030 arg = create_arg_op(btype);
1031 if (current_op)
1032 ret = add_right(current_op, arg, error_str);
1033 if (ret < 0)
1034 goto fail;
1035 current_exp = arg;
1036 ret = process_filter(event, &arg, error_str, 1);
1037 if (ret < 0)
1038 goto fail;
1039 ret = add_right(current_exp, arg, error_str);
1040 if (ret < 0)
1041 goto fail;
1042 break;
1043
1044 case OP_EXP:
1045 case OP_CMP:
1046 if (op_type == OP_EXP)
1047 arg = create_arg_exp(etype);
1048 else
1049 arg = create_arg_cmp(ctype);
1050
1051 if (current_op)
1052 ret = add_right(current_op, arg, error_str);
1053 if (ret < 0)
1054 goto fail;
1055 ret = add_left(arg, left_item);
1056 if (ret < 0) {
1057 arg = NULL;
1058 goto fail_print;
1059 }
1060 current_exp = arg;
1061 break;
1062 default:
1063 break;
1064 }
1065 arg = NULL;
1066 if (ret < 0)
1067 goto fail_print;
1068 break;
1069 case EVENT_NONE:
1070 break;
1071 default:
1072 goto fail_print;
1073 }
1074 } while (type != EVENT_NONE);
1075
1076 if (!current_op && !current_exp)
1077 goto fail_print;
1078
1079 if (!current_op)
1080 current_op = current_exp;
1081
1082 current_op = collapse_tree(current_op);
1083
1084 *parg = current_op;
1085
1086 return 0;
1087
1088 fail_print:
1089 show_error(error_str, "Syntax error");
1090 fail:
1091 free_arg(current_op);
1092 free_arg(current_exp);
1093 free_arg(arg);
1094 free(token);
1095 return -1;
1096}
1097
1098static int
1099process_event(struct event_format *event, const char *filter_str,
1100 struct filter_arg **parg, char **error_str)
1101{
1102 int ret;
1103
1104 pevent_buffer_init(filter_str, strlen(filter_str));
1105
1106 ret = process_filter(event, parg, error_str, 0);
1107 if (ret == 1) {
1108 show_error(error_str,
1109 "Unbalanced number of ')'");
1110 return -1;
1111 }
1112 if (ret < 0)
1113 return ret;
1114
1115 /* If parg is NULL, then make it into FALSE */
1116 if (!*parg) {
1117 *parg = allocate_arg();
1118 (*parg)->type = FILTER_ARG_BOOLEAN;
1119 (*parg)->bool.value = FILTER_FALSE;
1120 }
1121
1122 return 0;
1123}
1124
1125static int filter_event(struct event_filter *filter,
1126 struct event_format *event,
1127 const char *filter_str, char **error_str)
1128{
1129 struct filter_type *filter_type;
1130 struct filter_arg *arg;
1131 int ret;
1132
1133 if (filter_str) {
1134 ret = process_event(event, filter_str, &arg, error_str);
1135 if (ret < 0)
1136 return ret;
1137
1138 } else {
1139 /* just add a TRUE arg */
1140 arg = allocate_arg();
1141 arg->type = FILTER_ARG_BOOLEAN;
1142 arg->bool.value = FILTER_TRUE;
1143 }
1144
1145 filter_type = add_filter_type(filter, event->id);
1146 if (filter_type->filter)
1147 free_arg(filter_type->filter);
1148 filter_type->filter = arg;
1149
1150 return 0;
1151}
1152
1153/**
1154 * pevent_filter_add_filter_str - add a new filter
1155 * @filter: the event filter to add to
1156 * @filter_str: the filter string that contains the filter
1157 * @error_str: string containing reason for failed filter
1158 *
1159 * Returns 0 if the filter was successfully added
1160 * -1 if there was an error.
1161 *
1162 * On error, if @error_str points to a string pointer,
1163 * it is set to the reason that the filter failed.
1164 * This string must be freed with "free".
1165 */
1166int pevent_filter_add_filter_str(struct event_filter *filter,
1167 const char *filter_str,
1168 char **error_str)
1169{
1170 struct pevent *pevent = filter->pevent;
1171 struct event_list *event;
1172 struct event_list *events = NULL;
1173 const char *filter_start;
1174 const char *next_event;
1175 char *this_event;
1176 char *event_name = NULL;
1177 char *sys_name = NULL;
1178 char *sp;
1179 int rtn = 0;
1180 int len;
1181 int ret;
1182
1183 /* clear buffer to reset show error */
1184 pevent_buffer_init("", 0);
1185
1186 if (error_str)
1187 *error_str = NULL;
1188
1189 filter_start = strchr(filter_str, ':');
1190 if (filter_start)
1191 len = filter_start - filter_str;
1192 else
1193 len = strlen(filter_str);
1194
1195
1196 do {
1197 next_event = strchr(filter_str, ',');
1198 if (next_event &&
1199 (!filter_start || next_event < filter_start))
1200 len = next_event - filter_str;
1201 else if (filter_start)
1202 len = filter_start - filter_str;
1203 else
1204 len = strlen(filter_str);
1205
1206 this_event = malloc_or_die(len + 1);
1207 memcpy(this_event, filter_str, len);
1208 this_event[len] = 0;
1209
1210 if (next_event)
1211 next_event++;
1212
1213 filter_str = next_event;
1214
1215 sys_name = strtok_r(this_event, "/", &sp);
1216 event_name = strtok_r(NULL, "/", &sp);
1217
1218 if (!sys_name) {
1219 show_error(error_str, "No filter found");
1220 /* This can only happen when events is NULL, but still */
1221 free_events(events);
1222 free(this_event);
1223 return -1;
1224 }
1225
1226 /* Find this event */
1227 ret = find_event(pevent, &events, strim(sys_name), strim(event_name));
1228 if (ret < 0) {
1229 if (event_name)
1230 show_error(error_str,
1231 "No event found under '%s.%s'",
1232 sys_name, event_name);
1233 else
1234 show_error(error_str,
1235 "No event found under '%s'",
1236 sys_name);
1237 free_events(events);
1238 free(this_event);
1239 return -1;
1240 }
1241 free(this_event);
1242 } while (filter_str);
1243
1244 /* Skip the ':' */
1245 if (filter_start)
1246 filter_start++;
1247
1248 /* filter starts here */
1249 for (event = events; event; event = event->next) {
1250 ret = filter_event(filter, event->event, filter_start,
1251 error_str);
1252 /* Failures are returned if a parse error happened */
1253 if (ret < 0)
1254 rtn = ret;
1255
1256 if (ret >= 0 && pevent->test_filters) {
1257 char *test;
1258 test = pevent_filter_make_string(filter, event->event->id);
1259 printf(" '%s: %s'\n", event->event->name, test);
1260 free(test);
1261 }
1262 }
1263
1264 free_events(events);
1265
1266 if (rtn >= 0 && pevent->test_filters)
1267 exit(0);
1268
1269 return rtn;
1270}
1271
1272static void free_filter_type(struct filter_type *filter_type)
1273{
1274 free_arg(filter_type->filter);
1275}
1276
1277/**
1278 * pevent_filter_remove_event - remove a filter for an event
1279 * @filter: the event filter to remove from
1280 * @event_id: the event to remove a filter for
1281 *
1282 * Removes the filter saved for an event defined by @event_id
1283 * from the @filter.
1284 *
1285 * Returns 1: if an event was removed
1286 * 0: if the event was not found
1287 */
1288int pevent_filter_remove_event(struct event_filter *filter,
1289 int event_id)
1290{
1291 struct filter_type *filter_type;
1292 unsigned long len;
1293
1294 if (!filter->filters)
1295 return 0;
1296
1297 filter_type = find_filter_type(filter, event_id);
1298
1299 if (!filter_type)
1300 return 0;
1301
1302 free_filter_type(filter_type);
1303
1304 /* The filter_type points into the event_filters array */
1305 len = (unsigned long)(filter->event_filters + filter->filters) -
1306 (unsigned long)(filter_type + 1);
1307
1308 memmove(filter_type, filter_type + 1, len);
1309 filter->filters--;
1310
1311 memset(&filter->event_filters[filter->filters], 0,
1312 sizeof(*filter_type));
1313
1314 return 1;
1315}
1316
1317/**
1318 * pevent_filter_reset - clear all filters in a filter
1319 * @filter: the event filter to reset
1320 *
1321 * Removes all filters from a filter and resets it.
1322 */
1323void pevent_filter_reset(struct event_filter *filter)
1324{
1325 int i;
1326
1327 for (i = 0; i < filter->filters; i++)
1328 free_filter_type(&filter->event_filters[i]);
1329
1330 free(filter->event_filters);
1331 filter->filters = 0;
1332 filter->event_filters = NULL;
1333}
1334
1335void pevent_filter_free(struct event_filter *filter)
1336{
1337 pevent_unref(filter->pevent);
1338
1339 pevent_filter_reset(filter);
1340
1341 free(filter);
1342}
1343
1344static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg);
1345
1346static int copy_filter_type(struct event_filter *filter,
1347 struct event_filter *source,
1348 struct filter_type *filter_type)
1349{
1350 struct filter_arg *arg;
1351 struct event_format *event;
1352 const char *sys;
1353 const char *name;
1354 char *str;
1355
1356 /* Can't assume that the pevent's are the same */
1357 sys = filter_type->event->system;
1358 name = filter_type->event->name;
1359 event = pevent_find_event_by_name(filter->pevent, sys, name);
1360 if (!event)
1361 return -1;
1362
1363 str = arg_to_str(source, filter_type->filter);
1364 if (!str)
1365 return -1;
1366
1367 if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) {
1368 /* Add trivial event */
1369 arg = allocate_arg();
1370 arg->type = FILTER_ARG_BOOLEAN;
1371 if (strcmp(str, "TRUE") == 0)
1372 arg->bool.value = 1;
1373 else
1374 arg->bool.value = 0;
1375
1376 filter_type = add_filter_type(filter, event->id);
1377 filter_type->filter = arg;
1378
1379 free(str);
1380 return 0;
1381 }
1382
1383 filter_event(filter, event, str, NULL);
1384 free(str);
1385
1386 return 0;
1387}
1388
1389/**
1390 * pevent_filter_copy - copy a filter using another filter
1391 * @dest - the filter to copy to
1392 * @source - the filter to copy from
1393 *
1394 * Returns 0 on success and -1 if not all filters were copied
1395 */
1396int pevent_filter_copy(struct event_filter *dest, struct event_filter *source)
1397{
1398 int ret = 0;
1399 int i;
1400
1401 pevent_filter_reset(dest);
1402
1403 for (i = 0; i < source->filters; i++) {
1404 if (copy_filter_type(dest, source, &source->event_filters[i]))
1405 ret = -1;
1406 }
1407 return ret;
1408}
1409
1410
1411/**
1412 * pevent_update_trivial - update the trivial filters with the given filter
1413 * @dest - the filter to update
1414 * @source - the filter as the source of the update
1415 * @type - the type of trivial filter to update.
1416 *
1417 * Scan dest for trivial events matching @type to replace with the source.
1418 *
1419 * Returns 0 on success and -1 if there was a problem updating, but
1420 * events may have still been updated on error.
1421 */
1422int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
1423 enum filter_trivial_type type)
1424{
1425 struct pevent *src_pevent;
1426 struct pevent *dest_pevent;
1427 struct event_format *event;
1428 struct filter_type *filter_type;
1429 struct filter_arg *arg;
1430 char *str;
1431 int i;
1432
1433 src_pevent = source->pevent;
1434 dest_pevent = dest->pevent;
1435
1436 /* Do nothing if either of the filters has nothing to filter */
1437 if (!dest->filters || !source->filters)
1438 return 0;
1439
1440 for (i = 0; i < dest->filters; i++) {
1441 filter_type = &dest->event_filters[i];
1442 arg = filter_type->filter;
1443 if (arg->type != FILTER_ARG_BOOLEAN)
1444 continue;
1445 if ((arg->bool.value && type == FILTER_TRIVIAL_FALSE) ||
1446 (!arg->bool.value && type == FILTER_TRIVIAL_TRUE))
1447 continue;
1448
1449 event = filter_type->event;
1450
1451 if (src_pevent != dest_pevent) {
1452 /* do a look up */
1453 event = pevent_find_event_by_name(src_pevent,
1454 event->system,
1455 event->name);
1456 if (!event)
1457 return -1;
1458 }
1459
1460 str = pevent_filter_make_string(source, event->id);
1461 if (!str)
1462 continue;
1463
1464 /* Don't bother if the filter is trivial too */
1465 if (strcmp(str, "TRUE") != 0 && strcmp(str, "FALSE") != 0)
1466 filter_event(dest, event, str, NULL);
1467 free(str);
1468 }
1469 return 0;
1470}
1471
1472/**
1473 * pevent_filter_clear_trivial - clear TRUE and FALSE filters
1474 * @filter: the filter to remove trivial filters from
1475 * @type: remove only true, false, or both
1476 *
1477 * Removes filters that only contain a TRUE or FALES boolean arg.
1478 */
1479void pevent_filter_clear_trivial(struct event_filter *filter,
1480 enum filter_trivial_type type)
1481{
1482 struct filter_type *filter_type;
1483 int count = 0;
1484 int *ids;
1485 int i;
1486
1487 if (!filter->filters)
1488 return;
1489
1490 /*
1491 * Two steps, first get all ids with trivial filters.
1492 * then remove those ids.
1493 */
1494 for (i = 0; i < filter->filters; i++) {
1495 filter_type = &filter->event_filters[i];
1496 if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
1497 continue;
1498 switch (type) {
1499 case FILTER_TRIVIAL_FALSE:
1500 if (filter_type->filter->bool.value)
1501 continue;
1502 case FILTER_TRIVIAL_TRUE:
1503 if (!filter_type->filter->bool.value)
1504 continue;
1505 default:
1506 break;
1507 }
1508 if (count)
1509 ids = realloc(ids, sizeof(*ids) * (count + 1));
1510 else
1511 ids = malloc(sizeof(*ids));
1512 if (!ids)
1513 die("Can't allocate ids");
1514 ids[count++] = filter_type->event_id;
1515 }
1516
1517 if (!count)
1518 return;
1519
1520 for (i = 0; i < count; i++)
1521 pevent_filter_remove_event(filter, ids[i]);
1522
1523 free(ids);
1524}
1525
1526/**
1527 * pevent_filter_event_has_trivial - return true event contains trivial filter
1528 * @filter: the filter with the information
1529 * @event_id: the id of the event to test
1530 * @type: trivial type to test for (TRUE, FALSE, EITHER)
1531 *
1532 * Returns 1 if the event contains a matching trivial type
1533 * otherwise 0.
1534 */
1535int pevent_filter_event_has_trivial(struct event_filter *filter,
1536 int event_id,
1537 enum filter_trivial_type type)
1538{
1539 struct filter_type *filter_type;
1540
1541 if (!filter->filters)
1542 return 0;
1543
1544 filter_type = find_filter_type(filter, event_id);
1545
1546 if (!filter_type)
1547 return 0;
1548
1549 if (filter_type->filter->type != FILTER_ARG_BOOLEAN)
1550 return 0;
1551
1552 switch (type) {
1553 case FILTER_TRIVIAL_FALSE:
1554 return !filter_type->filter->bool.value;
1555
1556 case FILTER_TRIVIAL_TRUE:
1557 return filter_type->filter->bool.value;
1558 default:
1559 return 1;
1560 }
1561}
1562
1563static int test_filter(struct event_format *event,
1564 struct filter_arg *arg, struct record *record);
1565
1566static const char *
1567get_comm(struct event_format *event, struct record *record)
1568{
1569 const char *comm;
1570 int pid;
1571
1572 pid = pevent_data_pid(event->pevent, record);
1573 comm = pevent_data_comm_from_pid(event->pevent, pid);
1574 return comm;
1575}
1576
1577static unsigned long long
1578get_value(struct event_format *event,
1579 struct format_field *field, struct record *record)
1580{
1581 unsigned long long val;
1582
1583 /* Handle our dummy "comm" field */
1584 if (field == &comm) {
1585 const char *name;
1586
1587 name = get_comm(event, record);
1588 return (unsigned long long)name;
1589 }
1590
1591 pevent_read_number_field(field, record->data, &val);
1592
1593 if (!(field->flags & FIELD_IS_SIGNED))
1594 return val;
1595
1596 switch (field->size) {
1597 case 1:
1598 return (char)val;
1599 case 2:
1600 return (short)val;
1601 case 4:
1602 return (int)val;
1603 case 8:
1604 return (long long)val;
1605 }
1606 return val;
1607}
1608
1609static unsigned long long
1610get_arg_value(struct event_format *event, struct filter_arg *arg, struct record *record);
1611
1612static unsigned long long
1613get_exp_value(struct event_format *event, struct filter_arg *arg, struct record *record)
1614{
1615 unsigned long long lval, rval;
1616
1617 lval = get_arg_value(event, arg->exp.left, record);
1618 rval = get_arg_value(event, arg->exp.right, record);
1619
1620 switch (arg->exp.type) {
1621 case FILTER_EXP_ADD:
1622 return lval + rval;
1623
1624 case FILTER_EXP_SUB:
1625 return lval - rval;
1626
1627 case FILTER_EXP_MUL:
1628 return lval * rval;
1629
1630 case FILTER_EXP_DIV:
1631 return lval / rval;
1632
1633 case FILTER_EXP_MOD:
1634 return lval % rval;
1635
1636 case FILTER_EXP_RSHIFT:
1637 return lval >> rval;
1638
1639 case FILTER_EXP_LSHIFT:
1640 return lval << rval;
1641
1642 case FILTER_EXP_AND:
1643 return lval & rval;
1644
1645 case FILTER_EXP_OR:
1646 return lval | rval;
1647
1648 case FILTER_EXP_XOR:
1649 return lval ^ rval;
1650
1651 case FILTER_EXP_NOT:
1652 default:
1653 die("error in exp");
1654 }
1655 return 0;
1656}
1657
1658static unsigned long long
1659get_arg_value(struct event_format *event, struct filter_arg *arg, struct record *record)
1660{
1661 switch (arg->type) {
1662 case FILTER_ARG_FIELD:
1663 return get_value(event, arg->field.field, record);
1664
1665 case FILTER_ARG_VALUE:
1666 if (arg->value.type != FILTER_NUMBER)
1667 die("must have number field!");
1668 return arg->value.val;
1669
1670 case FILTER_ARG_EXP:
1671 return get_exp_value(event, arg, record);
1672
1673 default:
1674 die("oops in filter");
1675 }
1676 return 0;
1677}
1678
1679static int test_num(struct event_format *event,
1680 struct filter_arg *arg, struct record *record)
1681{
1682 unsigned long long lval, rval;
1683
1684 lval = get_arg_value(event, arg->num.left, record);
1685 rval = get_arg_value(event, arg->num.right, record);
1686
1687 switch (arg->num.type) {
1688 case FILTER_CMP_EQ:
1689 return lval == rval;
1690
1691 case FILTER_CMP_NE:
1692 return lval != rval;
1693
1694 case FILTER_CMP_GT:
1695 return lval > rval;
1696
1697 case FILTER_CMP_LT:
1698 return lval < rval;
1699
1700 case FILTER_CMP_GE:
1701 return lval >= rval;
1702
1703 case FILTER_CMP_LE:
1704 return lval <= rval;
1705
1706 default:
1707 /* ?? */
1708 return 0;
1709 }
1710}
1711
1712static const char *get_field_str(struct filter_arg *arg, struct record *record)
1713{
1714 const char *val = record->data + arg->str.field->offset;
1715
1716 /*
1717 * We need to copy the data since we can't be sure the field
1718 * is null terminated.
1719 */
1720 if (*(val + arg->str.field->size - 1)) {
1721 /* copy it */
1722 memcpy(arg->str.buffer, val, arg->str.field->size);
1723 /* the buffer is already NULL terminated */
1724 val = arg->str.buffer;
1725 }
1726 return val;
1727}
1728
1729static int test_str(struct event_format *event,
1730 struct filter_arg *arg, struct record *record)
1731{
1732 const char *val;
1733
1734 if (arg->str.field == &comm)
1735 val = get_comm(event, record);
1736 else
1737 val = get_field_str(arg, record);
1738
1739 switch (arg->str.type) {
1740 case FILTER_CMP_MATCH:
1741 return strcmp(val, arg->str.val) == 0;
1742
1743 case FILTER_CMP_NOT_MATCH:
1744 return strcmp(val, arg->str.val) != 0;
1745
1746 case FILTER_CMP_REGEX:
1747 /* Returns zero on match */
1748 return !regexec(&arg->str.reg, val, 0, NULL, 0);
1749
1750 case FILTER_CMP_NOT_REGEX:
1751 return regexec(&arg->str.reg, val, 0, NULL, 0);
1752
1753 default:
1754 /* ?? */
1755 return 0;
1756 }
1757}
1758
1759static int test_op(struct event_format *event,
1760 struct filter_arg *arg, struct record *record)
1761{
1762 switch (arg->op.type) {
1763 case FILTER_OP_AND:
1764 return test_filter(event, arg->op.left, record) &&
1765 test_filter(event, arg->op.right, record);
1766
1767 case FILTER_OP_OR:
1768 return test_filter(event, arg->op.left, record) ||
1769 test_filter(event, arg->op.right, record);
1770
1771 case FILTER_OP_NOT:
1772 return !test_filter(event, arg->op.right, record);
1773
1774 default:
1775 /* ?? */
1776 return 0;
1777 }
1778}
1779
1780static int test_filter(struct event_format *event,
1781 struct filter_arg *arg, struct record *record)
1782{
1783 switch (arg->type) {
1784 case FILTER_ARG_BOOLEAN:
1785 /* easy case */
1786 return arg->bool.value;
1787
1788 case FILTER_ARG_OP:
1789 return test_op(event, arg, record);
1790
1791 case FILTER_ARG_NUM:
1792 return test_num(event, arg, record);
1793
1794 case FILTER_ARG_STR:
1795 return test_str(event, arg, record);
1796
1797 case FILTER_ARG_EXP:
1798 case FILTER_ARG_VALUE:
1799 case FILTER_ARG_FIELD:
1800 /*
1801 * Expressions, fields and values evaluate
1802 * to true if they return non zero
1803 */
1804 return !!get_arg_value(event, arg, record);
1805
1806 default:
1807 die("oops!");
1808 /* ?? */
1809 return 0;
1810 }
1811}
1812
1813/**
1814 * pevent_event_filtered - return true if event has filter
1815 * @filter: filter struct with filter information
1816 * @event_id: event id to test if filter exists
1817 *
1818 * Returns 1 if filter found for @event_id
1819 * otherwise 0;
1820 */
1821int pevent_event_filtered(struct event_filter *filter,
1822 int event_id)
1823{
1824 struct filter_type *filter_type;
1825
1826 if (!filter->filters)
1827 return 0;
1828
1829 filter_type = find_filter_type(filter, event_id);
1830
1831 return filter_type ? 1 : 0;
1832}
1833
1834/**
1835 * pevent_filter_match - test if a record matches a filter
1836 * @filter: filter struct with filter information
1837 * @record: the record to test against the filter
1838 *
1839 * Returns:
1840 * 1 - filter found for event and @record matches
1841 * 0 - filter found for event and @record does not match
1842 * -1 - no filter found for @record's event
1843 * -2 - if no filters exist
1844 */
1845int pevent_filter_match(struct event_filter *filter,
1846 struct record *record)
1847{
1848 struct pevent *pevent = filter->pevent;
1849 struct filter_type *filter_type;
1850 int event_id;
1851
1852 if (!filter->filters)
1853 return FILTER_NONE;
1854
1855 event_id = pevent_data_type(pevent, record);
1856
1857 filter_type = find_filter_type(filter, event_id);
1858
1859 if (!filter_type)
1860 return FILTER_NOEXIST;
1861
1862 return test_filter(filter_type->event, filter_type->filter, record) ?
1863 FILTER_MATCH : FILTER_MISS;
1864}
1865
1866static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
1867{
1868 char *str = NULL;
1869 char *left = NULL;
1870 char *right = NULL;
1871 char *op = NULL;
1872 int left_val = -1;
1873 int right_val = -1;
1874 int val;
1875 int len;
1876
1877 switch (arg->op.type) {
1878 case FILTER_OP_AND:
1879 op = "&&";
1880 /* fall through */
1881 case FILTER_OP_OR:
1882 if (!op)
1883 op = "||";
1884
1885 left = arg_to_str(filter, arg->op.left);
1886 right = arg_to_str(filter, arg->op.right);
1887 if (!left || !right)
1888 break;
1889
1890 /* Try to consolidate boolean values */
1891 if (strcmp(left, "TRUE") == 0)
1892 left_val = 1;
1893 else if (strcmp(left, "FALSE") == 0)
1894 left_val = 0;
1895
1896 if (strcmp(right, "TRUE") == 0)
1897 right_val = 1;
1898 else if (strcmp(right, "FALSE") == 0)
1899 right_val = 0;
1900
1901 if (left_val >= 0) {
1902 if ((arg->op.type == FILTER_OP_AND && !left_val) ||
1903 (arg->op.type == FILTER_OP_OR && left_val)) {
1904 /* Just return left value */
1905 str = left;
1906 left = NULL;
1907 break;
1908 }
1909 if (right_val >= 0) {
1910 /* just evaluate this. */
1911 val = 0;
1912 switch (arg->op.type) {
1913 case FILTER_OP_AND:
1914 val = left_val && right_val;
1915 break;
1916 case FILTER_OP_OR:
1917 val = left_val || right_val;
1918 break;
1919 default:
1920 break;
1921 }
1922 str = malloc_or_die(6);
1923 if (val)
1924 strcpy(str, "TRUE");
1925 else
1926 strcpy(str, "FALSE");
1927 break;
1928 }
1929 }
1930 if (right_val >= 0) {
1931 if ((arg->op.type == FILTER_OP_AND && !right_val) ||
1932 (arg->op.type == FILTER_OP_OR && right_val)) {
1933 /* Just return right value */
1934 str = right;
1935 right = NULL;
1936 break;
1937 }
1938 /* The right value is meaningless */
1939 str = left;
1940 left = NULL;
1941 break;
1942 }
1943
1944 len = strlen(left) + strlen(right) + strlen(op) + 10;
1945 str = malloc_or_die(len);
1946 snprintf(str, len, "(%s) %s (%s)",
1947 left, op, right);
1948 break;
1949
1950 case FILTER_OP_NOT:
1951 op = "!";
1952 right = arg_to_str(filter, arg->op.right);
1953 if (!right)
1954 break;
1955
1956 /* See if we can consolidate */
1957 if (strcmp(right, "TRUE") == 0)
1958 right_val = 1;
1959 else if (strcmp(right, "FALSE") == 0)
1960 right_val = 0;
1961 if (right_val >= 0) {
1962 /* just return the opposite */
1963 str = malloc_or_die(6);
1964 if (right_val)
1965 strcpy(str, "FALSE");
1966 else
1967 strcpy(str, "TRUE");
1968 break;
1969 }
1970 len = strlen(right) + strlen(op) + 3;
1971 str = malloc_or_die(len);
1972 snprintf(str, len, "%s(%s)", op, right);
1973 break;
1974
1975 default:
1976 /* ?? */
1977 break;
1978 }
1979 free(left);
1980 free(right);
1981 return str;
1982}
1983
1984static char *val_to_str(struct event_filter *filter, struct filter_arg *arg)
1985{
1986 char *str;
1987
1988 str = malloc_or_die(30);
1989
1990 snprintf(str, 30, "%lld", arg->value.val);
1991
1992 return str;
1993}
1994
1995static char *field_to_str(struct event_filter *filter, struct filter_arg *arg)
1996{
1997 return strdup(arg->field.field->name);
1998}
1999
2000static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
2001{
2002 char *lstr;
2003 char *rstr;
2004 char *op;
2005 char *str;
2006 int len;
2007
2008 lstr = arg_to_str(filter, arg->exp.left);
2009 rstr = arg_to_str(filter, arg->exp.right);
2010
2011 switch (arg->exp.type) {
2012 case FILTER_EXP_ADD:
2013 op = "+";
2014 break;
2015 case FILTER_EXP_SUB:
2016 op = "-";
2017 break;
2018 case FILTER_EXP_MUL:
2019 op = "*";
2020 break;
2021 case FILTER_EXP_DIV:
2022 op = "/";
2023 break;
2024 case FILTER_EXP_MOD:
2025 op = "%";
2026 break;
2027 case FILTER_EXP_RSHIFT:
2028 op = ">>";
2029 break;
2030 case FILTER_EXP_LSHIFT:
2031 op = "<<";
2032 break;
2033 case FILTER_EXP_AND:
2034 op = "&";
2035 break;
2036 case FILTER_EXP_OR:
2037 op = "|";
2038 break;
2039 case FILTER_EXP_XOR:
2040 op = "^";
2041 break;
2042 default:
2043 die("oops in exp");
2044 }
2045
2046 len = strlen(op) + strlen(lstr) + strlen(rstr) + 4;
2047 str = malloc_or_die(len);
2048 snprintf(str, len, "%s %s %s", lstr, op, rstr);
2049 free(lstr);
2050 free(rstr);
2051
2052 return str;
2053}
2054
2055static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
2056{
2057 char *lstr;
2058 char *rstr;
2059 char *str = NULL;
2060 char *op = NULL;
2061 int len;
2062
2063 lstr = arg_to_str(filter, arg->num.left);
2064 rstr = arg_to_str(filter, arg->num.right);
2065
2066 switch (arg->num.type) {
2067 case FILTER_CMP_EQ:
2068 op = "==";
2069 /* fall through */
2070 case FILTER_CMP_NE:
2071 if (!op)
2072 op = "!=";
2073 /* fall through */
2074 case FILTER_CMP_GT:
2075 if (!op)
2076 op = ">";
2077 /* fall through */
2078 case FILTER_CMP_LT:
2079 if (!op)
2080 op = "<";
2081 /* fall through */
2082 case FILTER_CMP_GE:
2083 if (!op)
2084 op = ">=";
2085 /* fall through */
2086 case FILTER_CMP_LE:
2087 if (!op)
2088 op = "<=";
2089
2090 len = strlen(lstr) + strlen(op) + strlen(rstr) + 4;
2091 str = malloc_or_die(len);
2092 sprintf(str, "%s %s %s", lstr, op, rstr);
2093
2094 break;
2095
2096 default:
2097 /* ?? */
2098 break;
2099 }
2100
2101 free(lstr);
2102 free(rstr);
2103 return str;
2104}
2105
2106static char *str_to_str(struct event_filter *filter, struct filter_arg *arg)
2107{
2108 char *str = NULL;
2109 char *op = NULL;
2110 int len;
2111
2112 switch (arg->str.type) {
2113 case FILTER_CMP_MATCH:
2114 op = "==";
2115 /* fall through */
2116 case FILTER_CMP_NOT_MATCH:
2117 if (!op)
2118 op = "!=";
2119 /* fall through */
2120 case FILTER_CMP_REGEX:
2121 if (!op)
2122 op = "=~";
2123 /* fall through */
2124 case FILTER_CMP_NOT_REGEX:
2125 if (!op)
2126 op = "!~";
2127
2128 len = strlen(arg->str.field->name) + strlen(op) +
2129 strlen(arg->str.val) + 6;
2130 str = malloc_or_die(len);
2131 snprintf(str, len, "%s %s \"%s\"",
2132 arg->str.field->name,
2133 op, arg->str.val);
2134 break;
2135
2136 default:
2137 /* ?? */
2138 break;
2139 }
2140 return str;
2141}
2142
2143static char *arg_to_str(struct event_filter *filter, struct filter_arg *arg)
2144{
2145 char *str;
2146
2147 switch (arg->type) {
2148 case FILTER_ARG_BOOLEAN:
2149 str = malloc_or_die(6);
2150 if (arg->bool.value)
2151 strcpy(str, "TRUE");
2152 else
2153 strcpy(str, "FALSE");
2154 return str;
2155
2156 case FILTER_ARG_OP:
2157 return op_to_str(filter, arg);
2158
2159 case FILTER_ARG_NUM:
2160 return num_to_str(filter, arg);
2161
2162 case FILTER_ARG_STR:
2163 return str_to_str(filter, arg);
2164
2165 case FILTER_ARG_VALUE:
2166 return val_to_str(filter, arg);
2167
2168 case FILTER_ARG_FIELD:
2169 return field_to_str(filter, arg);
2170
2171 case FILTER_ARG_EXP:
2172 return exp_to_str(filter, arg);
2173
2174 default:
2175 /* ?? */
2176 return NULL;
2177 }
2178
2179}
2180
2181/**
2182 * pevent_filter_make_string - return a string showing the filter
2183 * @filter: filter struct with filter information
2184 * @event_id: the event id to return the filter string with
2185 *
2186 * Returns a string that displays the filter contents.
2187 * This string must be freed with free(str).
2188 * NULL is returned if no filter is found.
2189 */
2190char *
2191pevent_filter_make_string(struct event_filter *filter, int event_id)
2192{
2193 struct filter_type *filter_type;
2194
2195 if (!filter->filters)
2196 return NULL;
2197
2198 filter_type = find_filter_type(filter, event_id);
2199
2200 if (!filter_type)
2201 return NULL;
2202
2203 return arg_to_str(filter, filter_type->filter);
2204}
2205
2206/**
2207 * pevent_filter_compare - compare two filters and return if they are the same
2208 * @filter1: Filter to compare with @filter2
2209 * @filter2: Filter to compare with @filter1
2210 *
2211 * Returns:
2212 * 1 if the two filters hold the same content.
2213 * 0 if they do not.
2214 */
2215int pevent_filter_compare(struct event_filter *filter1, struct event_filter *filter2)
2216{
2217 struct filter_type *filter_type1;
2218 struct filter_type *filter_type2;
2219 char *str1, *str2;
2220 int result;
2221 int i;
2222
2223 /* Do the easy checks first */
2224 if (filter1->filters != filter2->filters)
2225 return 0;
2226 if (!filter1->filters && !filter2->filters)
2227 return 1;
2228
2229 /*
2230 * Now take a look at each of the events to see if they have the same
2231 * filters to them.
2232 */
2233 for (i = 0; i < filter1->filters; i++) {
2234 filter_type1 = &filter1->event_filters[i];
2235 filter_type2 = find_filter_type(filter2, filter_type1->event_id);
2236 if (!filter_type2)
2237 break;
2238 if (filter_type1->filter->type != filter_type2->filter->type)
2239 break;
2240 switch (filter_type1->filter->type) {
2241 case FILTER_TRIVIAL_FALSE:
2242 case FILTER_TRIVIAL_TRUE:
2243 /* trivial types just need the type compared */
2244 continue;
2245 default:
2246 break;
2247 }
2248 /* The best way to compare complex filters is with strings */
2249 str1 = arg_to_str(filter1, filter_type1->filter);
2250 str2 = arg_to_str(filter2, filter_type2->filter);
2251 result = strcmp(str1, str2) != 0;
2252 free(str1);
2253 free(str2);
2254 if (result)
2255 break;
2256 }
2257
2258 if (i < filter1->filters)
2259 return 0;
2260 return 1;
2261}
2262
diff --git a/tools/lib/traceevent/parse-utils.c b/tools/lib/traceevent/parse-utils.c
new file mode 100644
index 00000000000..f023a133abb
--- /dev/null
+++ b/tools/lib/traceevent/parse-utils.c
@@ -0,0 +1,110 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <stdarg.h>
5#include <errno.h>
6
7#define __weak __attribute__((weak))
8
9void __vdie(const char *fmt, va_list ap)
10{
11 int ret = errno;
12
13 if (errno)
14 perror("trace-cmd");
15 else
16 ret = -1;
17
18 fprintf(stderr, " ");
19 vfprintf(stderr, fmt, ap);
20
21 fprintf(stderr, "\n");
22 exit(ret);
23}
24
25void __die(const char *fmt, ...)
26{
27 va_list ap;
28
29 va_start(ap, fmt);
30 __vdie(fmt, ap);
31 va_end(ap);
32}
33
34void __weak die(const char *fmt, ...)
35{
36 va_list ap;
37
38 va_start(ap, fmt);
39 __vdie(fmt, ap);
40 va_end(ap);
41}
42
43void __vwarning(const char *fmt, va_list ap)
44{
45 if (errno)
46 perror("trace-cmd");
47 errno = 0;
48
49 fprintf(stderr, " ");
50 vfprintf(stderr, fmt, ap);
51
52 fprintf(stderr, "\n");
53}
54
55void __warning(const char *fmt, ...)
56{
57 va_list ap;
58
59 va_start(ap, fmt);
60 __vwarning(fmt, ap);
61 va_end(ap);
62}
63
64void __weak warning(const char *fmt, ...)
65{
66 va_list ap;
67
68 va_start(ap, fmt);
69 __vwarning(fmt, ap);
70 va_end(ap);
71}
72
73void __vpr_stat(const char *fmt, va_list ap)
74{
75 vprintf(fmt, ap);
76 printf("\n");
77}
78
79void __pr_stat(const char *fmt, ...)
80{
81 va_list ap;
82
83 va_start(ap, fmt);
84 __vpr_stat(fmt, ap);
85 va_end(ap);
86}
87
88void __weak vpr_stat(const char *fmt, va_list ap)
89{
90 __vpr_stat(fmt, ap);
91}
92
93void __weak pr_stat(const char *fmt, ...)
94{
95 va_list ap;
96
97 va_start(ap, fmt);
98 __vpr_stat(fmt, ap);
99 va_end(ap);
100}
101
102void __weak *malloc_or_die(unsigned int size)
103{
104 void *data;
105
106 data = malloc(size);
107 if (!data)
108 die("malloc");
109 return data;
110}
diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c
new file mode 100644
index 00000000000..d2f265b48cd
--- /dev/null
+++ b/tools/lib/traceevent/trace-seq.c
@@ -0,0 +1,199 @@
1/*
2 * Copyright (C) 2009 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation;
8 * version 2.1 of the License (not later!)
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <stdarg.h>
25
26#include "event-parse.h"
27
28/*
29 * The TRACE_SEQ_POISON is to catch the use of using
30 * a trace_seq structure after it was destroyed.
31 */
32#define TRACE_SEQ_POISON ((void *)0xdeadbeef)
33#define TRACE_SEQ_CHECK(s) \
34do { \
35 if ((s)->buffer == TRACE_SEQ_POISON) \
36 die("Usage of trace_seq after it was destroyed"); \
37} while (0)
38
39/**
40 * trace_seq_init - initialize the trace_seq structure
41 * @s: a pointer to the trace_seq structure to initialize
42 */
43void trace_seq_init(struct trace_seq *s)
44{
45 s->len = 0;
46 s->readpos = 0;
47 s->buffer_size = TRACE_SEQ_BUF_SIZE;
48 s->buffer = malloc_or_die(s->buffer_size);
49}
50
51/**
52 * trace_seq_destroy - free up memory of a trace_seq
53 * @s: a pointer to the trace_seq to free the buffer
54 *
55 * Only frees the buffer, not the trace_seq struct itself.
56 */
57void trace_seq_destroy(struct trace_seq *s)
58{
59 if (!s)
60 return;
61 TRACE_SEQ_CHECK(s);
62 free(s->buffer);
63 s->buffer = TRACE_SEQ_POISON;
64}
65
66static void expand_buffer(struct trace_seq *s)
67{
68 s->buffer_size += TRACE_SEQ_BUF_SIZE;
69 s->buffer = realloc(s->buffer, s->buffer_size);
70 if (!s->buffer)
71 die("Can't allocate trace_seq buffer memory");
72}
73
74/**
75 * trace_seq_printf - sequence printing of trace information
76 * @s: trace sequence descriptor
77 * @fmt: printf format string
78 *
79 * It returns 0 if the trace oversizes the buffer's free
80 * space, 1 otherwise.
81 *
82 * The tracer may use either sequence operations or its own
83 * copy to user routines. To simplify formating of a trace
84 * trace_seq_printf is used to store strings into a special
85 * buffer (@s). Then the output may be either used by
86 * the sequencer or pulled into another buffer.
87 */
88int
89trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
90{
91 va_list ap;
92 int len;
93 int ret;
94
95 TRACE_SEQ_CHECK(s);
96
97 try_again:
98 len = (s->buffer_size - 1) - s->len;
99
100 va_start(ap, fmt);
101 ret = vsnprintf(s->buffer + s->len, len, fmt, ap);
102 va_end(ap);
103
104 if (ret >= len) {
105 expand_buffer(s);
106 goto try_again;
107 }
108
109 s->len += ret;
110
111 return 1;
112}
113
114/**
115 * trace_seq_vprintf - sequence printing of trace information
116 * @s: trace sequence descriptor
117 * @fmt: printf format string
118 *
119 * The tracer may use either sequence operations or its own
120 * copy to user routines. To simplify formating of a trace
121 * trace_seq_printf is used to store strings into a special
122 * buffer (@s). Then the output may be either used by
123 * the sequencer or pulled into another buffer.
124 */
125int
126trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
127{
128 int len;
129 int ret;
130
131 TRACE_SEQ_CHECK(s);
132
133 try_again:
134 len = (s->buffer_size - 1) - s->len;
135
136 ret = vsnprintf(s->buffer + s->len, len, fmt, args);
137
138 if (ret >= len) {
139 expand_buffer(s);
140 goto try_again;
141 }
142
143 s->len += ret;
144
145 return len;
146}
147
148/**
149 * trace_seq_puts - trace sequence printing of simple string
150 * @s: trace sequence descriptor
151 * @str: simple string to record
152 *
153 * The tracer may use either the sequence operations or its own
154 * copy to user routines. This function records a simple string
155 * into a special buffer (@s) for later retrieval by a sequencer
156 * or other mechanism.
157 */
158int trace_seq_puts(struct trace_seq *s, const char *str)
159{
160 int len;
161
162 TRACE_SEQ_CHECK(s);
163
164 len = strlen(str);
165
166 while (len > ((s->buffer_size - 1) - s->len))
167 expand_buffer(s);
168
169 memcpy(s->buffer + s->len, str, len);
170 s->len += len;
171
172 return len;
173}
174
175int trace_seq_putc(struct trace_seq *s, unsigned char c)
176{
177 TRACE_SEQ_CHECK(s);
178
179 while (s->len >= (s->buffer_size - 1))
180 expand_buffer(s);
181
182 s->buffer[s->len++] = c;
183
184 return 1;
185}
186
187void trace_seq_terminate(struct trace_seq *s)
188{
189 TRACE_SEQ_CHECK(s);
190
191 /* There's always one character left on the buffer */
192 s->buffer[s->len] = 0;
193}
194
195int trace_seq_do_printf(struct trace_seq *s)
196{
197 TRACE_SEQ_CHECK(s);
198 return printf("%.*s", s->len, s->buffer);
199}