aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2012-04-05 18:47:56 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2012-04-25 07:28:48 -0400
commitaaf045f72335653b24784d6042be8e4aee114403 (patch)
tree55c11335e23759e56e0a5ae2daf1c31bb9769662
parent668fe01f1cea2154da479dd12946eeb53413396e (diff)
perf: Have perf use the new libtraceevent.a library
The event parsing code in perf was originally copied from trace-cmd but never was kept up-to-date with the changes that was done there. The trace-cmd libtraceevent.a code is much more mature than what is currently in perf. This updates the code to use wrappers to handle the calls to the new event parsing code. The new code requires a handle to be pass around, which removes the global event variables and allows more than one event structure to be read from different files (and different machines). But perf still has the old global events and the code throughout perf does not yet have a nice way to pass around a handle. A global 'pevent' has been made for perf and the old calls have been created as wrappers to the new event parsing code that uses the global pevent. With this change, perf can later incorporate the pevent handle into the perf structures and allow more than one file to be read and compared, that contains different events. Signed-off-by: Steven Rostedt <rostedt@goodmis.org> Cc: Ingo Molnar <mingo@kernel.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@infradead.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Arun Sharma <asharma@fb.com> Cc: Namhyung Kim <namhyung.kim@lge.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
-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.c350
-rw-r--r--tools/perf/util/trace-event-read.c34
-rw-r--r--tools/perf/util/trace-event.h50
-rw-r--r--tools/perf/util/trace-parse-events.c3125
-rw-r--r--tools/perf/util/trace-parse-events.h273
12 files changed, 481 insertions, 3467 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 46150ab073c7..af0e5d64a9f7 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
@@ -179,7 +179,15 @@ $(OUTPUT)python/perf.so: $(PYRF_OBJS) $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
179SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) 179SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
180 180
181EVENT_PARSE_DIR = ../lib/traceevent/ 181EVENT_PARSE_DIR = ../lib/traceevent/
182LIBTRACEEVENT = $(OUTPUT)$(EVENT_PARSE_DIR)libtraceevent.a 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
183 191
184# 192#
185# Single 'perf' binary right now: 193# Single 'perf' binary right now:
@@ -295,7 +303,6 @@ LIB_H += util/hist.h
295LIB_H += util/thread.h 303LIB_H += util/thread.h
296LIB_H += util/thread_map.h 304LIB_H += util/thread_map.h
297LIB_H += util/trace-event.h 305LIB_H += util/trace-event.h
298LIB_H += util/trace-parse-events.h
299LIB_H += util/probe-finder.h 306LIB_H += util/probe-finder.h
300LIB_H += util/dwarf-aux.h 307LIB_H += util/dwarf-aux.h
301LIB_H += util/probe-event.h 308LIB_H += util/probe-event.h
@@ -358,7 +365,6 @@ LIB_OBJS += $(OUTPUT)util/pmu-bison.o
358LIB_OBJS += $(OUTPUT)util/trace-event-read.o 365LIB_OBJS += $(OUTPUT)util/trace-event-read.o
359LIB_OBJS += $(OUTPUT)util/trace-event-info.o 366LIB_OBJS += $(OUTPUT)util/trace-event-info.o
360LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o 367LIB_OBJS += $(OUTPUT)util/trace-event-scripting.o
361LIB_OBJS += $(OUTPUT)util/trace-parse-events.o
362LIB_OBJS += $(OUTPUT)util/svghelper.o 368LIB_OBJS += $(OUTPUT)util/svghelper.o
363LIB_OBJS += $(OUTPUT)util/sort.o 369LIB_OBJS += $(OUTPUT)util/sort.o
364LIB_OBJS += $(OUTPUT)util/hist.o 370LIB_OBJS += $(OUTPUT)util/hist.o
@@ -402,7 +408,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
402BUILTIN_OBJS += $(OUTPUT)builtin-test.o 408BUILTIN_OBJS += $(OUTPUT)builtin-test.o
403BUILTIN_OBJS += $(OUTPUT)builtin-inject.o 409BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
404 410
405PERFLIBS = $(LIB_FILE) 411PERFLIBS = $(LIB_FILE) $(LIBPARSEVENT)
406 412
407# Files needed for the python binding, perf.so 413# Files needed for the python binding, perf.so
408# pyrf is just an internal name needed for all those wrappers. 414# pyrf is just an internal name needed for all those wrappers.
@@ -699,7 +705,7 @@ $(OUTPUT)perf.o: perf.c $(OUTPUT)common-cmds.h $(OUTPUT)PERF-CFLAGS
699 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \ 705 '-DPERF_HTML_PATH="$(htmldir_SQ)"' \
700 $(ALL_CFLAGS) -c $(filter %.c,$^) -o $@ 706 $(ALL_CFLAGS) -c $(filter %.c,$^) -o $@
701 707
702$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS) $(LIBTRACEEVENT) 708$(OUTPUT)perf: $(OUTPUT)perf.o $(BUILTIN_OBJS) $(PERFLIBS)
703 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(OUTPUT)perf.o \ 709 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) $(OUTPUT)perf.o \
704 $(BUILTIN_OBJS) $(LIBS) -o $@ 710 $(BUILTIN_OBJS) $(LIBS) -o $@
705 711
@@ -806,7 +812,7 @@ $(LIB_FILE): $(LIB_OBJS)
806 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS) 812 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
807 813
808# libparsevent.a 814# libparsevent.a
809$(LIBTRACEEVENT): 815$(LIBPARSEVENT):
810 make -C $(EVENT_PARSE_DIR) $(COMMAND_O) libtraceevent.a 816 make -C $(EVENT_PARSE_DIR) $(COMMAND_O) libtraceevent.a
811 817
812help: 818help:
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 94775199644e..4ec165a334e2 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -1,18 +1,358 @@
1/*
2 * Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 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 General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20 */
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <ctype.h>
25#include <errno.h>
26
1#include "../perf.h" 27#include "../perf.h"
2#include "util.h" 28#include "util.h"
3#include "trace-event.h" 29#include "trace-event.h"
4 30
5int common_pc(struct scripting_context *context) 31int header_page_size_size;
32int header_page_ts_size;
33int header_page_data_offset;
34
35struct pevent *perf_pevent;
36static struct pevent *pevent;
37
38bool latency_format;
39
40int read_trace_init(int file_bigendian, int host_bigendian)
6{ 41{
7 return parse_common_pc(context->event_data); 42 if (pevent)
43 return 0;
44
45 perf_pevent = pevent_alloc();
46 pevent = perf_pevent;
47
48 pevent_set_file_bigendian(pevent, file_bigendian);
49 pevent_set_host_bigendian(pevent, host_bigendian);
50
51 return 0;
8} 52}
9 53
10int common_flags(struct scripting_context *context) 54static int get_common_field(struct scripting_context *context,
55 int *offset, int *size, const char *type)
11{ 56{
12 return parse_common_flags(context->event_data); 57 struct event_format *event;
58 struct format_field *field;
59
60 if (!*size) {
61 if (!pevent->events)
62 return 0;
63
64 event = pevent->events[0];
65 field = pevent_find_common_field(event, type);
66 if (!field)
67 return 0;
68 *offset = field->offset;
69 *size = field->size;
70 }
71
72 return pevent_read_number(pevent, context->event_data + *offset, *size);
13} 73}
14 74
15int common_lock_depth(struct scripting_context *context) 75int common_lock_depth(struct scripting_context *context)
16{ 76{
17 return parse_common_lock_depth(context->event_data); 77 static int offset;
78 static int size;
79 int ret;
80
81 ret = get_common_field(context, &size, &offset,
82 "common_lock_depth");
83 if (ret < 0)
84 return -1;
85
86 return ret;
87}
88
89int common_flags(struct scripting_context *context)
90{
91 static int offset;
92 static int size;
93 int ret;
94
95 ret = get_common_field(context, &size, &offset,
96 "common_flags");
97 if (ret < 0)
98 return -1;
99
100 return ret;
101}
102
103int common_pc(struct scripting_context *context)
104{
105 static int offset;
106 static int size;
107 int ret;
108
109 ret = get_common_field(context, &size, &offset,
110 "common_preempt_count");
111 if (ret < 0)
112 return -1;
113
114 return ret;
115}
116
117unsigned long long
118raw_field_value(struct event_format *event, const char *name, void *data)
119{
120 struct format_field *field;
121 unsigned long long val;
122
123 field = pevent_find_any_field(event, name);
124 if (!field)
125 return 0ULL;
126
127 pevent_read_number_field(field, data, &val);
128
129 return val;
130}
131
132void *raw_field_ptr(struct event_format *event, const char *name, void *data)
133{
134 struct format_field *field;
135
136 field = pevent_find_any_field(event, name);
137 if (!field)
138 return NULL;
139
140 if (field->flags & FIELD_IS_DYNAMIC) {
141 int offset;
142
143 offset = *(int *)(data + field->offset);
144 offset &= 0xffff;
145
146 return data + offset;
147 }
148
149 return data + field->offset;
150}
151
152int trace_parse_common_type(void *data)
153{
154 struct record record;
155
156 record.data = data;
157 return pevent_data_type(pevent, &record);
158}
159
160int trace_parse_common_pid(void *data)
161{
162 struct record record;
163
164 record.data = data;
165 return pevent_data_pid(pevent, &record);
166}
167
168unsigned long long read_size(void *ptr, int size)
169{
170 return pevent_read_number(pevent, ptr, size);
171}
172
173struct event_format *trace_find_event(int type)
174{
175 return pevent_find_event(pevent, type);
176}
177
178
179void print_trace_event(int cpu, void *data, int size)
180{
181 struct event_format *event;
182 struct record record;
183 struct trace_seq s;
184 int type;
185
186 type = trace_parse_common_type(data);
187
188 event = trace_find_event(type);
189 if (!event) {
190 warning("ug! no event found for type %d", type);
191 return;
192 }
193
194 memset(&record, 0, sizeof(record));
195 record.cpu = cpu;
196 record.size = size;
197 record.data = data;
198
199 trace_seq_init(&s);
200 pevent_print_event(pevent, &s, &record);
201 trace_seq_do_printf(&s);
202 printf("\n");
203}
204
205void print_event(int cpu, void *data, int size, unsigned long long nsecs,
206 char *comm)
207{
208 struct record record;
209 struct trace_seq s;
210 int pid;
211
212 pevent->latency_format = latency_format;
213
214 record.ts = nsecs;
215 record.cpu = cpu;
216 record.size = size;
217 record.data = data;
218 pid = pevent_data_pid(pevent, &record);
219
220 if (!pevent_pid_is_registered(pevent, pid))
221 pevent_register_comm(pevent, comm, pid);
222
223 trace_seq_init(&s);
224 pevent_print_event(pevent, &s, &record);
225 trace_seq_do_printf(&s);
226 printf("\n");
227}
228
229void parse_proc_kallsyms(char *file, unsigned int size __unused)
230{
231 unsigned long long addr;
232 char *func;
233 char *line;
234 char *next = NULL;
235 char *addr_str;
236 char *mod;
237 char ch;
238
239 line = strtok_r(file, "\n", &next);
240 while (line) {
241 mod = NULL;
242 sscanf(line, "%as %c %as\t[%as",
243 (float *)(void *)&addr_str, /* workaround gcc warning */
244 &ch, (float *)(void *)&func, (float *)(void *)&mod);
245 addr = strtoull(addr_str, NULL, 16);
246 free(addr_str);
247
248 /* truncate the extra ']' */
249 if (mod)
250 mod[strlen(mod) - 1] = 0;
251
252 pevent_register_function(pevent, func, addr, mod);
253 free(func);
254 free(mod);
255
256 line = strtok_r(NULL, "\n", &next);
257 }
258}
259
260void parse_ftrace_printk(char *file, unsigned int size __unused)
261{
262 unsigned long long addr;
263 char *printk;
264 char *line;
265 char *next = NULL;
266 char *addr_str;
267 char *fmt;
268
269 line = strtok_r(file, "\n", &next);
270 while (line) {
271 addr_str = strtok_r(line, ":", &fmt);
272 if (!addr_str) {
273 warning("printk format with empty entry");
274 break;
275 }
276 addr = strtoull(addr_str, NULL, 16);
277 /* fmt still has a space, skip it */
278 printk = strdup(fmt+1);
279 line = strtok_r(NULL, "\n", &next);
280 pevent_register_print_string(pevent, printk, addr);
281 }
282}
283
284int parse_ftrace_file(char *buf, unsigned long size)
285{
286 return pevent_parse_event(pevent, buf, size, "ftrace");
287}
288
289int parse_event_file(char *buf, unsigned long size, char *sys)
290{
291 return pevent_parse_event(pevent, buf, size, sys);
292}
293
294struct event_format *trace_find_next_event(struct event_format *event)
295{
296 static int idx;
297
298 if (!pevent->events)
299 return NULL;
300
301 if (!event) {
302 idx = 0;
303 return pevent->events[0];
304 }
305
306 if (idx < pevent->nr_events && event == pevent->events[idx]) {
307 idx++;
308 if (idx == pevent->nr_events)
309 return NULL;
310 return pevent->events[idx];
311 }
312
313 for (idx = 1; idx < pevent->nr_events; idx++) {
314 if (event == pevent->events[idx - 1])
315 return pevent->events[idx];
316 }
317 return NULL;
318}
319
320struct flag {
321 const char *name;
322 unsigned long long value;
323};
324
325static const struct flag flags[] = {
326 { "HI_SOFTIRQ", 0 },
327 { "TIMER_SOFTIRQ", 1 },
328 { "NET_TX_SOFTIRQ", 2 },
329 { "NET_RX_SOFTIRQ", 3 },
330 { "BLOCK_SOFTIRQ", 4 },
331 { "BLOCK_IOPOLL_SOFTIRQ", 5 },
332 { "TASKLET_SOFTIRQ", 6 },
333 { "SCHED_SOFTIRQ", 7 },
334 { "HRTIMER_SOFTIRQ", 8 },
335 { "RCU_SOFTIRQ", 9 },
336
337 { "HRTIMER_NORESTART", 0 },
338 { "HRTIMER_RESTART", 1 },
339};
340
341unsigned long long eval_flag(const char *flag)
342{
343 int i;
344
345 /*
346 * Some flags in the format files do not get converted.
347 * If the flag is not numeric, see if it is something that
348 * we already know about.
349 */
350 if (isdigit(flag[0]))
351 return strtoull(flag, NULL, 0);
352
353 for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++)
354 if (strcmp(flags[i].name, flag) == 0)
355 return flags[i].value;
356
357 return 0;
18} 358}
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index b9592e0de8d7..29b92065b88e 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)
@@ -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;
@@ -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 e78ef1e10ee1..112bc2aa72e1 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -2,7 +2,7 @@
2#define _PERF_UTIL_TRACE_EVENT_H 2#define _PERF_UTIL_TRACE_EVENT_H
3 3
4#include "parse-events.h" 4#include "parse-events.h"
5#include "trace-parse-events.h" 5#include "event-parse.h"
6#include "session.h" 6#include "session.h"
7 7
8struct machine; 8struct machine;
@@ -10,6 +10,54 @@ struct perf_sample;
10union perf_event; 10union perf_event;
11struct thread; 11struct thread;
12 12
13extern int header_page_size_size;
14extern int header_page_ts_size;
15extern int header_page_data_offset;
16
17extern bool latency_format;
18extern struct pevent *perf_pevent;
19
20enum {
21 RINGBUF_TYPE_PADDING = 29,
22 RINGBUF_TYPE_TIME_EXTEND = 30,
23 RINGBUF_TYPE_TIME_STAMP = 31,
24};
25
26#ifndef TS_SHIFT
27#define TS_SHIFT 27
28#endif
29
30int bigendian(void);
31
32int read_trace_init(int file_bigendian, int host_bigendian);
33void print_trace_event(int cpu, void *data, int size);
34
35void print_event(int cpu, void *data, int size, unsigned long long nsecs,
36 char *comm);
37
38int parse_ftrace_file(char *buf, unsigned long size);
39int parse_event_file(char *buf, unsigned long size, char *sys);
40
41struct record *trace_peek_data(int cpu);
42struct event_format *trace_find_event(int type);
43
44unsigned long long
45raw_field_value(struct event_format *event, const char *name, void *data);
46void *raw_field_ptr(struct event_format *event, const char *name, void *data);
47
48void parse_proc_kallsyms(char *file, unsigned int size __unused);
49void parse_ftrace_printk(char *file, unsigned int size __unused);
50
51ssize_t trace_report(int fd, bool repipe);
52
53int trace_parse_common_type(void *data);
54int trace_parse_common_pid(void *data);
55
56struct event_format *trace_find_next_event(struct event_format *event);
57unsigned long long read_size(void *ptr, int size);
58unsigned long long eval_flag(const char *flag);
59
60struct record *trace_read_data(int cpu);
13int read_tracing_data(int fd, struct list_head *pattrs); 61int read_tracing_data(int fd, struct list_head *pattrs);
14 62
15struct tracing_data { 63struct tracing_data {
diff --git a/tools/perf/util/trace-parse-events.c b/tools/perf/util/trace-parse-events.c
deleted file mode 100644
index 8a3fbe643a1c..000000000000
--- a/tools/perf/util/trace-parse-events.c
+++ /dev/null
@@ -1,3125 +0,0 @@
1/*
2 * Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 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 General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
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 */
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <ctype.h>
28#include <errno.h>
29
30#include "../perf.h"
31#include "util.h"
32#include "trace-parse-events.h"
33
34int header_page_ts_offset;
35int header_page_ts_size;
36int header_page_size_offset;
37int header_page_size_size;
38int header_page_overwrite_offset;
39int header_page_overwrite_size;
40int 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
85void parse_cmdlines(char *file, int size __unused)
86{
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
96 line = strtok_r(file, "\n", &next);
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 i;
155
156 line = strtok_r(file, "\n", &next);
157 while (line) {
158 item = malloc_or_die(sizeof(*item));
159 item->mod = NULL;
160 sscanf(line, "%as %c %as\t[%as",
161 (float *)(void *)&addr_str, /* workaround gcc warning */
162 &ch,
163 (float *)(void *)&item->func,
164 (float *)(void *)&item->mod);
165 item->addr = strtoull(addr_str, NULL, 16);
166 free(addr_str);
167
168 /* truncate the extra ']' */
169 if (item->mod)
170 item->mod[strlen(item->mod) - 1] = 0;
171
172
173 item->next = list;
174 list = item;
175 line = strtok_r(NULL, "\n", &next);
176 func_count++;
177 }
178
179 func_list = malloc_or_die(sizeof(*func_list) * (func_count + 1));
180
181 i = 0;
182 while (list) {
183 func_list[i].func = list->func;
184 func_list[i].addr = list->addr;
185 func_list[i].mod = list->mod;
186 i++;
187 item = list;
188 list = list->next;
189 free(item);
190 }
191
192 qsort(func_list, func_count, sizeof(*func_list), func_cmp);
193
194 /*
195 * Add a special record at the end.
196 */
197 func_list[func_count].func = NULL;
198 func_list[func_count].addr = 0;
199 func_list[func_count].mod = NULL;
200}
201
202/*
203 * We are searching for a record in between, not an exact
204 * match.
205 */
206static int func_bcmp(const void *a, const void *b)
207{
208 const struct func_map *fa = a;
209 const struct func_map *fb = b;
210
211 if ((fa->addr == fb->addr) ||
212
213 (fa->addr > fb->addr &&
214 fa->addr < (fb+1)->addr))
215 return 0;
216
217 if (fa->addr < fb->addr)
218 return -1;
219
220 return 1;
221}
222
223static struct func_map *find_func(unsigned long long addr)
224{
225 struct func_map *func;
226 struct func_map key;
227
228 key.addr = addr;
229
230 func = bsearch(&key, func_list, func_count, sizeof(*func_list),
231 func_bcmp);
232
233 return func;
234}
235
236void print_funcs(void)
237{
238 int i;
239
240 for (i = 0; i < (int)func_count; i++) {
241 printf("%016llx %s",
242 func_list[i].addr,
243 func_list[i].func);
244 if (func_list[i].mod)
245 printf(" [%s]\n", func_list[i].mod);
246 else
247 printf("\n");
248 }
249}
250
251static struct printk_map {
252 unsigned long long addr;
253 char *printk;
254} *printk_list;
255static unsigned int printk_count;
256
257static int printk_cmp(const void *a, const void *b)
258{
259 const struct func_map *fa = a;
260 const struct func_map *fb = b;
261
262 if (fa->addr < fb->addr)
263 return -1;
264 if (fa->addr > fb->addr)
265 return 1;
266
267 return 0;
268}
269
270static struct printk_map *find_printk(unsigned long long addr)
271{
272 struct printk_map *printk;
273 struct printk_map key;
274
275 key.addr = addr;
276
277 printk = bsearch(&key, printk_list, printk_count, sizeof(*printk_list),
278 printk_cmp);
279
280 return printk;
281}
282
283void parse_ftrace_printk(char *file, unsigned int size __unused)
284{
285 struct printk_list {
286 struct printk_list *next;
287 unsigned long long addr;
288 char *printk;
289 } *list = NULL, *item;
290 char *line;
291 char *next = NULL;
292 char *addr_str;
293 int i;
294
295 line = strtok_r(file, "\n", &next);
296 while (line) {
297 addr_str = strsep(&line, ":");
298 if (!line) {
299 warning("error parsing print strings");
300 break;
301 }
302 item = malloc_or_die(sizeof(*item));
303 item->addr = strtoull(addr_str, NULL, 16);
304 /* fmt still has a space, skip it */
305 item->printk = strdup(line+1);
306 item->next = list;
307 list = item;
308 line = strtok_r(NULL, "\n", &next);
309 printk_count++;
310 }
311
312 printk_list = malloc_or_die(sizeof(*printk_list) * printk_count + 1);
313
314 i = 0;
315 while (list) {
316 printk_list[i].printk = list->printk;
317 printk_list[i].addr = list->addr;
318 i++;
319 item = list;
320 list = list->next;
321 free(item);
322 }
323
324 qsort(printk_list, printk_count, sizeof(*printk_list), printk_cmp);
325}
326
327void print_printk(void)
328{
329 int i;
330
331 for (i = 0; i < (int)printk_count; i++) {
332 printf("%016llx %s\n",
333 printk_list[i].addr,
334 printk_list[i].printk);
335 }
336}
337
338static struct event *alloc_event(void)
339{
340 struct event *event;
341
342 event = malloc_or_die(sizeof(*event));
343 memset(event, 0, sizeof(*event));
344
345 return event;
346}
347
348enum event_type {
349 EVENT_ERROR,
350 EVENT_NONE,
351 EVENT_SPACE,
352 EVENT_NEWLINE,
353 EVENT_OP,
354 EVENT_DELIM,
355 EVENT_ITEM,
356 EVENT_DQUOTE,
357 EVENT_SQUOTE,
358};
359
360static struct event *event_list;
361
362static void add_event(struct event *event)
363{
364 event->next = event_list;
365 event_list = event;
366}
367
368static int event_item_type(enum event_type type)
369{
370 switch (type) {
371 case EVENT_ITEM ... EVENT_SQUOTE:
372 return 1;
373 case EVENT_ERROR ... EVENT_DELIM:
374 default:
375 return 0;
376 }
377}
378
379static void free_arg(struct print_arg *arg)
380{
381 if (!arg)
382 return;
383
384 switch (arg->type) {
385 case PRINT_ATOM:
386 if (arg->atom.atom)
387 free(arg->atom.atom);
388 break;
389 case PRINT_NULL:
390 case PRINT_FIELD ... PRINT_OP:
391 default:
392 /* todo */
393 break;
394 }
395
396 free(arg);
397}
398
399static enum event_type get_type(int ch)
400{
401 if (ch == '\n')
402 return EVENT_NEWLINE;
403 if (isspace(ch))
404 return EVENT_SPACE;
405 if (isalnum(ch) || ch == '_')
406 return EVENT_ITEM;
407 if (ch == '\'')
408 return EVENT_SQUOTE;
409 if (ch == '"')
410 return EVENT_DQUOTE;
411 if (!isprint(ch))
412 return EVENT_NONE;
413 if (ch == '(' || ch == ')' || ch == ',')
414 return EVENT_DELIM;
415
416 return EVENT_OP;
417}
418
419static int __read_char(void)
420{
421 if (input_buf_ptr >= input_buf_siz)
422 return -1;
423
424 return input_buf[input_buf_ptr++];
425}
426
427static int __peek_char(void)
428{
429 if (input_buf_ptr >= input_buf_siz)
430 return -1;
431
432 return input_buf[input_buf_ptr];
433}
434
435static enum event_type __read_token(char **tok)
436{
437 char buf[BUFSIZ];
438 int ch, last_ch, quote_ch, next_ch;
439 int i = 0;
440 int tok_size = 0;
441 enum event_type type;
442
443 *tok = NULL;
444
445
446 ch = __read_char();
447 if (ch < 0)
448 return EVENT_NONE;
449
450 type = get_type(ch);
451 if (type == EVENT_NONE)
452 return type;
453
454 buf[i++] = ch;
455
456 switch (type) {
457 case EVENT_NEWLINE:
458 case EVENT_DELIM:
459 *tok = malloc_or_die(2);
460 (*tok)[0] = ch;
461 (*tok)[1] = 0;
462 return type;
463
464 case EVENT_OP:
465 switch (ch) {
466 case '-':
467 next_ch = __peek_char();
468 if (next_ch == '>') {
469 buf[i++] = __read_char();
470 break;
471 }
472 /* fall through */
473 case '+':
474 case '|':
475 case '&':
476 case '>':
477 case '<':
478 last_ch = ch;
479 ch = __peek_char();
480 if (ch != last_ch)
481 goto test_equal;
482 buf[i++] = __read_char();
483 switch (last_ch) {
484 case '>':
485 case '<':
486 goto test_equal;
487 default:
488 break;
489 }
490 break;
491 case '!':
492 case '=':
493 goto test_equal;
494 default: /* what should we do instead? */
495 break;
496 }
497 buf[i] = 0;
498 *tok = strdup(buf);
499 return type;
500
501 test_equal:
502 ch = __peek_char();
503 if (ch == '=')
504 buf[i++] = __read_char();
505 break;
506
507 case EVENT_DQUOTE:
508 case EVENT_SQUOTE:
509 /* don't keep quotes */
510 i--;
511 quote_ch = ch;
512 last_ch = 0;
513 do {
514 if (i == (BUFSIZ - 1)) {
515 buf[i] = 0;
516 if (*tok) {
517 *tok = realloc(*tok, tok_size + BUFSIZ);
518 if (!*tok)
519 return EVENT_NONE;
520 strcat(*tok, buf);
521 } else
522 *tok = strdup(buf);
523
524 if (!*tok)
525 return EVENT_NONE;
526 tok_size += BUFSIZ;
527 i = 0;
528 }
529 last_ch = ch;
530 ch = __read_char();
531 buf[i++] = ch;
532 /* the '\' '\' will cancel itself */
533 if (ch == '\\' && last_ch == '\\')
534 last_ch = 0;
535 } while (ch != quote_ch || last_ch == '\\');
536 /* remove the last quote */
537 i--;
538 goto out;
539
540 case EVENT_ERROR ... EVENT_SPACE:
541 case EVENT_ITEM:
542 default:
543 break;
544 }
545
546 while (get_type(__peek_char()) == type) {
547 if (i == (BUFSIZ - 1)) {
548 buf[i] = 0;
549 if (*tok) {
550 *tok = realloc(*tok, tok_size + BUFSIZ);
551 if (!*tok)
552 return EVENT_NONE;
553 strcat(*tok, buf);
554 } else
555 *tok = strdup(buf);
556
557 if (!*tok)
558 return EVENT_NONE;
559 tok_size += BUFSIZ;
560 i = 0;
561 }
562 ch = __read_char();
563 buf[i++] = ch;
564 }
565
566 out:
567 buf[i] = 0;
568 if (*tok) {
569 *tok = realloc(*tok, tok_size + i);
570 if (!*tok)
571 return EVENT_NONE;
572 strcat(*tok, buf);
573 } else
574 *tok = strdup(buf);
575 if (!*tok)
576 return EVENT_NONE;
577
578 return type;
579}
580
581static void free_token(char *tok)
582{
583 if (tok)
584 free(tok);
585}
586
587static enum event_type read_token(char **tok)
588{
589 enum event_type type;
590
591 for (;;) {
592 type = __read_token(tok);
593 if (type != EVENT_SPACE)
594 return type;
595
596 free_token(*tok);
597 }
598
599 /* not reached */
600 return EVENT_NONE;
601}
602
603/* no newline */
604static enum event_type read_token_item(char **tok)
605{
606 enum event_type type;
607
608 for (;;) {
609 type = __read_token(tok);
610 if (type != EVENT_SPACE && type != EVENT_NEWLINE)
611 return type;
612
613 free_token(*tok);
614 }
615
616 /* not reached */
617 return EVENT_NONE;
618}
619
620static int test_type(enum event_type type, enum event_type expect)
621{
622 if (type != expect) {
623 warning("Error: expected type %d but read %d",
624 expect, type);
625 return -1;
626 }
627 return 0;
628}
629
630static int __test_type_token(enum event_type type, char *token,
631 enum event_type expect, const char *expect_tok,
632 bool warn)
633{
634 if (type != expect) {
635 if (warn)
636 warning("Error: expected type %d but read %d",
637 expect, type);
638 return -1;
639 }
640
641 if (strcmp(token, expect_tok) != 0) {
642 if (warn)
643 warning("Error: expected '%s' but read '%s'",
644 expect_tok, token);
645 return -1;
646 }
647 return 0;
648}
649
650static int test_type_token(enum event_type type, char *token,
651 enum event_type expect, const char *expect_tok)
652{
653 return __test_type_token(type, token, expect, expect_tok, true);
654}
655
656static int __read_expect_type(enum event_type expect, char **tok, int newline_ok)
657{
658 enum event_type type;
659
660 if (newline_ok)
661 type = read_token(tok);
662 else
663 type = read_token_item(tok);
664 return test_type(type, expect);
665}
666
667static int read_expect_type(enum event_type expect, char **tok)
668{
669 return __read_expect_type(expect, tok, 1);
670}
671
672static int __read_expected(enum event_type expect, const char *str,
673 int newline_ok, bool warn)
674{
675 enum event_type type;
676 char *token;
677 int ret;
678
679 if (newline_ok)
680 type = read_token(&token);
681 else
682 type = read_token_item(&token);
683
684 ret = __test_type_token(type, token, expect, str, warn);
685
686 free_token(token);
687
688 return ret;
689}
690
691static int read_expected(enum event_type expect, const char *str)
692{
693 return __read_expected(expect, str, 1, true);
694}
695
696static int read_expected_item(enum event_type expect, const char *str)
697{
698 return __read_expected(expect, str, 0, true);
699}
700
701static char *event_read_name(void)
702{
703 char *token;
704
705 if (read_expected(EVENT_ITEM, "name") < 0)
706 return NULL;
707
708 if (read_expected(EVENT_OP, ":") < 0)
709 return NULL;
710
711 if (read_expect_type(EVENT_ITEM, &token) < 0)
712 goto fail;
713
714 return token;
715
716 fail:
717 free_token(token);
718 return NULL;
719}
720
721static int event_read_id(void)
722{
723 char *token;
724 int id;
725
726 if (read_expected_item(EVENT_ITEM, "ID") < 0)
727 return -1;
728
729 if (read_expected(EVENT_OP, ":") < 0)
730 return -1;
731
732 if (read_expect_type(EVENT_ITEM, &token) < 0)
733 goto fail;
734
735 id = strtoul(token, NULL, 0);
736 free_token(token);
737 return id;
738
739 fail:
740 free_token(token);
741 return -1;
742}
743
744static int field_is_string(struct format_field *field)
745{
746 if ((field->flags & FIELD_IS_ARRAY) &&
747 (!strstr(field->type, "char") || !strstr(field->type, "u8") ||
748 !strstr(field->type, "s8")))
749 return 1;
750
751 return 0;
752}
753
754static int field_is_dynamic(struct format_field *field)
755{
756 if (!strncmp(field->type, "__data_loc", 10))
757 return 1;
758
759 return 0;
760}
761
762static int event_read_fields(struct event *event, struct format_field **fields)
763{
764 struct format_field *field = NULL;
765 enum event_type type;
766 char *token;
767 char *last_token;
768 int count = 0;
769
770 do {
771 type = read_token(&token);
772 if (type == EVENT_NEWLINE) {
773 free_token(token);
774 return count;
775 }
776
777 count++;
778
779 if (test_type_token(type, token, EVENT_ITEM, "field"))
780 goto fail;
781 free_token(token);
782
783 type = read_token(&token);
784 /*
785 * The ftrace fields may still use the "special" name.
786 * Just ignore it.
787 */
788 if (event->flags & EVENT_FL_ISFTRACE &&
789 type == EVENT_ITEM && strcmp(token, "special") == 0) {
790 free_token(token);
791 type = read_token(&token);
792 }
793
794 if (test_type_token(type, token, EVENT_OP, ":") < 0)
795 return -1;
796
797 if (read_expect_type(EVENT_ITEM, &token) < 0)
798 goto fail;
799
800 last_token = token;
801
802 field = malloc_or_die(sizeof(*field));
803 memset(field, 0, sizeof(*field));
804
805 /* read the rest of the type */
806 for (;;) {
807 type = read_token(&token);
808 if (type == EVENT_ITEM ||
809 (type == EVENT_OP && strcmp(token, "*") == 0) ||
810 /*
811 * Some of the ftrace fields are broken and have
812 * an illegal "." in them.
813 */
814 (event->flags & EVENT_FL_ISFTRACE &&
815 type == EVENT_OP && strcmp(token, ".") == 0)) {
816
817 if (strcmp(token, "*") == 0)
818 field->flags |= FIELD_IS_POINTER;
819
820 if (field->type) {
821 field->type = realloc(field->type,
822 strlen(field->type) +
823 strlen(last_token) + 2);
824 strcat(field->type, " ");
825 strcat(field->type, last_token);
826 } else
827 field->type = last_token;
828 last_token = token;
829 continue;
830 }
831
832 break;
833 }
834
835 if (!field->type) {
836 die("no type found");
837 goto fail;
838 }
839 field->name = last_token;
840
841 if (test_type(type, EVENT_OP))
842 goto fail;
843
844 if (strcmp(token, "[") == 0) {
845 enum event_type last_type = type;
846 char *brackets = token;
847 int len;
848
849 field->flags |= FIELD_IS_ARRAY;
850
851 type = read_token(&token);
852 while (strcmp(token, "]") != 0) {
853 if (last_type == EVENT_ITEM &&
854 type == EVENT_ITEM)
855 len = 2;
856 else
857 len = 1;
858 last_type = type;
859
860 brackets = realloc(brackets,
861 strlen(brackets) +
862 strlen(token) + len);
863 if (len == 2)
864 strcat(brackets, " ");
865 strcat(brackets, token);
866 free_token(token);
867 type = read_token(&token);
868 if (type == EVENT_NONE) {
869 die("failed to find token");
870 goto fail;
871 }
872 }
873
874 free_token(token);
875
876 brackets = realloc(brackets, strlen(brackets) + 2);
877 strcat(brackets, "]");
878
879 /* add brackets to type */
880
881 type = read_token(&token);
882 /*
883 * If the next token is not an OP, then it is of
884 * the format: type [] item;
885 */
886 if (type == EVENT_ITEM) {
887 field->type = realloc(field->type,
888 strlen(field->type) +
889 strlen(field->name) +
890 strlen(brackets) + 2);
891 strcat(field->type, " ");
892 strcat(field->type, field->name);
893 free_token(field->name);
894 strcat(field->type, brackets);
895 field->name = token;
896 type = read_token(&token);
897 } else {
898 field->type = realloc(field->type,
899 strlen(field->type) +
900 strlen(brackets) + 1);
901 strcat(field->type, brackets);
902 }
903 free(brackets);
904 }
905
906 if (field_is_string(field)) {
907 field->flags |= FIELD_IS_STRING;
908 if (field_is_dynamic(field))
909 field->flags |= FIELD_IS_DYNAMIC;
910 }
911
912 if (test_type_token(type, token, EVENT_OP, ";"))
913 goto fail;
914 free_token(token);
915
916 if (read_expected(EVENT_ITEM, "offset") < 0)
917 goto fail_expect;
918
919 if (read_expected(EVENT_OP, ":") < 0)
920 goto fail_expect;
921
922 if (read_expect_type(EVENT_ITEM, &token))
923 goto fail;
924 field->offset = strtoul(token, NULL, 0);
925 free_token(token);
926
927 if (read_expected(EVENT_OP, ";") < 0)
928 goto fail_expect;
929
930 if (read_expected(EVENT_ITEM, "size") < 0)
931 goto fail_expect;
932
933 if (read_expected(EVENT_OP, ":") < 0)
934 goto fail_expect;
935
936 if (read_expect_type(EVENT_ITEM, &token))
937 goto fail;
938 field->size = strtoul(token, NULL, 0);
939 free_token(token);
940
941 if (read_expected(EVENT_OP, ";") < 0)
942 goto fail_expect;
943
944 type = read_token(&token);
945 if (type != EVENT_NEWLINE) {
946 /* newer versions of the kernel have a "signed" type */
947 if (test_type_token(type, token, EVENT_ITEM, "signed"))
948 goto fail;
949
950 free_token(token);
951
952 if (read_expected(EVENT_OP, ":") < 0)
953 goto fail_expect;
954
955 if (read_expect_type(EVENT_ITEM, &token))
956 goto fail;
957
958 if (strtoul(token, NULL, 0))
959 field->flags |= FIELD_IS_SIGNED;
960
961 free_token(token);
962 if (read_expected(EVENT_OP, ";") < 0)
963 goto fail_expect;
964
965 if (read_expect_type(EVENT_NEWLINE, &token))
966 goto fail;
967 }
968
969 free_token(token);
970
971 *fields = field;
972 fields = &field->next;
973
974 } while (1);
975
976 return 0;
977
978fail:
979 free_token(token);
980fail_expect:
981 if (field)
982 free(field);
983 return -1;
984}
985
986static int event_read_format(struct event *event)
987{
988 char *token;
989 int ret;
990
991 if (read_expected_item(EVENT_ITEM, "format") < 0)
992 return -1;
993
994 if (read_expected(EVENT_OP, ":") < 0)
995 return -1;
996
997 if (read_expect_type(EVENT_NEWLINE, &token))
998 goto fail;
999 free_token(token);
1000
1001 ret = event_read_fields(event, &event->format.common_fields);
1002 if (ret < 0)
1003 return ret;
1004 event->format.nr_common = ret;
1005
1006 ret = event_read_fields(event, &event->format.fields);
1007 if (ret < 0)
1008 return ret;
1009 event->format.nr_fields = ret;
1010
1011 return 0;
1012
1013 fail:
1014 free_token(token);
1015 return -1;
1016}
1017
1018enum event_type
1019process_arg_token(struct event *event, struct print_arg *arg,
1020 char **tok, enum event_type type);
1021
1022static enum event_type
1023process_arg(struct event *event, struct print_arg *arg, char **tok)
1024{
1025 enum event_type type;
1026 char *token;
1027
1028 type = read_token(&token);
1029 *tok = token;
1030
1031 return process_arg_token(event, arg, tok, type);
1032}
1033
1034static enum event_type
1035process_cond(struct event *event, struct print_arg *top, char **tok)
1036{
1037 struct print_arg *arg, *left, *right;
1038 enum event_type type;
1039 char *token = NULL;
1040
1041 arg = malloc_or_die(sizeof(*arg));
1042 memset(arg, 0, sizeof(*arg));
1043
1044 left = malloc_or_die(sizeof(*left));
1045
1046 right = malloc_or_die(sizeof(*right));
1047
1048 arg->type = PRINT_OP;
1049 arg->op.left = left;
1050 arg->op.right = right;
1051
1052 *tok = NULL;
1053 type = process_arg(event, left, &token);
1054 if (test_type_token(type, token, EVENT_OP, ":"))
1055 goto out_free;
1056
1057 arg->op.op = token;
1058
1059 type = process_arg(event, right, &token);
1060
1061 top->op.right = arg;
1062
1063 *tok = token;
1064 return type;
1065
1066out_free:
1067 free_token(*tok);
1068 free(right);
1069 free(left);
1070 free_arg(arg);
1071 return EVENT_ERROR;
1072}
1073
1074static enum event_type
1075process_array(struct event *event, struct print_arg *top, char **tok)
1076{
1077 struct print_arg *arg;
1078 enum event_type type;
1079 char *token = NULL;
1080
1081 arg = malloc_or_die(sizeof(*arg));
1082 memset(arg, 0, sizeof(*arg));
1083
1084 *tok = NULL;
1085 type = process_arg(event, arg, &token);
1086 if (test_type_token(type, token, EVENT_OP, "]"))
1087 goto out_free;
1088
1089 top->op.right = arg;
1090
1091 free_token(token);
1092 type = read_token_item(&token);
1093 *tok = token;
1094
1095 return type;
1096
1097out_free:
1098 free_token(*tok);
1099 free_arg(arg);
1100 return EVENT_ERROR;
1101}
1102
1103static int get_op_prio(char *op)
1104{
1105 if (!op[1]) {
1106 switch (op[0]) {
1107 case '*':
1108 case '/':
1109 case '%':
1110 return 6;
1111 case '+':
1112 case '-':
1113 return 7;
1114 /* '>>' and '<<' are 8 */
1115 case '<':
1116 case '>':
1117 return 9;
1118 /* '==' and '!=' are 10 */
1119 case '&':
1120 return 11;
1121 case '^':
1122 return 12;
1123 case '|':
1124 return 13;
1125 case '?':
1126 return 16;
1127 default:
1128 die("unknown op '%c'", op[0]);
1129 return -1;
1130 }
1131 } else {
1132 if (strcmp(op, "++") == 0 ||
1133 strcmp(op, "--") == 0) {
1134 return 3;
1135 } else if (strcmp(op, ">>") == 0 ||
1136 strcmp(op, "<<") == 0) {
1137 return 8;
1138 } else if (strcmp(op, ">=") == 0 ||
1139 strcmp(op, "<=") == 0) {
1140 return 9;
1141 } else if (strcmp(op, "==") == 0 ||
1142 strcmp(op, "!=") == 0) {
1143 return 10;
1144 } else if (strcmp(op, "&&") == 0) {
1145 return 14;
1146 } else if (strcmp(op, "||") == 0) {
1147 return 15;
1148 } else {
1149 die("unknown op '%s'", op);
1150 return -1;
1151 }
1152 }
1153}
1154
1155static void set_op_prio(struct print_arg *arg)
1156{
1157
1158 /* single ops are the greatest */
1159 if (!arg->op.left || arg->op.left->type == PRINT_NULL) {
1160 arg->op.prio = 0;
1161 return;
1162 }
1163
1164 arg->op.prio = get_op_prio(arg->op.op);
1165}
1166
1167static enum event_type
1168process_op(struct event *event, struct print_arg *arg, char **tok)
1169{
1170 struct print_arg *left, *right = NULL;
1171 enum event_type type;
1172 char *token;
1173
1174 /* the op is passed in via tok */
1175 token = *tok;
1176
1177 if (arg->type == PRINT_OP && !arg->op.left) {
1178 /* handle single op */
1179 if (token[1]) {
1180 die("bad op token %s", token);
1181 return EVENT_ERROR;
1182 }
1183 switch (token[0]) {
1184 case '!':
1185 case '+':
1186 case '-':
1187 break;
1188 default:
1189 die("bad op token %s", token);
1190 return EVENT_ERROR;
1191 }
1192
1193 /* make an empty left */
1194 left = malloc_or_die(sizeof(*left));
1195 left->type = PRINT_NULL;
1196 arg->op.left = left;
1197
1198 right = malloc_or_die(sizeof(*right));
1199 arg->op.right = right;
1200
1201 type = process_arg(event, right, tok);
1202
1203 } else if (strcmp(token, "?") == 0) {
1204
1205 left = malloc_or_die(sizeof(*left));
1206 /* copy the top arg to the left */
1207 *left = *arg;
1208
1209 arg->type = PRINT_OP;
1210 arg->op.op = token;
1211 arg->op.left = left;
1212 arg->op.prio = 0;
1213
1214 type = process_cond(event, arg, tok);
1215
1216 } else if (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 strcmp(token, "!=") == 0) {
1231
1232 left = malloc_or_die(sizeof(*left));
1233
1234 /* copy the top arg to the left */
1235 *left = *arg;
1236
1237 arg->type = PRINT_OP;
1238 arg->op.op = token;
1239 arg->op.left = left;
1240
1241 set_op_prio(arg);
1242
1243 right = malloc_or_die(sizeof(*right));
1244
1245 type = read_token_item(&token);
1246 *tok = token;
1247
1248 /* could just be a type pointer */
1249 if ((strcmp(arg->op.op, "*") == 0) &&
1250 type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
1251 if (left->type != PRINT_ATOM)
1252 die("bad pointer type");
1253 left->atom.atom = realloc(left->atom.atom,
1254 sizeof(left->atom.atom) + 3);
1255 strcat(left->atom.atom, " *");
1256 *arg = *left;
1257 free(arg);
1258
1259 return type;
1260 }
1261
1262 type = process_arg_token(event, right, tok, type);
1263
1264 arg->op.right = right;
1265
1266 } else if (strcmp(token, "[") == 0) {
1267
1268 left = malloc_or_die(sizeof(*left));
1269 *left = *arg;
1270
1271 arg->type = PRINT_OP;
1272 arg->op.op = token;
1273 arg->op.left = left;
1274
1275 arg->op.prio = 0;
1276 type = process_array(event, arg, tok);
1277
1278 } else {
1279 warning("unknown op '%s'", token);
1280 event->flags |= EVENT_FL_FAILED;
1281 /* the arg is now the left side */
1282 return EVENT_NONE;
1283 }
1284
1285 if (type == EVENT_OP) {
1286 int prio;
1287
1288 /* higher prios need to be closer to the root */
1289 prio = get_op_prio(*tok);
1290
1291 if (prio > arg->op.prio)
1292 return process_op(event, arg, tok);
1293
1294 return process_op(event, right, tok);
1295 }
1296
1297 return type;
1298}
1299
1300static enum event_type
1301process_entry(struct event *event __unused, struct print_arg *arg,
1302 char **tok)
1303{
1304 enum event_type type;
1305 char *field;
1306 char *token;
1307
1308 if (read_expected(EVENT_OP, "->") < 0)
1309 return EVENT_ERROR;
1310
1311 if (read_expect_type(EVENT_ITEM, &token) < 0)
1312 goto fail;
1313 field = token;
1314
1315 arg->type = PRINT_FIELD;
1316 arg->field.name = field;
1317
1318 if (is_flag_field) {
1319 arg->field.field = find_any_field(event, arg->field.name);
1320 arg->field.field->flags |= FIELD_IS_FLAG;
1321 is_flag_field = 0;
1322 } else if (is_symbolic_field) {
1323 arg->field.field = find_any_field(event, arg->field.name);
1324 arg->field.field->flags |= FIELD_IS_SYMBOLIC;
1325 is_symbolic_field = 0;
1326 }
1327
1328 type = read_token(&token);
1329 *tok = token;
1330
1331 return type;
1332
1333fail:
1334 free_token(token);
1335 return EVENT_ERROR;
1336}
1337
1338static char *arg_eval (struct print_arg *arg);
1339
1340static long long arg_num_eval(struct print_arg *arg)
1341{
1342 long long left, right;
1343 long long val = 0;
1344
1345 switch (arg->type) {
1346 case PRINT_ATOM:
1347 val = strtoll(arg->atom.atom, NULL, 0);
1348 break;
1349 case PRINT_TYPE:
1350 val = arg_num_eval(arg->typecast.item);
1351 break;
1352 case PRINT_OP:
1353 switch (arg->op.op[0]) {
1354 case '|':
1355 left = arg_num_eval(arg->op.left);
1356 right = arg_num_eval(arg->op.right);
1357 if (arg->op.op[1])
1358 val = left || right;
1359 else
1360 val = left | right;
1361 break;
1362 case '&':
1363 left = arg_num_eval(arg->op.left);
1364 right = arg_num_eval(arg->op.right);
1365 if (arg->op.op[1])
1366 val = left && right;
1367 else
1368 val = left & right;
1369 break;
1370 case '<':
1371 left = arg_num_eval(arg->op.left);
1372 right = arg_num_eval(arg->op.right);
1373 switch (arg->op.op[1]) {
1374 case 0:
1375 val = left < right;
1376 break;
1377 case '<':
1378 val = left << right;
1379 break;
1380 case '=':
1381 val = left <= right;
1382 break;
1383 default:
1384 die("unknown op '%s'", arg->op.op);
1385 }
1386 break;
1387 case '>':
1388 left = arg_num_eval(arg->op.left);
1389 right = arg_num_eval(arg->op.right);
1390 switch (arg->op.op[1]) {
1391 case 0:
1392 val = left > right;
1393 break;
1394 case '>':
1395 val = left >> right;
1396 break;
1397 case '=':
1398 val = left >= right;
1399 break;
1400 default:
1401 die("unknown op '%s'", arg->op.op);
1402 }
1403 break;
1404 case '=':
1405 left = arg_num_eval(arg->op.left);
1406 right = arg_num_eval(arg->op.right);
1407
1408 if (arg->op.op[1] != '=')
1409 die("unknown op '%s'", arg->op.op);
1410
1411 val = left == right;
1412 break;
1413 case '!':
1414 left = arg_num_eval(arg->op.left);
1415 right = arg_num_eval(arg->op.right);
1416
1417 switch (arg->op.op[1]) {
1418 case '=':
1419 val = left != right;
1420 break;
1421 default:
1422 die("unknown op '%s'", arg->op.op);
1423 }
1424 break;
1425 default:
1426 die("unknown op '%s'", arg->op.op);
1427 }
1428 break;
1429
1430 case PRINT_NULL:
1431 case PRINT_FIELD ... PRINT_SYMBOL:
1432 case PRINT_STRING:
1433 default:
1434 die("invalid eval type %d", arg->type);
1435
1436 }
1437 return val;
1438}
1439
1440static char *arg_eval (struct print_arg *arg)
1441{
1442 long long val;
1443 static char buf[20];
1444
1445 switch (arg->type) {
1446 case PRINT_ATOM:
1447 return arg->atom.atom;
1448 case PRINT_TYPE:
1449 return arg_eval(arg->typecast.item);
1450 case PRINT_OP:
1451 val = arg_num_eval(arg);
1452 sprintf(buf, "%lld", val);
1453 return buf;
1454
1455 case PRINT_NULL:
1456 case PRINT_FIELD ... PRINT_SYMBOL:
1457 case PRINT_STRING:
1458 default:
1459 die("invalid eval type %d", arg->type);
1460 break;
1461 }
1462
1463 return NULL;
1464}
1465
1466static enum event_type
1467process_fields(struct event *event, struct print_flag_sym **list, char **tok)
1468{
1469 enum event_type type;
1470 struct print_arg *arg = NULL;
1471 struct print_flag_sym *field;
1472 char *token = NULL;
1473 char *value;
1474
1475 do {
1476 free_token(token);
1477 type = read_token_item(&token);
1478 if (test_type_token(type, token, EVENT_OP, "{"))
1479 break;
1480
1481 arg = malloc_or_die(sizeof(*arg));
1482
1483 free_token(token);
1484 type = process_arg(event, arg, &token);
1485 if (test_type_token(type, token, EVENT_DELIM, ","))
1486 goto out_free;
1487
1488 field = malloc_or_die(sizeof(*field));
1489 memset(field, 0, sizeof(*field));
1490
1491 value = arg_eval(arg);
1492 field->value = strdup(value);
1493
1494 free_token(token);
1495 type = process_arg(event, arg, &token);
1496 if (test_type_token(type, token, EVENT_OP, "}"))
1497 goto out_free;
1498
1499 value = arg_eval(arg);
1500 field->str = strdup(value);
1501 free_arg(arg);
1502 arg = NULL;
1503
1504 *list = field;
1505 list = &field->next;
1506
1507 free_token(token);
1508 type = read_token_item(&token);
1509 } while (type == EVENT_DELIM && strcmp(token, ",") == 0);
1510
1511 *tok = token;
1512 return type;
1513
1514out_free:
1515 free_arg(arg);
1516 free_token(token);
1517
1518 return EVENT_ERROR;
1519}
1520
1521static enum event_type
1522process_flags(struct event *event, struct print_arg *arg, char **tok)
1523{
1524 struct print_arg *field;
1525 enum event_type type;
1526 char *token;
1527
1528 memset(arg, 0, sizeof(*arg));
1529 arg->type = PRINT_FLAGS;
1530
1531 if (read_expected_item(EVENT_DELIM, "(") < 0)
1532 return EVENT_ERROR;
1533
1534 field = malloc_or_die(sizeof(*field));
1535
1536 type = process_arg(event, field, &token);
1537 if (test_type_token(type, token, EVENT_DELIM, ","))
1538 goto out_free;
1539
1540 arg->flags.field = field;
1541
1542 type = read_token_item(&token);
1543 if (event_item_type(type)) {
1544 arg->flags.delim = token;
1545 type = read_token_item(&token);
1546 }
1547
1548 if (test_type_token(type, token, EVENT_DELIM, ","))
1549 goto out_free;
1550
1551 type = process_fields(event, &arg->flags.flags, &token);
1552 if (test_type_token(type, token, EVENT_DELIM, ")"))
1553 goto out_free;
1554
1555 free_token(token);
1556 type = read_token_item(tok);
1557 return type;
1558
1559out_free:
1560 free_token(token);
1561 return EVENT_ERROR;
1562}
1563
1564static enum event_type
1565process_symbols(struct event *event, struct print_arg *arg, char **tok)
1566{
1567 struct print_arg *field;
1568 enum event_type type;
1569 char *token;
1570
1571 memset(arg, 0, sizeof(*arg));
1572 arg->type = PRINT_SYMBOL;
1573
1574 if (read_expected_item(EVENT_DELIM, "(") < 0)
1575 return EVENT_ERROR;
1576
1577 field = malloc_or_die(sizeof(*field));
1578
1579 type = process_arg(event, field, &token);
1580 if (test_type_token(type, token, EVENT_DELIM, ","))
1581 goto out_free;
1582
1583 arg->symbol.field = field;
1584
1585 type = process_fields(event, &arg->symbol.symbols, &token);
1586 if (test_type_token(type, token, EVENT_DELIM, ")"))
1587 goto out_free;
1588
1589 free_token(token);
1590 type = read_token_item(tok);
1591 return type;
1592
1593out_free:
1594 free_token(token);
1595 return EVENT_ERROR;
1596}
1597
1598static enum event_type
1599process_paren(struct event *event, struct print_arg *arg, char **tok)
1600{
1601 struct print_arg *item_arg;
1602 enum event_type type;
1603 char *token;
1604
1605 type = process_arg(event, arg, &token);
1606
1607 if (type == EVENT_ERROR)
1608 return EVENT_ERROR;
1609
1610 if (type == EVENT_OP)
1611 type = process_op(event, arg, &token);
1612
1613 if (type == EVENT_ERROR)
1614 return EVENT_ERROR;
1615
1616 if (test_type_token(type, token, EVENT_DELIM, ")")) {
1617 free_token(token);
1618 return EVENT_ERROR;
1619 }
1620
1621 free_token(token);
1622 type = read_token_item(&token);
1623
1624 /*
1625 * If the next token is an item or another open paren, then
1626 * this was a typecast.
1627 */
1628 if (event_item_type(type) ||
1629 (type == EVENT_DELIM && strcmp(token, "(") == 0)) {
1630
1631 /* make this a typecast and contine */
1632
1633 /* prevous must be an atom */
1634 if (arg->type != PRINT_ATOM)
1635 die("previous needed to be PRINT_ATOM");
1636
1637 item_arg = malloc_or_die(sizeof(*item_arg));
1638
1639 arg->type = PRINT_TYPE;
1640 arg->typecast.type = arg->atom.atom;
1641 arg->typecast.item = item_arg;
1642 type = process_arg_token(event, item_arg, &token, type);
1643
1644 }
1645
1646 *tok = token;
1647 return type;
1648}
1649
1650
1651static enum event_type
1652process_str(struct event *event __unused, struct print_arg *arg, char **tok)
1653{
1654 enum event_type type;
1655 char *token;
1656
1657 if (read_expected(EVENT_DELIM, "(") < 0)
1658 return EVENT_ERROR;
1659
1660 if (read_expect_type(EVENT_ITEM, &token) < 0)
1661 goto fail;
1662
1663 arg->type = PRINT_STRING;
1664 arg->string.string = token;
1665 arg->string.offset = -1;
1666
1667 if (read_expected(EVENT_DELIM, ")") < 0)
1668 return EVENT_ERROR;
1669
1670 type = read_token(&token);
1671 *tok = token;
1672
1673 return type;
1674fail:
1675 free_token(token);
1676 return EVENT_ERROR;
1677}
1678
1679enum event_type
1680process_arg_token(struct event *event, struct print_arg *arg,
1681 char **tok, enum event_type type)
1682{
1683 char *token;
1684 char *atom;
1685
1686 token = *tok;
1687
1688 switch (type) {
1689 case EVENT_ITEM:
1690 if (strcmp(token, "REC") == 0) {
1691 free_token(token);
1692 type = process_entry(event, arg, &token);
1693 } else if (strcmp(token, "__print_flags") == 0) {
1694 free_token(token);
1695 is_flag_field = 1;
1696 type = process_flags(event, arg, &token);
1697 } else if (strcmp(token, "__print_symbolic") == 0) {
1698 free_token(token);
1699 is_symbolic_field = 1;
1700 type = process_symbols(event, arg, &token);
1701 } else if (strcmp(token, "__get_str") == 0) {
1702 free_token(token);
1703 type = process_str(event, arg, &token);
1704 } else {
1705 atom = token;
1706 /* test the next token */
1707 type = read_token_item(&token);
1708
1709 /* atoms can be more than one token long */
1710 while (type == EVENT_ITEM) {
1711 atom = realloc(atom, strlen(atom) + strlen(token) + 2);
1712 strcat(atom, " ");
1713 strcat(atom, token);
1714 free_token(token);
1715 type = read_token_item(&token);
1716 }
1717
1718 /* todo, test for function */
1719
1720 arg->type = PRINT_ATOM;
1721 arg->atom.atom = atom;
1722 }
1723 break;
1724 case EVENT_DQUOTE:
1725 case EVENT_SQUOTE:
1726 arg->type = PRINT_ATOM;
1727 arg->atom.atom = token;
1728 type = read_token_item(&token);
1729 break;
1730 case EVENT_DELIM:
1731 if (strcmp(token, "(") == 0) {
1732 free_token(token);
1733 type = process_paren(event, arg, &token);
1734 break;
1735 }
1736 case EVENT_OP:
1737 /* handle single ops */
1738 arg->type = PRINT_OP;
1739 arg->op.op = token;
1740 arg->op.left = NULL;
1741 type = process_op(event, arg, &token);
1742
1743 break;
1744
1745 case EVENT_ERROR ... EVENT_NEWLINE:
1746 default:
1747 die("unexpected type %d", type);
1748 }
1749 *tok = token;
1750
1751 return type;
1752}
1753
1754static int event_read_print_args(struct event *event, struct print_arg **list)
1755{
1756 enum event_type type = EVENT_ERROR;
1757 struct print_arg *arg;
1758 char *token;
1759 int args = 0;
1760
1761 do {
1762 if (type == EVENT_NEWLINE) {
1763 free_token(token);
1764 type = read_token_item(&token);
1765 continue;
1766 }
1767
1768 arg = malloc_or_die(sizeof(*arg));
1769 memset(arg, 0, sizeof(*arg));
1770
1771 type = process_arg(event, arg, &token);
1772
1773 if (type == EVENT_ERROR) {
1774 free_arg(arg);
1775 return -1;
1776 }
1777
1778 *list = arg;
1779 args++;
1780
1781 if (type == EVENT_OP) {
1782 type = process_op(event, arg, &token);
1783 list = &arg->next;
1784 continue;
1785 }
1786
1787 if (type == EVENT_DELIM && strcmp(token, ",") == 0) {
1788 free_token(token);
1789 *list = arg;
1790 list = &arg->next;
1791 continue;
1792 }
1793 break;
1794 } while (type != EVENT_NONE);
1795
1796 if (type != EVENT_NONE)
1797 free_token(token);
1798
1799 return args;
1800}
1801
1802static int event_read_print(struct event *event)
1803{
1804 enum event_type type;
1805 char *token;
1806 int ret;
1807
1808 if (read_expected_item(EVENT_ITEM, "print") < 0)
1809 return -1;
1810
1811 if (read_expected(EVENT_ITEM, "fmt") < 0)
1812 return -1;
1813
1814 if (read_expected(EVENT_OP, ":") < 0)
1815 return -1;
1816
1817 if (read_expect_type(EVENT_DQUOTE, &token) < 0)
1818 goto fail;
1819
1820 concat:
1821 event->print_fmt.format = token;
1822 event->print_fmt.args = NULL;
1823
1824 /* ok to have no arg */
1825 type = read_token_item(&token);
1826
1827 if (type == EVENT_NONE)
1828 return 0;
1829
1830 /* Handle concatination of print lines */
1831 if (type == EVENT_DQUOTE) {
1832 char *cat;
1833
1834 cat = malloc_or_die(strlen(event->print_fmt.format) +
1835 strlen(token) + 1);
1836 strcpy(cat, event->print_fmt.format);
1837 strcat(cat, token);
1838 free_token(token);
1839 free_token(event->print_fmt.format);
1840 event->print_fmt.format = NULL;
1841 token = cat;
1842 goto concat;
1843 }
1844
1845 if (test_type_token(type, token, EVENT_DELIM, ","))
1846 goto fail;
1847
1848 free_token(token);
1849
1850 ret = event_read_print_args(event, &event->print_fmt.args);
1851 if (ret < 0)
1852 return -1;
1853
1854 return ret;
1855
1856 fail:
1857 free_token(token);
1858 return -1;
1859}
1860
1861static struct format_field *
1862find_common_field(struct event *event, const char *name)
1863{
1864 struct format_field *format;
1865
1866 for (format = event->format.common_fields;
1867 format; format = format->next) {
1868 if (strcmp(format->name, name) == 0)
1869 break;
1870 }
1871
1872 return format;
1873}
1874
1875static struct format_field *
1876find_field(struct event *event, const char *name)
1877{
1878 struct format_field *format;
1879
1880 for (format = event->format.fields;
1881 format; format = format->next) {
1882 if (strcmp(format->name, name) == 0)
1883 break;
1884 }
1885
1886 return format;
1887}
1888
1889static struct format_field *
1890find_any_field(struct event *event, const char *name)
1891{
1892 struct format_field *format;
1893
1894 format = find_common_field(event, name);
1895 if (format)
1896 return format;
1897 return find_field(event, name);
1898}
1899
1900unsigned long long read_size(void *ptr, int size)
1901{
1902 switch (size) {
1903 case 1:
1904 return *(unsigned char *)ptr;
1905 case 2:
1906 return data2host2(ptr);
1907 case 4:
1908 return data2host4(ptr);
1909 case 8:
1910 return data2host8(ptr);
1911 default:
1912 /* BUG! */
1913 return 0;
1914 }
1915}
1916
1917unsigned long long
1918raw_field_value(struct event *event, const char *name, void *data)
1919{
1920 struct format_field *field;
1921
1922 field = find_any_field(event, name);
1923 if (!field)
1924 return 0ULL;
1925
1926 return read_size(data + field->offset, field->size);
1927}
1928
1929void *raw_field_ptr(struct event *event, const char *name, void *data)
1930{
1931 struct format_field *field;
1932
1933 field = find_any_field(event, name);
1934 if (!field)
1935 return NULL;
1936
1937 if (field->flags & FIELD_IS_DYNAMIC) {
1938 int offset;
1939
1940 offset = *(int *)(data + field->offset);
1941 offset &= 0xffff;
1942
1943 return data + offset;
1944 }
1945
1946 return data + field->offset;
1947}
1948
1949static int get_common_info(const char *type, int *offset, int *size)
1950{
1951 struct event *event;
1952 struct format_field *field;
1953
1954 /*
1955 * All events should have the same common elements.
1956 * Pick any event to find where the type is;
1957 */
1958 if (!event_list)
1959 die("no event_list!");
1960
1961 event = event_list;
1962 field = find_common_field(event, type);
1963 if (!field)
1964 die("field '%s' not found", type);
1965
1966 *offset = field->offset;
1967 *size = field->size;
1968
1969 return 0;
1970}
1971
1972static int __parse_common(void *data, int *size, int *offset,
1973 const char *name)
1974{
1975 int ret;
1976
1977 if (!*size) {
1978 ret = get_common_info(name, offset, size);
1979 if (ret < 0)
1980 return ret;
1981 }
1982 return read_size(data + *offset, *size);
1983}
1984
1985int trace_parse_common_type(void *data)
1986{
1987 static int type_offset;
1988 static int type_size;
1989
1990 return __parse_common(data, &type_size, &type_offset,
1991 "common_type");
1992}
1993
1994int trace_parse_common_pid(void *data)
1995{
1996 static int pid_offset;
1997 static int pid_size;
1998
1999 return __parse_common(data, &pid_size, &pid_offset,
2000 "common_pid");
2001}
2002
2003int parse_common_pc(void *data)
2004{
2005 static int pc_offset;
2006 static int pc_size;
2007
2008 return __parse_common(data, &pc_size, &pc_offset,
2009 "common_preempt_count");
2010}
2011
2012int parse_common_flags(void *data)
2013{
2014 static int flags_offset;
2015 static int flags_size;
2016
2017 return __parse_common(data, &flags_size, &flags_offset,
2018 "common_flags");
2019}
2020
2021int parse_common_lock_depth(void *data)
2022{
2023 static int ld_offset;
2024 static int ld_size;
2025 int ret;
2026
2027 ret = __parse_common(data, &ld_size, &ld_offset,
2028 "common_lock_depth");
2029 if (ret < 0)
2030 return -1;
2031
2032 return ret;
2033}
2034
2035struct event *trace_find_event(int id)
2036{
2037 struct event *event;
2038
2039 for (event = event_list; event; event = event->next) {
2040 if (event->id == id)
2041 break;
2042 }
2043 return event;
2044}
2045
2046struct event *trace_find_next_event(struct event *event)
2047{
2048 if (!event)
2049 return event_list;
2050
2051 return event->next;
2052}
2053
2054static unsigned long long eval_num_arg(void *data, int size,
2055 struct event *event, struct print_arg *arg)
2056{
2057 unsigned long long val = 0;
2058 unsigned long long left, right;
2059 struct print_arg *larg;
2060
2061 switch (arg->type) {
2062 case PRINT_NULL:
2063 /* ?? */
2064 return 0;
2065 case PRINT_ATOM:
2066 return strtoull(arg->atom.atom, NULL, 0);
2067 case PRINT_FIELD:
2068 if (!arg->field.field) {
2069 arg->field.field = find_any_field(event, arg->field.name);
2070 if (!arg->field.field)
2071 die("field %s not found", arg->field.name);
2072 }
2073 /* must be a number */
2074 val = read_size(data + arg->field.field->offset,
2075 arg->field.field->size);
2076 break;
2077 case PRINT_FLAGS:
2078 case PRINT_SYMBOL:
2079 break;
2080 case PRINT_TYPE:
2081 return eval_num_arg(data, size, event, arg->typecast.item);
2082 case PRINT_STRING:
2083 return 0;
2084 break;
2085 case PRINT_OP:
2086 if (strcmp(arg->op.op, "[") == 0) {
2087 /*
2088 * Arrays are special, since we don't want
2089 * to read the arg as is.
2090 */
2091 if (arg->op.left->type != PRINT_FIELD)
2092 goto default_op; /* oops, all bets off */
2093 larg = arg->op.left;
2094 if (!larg->field.field) {
2095 larg->field.field =
2096 find_any_field(event, larg->field.name);
2097 if (!larg->field.field)
2098 die("field %s not found", larg->field.name);
2099 }
2100 right = eval_num_arg(data, size, event, arg->op.right);
2101 val = read_size(data + larg->field.field->offset +
2102 right * long_size, long_size);
2103 break;
2104 }
2105 default_op:
2106 left = eval_num_arg(data, size, event, arg->op.left);
2107 right = eval_num_arg(data, size, event, arg->op.right);
2108 switch (arg->op.op[0]) {
2109 case '|':
2110 if (arg->op.op[1])
2111 val = left || right;
2112 else
2113 val = left | right;
2114 break;
2115 case '&':
2116 if (arg->op.op[1])
2117 val = left && right;
2118 else
2119 val = left & right;
2120 break;
2121 case '<':
2122 switch (arg->op.op[1]) {
2123 case 0:
2124 val = left < right;
2125 break;
2126 case '<':
2127 val = left << right;
2128 break;
2129 case '=':
2130 val = left <= right;
2131 break;
2132 default:
2133 die("unknown op '%s'", arg->op.op);
2134 }
2135 break;
2136 case '>':
2137 switch (arg->op.op[1]) {
2138 case 0:
2139 val = left > right;
2140 break;
2141 case '>':
2142 val = left >> right;
2143 break;
2144 case '=':
2145 val = left >= right;
2146 break;
2147 default:
2148 die("unknown op '%s'", arg->op.op);
2149 }
2150 break;
2151 case '=':
2152 if (arg->op.op[1] != '=')
2153 die("unknown op '%s'", arg->op.op);
2154 val = left == right;
2155 break;
2156 case '-':
2157 val = left - right;
2158 break;
2159 case '+':
2160 val = left + right;
2161 break;
2162 default:
2163 die("unknown op '%s'", arg->op.op);
2164 }
2165 break;
2166 default: /* not sure what to do there */
2167 return 0;
2168 }
2169 return val;
2170}
2171
2172struct flag {
2173 const char *name;
2174 unsigned long long value;
2175};
2176
2177static const struct flag flags[] = {
2178 { "HI_SOFTIRQ", 0 },
2179 { "TIMER_SOFTIRQ", 1 },
2180 { "NET_TX_SOFTIRQ", 2 },
2181 { "NET_RX_SOFTIRQ", 3 },
2182 { "BLOCK_SOFTIRQ", 4 },
2183 { "BLOCK_IOPOLL_SOFTIRQ", 5 },
2184 { "TASKLET_SOFTIRQ", 6 },
2185 { "SCHED_SOFTIRQ", 7 },
2186 { "HRTIMER_SOFTIRQ", 8 },
2187 { "RCU_SOFTIRQ", 9 },
2188
2189 { "HRTIMER_NORESTART", 0 },
2190 { "HRTIMER_RESTART", 1 },
2191};
2192
2193unsigned long long eval_flag(const char *flag)
2194{
2195 int i;
2196
2197 /*
2198 * Some flags in the format files do not get converted.
2199 * If the flag is not numeric, see if it is something that
2200 * we already know about.
2201 */
2202 if (isdigit(flag[0]))
2203 return strtoull(flag, NULL, 0);
2204
2205 for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); i++)
2206 if (strcmp(flags[i].name, flag) == 0)
2207 return flags[i].value;
2208
2209 return 0;
2210}
2211
2212static void print_str_arg(void *data, int size,
2213 struct event *event, struct print_arg *arg)
2214{
2215 struct print_flag_sym *flag;
2216 unsigned long long val, fval;
2217 char *str;
2218 int print;
2219
2220 switch (arg->type) {
2221 case PRINT_NULL:
2222 /* ?? */
2223 return;
2224 case PRINT_ATOM:
2225 printf("%s", arg->atom.atom);
2226 return;
2227 case PRINT_FIELD:
2228 if (!arg->field.field) {
2229 arg->field.field = find_any_field(event, arg->field.name);
2230 if (!arg->field.field)
2231 die("field %s not found", arg->field.name);
2232 }
2233 str = malloc_or_die(arg->field.field->size + 1);
2234 memcpy(str, data + arg->field.field->offset,
2235 arg->field.field->size);
2236 str[arg->field.field->size] = 0;
2237 printf("%s", str);
2238 free(str);
2239 break;
2240 case PRINT_FLAGS:
2241 val = eval_num_arg(data, size, event, arg->flags.field);
2242 print = 0;
2243 for (flag = arg->flags.flags; flag; flag = flag->next) {
2244 fval = eval_flag(flag->value);
2245 if (!val && !fval) {
2246 printf("%s", flag->str);
2247 break;
2248 }
2249 if (fval && (val & fval) == fval) {
2250 if (print && arg->flags.delim)
2251 printf("%s", arg->flags.delim);
2252 printf("%s", flag->str);
2253 print = 1;
2254 val &= ~fval;
2255 }
2256 }
2257 break;
2258 case PRINT_SYMBOL:
2259 val = eval_num_arg(data, size, event, arg->symbol.field);
2260 for (flag = arg->symbol.symbols; flag; flag = flag->next) {
2261 fval = eval_flag(flag->value);
2262 if (val == fval) {
2263 printf("%s", flag->str);
2264 break;
2265 }
2266 }
2267 break;
2268
2269 case PRINT_TYPE:
2270 break;
2271 case PRINT_STRING: {
2272 int str_offset;
2273
2274 if (arg->string.offset == -1) {
2275 struct format_field *f;
2276
2277 f = find_any_field(event, arg->string.string);
2278 arg->string.offset = f->offset;
2279 }
2280 str_offset = *(int *)(data + arg->string.offset);
2281 str_offset &= 0xffff;
2282 printf("%s", ((char *)data) + str_offset);
2283 break;
2284 }
2285 case PRINT_OP:
2286 /*
2287 * The only op for string should be ? :
2288 */
2289 if (arg->op.op[0] != '?')
2290 return;
2291 val = eval_num_arg(data, size, event, arg->op.left);
2292 if (val)
2293 print_str_arg(data, size, event, arg->op.right->op.left);
2294 else
2295 print_str_arg(data, size, event, arg->op.right->op.right);
2296 break;
2297 default:
2298 /* well... */
2299 break;
2300 }
2301}
2302
2303static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struct event *event)
2304{
2305 static struct format_field *field, *ip_field;
2306 struct print_arg *args, *arg, **next;
2307 unsigned long long ip, val;
2308 char *ptr;
2309 void *bptr;
2310
2311 if (!field) {
2312 field = find_field(event, "buf");
2313 if (!field)
2314 die("can't find buffer field for binary printk");
2315 ip_field = find_field(event, "ip");
2316 if (!ip_field)
2317 die("can't find ip field for binary printk");
2318 }
2319
2320 ip = read_size(data + ip_field->offset, ip_field->size);
2321
2322 /*
2323 * The first arg is the IP pointer.
2324 */
2325 args = malloc_or_die(sizeof(*args));
2326 arg = args;
2327 arg->next = NULL;
2328 next = &arg->next;
2329
2330 arg->type = PRINT_ATOM;
2331 arg->atom.atom = malloc_or_die(32);
2332 sprintf(arg->atom.atom, "%lld", ip);
2333
2334 /* skip the first "%pf : " */
2335 for (ptr = fmt + 6, bptr = data + field->offset;
2336 bptr < data + size && *ptr; ptr++) {
2337 int ls = 0;
2338
2339 if (*ptr == '%') {
2340 process_again:
2341 ptr++;
2342 switch (*ptr) {
2343 case '%':
2344 break;
2345 case 'l':
2346 ls++;
2347 goto process_again;
2348 case 'L':
2349 ls = 2;
2350 goto process_again;
2351 case '0' ... '9':
2352 goto process_again;
2353 case 'p':
2354 ls = 1;
2355 /* fall through */
2356 case 'd':
2357 case 'u':
2358 case 'x':
2359 case 'i':
2360 /* the pointers are always 4 bytes aligned */
2361 bptr = (void *)(((unsigned long)bptr + 3) &
2362 ~3);
2363 switch (ls) {
2364 case 0:
2365 case 1:
2366 ls = long_size;
2367 break;
2368 case 2:
2369 ls = 8;
2370 default:
2371 break;
2372 }
2373 val = read_size(bptr, ls);
2374 bptr += ls;
2375 arg = malloc_or_die(sizeof(*arg));
2376 arg->next = NULL;
2377 arg->type = PRINT_ATOM;
2378 arg->atom.atom = malloc_or_die(32);
2379 sprintf(arg->atom.atom, "%lld", val);
2380 *next = arg;
2381 next = &arg->next;
2382 break;
2383 case 's':
2384 arg = malloc_or_die(sizeof(*arg));
2385 arg->next = NULL;
2386 arg->type = PRINT_STRING;
2387 arg->string.string = strdup(bptr);
2388 bptr += strlen(bptr) + 1;
2389 *next = arg;
2390 next = &arg->next;
2391 default:
2392 break;
2393 }
2394 }
2395 }
2396
2397 return args;
2398}
2399
2400static void free_args(struct print_arg *args)
2401{
2402 struct print_arg *next;
2403
2404 while (args) {
2405 next = args->next;
2406
2407 if (args->type == PRINT_ATOM)
2408 free(args->atom.atom);
2409 else
2410 free(args->string.string);
2411 free(args);
2412 args = next;
2413 }
2414}
2415
2416static char *get_bprint_format(void *data, int size __unused, struct event *event)
2417{
2418 unsigned long long addr;
2419 static struct format_field *field;
2420 struct printk_map *printk;
2421 char *format;
2422 char *p;
2423
2424 if (!field) {
2425 field = find_field(event, "fmt");
2426 if (!field)
2427 die("can't find format field for binary printk");
2428 printf("field->offset = %d size=%d\n", field->offset, field->size);
2429 }
2430
2431 addr = read_size(data + field->offset, field->size);
2432
2433 printk = find_printk(addr);
2434 if (!printk) {
2435 format = malloc_or_die(45);
2436 sprintf(format, "%%pf : (NO FORMAT FOUND at %llx)\n",
2437 addr);
2438 return format;
2439 }
2440
2441 p = printk->printk;
2442 /* Remove any quotes. */
2443 if (*p == '"')
2444 p++;
2445 format = malloc_or_die(strlen(p) + 10);
2446 sprintf(format, "%s : %s", "%pf", p);
2447 /* remove ending quotes and new line since we will add one too */
2448 p = format + strlen(format) - 1;
2449 if (*p == '"')
2450 *p = 0;
2451
2452 p -= 2;
2453 if (strcmp(p, "\\n") == 0)
2454 *p = 0;
2455
2456 return format;
2457}
2458
2459static void pretty_print(void *data, int size, struct event *event)
2460{
2461 struct print_fmt *print_fmt = &event->print_fmt;
2462 struct print_arg *arg = print_fmt->args;
2463 struct print_arg *args = NULL;
2464 const char *ptr = print_fmt->format;
2465 unsigned long long val;
2466 struct func_map *func;
2467 const char *saveptr;
2468 char *bprint_fmt = NULL;
2469 char format[32];
2470 int show_func;
2471 int len;
2472 int ls;
2473
2474 if (event->flags & EVENT_FL_ISFUNC)
2475 ptr = " %pF <-- %pF";
2476
2477 if (event->flags & EVENT_FL_ISBPRINT) {
2478 bprint_fmt = get_bprint_format(data, size, event);
2479 args = make_bprint_args(bprint_fmt, data, size, event);
2480 arg = args;
2481 ptr = bprint_fmt;
2482 }
2483
2484 for (; *ptr; ptr++) {
2485 ls = 0;
2486 if (*ptr == '\\') {
2487 ptr++;
2488 switch (*ptr) {
2489 case 'n':
2490 printf("\n");
2491 break;
2492 case 't':
2493 printf("\t");
2494 break;
2495 case 'r':
2496 printf("\r");
2497 break;
2498 case '\\':
2499 printf("\\");
2500 break;
2501 default:
2502 printf("%c", *ptr);
2503 break;
2504 }
2505
2506 } else if (*ptr == '%') {
2507 saveptr = ptr;
2508 show_func = 0;
2509 cont_process:
2510 ptr++;
2511 switch (*ptr) {
2512 case '%':
2513 printf("%%");
2514 break;
2515 case 'l':
2516 ls++;
2517 goto cont_process;
2518 case 'L':
2519 ls = 2;
2520 goto cont_process;
2521 case 'z':
2522 case 'Z':
2523 case '0' ... '9':
2524 goto cont_process;
2525 case 'p':
2526 if (long_size == 4)
2527 ls = 1;
2528 else
2529 ls = 2;
2530
2531 if (*(ptr+1) == 'F' ||
2532 *(ptr+1) == 'f') {
2533 ptr++;
2534 show_func = *ptr;
2535 }
2536
2537 /* fall through */
2538 case 'd':
2539 case 'i':
2540 case 'x':
2541 case 'X':
2542 case 'u':
2543 if (!arg)
2544 die("no argument match");
2545
2546 len = ((unsigned long)ptr + 1) -
2547 (unsigned long)saveptr;
2548
2549 /* should never happen */
2550 if (len > 32)
2551 die("bad format!");
2552
2553 memcpy(format, saveptr, len);
2554 format[len] = 0;
2555
2556 val = eval_num_arg(data, size, event, arg);
2557 arg = arg->next;
2558
2559 if (show_func) {
2560 func = find_func(val);
2561 if (func) {
2562 printf("%s", func->func);
2563 if (show_func == 'F')
2564 printf("+0x%llx",
2565 val - func->addr);
2566 break;
2567 }
2568 }
2569 switch (ls) {
2570 case 0:
2571 printf(format, (int)val);
2572 break;
2573 case 1:
2574 printf(format, (long)val);
2575 break;
2576 case 2:
2577 printf(format, (long long)val);
2578 break;
2579 default:
2580 die("bad count (%d)", ls);
2581 }
2582 break;
2583 case 's':
2584 if (!arg)
2585 die("no matching argument");
2586
2587 print_str_arg(data, size, event, arg);
2588 arg = arg->next;
2589 break;
2590 default:
2591 printf(">%c<", *ptr);
2592
2593 }
2594 } else
2595 printf("%c", *ptr);
2596 }
2597
2598 if (args) {
2599 free_args(args);
2600 free(bprint_fmt);
2601 }
2602}
2603
2604static inline int log10_cpu(int nb)
2605{
2606 if (nb / 100)
2607 return 3;
2608 if (nb / 10)
2609 return 2;
2610 return 1;
2611}
2612
2613static void print_lat_fmt(void *data, int size __unused)
2614{
2615 unsigned int lat_flags;
2616 unsigned int pc;
2617 int lock_depth;
2618 int hardirq;
2619 int softirq;
2620
2621 lat_flags = parse_common_flags(data);
2622 pc = parse_common_pc(data);
2623 lock_depth = parse_common_lock_depth(data);
2624
2625 hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
2626 softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
2627
2628 printf("%c%c%c",
2629 (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' :
2630 (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ?
2631 'X' : '.',
2632 (lat_flags & TRACE_FLAG_NEED_RESCHED) ?
2633 'N' : '.',
2634 (hardirq && softirq) ? 'H' :
2635 hardirq ? 'h' : softirq ? 's' : '.');
2636
2637 if (pc)
2638 printf("%x", pc);
2639 else
2640 printf(".");
2641
2642 if (lock_depth < 0)
2643 printf(". ");
2644 else
2645 printf("%d ", lock_depth);
2646}
2647
2648#define TRACE_GRAPH_INDENT 2
2649
2650static struct record *
2651get_return_for_leaf(int cpu, int cur_pid, unsigned long long cur_func,
2652 struct record *next)
2653{
2654 struct format_field *field;
2655 struct event *event;
2656 unsigned long val;
2657 int type;
2658 int pid;
2659
2660 type = trace_parse_common_type(next->data);
2661 event = trace_find_event(type);
2662 if (!event)
2663 return NULL;
2664
2665 if (!(event->flags & EVENT_FL_ISFUNCRET))
2666 return NULL;
2667
2668 pid = trace_parse_common_pid(next->data);
2669 field = find_field(event, "func");
2670 if (!field)
2671 die("function return does not have field func");
2672
2673 val = read_size(next->data + field->offset, field->size);
2674
2675 if (cur_pid != pid || cur_func != val)
2676 return NULL;
2677
2678 /* this is a leaf, now advance the iterator */
2679 return trace_read_data(cpu);
2680}
2681
2682/* Signal a overhead of time execution to the output */
2683static void print_graph_overhead(unsigned long long duration)
2684{
2685 /* Non nested entry or return */
2686 if (duration == ~0ULL)
2687 return (void)printf(" ");
2688
2689 /* Duration exceeded 100 msecs */
2690 if (duration > 100000ULL)
2691 return (void)printf("! ");
2692
2693 /* Duration exceeded 10 msecs */
2694 if (duration > 10000ULL)
2695 return (void)printf("+ ");
2696
2697 printf(" ");
2698}
2699
2700static void print_graph_duration(unsigned long long duration)
2701{
2702 unsigned long usecs = duration / 1000;
2703 unsigned long nsecs_rem = duration % 1000;
2704 /* log10(ULONG_MAX) + '\0' */
2705 char msecs_str[21];
2706 char nsecs_str[5];
2707 int len;
2708 int i;
2709
2710 sprintf(msecs_str, "%lu", usecs);
2711
2712 /* Print msecs */
2713 len = printf("%lu", usecs);
2714
2715 /* Print nsecs (we don't want to exceed 7 numbers) */
2716 if (len < 7) {
2717 snprintf(nsecs_str, 8 - len, "%03lu", nsecs_rem);
2718 len += printf(".%s", nsecs_str);
2719 }
2720
2721 printf(" us ");
2722
2723 /* Print remaining spaces to fit the row's width */
2724 for (i = len; i < 7; i++)
2725 printf(" ");
2726
2727 printf("| ");
2728}
2729
2730static void
2731print_graph_entry_leaf(struct event *event, void *data, struct record *ret_rec)
2732{
2733 unsigned long long rettime, calltime;
2734 unsigned long long duration, depth;
2735 unsigned long long val;
2736 struct format_field *field;
2737 struct func_map *func;
2738 struct event *ret_event;
2739 int type;
2740 int i;
2741
2742 type = trace_parse_common_type(ret_rec->data);
2743 ret_event = trace_find_event(type);
2744
2745 field = find_field(ret_event, "rettime");
2746 if (!field)
2747 die("can't find rettime in return graph");
2748 rettime = read_size(ret_rec->data + field->offset, field->size);
2749
2750 field = find_field(ret_event, "calltime");
2751 if (!field)
2752 die("can't find rettime in return graph");
2753 calltime = read_size(ret_rec->data + field->offset, field->size);
2754
2755 duration = rettime - calltime;
2756
2757 /* Overhead */
2758 print_graph_overhead(duration);
2759
2760 /* Duration */
2761 print_graph_duration(duration);
2762
2763 field = find_field(event, "depth");
2764 if (!field)
2765 die("can't find depth in entry graph");
2766 depth = read_size(data + field->offset, field->size);
2767
2768 /* Function */
2769 for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++)
2770 printf(" ");
2771
2772 field = find_field(event, "func");
2773 if (!field)
2774 die("can't find func in entry graph");
2775 val = read_size(data + field->offset, field->size);
2776 func = find_func(val);
2777
2778 if (func)
2779 printf("%s();", func->func);
2780 else
2781 printf("%llx();", val);
2782}
2783
2784static void print_graph_nested(struct event *event, void *data)
2785{
2786 struct format_field *field;
2787 unsigned long long depth;
2788 unsigned long long val;
2789 struct func_map *func;
2790 int i;
2791
2792 /* No overhead */
2793 print_graph_overhead(-1);
2794
2795 /* No time */
2796 printf(" | ");
2797
2798 field = find_field(event, "depth");
2799 if (!field)
2800 die("can't find depth in entry graph");
2801 depth = read_size(data + field->offset, field->size);
2802
2803 /* Function */
2804 for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++)
2805 printf(" ");
2806
2807 field = find_field(event, "func");
2808 if (!field)
2809 die("can't find func in entry graph");
2810 val = read_size(data + field->offset, field->size);
2811 func = find_func(val);
2812
2813 if (func)
2814 printf("%s() {", func->func);
2815 else
2816 printf("%llx() {", val);
2817}
2818
2819static void
2820pretty_print_func_ent(void *data, int size, struct event *event,
2821 int cpu, int pid)
2822{
2823 struct format_field *field;
2824 struct record *rec;
2825 void *copy_data;
2826 unsigned long val;
2827
2828 if (latency_format) {
2829 print_lat_fmt(data, size);
2830 printf(" | ");
2831 }
2832
2833 field = find_field(event, "func");
2834 if (!field)
2835 die("function entry does not have func field");
2836
2837 val = read_size(data + field->offset, field->size);
2838
2839 /*
2840 * peek_data may unmap the data pointer. Copy it first.
2841 */
2842 copy_data = malloc_or_die(size);
2843 memcpy(copy_data, data, size);
2844 data = copy_data;
2845
2846 rec = trace_peek_data(cpu);
2847 if (rec) {
2848 rec = get_return_for_leaf(cpu, pid, val, rec);
2849 if (rec) {
2850 print_graph_entry_leaf(event, data, rec);
2851 goto out_free;
2852 }
2853 }
2854 print_graph_nested(event, data);
2855out_free:
2856 free(data);
2857}
2858
2859static void
2860pretty_print_func_ret(void *data, int size __unused, struct event *event)
2861{
2862 unsigned long long rettime, calltime;
2863 unsigned long long duration, depth;
2864 struct format_field *field;
2865 int i;
2866
2867 if (latency_format) {
2868 print_lat_fmt(data, size);
2869 printf(" | ");
2870 }
2871
2872 field = find_field(event, "rettime");
2873 if (!field)
2874 die("can't find rettime in return graph");
2875 rettime = read_size(data + field->offset, field->size);
2876
2877 field = find_field(event, "calltime");
2878 if (!field)
2879 die("can't find calltime in return graph");
2880 calltime = read_size(data + field->offset, field->size);
2881
2882 duration = rettime - calltime;
2883
2884 /* Overhead */
2885 print_graph_overhead(duration);
2886
2887 /* Duration */
2888 print_graph_duration(duration);
2889
2890 field = find_field(event, "depth");
2891 if (!field)
2892 die("can't find depth in entry graph");
2893 depth = read_size(data + field->offset, field->size);
2894
2895 /* Function */
2896 for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++)
2897 printf(" ");
2898
2899 printf("}");
2900}
2901
2902static void
2903pretty_print_func_graph(void *data, int size, struct event *event,
2904 int cpu, int pid)
2905{
2906 if (event->flags & EVENT_FL_ISFUNCENT)
2907 pretty_print_func_ent(data, size, event, cpu, pid);
2908 else if (event->flags & EVENT_FL_ISFUNCRET)
2909 pretty_print_func_ret(data, size, event);
2910 printf("\n");
2911}
2912
2913void print_trace_event(int cpu, void *data, int size)
2914{
2915 struct event *event;
2916 int type;
2917 int pid;
2918
2919 type = trace_parse_common_type(data);
2920
2921 event = trace_find_event(type);
2922 if (!event) {
2923 warning("ug! no event found for type %d", type);
2924 return;
2925 }
2926
2927 pid = trace_parse_common_pid(data);
2928
2929 if (event->flags & (EVENT_FL_ISFUNCENT | EVENT_FL_ISFUNCRET))
2930 return pretty_print_func_graph(data, size, event, cpu, pid);
2931
2932 if (latency_format)
2933 print_lat_fmt(data, size);
2934
2935 if (event->flags & EVENT_FL_FAILED) {
2936 printf("EVENT '%s' FAILED TO PARSE\n",
2937 event->name);
2938 return;
2939 }
2940
2941 pretty_print(data, size, event);
2942}
2943
2944static void print_fields(struct print_flag_sym *field)
2945{
2946 printf("{ %s, %s }", field->value, field->str);
2947 if (field->next) {
2948 printf(", ");
2949 print_fields(field->next);
2950 }
2951}
2952
2953static void print_args(struct print_arg *args)
2954{
2955 int print_paren = 1;
2956
2957 switch (args->type) {
2958 case PRINT_NULL:
2959 printf("null");
2960 break;
2961 case PRINT_ATOM:
2962 printf("%s", args->atom.atom);
2963 break;
2964 case PRINT_FIELD:
2965 printf("REC->%s", args->field.name);
2966 break;
2967 case PRINT_FLAGS:
2968 printf("__print_flags(");
2969 print_args(args->flags.field);
2970 printf(", %s, ", args->flags.delim);
2971 print_fields(args->flags.flags);
2972 printf(")");
2973 break;
2974 case PRINT_SYMBOL:
2975 printf("__print_symbolic(");
2976 print_args(args->symbol.field);
2977 printf(", ");
2978 print_fields(args->symbol.symbols);
2979 printf(")");
2980 break;
2981 case PRINT_STRING:
2982 printf("__get_str(%s)", args->string.string);
2983 break;
2984 case PRINT_TYPE:
2985 printf("(%s)", args->typecast.type);
2986 print_args(args->typecast.item);
2987 break;
2988 case PRINT_OP:
2989 if (strcmp(args->op.op, ":") == 0)
2990 print_paren = 0;
2991 if (print_paren)
2992 printf("(");
2993 print_args(args->op.left);
2994 printf(" %s ", args->op.op);
2995 print_args(args->op.right);
2996 if (print_paren)
2997 printf(")");
2998 break;
2999 default:
3000 /* we should warn... */
3001 return;
3002 }
3003 if (args->next) {
3004 printf("\n");
3005 print_args(args->next);
3006 }
3007}
3008
3009int parse_ftrace_file(char *buf, unsigned long size)
3010{
3011 struct format_field *field;
3012 struct print_arg *arg, **list;
3013 struct event *event;
3014 int ret;
3015
3016 init_input_buf(buf, size);
3017
3018 event = alloc_event();
3019 if (!event)
3020 return -ENOMEM;
3021
3022 event->flags |= EVENT_FL_ISFTRACE;
3023
3024 event->name = event_read_name();
3025 if (!event->name)
3026 die("failed to read ftrace event name");
3027
3028 if (strcmp(event->name, "function") == 0)
3029 event->flags |= EVENT_FL_ISFUNC;
3030
3031 else if (strcmp(event->name, "funcgraph_entry") == 0)
3032 event->flags |= EVENT_FL_ISFUNCENT;
3033
3034 else if (strcmp(event->name, "funcgraph_exit") == 0)
3035 event->flags |= EVENT_FL_ISFUNCRET;
3036
3037 else if (strcmp(event->name, "bprint") == 0)
3038 event->flags |= EVENT_FL_ISBPRINT;
3039
3040 event->id = event_read_id();
3041 if (event->id < 0)
3042 die("failed to read ftrace event id");
3043
3044 add_event(event);
3045
3046 ret = event_read_format(event);
3047 if (ret < 0)
3048 die("failed to read ftrace event format");
3049
3050 ret = event_read_print(event);
3051 if (ret < 0)
3052 die("failed to read ftrace event print fmt");
3053
3054 /* New ftrace handles args */
3055 if (ret > 0)
3056 return 0;
3057 /*
3058 * The arguments for ftrace files are parsed by the fields.
3059 * Set up the fields as their arguments.
3060 */
3061 list = &event->print_fmt.args;
3062 for (field = event->format.fields; field; field = field->next) {
3063 arg = malloc_or_die(sizeof(*arg));
3064 memset(arg, 0, sizeof(*arg));
3065 *list = arg;
3066 list = &arg->next;
3067 arg->type = PRINT_FIELD;
3068 arg->field.name = field->name;
3069 arg->field.field = field;
3070 }
3071 return 0;
3072}
3073
3074int parse_event_file(char *buf, unsigned long size, char *sys)
3075{
3076 struct event *event;
3077 int ret;
3078
3079 init_input_buf(buf, size);
3080
3081 event = alloc_event();
3082 if (!event)
3083 return -ENOMEM;
3084
3085 event->name = event_read_name();
3086 if (!event->name)
3087 die("failed to read event name");
3088
3089 event->id = event_read_id();
3090 if (event->id < 0)
3091 die("failed to read event id");
3092
3093 ret = event_read_format(event);
3094 if (ret < 0) {
3095 warning("failed to read event format for %s", event->name);
3096 goto event_failed;
3097 }
3098
3099 ret = event_read_print(event);
3100 if (ret < 0) {
3101 warning("failed to read event print fmt for %s", event->name);
3102 goto event_failed;
3103 }
3104
3105 event->system = strdup(sys);
3106
3107#define PRINT_ARGS 0
3108 if (PRINT_ARGS && event->print_fmt.args)
3109 print_args(event->print_fmt.args);
3110
3111 add_event(event);
3112 return 0;
3113
3114 event_failed:
3115 event->flags |= EVENT_FL_FAILED;
3116 /* still add it even if it failed */
3117 add_event(event);
3118 return -1;
3119}
3120
3121void parse_set_info(int nr_cpus, int long_sz)
3122{
3123 cpus = nr_cpus;
3124 long_size = long_sz;
3125}
diff --git a/tools/perf/util/trace-parse-events.h b/tools/perf/util/trace-parse-events.h
deleted file mode 100644
index 794ec15ef084..000000000000
--- a/tools/perf/util/trace-parse-events.h
+++ /dev/null
@@ -1,273 +0,0 @@
1#ifndef __PERF_TRACE_EVENTS_H
2#define __PERF_TRACE_EVENTS_H
3
4#include <stdbool.h>
5#include <unistd.h>
6
7#define __unused __attribute__((unused))
8
9
10#ifndef PAGE_MASK
11#define PAGE_MASK (page_size - 1)
12#endif
13
14enum {
15 RINGBUF_TYPE_PADDING = 29,
16 RINGBUF_TYPE_TIME_EXTEND = 30,
17 RINGBUF_TYPE_TIME_STAMP = 31,
18};
19
20#ifndef TS_SHIFT
21#define TS_SHIFT 27
22#endif
23
24#define NSECS_PER_SEC 1000000000ULL
25#define NSECS_PER_USEC 1000ULL
26
27enum format_flags {
28 FIELD_IS_ARRAY = 1,
29 FIELD_IS_POINTER = 2,
30 FIELD_IS_SIGNED = 4,
31 FIELD_IS_STRING = 8,
32 FIELD_IS_DYNAMIC = 16,
33 FIELD_IS_FLAG = 32,
34 FIELD_IS_SYMBOLIC = 64,
35};
36
37struct format_field {
38 struct format_field *next;
39 char *type;
40 char *name;
41 int offset;
42 int size;
43 unsigned long flags;
44};
45
46struct format {
47 int nr_common;
48 int nr_fields;
49 struct format_field *common_fields;
50 struct format_field *fields;
51};
52
53struct print_arg_atom {
54 char *atom;
55};
56
57struct print_arg_string {
58 char *string;
59 int offset;
60};
61
62struct print_arg_field {
63 char *name;
64 struct format_field *field;
65};
66
67struct print_flag_sym {
68 struct print_flag_sym *next;
69 char *value;
70 char *str;
71};
72
73struct print_arg_typecast {
74 char *type;
75 struct print_arg *item;
76};
77
78struct print_arg_flags {
79 struct print_arg *field;
80 char *delim;
81 struct print_flag_sym *flags;
82};
83
84struct print_arg_symbol {
85 struct print_arg *field;
86 struct print_flag_sym *symbols;
87};
88
89struct print_arg;
90
91struct print_arg_op {
92 char *op;
93 int prio;
94 struct print_arg *left;
95 struct print_arg *right;
96};
97
98struct print_arg_func {
99 char *name;
100 struct print_arg *args;
101};
102
103enum print_arg_type {
104 PRINT_NULL,
105 PRINT_ATOM,
106 PRINT_FIELD,
107 PRINT_FLAGS,
108 PRINT_SYMBOL,
109 PRINT_TYPE,
110 PRINT_STRING,
111 PRINT_OP,
112};
113
114struct print_arg {
115 struct print_arg *next;
116 enum print_arg_type type;
117 union {
118 struct print_arg_atom atom;
119 struct print_arg_field field;
120 struct print_arg_typecast typecast;
121 struct print_arg_flags flags;
122 struct print_arg_symbol symbol;
123 struct print_arg_func func;
124 struct print_arg_string string;
125 struct print_arg_op op;
126 };
127};
128
129struct print_fmt {
130 char *format;
131 struct print_arg *args;
132};
133
134struct event {
135 struct event *next;
136 char *name;
137 int id;
138 int flags;
139 struct format format;
140 struct print_fmt print_fmt;
141 char *system;
142};
143
144enum {
145 EVENT_FL_ISFTRACE = 0x01,
146 EVENT_FL_ISPRINT = 0x02,
147 EVENT_FL_ISBPRINT = 0x04,
148 EVENT_FL_ISFUNC = 0x08,
149 EVENT_FL_ISFUNCENT = 0x10,
150 EVENT_FL_ISFUNCRET = 0x20,
151
152 EVENT_FL_FAILED = 0x80000000
153};
154
155struct record {
156 unsigned long long ts;
157 int size;
158 void *data;
159};
160
161struct record *trace_peek_data(int cpu);
162struct record *trace_read_data(int cpu);
163
164void parse_set_info(int nr_cpus, int long_sz);
165
166ssize_t trace_report(int fd, bool repipe);
167
168void *malloc_or_die(unsigned int size);
169
170void parse_cmdlines(char *file, int size);
171void parse_proc_kallsyms(char *file, unsigned int size);
172void parse_ftrace_printk(char *file, unsigned int size);
173
174void print_funcs(void);
175void print_printk(void);
176
177int parse_ftrace_file(char *buf, unsigned long size);
178int parse_event_file(char *buf, unsigned long size, char *sys);
179void print_trace_event(int cpu, void *data, int size);
180
181extern int file_bigendian;
182extern int host_bigendian;
183
184int bigendian(void);
185
186static inline unsigned short __data2host2(unsigned short data)
187{
188 unsigned short swap;
189
190 if (host_bigendian == file_bigendian)
191 return data;
192
193 swap = ((data & 0xffULL) << 8) |
194 ((data & (0xffULL << 8)) >> 8);
195
196 return swap;
197}
198
199static inline unsigned int __data2host4(unsigned int data)
200{
201 unsigned int swap;
202
203 if (host_bigendian == file_bigendian)
204 return data;
205
206 swap = ((data & 0xffULL) << 24) |
207 ((data & (0xffULL << 8)) << 8) |
208 ((data & (0xffULL << 16)) >> 8) |
209 ((data & (0xffULL << 24)) >> 24);
210
211 return swap;
212}
213
214static inline unsigned long long __data2host8(unsigned long long data)
215{
216 unsigned long long swap;
217
218 if (host_bigendian == file_bigendian)
219 return data;
220
221 swap = ((data & 0xffULL) << 56) |
222 ((data & (0xffULL << 8)) << 40) |
223 ((data & (0xffULL << 16)) << 24) |
224 ((data & (0xffULL << 24)) << 8) |
225 ((data & (0xffULL << 32)) >> 8) |
226 ((data & (0xffULL << 40)) >> 24) |
227 ((data & (0xffULL << 48)) >> 40) |
228 ((data & (0xffULL << 56)) >> 56);
229
230 return swap;
231}
232
233#define data2host2(ptr) __data2host2(*(unsigned short *)ptr)
234#define data2host4(ptr) __data2host4(*(unsigned int *)ptr)
235#define data2host8(ptr) ({ \
236 unsigned long long __val; \
237 \
238 memcpy(&__val, (ptr), sizeof(unsigned long long)); \
239 __data2host8(__val); \
240})
241
242extern int header_page_ts_offset;
243extern int header_page_ts_size;
244extern int header_page_size_offset;
245extern int header_page_size_size;
246extern int header_page_data_offset;
247extern int header_page_data_size;
248
249extern bool latency_format;
250
251int trace_parse_common_type(void *data);
252int trace_parse_common_pid(void *data);
253int parse_common_pc(void *data);
254int parse_common_flags(void *data);
255int parse_common_lock_depth(void *data);
256struct event *trace_find_event(int id);
257struct event *trace_find_next_event(struct event *event);
258unsigned long long read_size(void *ptr, int size);
259unsigned long long
260raw_field_value(struct event *event, const char *name, void *data);
261void *raw_field_ptr(struct event *event, const char *name, void *data);
262unsigned long long eval_flag(const char *flag);
263
264/* taken from kernel/trace/trace.h */
265enum trace_flag_type {
266 TRACE_FLAG_IRQS_OFF = 0x01,
267 TRACE_FLAG_IRQS_NOSUPPORT = 0x02,
268 TRACE_FLAG_NEED_RESCHED = 0x04,
269 TRACE_FLAG_HARDIRQ = 0x08,
270 TRACE_FLAG_SOFTIRQ = 0x10,
271};
272
273#endif /* __PERF_TRACE_EVENTS_H */