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