aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2012-04-05 18:47:53 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2012-04-25 06:28:28 -0400
commitf7d82350e597d76dc8765a55c7849843395728b0 (patch)
tree6e254dde9c6b30dc9f5dc4fb28d3eeec86382e32 /tools
parent4ace73eef52c651b8f58415fb4476f4791c95e72 (diff)
tools/events: Add files to create libtraceevent.a
Copy over the files from trace-cmd to the Linux tools directory such that applications like perf and latencytrace can use the more advanced parsing code. Because some of the file names of perf conflict with trace-cmd file names, the trace-cmd files have been renamed as follows: parse-events.c ==> event-parse.c parse-events.h ==> event-parse.h utils.h ==> event-utils.h The files have been updated to handle the changes to the header files but other than that, they are identical to what was in the trace-cmd repository. The history of these files, including authorship is available at the git repo: git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/trace-cmd.git The Makefile was also copied over, but most of it was removed to focus on the parse-events code first. The parts of the Makefile for the plugins have also been removed, but will be added back when the plugin code is copied over as well. But that may be in its own separate directory. Signed-off-by: Steven Rostedt <rostedt@goodmis.org> Cc: Ingo Molnar <mingo@kernel.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@infradead.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Arun Sharma <asharma@fb.com> Cc: Namhyung Kim <namhyung.kim@lge.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
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}