aboutsummaryrefslogtreecommitdiffstats
path: root/tools/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-04-14 17:37:47 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-04-14 17:37:47 -0400
commit6c8a53c9e6a151fffb07f8b4c34bd1e33dddd467 (patch)
tree791caf826ef136c521a97b7878f226b6ba1c1d75 /tools/lib
parente95e7f627062be5e6ce971ce873e6234c91ffc50 (diff)
parent066450be419fa48007a9f29e19828f2a86198754 (diff)
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf changes from Ingo Molnar: "Core kernel changes: - One of the more interesting features in this cycle is the ability to attach eBPF programs (user-defined, sandboxed bytecode executed by the kernel) to kprobes. This allows user-defined instrumentation on a live kernel image that can never crash, hang or interfere with the kernel negatively. (Right now it's limited to root-only, but in the future we might allow unprivileged use as well.) (Alexei Starovoitov) - Another non-trivial feature is per event clockid support: this allows, amongst other things, the selection of different clock sources for event timestamps traced via perf. This feature is sought by people who'd like to merge perf generated events with external events that were measured with different clocks: - cluster wide profiling - for system wide tracing with user-space events, - JIT profiling events etc. Matching perf tooling support is added as well, available via the -k, --clockid <clockid> parameter to perf record et al. (Peter Zijlstra) Hardware enablement kernel changes: - x86 Intel Processor Trace (PT) support: which is a hardware tracer on steroids, available on Broadwell CPUs. The hardware trace stream is directly output into the user-space ring-buffer, using the 'AUX' data format extension that was added to the perf core to support hardware constraints such as the necessity to have the tracing buffer physically contiguous. This patch-set was developed for two years and this is the result. A simple way to make use of this is to use BTS tracing, the PT driver emulates BTS output - available via the 'intel_bts' PMU. More explicit PT specific tooling support is in the works as well - will probably be ready by 4.2. (Alexander Shishkin, Peter Zijlstra) - x86 Intel Cache QoS Monitoring (CQM) support: this is a hardware feature of Intel Xeon CPUs that allows the measurement and allocation/partitioning of caches to individual workloads. These kernel changes expose the measurement side as a new PMU driver, which exposes various QoS related PMU events. (The partitioning change is work in progress and is planned to be merged as a cgroup extension.) (Matt Fleming, Peter Zijlstra; CPU feature detection by Peter P Waskiewicz Jr) - x86 Intel Haswell LBR call stack support: this is a new Haswell feature that allows the hardware recording of call chains, plus tooling support. To activate this feature you have to enable it via the new 'lbr' call-graph recording option: perf record --call-graph lbr perf report or: perf top --call-graph lbr This hardware feature is a lot faster than stack walk or dwarf based unwinding, but has some limitations: - It reuses the current LBR facility, so LBR call stack and branch record can not be enabled at the same time. - It is only available for user-space callchains. (Yan, Zheng) - x86 Intel Broadwell CPU support and various event constraints and event table fixes for earlier models. (Andi Kleen) - x86 Intel HT CPUs event scheduling workarounds. This is a complex CPU bug affecting the SNB,IVB,HSW families that results in counter value corruption. The mitigation code is automatically enabled and is transparent. (Maria Dimakopoulou, Stephane Eranian) The perf tooling side had a ton of changes in this cycle as well, so I'm only able to list the user visible changes here, in addition to the tooling changes outlined above: User visible changes affecting all tools: - Improve support of compressed kernel modules (Jiri Olsa) - Save DSO loading errno to better report errors (Arnaldo Carvalho de Melo) - Bash completion for subcommands (Yunlong Song) - Add 'I' event modifier for perf_event_attr.exclude_idle bit (Jiri Olsa) - Support missing -f to override perf.data file ownership. (Yunlong Song) - Show the first event with an invalid filter (David Ahern, Arnaldo Carvalho de Melo) User visible changes in individual tools: 'perf data': New tool for converting perf.data to other formats, initially for the CTF (Common Trace Format) from LTTng (Jiri Olsa, Sebastian Siewior) 'perf diff': Add --kallsyms option (David Ahern) 'perf list': Allow listing events with 'tracepoint' prefix (Yunlong Song) Sort the output of the command (Yunlong Song) 'perf kmem': Respect -i option (Jiri Olsa) Print big numbers using thousands' group (Namhyung Kim) Allow -v option (Namhyung Kim) Fix alignment of slab result table (Namhyung Kim) 'perf probe': Support multiple probes on different binaries on the same command line (Masami Hiramatsu) Support unnamed union/structure members data collection. (Masami Hiramatsu) Check kprobes blacklist when adding new events. (Masami Hiramatsu) 'perf record': Teach 'perf record' about perf_event_attr.clockid (Peter Zijlstra) Support recording running/enabled time (Andi Kleen) 'perf sched': Improve the performance of 'perf sched replay' on high CPU core count machines (Yunlong Song) 'perf report' and 'perf top': Allow annotating entries in callchains in the hists browser (Arnaldo Carvalho de Melo) Indicate which callchain entries are annotated in the TUI hists browser (Arnaldo Carvalho de Melo) Add pid/tid filtering to 'report' and 'script' commands (David Ahern) Consider PERF_RECORD_ events with cpumode == 0 in 'perf top', removing one cause of long term memory usage buildup, i.e. not processing PERF_RECORD_EXIT events (Arnaldo Carvalho de Melo) 'perf stat': Report unsupported events properly (Suzuki K. Poulose) Output running time and run/enabled ratio in CSV mode (Andi Kleen) 'perf trace': Handle legacy syscalls tracepoints (David Ahern, Arnaldo Carvalho de Melo) Only insert blank duration bracket when tracing syscalls (Arnaldo Carvalho de Melo) Filter out the trace pid when no threads are specified (Arnaldo Carvalho de Melo) Dump stack on segfaults (Arnaldo Carvalho de Melo) No need to explicitely enable evsels for workload started from perf, let it be enabled via perf_event_attr.enable_on_exec, removing some events that take place in the 'perf trace' before a workload is really started by it. (Arnaldo Carvalho de Melo) Allow mixing with tracepoints and suppressing plain syscalls. (Arnaldo Carvalho de Melo) There's also been a ton of infrastructure work done, such as the split-out of perf's build system into tools/build/ and other changes - see the shortlog and changelog for details" * 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (358 commits) perf/x86/intel/pt: Clean up the control flow in pt_pmu_hw_init() perf evlist: Fix type for references to data_head/tail perf probe: Check the orphaned -x option perf probe: Support multiple probes on different binaries perf buildid-list: Fix segfault when show DSOs with hits perf tools: Fix cross-endian analysis perf tools: Fix error path to do closedir() when synthesizing threads perf tools: Fix synthesizing fork_event.ppid for non-main thread perf tools: Add 'I' event modifier for exclude_idle bit perf report: Don't call map__kmap if map is NULL. perf tests: Fix attr tests perf probe: Fix ARM 32 building error perf tools: Merge all perf_event_attr print functions perf record: Add clockid parameter perf sched replay: Use replay_repeat to calculate the runavg of cpu usage instead of the default value 10 perf sched replay: Support using -f to override perf.data file ownership perf sched replay: Fix the EMFILE error caused by the limitation of the maximum open files perf sched replay: Handle the dead halt of sem_wait when create_tasks() fails for any task perf sched replay: Fix the segmentation fault problem caused by pr_err in threads perf sched replay: Realloc the memory of pid_to_task stepwise to adapt to the different pid_max configurations ...
Diffstat (limited to 'tools/lib')
-rw-r--r--tools/lib/api/Build2
-rw-r--r--tools/lib/api/Makefile58
-rw-r--r--tools/lib/api/fd/Build1
-rw-r--r--tools/lib/api/fs/Build4
-rw-r--r--tools/lib/api/fs/debugfs.c69
-rw-r--r--tools/lib/api/fs/debugfs.h13
-rw-r--r--tools/lib/api/fs/findfs.c63
-rw-r--r--tools/lib/api/fs/findfs.h23
-rw-r--r--tools/lib/api/fs/tracefs.c78
-rw-r--r--tools/lib/api/fs/tracefs.h21
-rw-r--r--tools/lib/lockdep/Build1
-rw-r--r--tools/lib/lockdep/Makefile132
-rw-r--r--tools/lib/traceevent/Build17
-rw-r--r--tools/lib/traceevent/Makefile169
-rw-r--r--tools/lib/traceevent/event-parse.c305
-rw-r--r--tools/lib/traceevent/event-parse.h24
-rw-r--r--tools/lib/traceevent/event-plugin.c60
-rw-r--r--tools/lib/traceevent/kbuffer-parse.c12
-rw-r--r--tools/lib/traceevent/kbuffer.h1
-rw-r--r--tools/lib/traceevent/parse-filter.c2
-rw-r--r--tools/lib/traceevent/trace-seq.c13
21 files changed, 689 insertions, 379 deletions
diff --git a/tools/lib/api/Build b/tools/lib/api/Build
new file mode 100644
index 000000000000..3653965cf481
--- /dev/null
+++ b/tools/lib/api/Build
@@ -0,0 +1,2 @@
1libapi-y += fd/
2libapi-y += fs/
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index 36c08b1f4afb..d8fe29fc19a4 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -1,49 +1,43 @@
1include ../../scripts/Makefile.include 1include ../../scripts/Makefile.include
2include ../../perf/config/utilities.mak # QUIET_CLEAN 2include ../../perf/config/utilities.mak # QUIET_CLEAN
3 3
4ifeq ($(srctree),)
5srctree := $(patsubst %/,%,$(dir $(shell pwd)))
6srctree := $(patsubst %/,%,$(dir $(srctree)))
7srctree := $(patsubst %/,%,$(dir $(srctree)))
8#$(info Determined 'srctree' to be $(srctree))
9endif
10
4CC = $(CROSS_COMPILE)gcc 11CC = $(CROSS_COMPILE)gcc
5AR = $(CROSS_COMPILE)ar 12AR = $(CROSS_COMPILE)ar
6 13
7# guard against environment variables 14MAKEFLAGS += --no-print-directory
8LIB_H=
9LIB_OBJS=
10
11LIB_H += fs/debugfs.h
12LIB_H += fs/fs.h
13# See comment below about piggybacking...
14LIB_H += fd/array.h
15
16LIB_OBJS += $(OUTPUT)fs/debugfs.o
17LIB_OBJS += $(OUTPUT)fs/fs.o
18# XXX piggybacking here, need to introduce libapikfd, or rename this
19# to plain libapik.a and make it have it all api goodies
20LIB_OBJS += $(OUTPUT)fd/array.o
21 15
22LIBFILE = libapikfs.a 16LIBFILE = $(OUTPUT)libapi.a
23 17
24CFLAGS = -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) -fPIC 18CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
25EXTLIBS = -lelf -lpthread -lrt -lm 19CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 -fPIC
26ALL_CFLAGS = $(CFLAGS) $(BASIC_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 20CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
27ALL_LDFLAGS = $(LDFLAGS)
28 21
29RM = rm -f 22RM = rm -f
30 23
31$(LIBFILE): $(LIB_OBJS) 24build := -f $(srctree)/tools/build/Makefile.build dir=. obj
32 $(QUIET_AR)$(RM) $@ && $(AR) rcs $(OUTPUT)$@ $(LIB_OBJS) 25API_IN := $(OUTPUT)libapi-in.o
33 26
34$(LIB_OBJS): $(LIB_H) 27export srctree OUTPUT CC LD CFLAGS V
35 28
36libapi_dirs: 29all: $(LIBFILE)
37 $(QUIET_MKDIR)mkdir -p $(OUTPUT)fd $(OUTPUT)fs
38 30
39$(OUTPUT)%.o: %.c libapi_dirs 31$(API_IN): FORCE
40 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $< 32 @$(MAKE) $(build)=libapi
41$(OUTPUT)%.s: %.c libapi_dirs 33
42 $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $< 34$(LIBFILE): $(API_IN)
43$(OUTPUT)%.o: %.S libapi_dirs 35 $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(API_IN)
44 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $<
45 36
46clean: 37clean:
47 $(call QUIET_CLEAN, libapi) $(RM) $(LIB_OBJS) $(LIBFILE) 38 $(call QUIET_CLEAN, libapi) $(RM) $(LIBFILE); \
39 find $(if $(OUTPUT),$(OUTPUT),.) -name \*.o | xargs $(RM)
40
41FORCE:
48 42
49.PHONY: clean 43.PHONY: clean FORCE
diff --git a/tools/lib/api/fd/Build b/tools/lib/api/fd/Build
new file mode 100644
index 000000000000..605d99f6d71a
--- /dev/null
+++ b/tools/lib/api/fd/Build
@@ -0,0 +1 @@
libapi-y += array.o
diff --git a/tools/lib/api/fs/Build b/tools/lib/api/fs/Build
new file mode 100644
index 000000000000..6de5a4f0b501
--- /dev/null
+++ b/tools/lib/api/fs/Build
@@ -0,0 +1,4 @@
1libapi-y += fs.o
2libapi-y += debugfs.o
3libapi-y += findfs.o
4libapi-y += tracefs.o
diff --git a/tools/lib/api/fs/debugfs.c b/tools/lib/api/fs/debugfs.c
index d2b18e887071..8305b3e9d48e 100644
--- a/tools/lib/api/fs/debugfs.c
+++ b/tools/lib/api/fs/debugfs.c
@@ -3,75 +3,50 @@
3#include <stdio.h> 3#include <stdio.h>
4#include <stdlib.h> 4#include <stdlib.h>
5#include <string.h> 5#include <string.h>
6#include <unistd.h>
6#include <stdbool.h> 7#include <stdbool.h>
7#include <sys/vfs.h> 8#include <sys/vfs.h>
9#include <sys/types.h>
10#include <sys/stat.h>
8#include <sys/mount.h> 11#include <sys/mount.h>
9#include <linux/kernel.h> 12#include <linux/kernel.h>
10 13
11#include "debugfs.h" 14#include "debugfs.h"
12 15
13char debugfs_mountpoint[PATH_MAX + 1] = "/sys/kernel/debug"; 16#ifndef DEBUGFS_DEFAULT_PATH
17#define DEBUGFS_DEFAULT_PATH "/sys/kernel/debug"
18#endif
19
20char debugfs_mountpoint[PATH_MAX + 1] = DEBUGFS_DEFAULT_PATH;
14 21
15static const char * const debugfs_known_mountpoints[] = { 22static const char * const debugfs_known_mountpoints[] = {
16 "/sys/kernel/debug", 23 DEBUGFS_DEFAULT_PATH,
17 "/debug", 24 "/debug",
18 0, 25 0,
19}; 26};
20 27
21static bool debugfs_found; 28static bool debugfs_found;
22 29
30bool debugfs_configured(void)
31{
32 return debugfs_find_mountpoint() != NULL;
33}
34
23/* find the path to the mounted debugfs */ 35/* find the path to the mounted debugfs */
24const char *debugfs_find_mountpoint(void) 36const char *debugfs_find_mountpoint(void)
25{ 37{
26 const char * const *ptr; 38 const char *ret;
27 char type[100];
28 FILE *fp;
29 39
30 if (debugfs_found) 40 if (debugfs_found)
31 return (const char *)debugfs_mountpoint; 41 return (const char *)debugfs_mountpoint;
32 42
33 ptr = debugfs_known_mountpoints; 43 ret = find_mountpoint("debugfs", (long) DEBUGFS_MAGIC,
34 while (*ptr) { 44 debugfs_mountpoint, PATH_MAX + 1,
35 if (debugfs_valid_mountpoint(*ptr) == 0) { 45 debugfs_known_mountpoints);
36 debugfs_found = true; 46 if (ret)
37 strcpy(debugfs_mountpoint, *ptr); 47 debugfs_found = true;
38 return debugfs_mountpoint;
39 }
40 ptr++;
41 }
42
43 /* give up and parse /proc/mounts */
44 fp = fopen("/proc/mounts", "r");
45 if (fp == NULL)
46 return NULL;
47
48 while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
49 debugfs_mountpoint, type) == 2) {
50 if (strcmp(type, "debugfs") == 0)
51 break;
52 }
53 fclose(fp);
54 48
55 if (strcmp(type, "debugfs") != 0) 49 return ret;
56 return NULL;
57
58 debugfs_found = true;
59
60 return debugfs_mountpoint;
61}
62
63/* verify that a mountpoint is actually a debugfs instance */
64
65int debugfs_valid_mountpoint(const char *debugfs)
66{
67 struct statfs st_fs;
68
69 if (statfs(debugfs, &st_fs) < 0)
70 return -ENOENT;
71 else if ((long)st_fs.f_type != (long)DEBUGFS_MAGIC)
72 return -ENOENT;
73
74 return 0;
75} 50}
76 51
77/* mount the debugfs somewhere if it's not mounted */ 52/* mount the debugfs somewhere if it's not mounted */
@@ -87,7 +62,7 @@ char *debugfs_mount(const char *mountpoint)
87 mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT); 62 mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT);
88 /* if no environment variable, use default */ 63 /* if no environment variable, use default */
89 if (mountpoint == NULL) 64 if (mountpoint == NULL)
90 mountpoint = "/sys/kernel/debug"; 65 mountpoint = DEBUGFS_DEFAULT_PATH;
91 } 66 }
92 67
93 if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0) 68 if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0)
diff --git a/tools/lib/api/fs/debugfs.h b/tools/lib/api/fs/debugfs.h
index 0739881a9897..455023698d2b 100644
--- a/tools/lib/api/fs/debugfs.h
+++ b/tools/lib/api/fs/debugfs.h
@@ -1,16 +1,7 @@
1#ifndef __API_DEBUGFS_H__ 1#ifndef __API_DEBUGFS_H__
2#define __API_DEBUGFS_H__ 2#define __API_DEBUGFS_H__
3 3
4#define _STR(x) #x 4#include "findfs.h"
5#define STR(x) _STR(x)
6
7/*
8 * On most systems <limits.h> would have given us this, but not on some systems
9 * (e.g. GNU/Hurd).
10 */
11#ifndef PATH_MAX
12#define PATH_MAX 4096
13#endif
14 5
15#ifndef DEBUGFS_MAGIC 6#ifndef DEBUGFS_MAGIC
16#define DEBUGFS_MAGIC 0x64626720 7#define DEBUGFS_MAGIC 0x64626720
@@ -20,8 +11,8 @@
20#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" 11#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
21#endif 12#endif
22 13
14bool debugfs_configured(void);
23const char *debugfs_find_mountpoint(void); 15const char *debugfs_find_mountpoint(void);
24int debugfs_valid_mountpoint(const char *debugfs);
25char *debugfs_mount(const char *mountpoint); 16char *debugfs_mount(const char *mountpoint);
26 17
27extern char debugfs_mountpoint[]; 18extern char debugfs_mountpoint[];
diff --git a/tools/lib/api/fs/findfs.c b/tools/lib/api/fs/findfs.c
new file mode 100644
index 000000000000..49946cb6d7af
--- /dev/null
+++ b/tools/lib/api/fs/findfs.c
@@ -0,0 +1,63 @@
1#include <errno.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <stdbool.h>
6#include <sys/vfs.h>
7
8#include "findfs.h"
9
10/* verify that a mountpoint is actually the type we want */
11
12int valid_mountpoint(const char *mount, long magic)
13{
14 struct statfs st_fs;
15
16 if (statfs(mount, &st_fs) < 0)
17 return -ENOENT;
18 else if ((long)st_fs.f_type != magic)
19 return -ENOENT;
20
21 return 0;
22}
23
24/* find the path to a mounted file system */
25const char *find_mountpoint(const char *fstype, long magic,
26 char *mountpoint, int len,
27 const char * const *known_mountpoints)
28{
29 const char * const *ptr;
30 char format[128];
31 char type[100];
32 FILE *fp;
33
34 if (known_mountpoints) {
35 ptr = known_mountpoints;
36 while (*ptr) {
37 if (valid_mountpoint(*ptr, magic) == 0) {
38 strncpy(mountpoint, *ptr, len - 1);
39 mountpoint[len-1] = 0;
40 return mountpoint;
41 }
42 ptr++;
43 }
44 }
45
46 /* give up and parse /proc/mounts */
47 fp = fopen("/proc/mounts", "r");
48 if (fp == NULL)
49 return NULL;
50
51 snprintf(format, 128, "%%*s %%%ds %%99s %%*s %%*d %%*d\n", len);
52
53 while (fscanf(fp, format, mountpoint, type) == 2) {
54 if (strcmp(type, fstype) == 0)
55 break;
56 }
57 fclose(fp);
58
59 if (strcmp(type, fstype) != 0)
60 return NULL;
61
62 return mountpoint;
63}
diff --git a/tools/lib/api/fs/findfs.h b/tools/lib/api/fs/findfs.h
new file mode 100644
index 000000000000..b6f5d05acc42
--- /dev/null
+++ b/tools/lib/api/fs/findfs.h
@@ -0,0 +1,23 @@
1#ifndef __API_FINDFS_H__
2#define __API_FINDFS_H__
3
4#include <stdbool.h>
5
6#define _STR(x) #x
7#define STR(x) _STR(x)
8
9/*
10 * On most systems <limits.h> would have given us this, but not on some systems
11 * (e.g. GNU/Hurd).
12 */
13#ifndef PATH_MAX
14#define PATH_MAX 4096
15#endif
16
17const char *find_mountpoint(const char *fstype, long magic,
18 char *mountpoint, int len,
19 const char * const *known_mountpoints);
20
21int valid_mountpoint(const char *mount, long magic);
22
23#endif /* __API_FINDFS_H__ */
diff --git a/tools/lib/api/fs/tracefs.c b/tools/lib/api/fs/tracefs.c
new file mode 100644
index 000000000000..e4aa9688b71e
--- /dev/null
+++ b/tools/lib/api/fs/tracefs.c
@@ -0,0 +1,78 @@
1#include <errno.h>
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <unistd.h>
6#include <stdbool.h>
7#include <sys/vfs.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <sys/mount.h>
11#include <linux/kernel.h>
12
13#include "tracefs.h"
14
15#ifndef TRACEFS_DEFAULT_PATH
16#define TRACEFS_DEFAULT_PATH "/sys/kernel/tracing"
17#endif
18
19char tracefs_mountpoint[PATH_MAX + 1] = TRACEFS_DEFAULT_PATH;
20
21static const char * const tracefs_known_mountpoints[] = {
22 TRACEFS_DEFAULT_PATH,
23 "/sys/kernel/debug/tracing",
24 "/tracing",
25 "/trace",
26 0,
27};
28
29static bool tracefs_found;
30
31bool tracefs_configured(void)
32{
33 return tracefs_find_mountpoint() != NULL;
34}
35
36/* find the path to the mounted tracefs */
37const char *tracefs_find_mountpoint(void)
38{
39 const char *ret;
40
41 if (tracefs_found)
42 return (const char *)tracefs_mountpoint;
43
44 ret = find_mountpoint("tracefs", (long) TRACEFS_MAGIC,
45 tracefs_mountpoint, PATH_MAX + 1,
46 tracefs_known_mountpoints);
47
48 if (ret)
49 tracefs_found = true;
50
51 return ret;
52}
53
54/* mount the tracefs somewhere if it's not mounted */
55char *tracefs_mount(const char *mountpoint)
56{
57 /* see if it's already mounted */
58 if (tracefs_find_mountpoint())
59 goto out;
60
61 /* if not mounted and no argument */
62 if (mountpoint == NULL) {
63 /* see if environment variable set */
64 mountpoint = getenv(PERF_TRACEFS_ENVIRONMENT);
65 /* if no environment variable, use default */
66 if (mountpoint == NULL)
67 mountpoint = TRACEFS_DEFAULT_PATH;
68 }
69
70 if (mount(NULL, mountpoint, "tracefs", 0, NULL) < 0)
71 return NULL;
72
73 /* save the mountpoint */
74 tracefs_found = true;
75 strncpy(tracefs_mountpoint, mountpoint, sizeof(tracefs_mountpoint));
76out:
77 return tracefs_mountpoint;
78}
diff --git a/tools/lib/api/fs/tracefs.h b/tools/lib/api/fs/tracefs.h
new file mode 100644
index 000000000000..da780ac49acb
--- /dev/null
+++ b/tools/lib/api/fs/tracefs.h
@@ -0,0 +1,21 @@
1#ifndef __API_TRACEFS_H__
2#define __API_TRACEFS_H__
3
4#include "findfs.h"
5
6#ifndef TRACEFS_MAGIC
7#define TRACEFS_MAGIC 0x74726163
8#endif
9
10#ifndef PERF_TRACEFS_ENVIRONMENT
11#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
12#endif
13
14bool tracefs_configured(void);
15const char *tracefs_find_mountpoint(void);
16int tracefs_valid_mountpoint(const char *debugfs);
17char *tracefs_mount(const char *mountpoint);
18
19extern char tracefs_mountpoint[];
20
21#endif /* __API_DEBUGFS_H__ */
diff --git a/tools/lib/lockdep/Build b/tools/lib/lockdep/Build
new file mode 100644
index 000000000000..6f667355b068
--- /dev/null
+++ b/tools/lib/lockdep/Build
@@ -0,0 +1 @@
liblockdep-y += common.o lockdep.o preload.o rbtree.o
diff --git a/tools/lib/lockdep/Makefile b/tools/lib/lockdep/Makefile
index 4b866c54f624..0c356fb65022 100644
--- a/tools/lib/lockdep/Makefile
+++ b/tools/lib/lockdep/Makefile
@@ -35,6 +35,10 @@ bindir = $(prefix)/$(bindir_relative)
35 35
36export DESTDIR DESTDIR_SQ INSTALL 36export DESTDIR DESTDIR_SQ INSTALL
37 37
38MAKEFLAGS += --no-print-directory
39
40include ../../scripts/Makefile.include
41
38# copy a bit from Linux kbuild 42# copy a bit from Linux kbuild
39 43
40ifeq ("$(origin V)", "command line") 44ifeq ("$(origin V)", "command line")
@@ -44,56 +48,21 @@ ifndef VERBOSE
44 VERBOSE = 0 48 VERBOSE = 0
45endif 49endif
46 50
47ifeq ("$(origin O)", "command line") 51ifeq ($(srctree),)
48 BUILD_OUTPUT := $(O) 52srctree := $(patsubst %/,%,$(dir $(shell pwd)))
53srctree := $(patsubst %/,%,$(dir $(srctree)))
54srctree := $(patsubst %/,%,$(dir $(srctree)))
55#$(info Determined 'srctree' to be $(srctree))
49endif 56endif
50 57
51ifeq ($(BUILD_SRC),)
52ifneq ($(BUILD_OUTPUT),)
53
54define build_output
55 $(if $(VERBOSE:1=),@)$(MAKE) -C $(BUILD_OUTPUT) \
56 BUILD_SRC=$(CURDIR) -f $(CURDIR)/Makefile $1
57endef
58
59saved-output := $(BUILD_OUTPUT)
60BUILD_OUTPUT := $(shell cd $(BUILD_OUTPUT) && /bin/pwd)
61$(if $(BUILD_OUTPUT),, \
62 $(error output directory "$(saved-output)" does not exist))
63
64all: sub-make
65
66gui: force
67 $(call build_output, all_cmd)
68
69$(filter-out gui,$(MAKECMDGOALS)): sub-make
70
71sub-make: force
72 $(call build_output, $(MAKECMDGOALS))
73
74
75# Leave processing to above invocation of make
76skip-makefile := 1
77
78endif # BUILD_OUTPUT
79endif # BUILD_SRC
80
81# We process the rest of the Makefile if this is the final invocation of make
82ifeq ($(skip-makefile),)
83
84srctree := $(realpath $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR)))
85objtree := $(realpath $(CURDIR))
86src := $(srctree)
87obj := $(objtree)
88
89export prefix libdir bindir src obj
90
91# Shell quotes 58# Shell quotes
92libdir_SQ = $(subst ','\'',$(libdir)) 59libdir_SQ = $(subst ','\'',$(libdir))
93bindir_SQ = $(subst ','\'',$(bindir)) 60bindir_SQ = $(subst ','\'',$(bindir))
94 61
95LIB_FILE = liblockdep.a liblockdep.so.$(LIBLOCKDEP_VERSION) 62LIB_IN := $(OUTPUT)liblockdep-in.o
63
96BIN_FILE = lockdep 64BIN_FILE = lockdep
65LIB_FILE = $(OUTPUT)liblockdep.a $(OUTPUT)liblockdep.so.$(LIBLOCKDEP_VERSION)
97 66
98CONFIG_INCLUDES = 67CONFIG_INCLUDES =
99CONFIG_LIBS = 68CONFIG_LIBS =
@@ -108,33 +77,23 @@ INCLUDES = -I. -I./uinclude -I./include -I../../include $(CONFIG_INCLUDES)
108 77
109# Set compile option CFLAGS if not set elsewhere 78# Set compile option CFLAGS if not set elsewhere
110CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g 79CFLAGS ?= -g -DCONFIG_LOCKDEP -DCONFIG_STACKTRACE -DCONFIG_PROVE_LOCKING -DBITS_PER_LONG=__WORDSIZE -DLIBLOCKDEP_VERSION='"$(LIBLOCKDEP_VERSION)"' -rdynamic -O0 -g
80CFLAGS += -fPIC
111 81
112override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) 82override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
113 83
114ifeq ($(VERBOSE),1) 84ifeq ($(VERBOSE),1)
115 Q = 85 Q =
116 print_compile =
117 print_app_build =
118 print_fpic_compile =
119 print_shared_lib_compile = 86 print_shared_lib_compile =
120 print_install = 87 print_install =
121else 88else
122 Q = @ 89 Q = @
123 print_compile = echo ' CC '$(OBJ); 90 print_shared_lib_compile = echo ' LD '$(OBJ);
124 print_app_build = echo ' BUILD '$(OBJ); 91 print_static_lib_build = echo ' LD '$(OBJ);
125 print_fpic_compile = echo ' CC FPIC '$(OBJ); 92 print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
126 print_shared_lib_compile = echo ' BUILD SHARED LIB '$(OBJ);
127 print_static_lib_build = echo ' BUILD STATIC LIB '$(OBJ);
128 print_install = echo ' INSTALL '$1' to $(DESTDIR_SQ)$2';
129endif 93endif
130 94
131do_fpic_compile = \ 95export srctree OUTPUT CC LD CFLAGS V
132 ($(print_fpic_compile) \ 96build := -f $(srctree)/tools/build/Makefile.build dir=. obj
133 $(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@)
134
135do_app_build = \
136 ($(print_app_build) \
137 $(CC) $^ -rdynamic -o $@ $(CONFIG_LIBS) $(LIBS))
138 97
139do_compile_shared_library = \ 98do_compile_shared_library = \
140 ($(print_shared_lib_compile) \ 99 ($(print_shared_lib_compile) \
@@ -144,22 +103,6 @@ do_build_static_lib = \
144 ($(print_static_lib_build) \ 103 ($(print_static_lib_build) \
145 $(RM) $@; $(AR) rcs $@ $^) 104 $(RM) $@; $(AR) rcs $@ $^)
146 105
147
148define do_compile
149 $(print_compile) \
150 $(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
151endef
152
153$(obj)/%.o: $(src)/%.c
154 $(Q)$(call do_compile)
155
156%.o: $(src)/%.c
157 $(Q)$(call do_compile)
158
159PEVENT_LIB_OBJS = common.o lockdep.o preload.o rbtree.o
160
161ALL_OBJS = $(PEVENT_LIB_OBJS)
162
163CMD_TARGETS = $(LIB_FILE) 106CMD_TARGETS = $(LIB_FILE)
164 107
165TARGETS = $(CMD_TARGETS) 108TARGETS = $(CMD_TARGETS)
@@ -169,42 +112,15 @@ all: all_cmd
169 112
170all_cmd: $(CMD_TARGETS) 113all_cmd: $(CMD_TARGETS)
171 114
172liblockdep.so.$(LIBLOCKDEP_VERSION): $(PEVENT_LIB_OBJS) 115$(LIB_IN): force
116 $(Q)$(MAKE) $(build)=liblockdep
117
118liblockdep.so.$(LIBLOCKDEP_VERSION): $(LIB_IN)
173 $(Q)$(do_compile_shared_library) 119 $(Q)$(do_compile_shared_library)
174 120
175liblockdep.a: $(PEVENT_LIB_OBJS) 121liblockdep.a: $(LIB_IN)
176 $(Q)$(do_build_static_lib) 122 $(Q)$(do_build_static_lib)
177 123
178$(PEVENT_LIB_OBJS): %.o: $(src)/%.c
179 $(Q)$(do_fpic_compile)
180
181## make deps
182
183all_objs := $(sort $(ALL_OBJS))
184all_deps := $(all_objs:%.o=.%.d)
185
186# let .d file also depends on the source and header files
187define check_deps
188 @set -e; $(RM) $@; \
189 $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
190 sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
191 $(RM) $@.$$$$
192endef
193
194$(all_deps): .%.d: $(src)/%.c
195 $(Q)$(call check_deps)
196
197$(all_objs) : %.o : .%.d
198
199dep_includes := $(wildcard $(all_deps))
200
201ifneq ($(dep_includes),)
202 include $(dep_includes)
203endif
204
205### Detect environment changes
206TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
207
208tags: force 124tags: force
209 $(RM) tags 125 $(RM) tags
210 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \ 126 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
@@ -233,8 +149,6 @@ clean:
233 $(RM) *.o *~ $(TARGETS) *.a *liblockdep*.so* $(VERSION_FILES) .*.d 149 $(RM) *.o *~ $(TARGETS) *.a *liblockdep*.so* $(VERSION_FILES) .*.d
234 $(RM) tags TAGS 150 $(RM) tags TAGS
235 151
236endif # skip-makefile
237
238PHONY += force 152PHONY += force
239force: 153force:
240 154
diff --git a/tools/lib/traceevent/Build b/tools/lib/traceevent/Build
new file mode 100644
index 000000000000..c681d0575d16
--- /dev/null
+++ b/tools/lib/traceevent/Build
@@ -0,0 +1,17 @@
1libtraceevent-y += event-parse.o
2libtraceevent-y += event-plugin.o
3libtraceevent-y += trace-seq.o
4libtraceevent-y += parse-filter.o
5libtraceevent-y += parse-utils.o
6libtraceevent-y += kbuffer-parse.o
7
8plugin_jbd2-y += plugin_jbd2.o
9plugin_hrtimer-y += plugin_hrtimer.o
10plugin_kmem-y += plugin_kmem.o
11plugin_kvm-y += plugin_kvm.o
12plugin_mac80211-y += plugin_mac80211.o
13plugin_sched_switch-y += plugin_sched_switch.o
14plugin_function-y += plugin_function.o
15plugin_xen-y += plugin_xen.o
16plugin_scsi-y += plugin_scsi.o
17plugin_cfg80211-y += plugin_cfg80211.o
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index 005c9cc06935..d410da335e3d 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -67,7 +67,7 @@ PLUGIN_DIR = -DPLUGIN_DIR="$(plugin_dir)"
67PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))' 67PLUGIN_DIR_SQ = '$(subst ','\'',$(PLUGIN_DIR))'
68endif 68endif
69 69
70include $(if $(BUILD_SRC),$(BUILD_SRC)/)../../scripts/Makefile.include 70include ../../scripts/Makefile.include
71 71
72# copy a bit from Linux kbuild 72# copy a bit from Linux kbuild
73 73
@@ -78,40 +78,13 @@ ifndef VERBOSE
78 VERBOSE = 0 78 VERBOSE = 0
79endif 79endif
80 80
81ifeq ("$(origin O)", "command line") 81ifeq ($(srctree),)
82 BUILD_OUTPUT := $(O) 82srctree := $(patsubst %/,%,$(dir $(shell pwd)))
83srctree := $(patsubst %/,%,$(dir $(srctree)))
84srctree := $(patsubst %/,%,$(dir $(srctree)))
85#$(info Determined 'srctree' to be $(srctree))
83endif 86endif
84 87
85ifeq ($(BUILD_SRC),)
86ifneq ($(OUTPUT),)
87
88define build_output
89 $(if $(VERBOSE:1=),@)+$(MAKE) -C $(OUTPUT) \
90 BUILD_SRC=$(CURDIR)/ -f $(CURDIR)/Makefile $1
91endef
92
93all: sub-make
94
95$(MAKECMDGOALS): sub-make
96
97sub-make: force
98 $(call build_output, $(MAKECMDGOALS))
99
100
101# Leave processing to above invocation of make
102skip-makefile := 1
103
104endif # OUTPUT
105endif # BUILD_SRC
106
107# We process the rest of the Makefile if this is the final invocation of make
108ifeq ($(skip-makefile),)
109
110srctree := $(if $(BUILD_SRC),$(BUILD_SRC),$(CURDIR))
111objtree := $(CURDIR)
112src := $(srctree)
113obj := $(objtree)
114
115export prefix bindir src obj 88export prefix bindir src obj
116 89
117# Shell quotes 90# Shell quotes
@@ -132,16 +105,19 @@ EXTRAVERSION = $(EP_EXTRAVERSION)
132OBJ = $@ 105OBJ = $@
133N = 106N =
134 107
135export Q VERBOSE
136
137EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION) 108EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
138 109
139INCLUDES = -I. -I $(srctree)/../../include $(CONFIG_INCLUDES) 110INCLUDES = -I. -I $(srctree)/tools/include $(CONFIG_INCLUDES)
140 111
141# Set compile option CFLAGS if not set elsewhere 112# Set compile option CFLAGS
142CFLAGS ?= -g -Wall 113ifdef EXTRA_CFLAGS
114 CFLAGS := $(EXTRA_CFLAGS)
115else
116 CFLAGS := -g -Wall
117endif
143 118
144# Append required CFLAGS 119# Append required CFLAGS
120override CFLAGS += -fPIC
145override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ) 121override CFLAGS += $(CONFIG_FLAGS) $(INCLUDES) $(PLUGIN_DIR_SQ)
146override CFLAGS += $(udis86-flags) -D_GNU_SOURCE 122override CFLAGS += $(udis86-flags) -D_GNU_SOURCE
147 123
@@ -151,74 +127,58 @@ else
151 Q = @ 127 Q = @
152endif 128endif
153 129
154do_compile_shared_library = \ 130# Disable command line variables (CFLAGS) overide from top
155 ($(print_shared_lib_compile) \ 131# level Makefile (perf), otherwise build Makefile will get
156 $(CC) --shared $^ -o $@) 132# the same command line setup.
157 133MAKEOVERRIDES=
158do_plugin_build = \
159 ($(print_plugin_build) \
160 $(CC) $(CFLAGS) -shared -nostartfiles -o $@ $<)
161
162do_build_static_lib = \
163 ($(print_static_lib_build) \
164 $(RM) $@; $(AR) rcs $@ $^)
165
166
167do_compile = $(QUIET_CC)$(CC) -c $(CFLAGS) $(EXT) $< -o $(obj)/$@;
168 134
169$(obj)/%.o: $(src)/%.c 135export srctree OUTPUT CC LD CFLAGS V
170 $(call do_compile) 136build := -f $(srctree)/tools/build/Makefile.build dir=. obj
171 137
172%.o: $(src)/%.c 138PLUGINS = plugin_jbd2.so
173 $(call do_compile) 139PLUGINS += plugin_hrtimer.so
140PLUGINS += plugin_kmem.so
141PLUGINS += plugin_kvm.so
142PLUGINS += plugin_mac80211.so
143PLUGINS += plugin_sched_switch.so
144PLUGINS += plugin_function.so
145PLUGINS += plugin_xen.so
146PLUGINS += plugin_scsi.so
147PLUGINS += plugin_cfg80211.so
174 148
175PEVENT_LIB_OBJS = event-parse.o 149PLUGINS := $(addprefix $(OUTPUT),$(PLUGINS))
176PEVENT_LIB_OBJS += event-plugin.o 150PLUGINS_IN := $(PLUGINS:.so=-in.o)
177PEVENT_LIB_OBJS += trace-seq.o
178PEVENT_LIB_OBJS += parse-filter.o
179PEVENT_LIB_OBJS += parse-utils.o
180PEVENT_LIB_OBJS += kbuffer-parse.o
181 151
182PLUGIN_OBJS = plugin_jbd2.o 152TE_IN := $(OUTPUT)libtraceevent-in.o
183PLUGIN_OBJS += plugin_hrtimer.o 153LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE))
184PLUGIN_OBJS += plugin_kmem.o
185PLUGIN_OBJS += plugin_kvm.o
186PLUGIN_OBJS += plugin_mac80211.o
187PLUGIN_OBJS += plugin_sched_switch.o
188PLUGIN_OBJS += plugin_function.o
189PLUGIN_OBJS += plugin_xen.o
190PLUGIN_OBJS += plugin_scsi.o
191PLUGIN_OBJS += plugin_cfg80211.o
192
193PLUGINS := $(PLUGIN_OBJS:.o=.so)
194
195ALL_OBJS = $(PEVENT_LIB_OBJS) $(PLUGIN_OBJS)
196 154
197CMD_TARGETS = $(LIB_FILE) $(PLUGINS) 155CMD_TARGETS = $(LIB_FILE) $(PLUGINS)
198 156
199TARGETS = $(CMD_TARGETS) 157TARGETS = $(CMD_TARGETS)
200 158
201
202all: all_cmd 159all: all_cmd
203 160
204all_cmd: $(CMD_TARGETS) 161all_cmd: $(CMD_TARGETS)
205 162
206libtraceevent.so: $(PEVENT_LIB_OBJS) 163$(TE_IN): force
164 $(Q)$(MAKE) $(build)=libtraceevent
165
166$(OUTPUT)libtraceevent.so: $(TE_IN)
207 $(QUIET_LINK)$(CC) --shared $^ -o $@ 167 $(QUIET_LINK)$(CC) --shared $^ -o $@
208 168
209libtraceevent.a: $(PEVENT_LIB_OBJS) 169$(OUTPUT)libtraceevent.a: $(TE_IN)
210 $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^ 170 $(QUIET_LINK)$(RM) $@; $(AR) rcs $@ $^
211 171
212plugins: $(PLUGINS) 172plugins: $(PLUGINS)
213 173
214$(PEVENT_LIB_OBJS): %.o: $(src)/%.c TRACEEVENT-CFLAGS 174__plugin_obj = $(notdir $@)
215 $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) $(EXT) -fPIC $< -o $@ 175 plugin_obj = $(__plugin_obj:-in.o=)
216 176
217$(PLUGIN_OBJS): %.o : $(src)/%.c 177$(PLUGINS_IN): force
218 $(QUIET_CC_FPIC)$(CC) -c $(CFLAGS) -fPIC -o $@ $< 178 $(Q)$(MAKE) $(build)=$(plugin_obj)
219 179
220$(PLUGINS): %.so: %.o 180$(OUTPUT)%.so: $(OUTPUT)%-in.o
221 $(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $< 181 $(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $^
222 182
223define make_version.h 183define make_version.h
224 (echo '/* This file is automatically generated. Do not modify. */'; \ 184 (echo '/* This file is automatically generated. Do not modify. */'; \
@@ -255,40 +215,6 @@ define update_dir
255 fi); 215 fi);
256endef 216endef
257 217
258## make deps
259
260all_objs := $(sort $(ALL_OBJS))
261all_deps := $(all_objs:%.o=.%.d)
262
263# let .d file also depends on the source and header files
264define check_deps
265 @set -e; $(RM) $@; \
266 $(CC) -MM $(CFLAGS) $< > $@.$$$$; \
267 sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
268 $(RM) $@.$$$$
269endef
270
271$(all_deps): .%.d: $(src)/%.c
272 $(Q)$(call check_deps)
273
274$(all_objs) : %.o : .%.d
275
276dep_includes := $(wildcard $(all_deps))
277
278ifneq ($(dep_includes),)
279 include $(dep_includes)
280endif
281
282### Detect environment changes
283TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
284
285TRACEEVENT-CFLAGS: force
286 @FLAGS='$(TRACK_CFLAGS)'; \
287 if test x"$$FLAGS" != x"`cat TRACEEVENT-CFLAGS 2>/dev/null`" ; then \
288 echo 1>&2 " FLAGS: * new build flags or cross compiler"; \
289 echo "$$FLAGS" >TRACEEVENT-CFLAGS; \
290 fi
291
292tags: force 218tags: force
293 $(RM) tags 219 $(RM) tags
294 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \ 220 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
@@ -327,14 +253,9 @@ clean:
327 $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \ 253 $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \
328 $(RM) TRACEEVENT-CFLAGS tags TAGS 254 $(RM) TRACEEVENT-CFLAGS tags TAGS
329 255
330endif # skip-makefile
331
332PHONY += force plugins 256PHONY += force plugins
333force: 257force:
334 258
335plugins:
336 @echo > /dev/null
337
338# Declare the contents of the .PHONY variable as phony. We keep that 259# Declare the contents of the .PHONY variable as phony. We keep that
339# information in a variable so we can use it in if_changed and friends. 260# information in a variable so we can use it in if_changed and friends.
340.PHONY: $(PHONY) 261.PHONY: $(PHONY)
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 2c0bd8f2aad0..e0917c0f5d9f 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -304,7 +304,10 @@ int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
304 if (!item) 304 if (!item)
305 return -1; 305 return -1;
306 306
307 item->comm = strdup(comm); 307 if (comm)
308 item->comm = strdup(comm);
309 else
310 item->comm = strdup("<...>");
308 if (!item->comm) { 311 if (!item->comm) {
309 free(item); 312 free(item);
310 return -1; 313 return -1;
@@ -318,9 +321,14 @@ int pevent_register_comm(struct pevent *pevent, const char *comm, int pid)
318 return 0; 321 return 0;
319} 322}
320 323
321void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock) 324int pevent_register_trace_clock(struct pevent *pevent, const char *trace_clock)
322{ 325{
323 pevent->trace_clock = trace_clock; 326 pevent->trace_clock = strdup(trace_clock);
327 if (!pevent->trace_clock) {
328 errno = ENOMEM;
329 return -1;
330 }
331 return 0;
324} 332}
325 333
326struct func_map { 334struct func_map {
@@ -758,6 +766,11 @@ static void free_arg(struct print_arg *arg)
758 free_arg(arg->hex.field); 766 free_arg(arg->hex.field);
759 free_arg(arg->hex.size); 767 free_arg(arg->hex.size);
760 break; 768 break;
769 case PRINT_INT_ARRAY:
770 free_arg(arg->int_array.field);
771 free_arg(arg->int_array.count);
772 free_arg(arg->int_array.el_size);
773 break;
761 case PRINT_TYPE: 774 case PRINT_TYPE:
762 free(arg->typecast.type); 775 free(arg->typecast.type);
763 free_arg(arg->typecast.item); 776 free_arg(arg->typecast.item);
@@ -1926,7 +1939,22 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
1926 goto out_warn_free; 1939 goto out_warn_free;
1927 1940
1928 type = process_arg_token(event, right, tok, type); 1941 type = process_arg_token(event, right, tok, type);
1929 arg->op.right = right; 1942
1943 if (right->type == PRINT_OP &&
1944 get_op_prio(arg->op.op) < get_op_prio(right->op.op)) {
1945 struct print_arg tmp;
1946
1947 /* rotate ops according to the priority */
1948 arg->op.right = right->op.left;
1949
1950 tmp = *arg;
1951 *arg = *right;
1952 *right = tmp;
1953
1954 arg->op.left = right;
1955 } else {
1956 arg->op.right = right;
1957 }
1930 1958
1931 } else if (strcmp(token, "[") == 0) { 1959 } else if (strcmp(token, "[") == 0) {
1932 1960
@@ -2014,6 +2042,38 @@ process_entry(struct event_format *event __maybe_unused, struct print_arg *arg,
2014 return EVENT_ERROR; 2042 return EVENT_ERROR;
2015} 2043}
2016 2044
2045static int alloc_and_process_delim(struct event_format *event, char *next_token,
2046 struct print_arg **print_arg)
2047{
2048 struct print_arg *field;
2049 enum event_type type;
2050 char *token;
2051 int ret = 0;
2052
2053 field = alloc_arg();
2054 if (!field) {
2055 do_warning_event(event, "%s: not enough memory!", __func__);
2056 errno = ENOMEM;
2057 return -1;
2058 }
2059
2060 type = process_arg(event, field, &token);
2061
2062 if (test_type_token(type, token, EVENT_DELIM, next_token)) {
2063 errno = EINVAL;
2064 ret = -1;
2065 free_arg(field);
2066 goto out_free_token;
2067 }
2068
2069 *print_arg = field;
2070
2071out_free_token:
2072 free_token(token);
2073
2074 return ret;
2075}
2076
2017static char *arg_eval (struct print_arg *arg); 2077static char *arg_eval (struct print_arg *arg);
2018 2078
2019static unsigned long long 2079static unsigned long long
@@ -2486,49 +2546,46 @@ out_free:
2486static enum event_type 2546static enum event_type
2487process_hex(struct event_format *event, struct print_arg *arg, char **tok) 2547process_hex(struct event_format *event, struct print_arg *arg, char **tok)
2488{ 2548{
2489 struct print_arg *field;
2490 enum event_type type;
2491 char *token = NULL;
2492
2493 memset(arg, 0, sizeof(*arg)); 2549 memset(arg, 0, sizeof(*arg));
2494 arg->type = PRINT_HEX; 2550 arg->type = PRINT_HEX;
2495 2551
2496 field = alloc_arg(); 2552 if (alloc_and_process_delim(event, ",", &arg->hex.field))
2497 if (!field) { 2553 goto out;
2498 do_warning_event(event, "%s: not enough memory!", __func__);
2499 goto out_free;
2500 }
2501 2554
2502 type = process_arg(event, field, &token); 2555 if (alloc_and_process_delim(event, ")", &arg->hex.size))
2556 goto free_field;
2503 2557
2504 if (test_type_token(type, token, EVENT_DELIM, ",")) 2558 return read_token_item(tok);
2505 goto out_free;
2506
2507 arg->hex.field = field;
2508 2559
2509 free_token(token); 2560free_field:
2561 free_arg(arg->hex.field);
2562out:
2563 *tok = NULL;
2564 return EVENT_ERROR;
2565}
2510 2566
2511 field = alloc_arg(); 2567static enum event_type
2512 if (!field) { 2568process_int_array(struct event_format *event, struct print_arg *arg, char **tok)
2513 do_warning_event(event, "%s: not enough memory!", __func__); 2569{
2514 *tok = NULL; 2570 memset(arg, 0, sizeof(*arg));
2515 return EVENT_ERROR; 2571 arg->type = PRINT_INT_ARRAY;
2516 }
2517 2572
2518 type = process_arg(event, field, &token); 2573 if (alloc_and_process_delim(event, ",", &arg->int_array.field))
2574 goto out;
2519 2575
2520 if (test_type_token(type, token, EVENT_DELIM, ")")) 2576 if (alloc_and_process_delim(event, ",", &arg->int_array.count))
2521 goto out_free; 2577 goto free_field;
2522 2578
2523 arg->hex.size = field; 2579 if (alloc_and_process_delim(event, ")", &arg->int_array.el_size))
2580 goto free_size;
2524 2581
2525 free_token(token); 2582 return read_token_item(tok);
2526 type = read_token_item(tok);
2527 return type;
2528 2583
2529 out_free: 2584free_size:
2530 free_arg(field); 2585 free_arg(arg->int_array.count);
2531 free_token(token); 2586free_field:
2587 free_arg(arg->int_array.field);
2588out:
2532 *tok = NULL; 2589 *tok = NULL;
2533 return EVENT_ERROR; 2590 return EVENT_ERROR;
2534} 2591}
@@ -2828,6 +2885,10 @@ process_function(struct event_format *event, struct print_arg *arg,
2828 free_token(token); 2885 free_token(token);
2829 return process_hex(event, arg, tok); 2886 return process_hex(event, arg, tok);
2830 } 2887 }
2888 if (strcmp(token, "__print_array") == 0) {
2889 free_token(token);
2890 return process_int_array(event, arg, tok);
2891 }
2831 if (strcmp(token, "__get_str") == 0) { 2892 if (strcmp(token, "__get_str") == 0) {
2832 free_token(token); 2893 free_token(token);
2833 return process_str(event, arg, tok); 2894 return process_str(event, arg, tok);
@@ -3356,6 +3417,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
3356 break; 3417 break;
3357 case PRINT_FLAGS: 3418 case PRINT_FLAGS:
3358 case PRINT_SYMBOL: 3419 case PRINT_SYMBOL:
3420 case PRINT_INT_ARRAY:
3359 case PRINT_HEX: 3421 case PRINT_HEX:
3360 break; 3422 break;
3361 case PRINT_TYPE: 3423 case PRINT_TYPE:
@@ -3568,7 +3630,7 @@ static const struct flag flags[] = {
3568 { "HRTIMER_RESTART", 1 }, 3630 { "HRTIMER_RESTART", 1 },
3569}; 3631};
3570 3632
3571static unsigned long long eval_flag(const char *flag) 3633static long long eval_flag(const char *flag)
3572{ 3634{
3573 int i; 3635 int i;
3574 3636
@@ -3584,7 +3646,7 @@ static unsigned long long eval_flag(const char *flag)
3584 if (strcmp(flags[i].name, flag) == 0) 3646 if (strcmp(flags[i].name, flag) == 0)
3585 return flags[i].value; 3647 return flags[i].value;
3586 3648
3587 return 0; 3649 return -1LL;
3588} 3650}
3589 3651
3590static void print_str_to_seq(struct trace_seq *s, const char *format, 3652static void print_str_to_seq(struct trace_seq *s, const char *format,
@@ -3658,7 +3720,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3658 struct print_flag_sym *flag; 3720 struct print_flag_sym *flag;
3659 struct format_field *field; 3721 struct format_field *field;
3660 struct printk_map *printk; 3722 struct printk_map *printk;
3661 unsigned long long val, fval; 3723 long long val, fval;
3662 unsigned long addr; 3724 unsigned long addr;
3663 char *str; 3725 char *str;
3664 unsigned char *hex; 3726 unsigned char *hex;
@@ -3717,11 +3779,11 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3717 print = 0; 3779 print = 0;
3718 for (flag = arg->flags.flags; flag; flag = flag->next) { 3780 for (flag = arg->flags.flags; flag; flag = flag->next) {
3719 fval = eval_flag(flag->value); 3781 fval = eval_flag(flag->value);
3720 if (!val && !fval) { 3782 if (!val && fval < 0) {
3721 print_str_to_seq(s, format, len_arg, flag->str); 3783 print_str_to_seq(s, format, len_arg, flag->str);
3722 break; 3784 break;
3723 } 3785 }
3724 if (fval && (val & fval) == fval) { 3786 if (fval > 0 && (val & fval) == fval) {
3725 if (print && arg->flags.delim) 3787 if (print && arg->flags.delim)
3726 trace_seq_puts(s, arg->flags.delim); 3788 trace_seq_puts(s, arg->flags.delim);
3727 print_str_to_seq(s, format, len_arg, flag->str); 3789 print_str_to_seq(s, format, len_arg, flag->str);
@@ -3766,6 +3828,54 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3766 } 3828 }
3767 break; 3829 break;
3768 3830
3831 case PRINT_INT_ARRAY: {
3832 void *num;
3833 int el_size;
3834
3835 if (arg->int_array.field->type == PRINT_DYNAMIC_ARRAY) {
3836 unsigned long offset;
3837 struct format_field *field =
3838 arg->int_array.field->dynarray.field;
3839 offset = pevent_read_number(pevent,
3840 data + field->offset,
3841 field->size);
3842 num = data + (offset & 0xffff);
3843 } else {
3844 field = arg->int_array.field->field.field;
3845 if (!field) {
3846 str = arg->int_array.field->field.name;
3847 field = pevent_find_any_field(event, str);
3848 if (!field)
3849 goto out_warning_field;
3850 arg->int_array.field->field.field = field;
3851 }
3852 num = data + field->offset;
3853 }
3854 len = eval_num_arg(data, size, event, arg->int_array.count);
3855 el_size = eval_num_arg(data, size, event,
3856 arg->int_array.el_size);
3857 for (i = 0; i < len; i++) {
3858 if (i)
3859 trace_seq_putc(s, ' ');
3860
3861 if (el_size == 1) {
3862 trace_seq_printf(s, "%u", *(uint8_t *)num);
3863 } else if (el_size == 2) {
3864 trace_seq_printf(s, "%u", *(uint16_t *)num);
3865 } else if (el_size == 4) {
3866 trace_seq_printf(s, "%u", *(uint32_t *)num);
3867 } else if (el_size == 8) {
3868 trace_seq_printf(s, "%lu", *(uint64_t *)num);
3869 } else {
3870 trace_seq_printf(s, "BAD SIZE:%d 0x%x",
3871 el_size, *(uint8_t *)num);
3872 el_size = 1;
3873 }
3874
3875 num += el_size;
3876 }
3877 break;
3878 }
3769 case PRINT_TYPE: 3879 case PRINT_TYPE:
3770 break; 3880 break;
3771 case PRINT_STRING: { 3881 case PRINT_STRING: {
@@ -3997,6 +4107,10 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
3997 goto process_again; 4107 goto process_again;
3998 case '.': 4108 case '.':
3999 goto process_again; 4109 goto process_again;
4110 case 'z':
4111 case 'Z':
4112 ls = 1;
4113 goto process_again;
4000 case 'p': 4114 case 'p':
4001 ls = 1; 4115 ls = 1;
4002 /* fall through */ 4116 /* fall through */
@@ -4939,6 +5053,96 @@ const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid)
4939 return comm; 5053 return comm;
4940} 5054}
4941 5055
5056static struct cmdline *
5057pid_from_cmdlist(struct pevent *pevent, const char *comm, struct cmdline *next)
5058{
5059 struct cmdline_list *cmdlist = (struct cmdline_list *)next;
5060
5061 if (cmdlist)
5062 cmdlist = cmdlist->next;
5063 else
5064 cmdlist = pevent->cmdlist;
5065
5066 while (cmdlist && strcmp(cmdlist->comm, comm) != 0)
5067 cmdlist = cmdlist->next;
5068
5069 return (struct cmdline *)cmdlist;
5070}
5071
5072/**
5073 * pevent_data_pid_from_comm - return the pid from a given comm
5074 * @pevent: a handle to the pevent
5075 * @comm: the cmdline to find the pid from
5076 * @next: the cmdline structure to find the next comm
5077 *
5078 * This returns the cmdline structure that holds a pid for a given
5079 * comm, or NULL if none found. As there may be more than one pid for
5080 * a given comm, the result of this call can be passed back into
5081 * a recurring call in the @next paramater, and then it will find the
5082 * next pid.
5083 * Also, it does a linear seach, so it may be slow.
5084 */
5085struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *comm,
5086 struct cmdline *next)
5087{
5088 struct cmdline *cmdline;
5089
5090 /*
5091 * If the cmdlines have not been converted yet, then use
5092 * the list.
5093 */
5094 if (!pevent->cmdlines)
5095 return pid_from_cmdlist(pevent, comm, next);
5096
5097 if (next) {
5098 /*
5099 * The next pointer could have been still from
5100 * a previous call before cmdlines were created
5101 */
5102 if (next < pevent->cmdlines ||
5103 next >= pevent->cmdlines + pevent->cmdline_count)
5104 next = NULL;
5105 else
5106 cmdline = next++;
5107 }
5108
5109 if (!next)
5110 cmdline = pevent->cmdlines;
5111
5112 while (cmdline < pevent->cmdlines + pevent->cmdline_count) {
5113 if (strcmp(cmdline->comm, comm) == 0)
5114 return cmdline;
5115 cmdline++;
5116 }
5117 return NULL;
5118}
5119
5120/**
5121 * pevent_cmdline_pid - return the pid associated to a given cmdline
5122 * @cmdline: The cmdline structure to get the pid from
5123 *
5124 * Returns the pid for a give cmdline. If @cmdline is NULL, then
5125 * -1 is returned.
5126 */
5127int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline)
5128{
5129 struct cmdline_list *cmdlist = (struct cmdline_list *)cmdline;
5130
5131 if (!cmdline)
5132 return -1;
5133
5134 /*
5135 * If cmdlines have not been created yet, or cmdline is
5136 * not part of the array, then treat it as a cmdlist instead.
5137 */
5138 if (!pevent->cmdlines ||
5139 cmdline < pevent->cmdlines ||
5140 cmdline >= pevent->cmdlines + pevent->cmdline_count)
5141 return cmdlist->pid;
5142
5143 return cmdline->pid;
5144}
5145
4942/** 5146/**
4943 * pevent_data_comm_from_pid - parse the data into the print format 5147 * pevent_data_comm_from_pid - parse the data into the print format
4944 * @s: the trace_seq to write to 5148 * @s: the trace_seq to write to
@@ -5256,6 +5460,15 @@ static void print_args(struct print_arg *args)
5256 print_args(args->hex.size); 5460 print_args(args->hex.size);
5257 printf(")"); 5461 printf(")");
5258 break; 5462 break;
5463 case PRINT_INT_ARRAY:
5464 printf("__print_array(");
5465 print_args(args->int_array.field);
5466 printf(", ");
5467 print_args(args->int_array.count);
5468 printf(", ");
5469 print_args(args->int_array.el_size);
5470 printf(")");
5471 break;
5259 case PRINT_STRING: 5472 case PRINT_STRING:
5260 case PRINT_BSTRING: 5473 case PRINT_BSTRING:
5261 printf("__get_str(%s)", args->string.string); 5474 printf("__get_str(%s)", args->string.string);
@@ -6228,15 +6441,20 @@ void pevent_ref(struct pevent *pevent)
6228 pevent->ref_count++; 6441 pevent->ref_count++;
6229} 6442}
6230 6443
6444void pevent_free_format_field(struct format_field *field)
6445{
6446 free(field->type);
6447 free(field->name);
6448 free(field);
6449}
6450
6231static void free_format_fields(struct format_field *field) 6451static void free_format_fields(struct format_field *field)
6232{ 6452{
6233 struct format_field *next; 6453 struct format_field *next;
6234 6454
6235 while (field) { 6455 while (field) {
6236 next = field->next; 6456 next = field->next;
6237 free(field->type); 6457 pevent_free_format_field(field);
6238 free(field->name);
6239 free(field);
6240 field = next; 6458 field = next;
6241 } 6459 }
6242} 6460}
@@ -6341,6 +6559,7 @@ void pevent_free(struct pevent *pevent)
6341 free_handler(handle); 6559 free_handler(handle);
6342 } 6560 }
6343 6561
6562 free(pevent->trace_clock);
6344 free(pevent->events); 6563 free(pevent->events);
6345 free(pevent->sort_events); 6564 free(pevent->sort_events);
6346 6565
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 7a3873ff9a4f..86a5839fb048 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -22,6 +22,7 @@
22 22
23#include <stdbool.h> 23#include <stdbool.h>
24#include <stdarg.h> 24#include <stdarg.h>
25#include <stdio.h>
25#include <regex.h> 26#include <regex.h>
26#include <string.h> 27#include <string.h>
27 28
@@ -91,6 +92,7 @@ extern int trace_seq_putc(struct trace_seq *s, unsigned char c);
91 92
92extern void trace_seq_terminate(struct trace_seq *s); 93extern void trace_seq_terminate(struct trace_seq *s);
93 94
95extern int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp);
94extern int trace_seq_do_printf(struct trace_seq *s); 96extern int trace_seq_do_printf(struct trace_seq *s);
95 97
96 98
@@ -114,7 +116,7 @@ struct pevent_plugin_option {
114 char *name; 116 char *name;
115 char *plugin_alias; 117 char *plugin_alias;
116 char *description; 118 char *description;
117 char *value; 119 const char *value;
118 void *priv; 120 void *priv;
119 int set; 121 int set;
120}; 122};
@@ -152,6 +154,10 @@ struct pevent_plugin_option {
152 * .plugin_alias is used to give a shorter name to access 154 * .plugin_alias is used to give a shorter name to access
153 * the vairable. Useful if a plugin handles more than one event. 155 * the vairable. Useful if a plugin handles more than one event.
154 * 156 *
157 * If .value is not set, then it is considered a boolean and only
158 * .set will be processed. If .value is defined, then it is considered
159 * a string option and .set will be ignored.
160 *
155 * PEVENT_PLUGIN_ALIAS: (optional) 161 * PEVENT_PLUGIN_ALIAS: (optional)
156 * The name to use for finding options (uses filename if not defined) 162 * The name to use for finding options (uses filename if not defined)
157 */ 163 */
@@ -245,6 +251,12 @@ struct print_arg_hex {
245 struct print_arg *size; 251 struct print_arg *size;
246}; 252};
247 253
254struct print_arg_int_array {
255 struct print_arg *field;
256 struct print_arg *count;
257 struct print_arg *el_size;
258};
259
248struct print_arg_dynarray { 260struct print_arg_dynarray {
249 struct format_field *field; 261 struct format_field *field;
250 struct print_arg *index; 262 struct print_arg *index;
@@ -273,6 +285,7 @@ enum print_arg_type {
273 PRINT_FLAGS, 285 PRINT_FLAGS,
274 PRINT_SYMBOL, 286 PRINT_SYMBOL,
275 PRINT_HEX, 287 PRINT_HEX,
288 PRINT_INT_ARRAY,
276 PRINT_TYPE, 289 PRINT_TYPE,
277 PRINT_STRING, 290 PRINT_STRING,
278 PRINT_BSTRING, 291 PRINT_BSTRING,
@@ -292,6 +305,7 @@ struct print_arg {
292 struct print_arg_flags flags; 305 struct print_arg_flags flags;
293 struct print_arg_symbol symbol; 306 struct print_arg_symbol symbol;
294 struct print_arg_hex hex; 307 struct print_arg_hex hex;
308 struct print_arg_int_array int_array;
295 struct print_arg_func func; 309 struct print_arg_func func;
296 struct print_arg_string string; 310 struct print_arg_string string;
297 struct print_arg_bitmask bitmask; 311 struct print_arg_bitmask bitmask;
@@ -597,7 +611,7 @@ enum trace_flag_type {
597}; 611};
598 612
599int pevent_register_comm(struct pevent *pevent, const char *comm, int pid); 613int pevent_register_comm(struct pevent *pevent, const char *comm, int pid);
600void pevent_register_trace_clock(struct pevent *pevent, char *trace_clock); 614int pevent_register_trace_clock(struct pevent *pevent, const char *trace_clock);
601int pevent_register_function(struct pevent *pevent, char *name, 615int pevent_register_function(struct pevent *pevent, char *name,
602 unsigned long long addr, char *mod); 616 unsigned long long addr, char *mod);
603int pevent_register_print_string(struct pevent *pevent, const char *fmt, 617int pevent_register_print_string(struct pevent *pevent, const char *fmt,
@@ -617,6 +631,7 @@ enum pevent_errno pevent_parse_format(struct pevent *pevent,
617 const char *buf, 631 const char *buf,
618 unsigned long size, const char *sys); 632 unsigned long size, const char *sys);
619void pevent_free_format(struct event_format *event); 633void pevent_free_format(struct event_format *event);
634void pevent_free_format_field(struct format_field *field);
620 635
621void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event, 636void *pevent_get_field_raw(struct trace_seq *s, struct event_format *event,
622 const char *name, struct pevent_record *record, 637 const char *name, struct pevent_record *record,
@@ -675,6 +690,11 @@ int pevent_data_type(struct pevent *pevent, struct pevent_record *rec);
675struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type); 690struct event_format *pevent_data_event_from_type(struct pevent *pevent, int type);
676int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec); 691int pevent_data_pid(struct pevent *pevent, struct pevent_record *rec);
677const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid); 692const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid);
693struct cmdline;
694struct cmdline *pevent_data_pid_from_comm(struct pevent *pevent, const char *comm,
695 struct cmdline *next);
696int pevent_cmdline_pid(struct pevent *pevent, struct cmdline *cmdline);
697
678void pevent_event_info(struct trace_seq *s, struct event_format *event, 698void pevent_event_info(struct trace_seq *s, struct event_format *event,
679 struct pevent_record *record); 699 struct pevent_record *record);
680int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum, 700int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum,
diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c
index 136162c03af1..a16756ae3526 100644
--- a/tools/lib/traceevent/event-plugin.c
+++ b/tools/lib/traceevent/event-plugin.c
@@ -18,6 +18,7 @@
18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 */ 19 */
20 20
21#include <ctype.h>
21#include <stdio.h> 22#include <stdio.h>
22#include <string.h> 23#include <string.h>
23#include <dlfcn.h> 24#include <dlfcn.h>
@@ -49,6 +50,52 @@ struct plugin_list {
49 void *handle; 50 void *handle;
50}; 51};
51 52
53static void lower_case(char *str)
54{
55 if (!str)
56 return;
57 for (; *str; str++)
58 *str = tolower(*str);
59}
60
61static int update_option_value(struct pevent_plugin_option *op, const char *val)
62{
63 char *op_val;
64
65 if (!val) {
66 /* toggle, only if option is boolean */
67 if (op->value)
68 /* Warn? */
69 return 0;
70 op->set ^= 1;
71 return 0;
72 }
73
74 /*
75 * If the option has a value then it takes a string
76 * otherwise the option is a boolean.
77 */
78 if (op->value) {
79 op->value = val;
80 return 0;
81 }
82
83 /* Option is boolean, must be either "1", "0", "true" or "false" */
84
85 op_val = strdup(val);
86 if (!op_val)
87 return -1;
88 lower_case(op_val);
89
90 if (strcmp(val, "1") == 0 || strcmp(val, "true") == 0)
91 op->set = 1;
92 else if (strcmp(val, "0") == 0 || strcmp(val, "false") == 0)
93 op->set = 0;
94 free(op_val);
95
96 return 0;
97}
98
52/** 99/**
53 * traceevent_plugin_list_options - get list of plugin options 100 * traceevent_plugin_list_options - get list of plugin options
54 * 101 *
@@ -120,6 +167,7 @@ update_option(const char *file, struct pevent_plugin_option *option)
120{ 167{
121 struct trace_plugin_options *op; 168 struct trace_plugin_options *op;
122 char *plugin; 169 char *plugin;
170 int ret = 0;
123 171
124 if (option->plugin_alias) { 172 if (option->plugin_alias) {
125 plugin = strdup(option->plugin_alias); 173 plugin = strdup(option->plugin_alias);
@@ -144,9 +192,10 @@ update_option(const char *file, struct pevent_plugin_option *option)
144 if (strcmp(op->option, option->name) != 0) 192 if (strcmp(op->option, option->name) != 0)
145 continue; 193 continue;
146 194
147 option->value = op->value; 195 ret = update_option_value(option, op->value);
148 option->set ^= 1; 196 if (ret)
149 goto out; 197 goto out;
198 break;
150 } 199 }
151 200
152 /* first look for unnamed options */ 201 /* first look for unnamed options */
@@ -156,14 +205,13 @@ update_option(const char *file, struct pevent_plugin_option *option)
156 if (strcmp(op->option, option->name) != 0) 205 if (strcmp(op->option, option->name) != 0)
157 continue; 206 continue;
158 207
159 option->value = op->value; 208 ret = update_option_value(option, op->value);
160 option->set ^= 1;
161 break; 209 break;
162 } 210 }
163 211
164 out: 212 out:
165 free(plugin); 213 free(plugin);
166 return 0; 214 return ret;
167} 215}
168 216
169/** 217/**
diff --git a/tools/lib/traceevent/kbuffer-parse.c b/tools/lib/traceevent/kbuffer-parse.c
index dcc665228c71..3bcada3ae05a 100644
--- a/tools/lib/traceevent/kbuffer-parse.c
+++ b/tools/lib/traceevent/kbuffer-parse.c
@@ -372,7 +372,6 @@ translate_data(struct kbuffer *kbuf, void *data, void **rptr,
372 switch (type_len) { 372 switch (type_len) {
373 case KBUFFER_TYPE_PADDING: 373 case KBUFFER_TYPE_PADDING:
374 *length = read_4(kbuf, data); 374 *length = read_4(kbuf, data);
375 data += *length;
376 break; 375 break;
377 376
378 case KBUFFER_TYPE_TIME_EXTEND: 377 case KBUFFER_TYPE_TIME_EXTEND:
@@ -730,3 +729,14 @@ void kbuffer_set_old_format(struct kbuffer *kbuf)
730 729
731 kbuf->next_event = __old_next_event; 730 kbuf->next_event = __old_next_event;
732} 731}
732
733/**
734 * kbuffer_start_of_data - return offset of where data starts on subbuffer
735 * @kbuf: The kbuffer
736 *
737 * Returns the location on the subbuffer where the data starts.
738 */
739int kbuffer_start_of_data(struct kbuffer *kbuf)
740{
741 return kbuf->start;
742}
diff --git a/tools/lib/traceevent/kbuffer.h b/tools/lib/traceevent/kbuffer.h
index c831f64b17a0..03dce757553f 100644
--- a/tools/lib/traceevent/kbuffer.h
+++ b/tools/lib/traceevent/kbuffer.h
@@ -63,5 +63,6 @@ int kbuffer_missed_events(struct kbuffer *kbuf);
63int kbuffer_subbuffer_size(struct kbuffer *kbuf); 63int kbuffer_subbuffer_size(struct kbuffer *kbuf);
64 64
65void kbuffer_set_old_format(struct kbuffer *kbuf); 65void kbuffer_set_old_format(struct kbuffer *kbuf);
66int kbuffer_start_of_data(struct kbuffer *kbuf);
66 67
67#endif /* _K_BUFFER_H */ 68#endif /* _K_BUFFER_H */
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
index b50234402fc2..0144b3d1bb77 100644
--- a/tools/lib/traceevent/parse-filter.c
+++ b/tools/lib/traceevent/parse-filter.c
@@ -1058,6 +1058,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
1058 *parg = current_op; 1058 *parg = current_op;
1059 else 1059 else
1060 *parg = current_exp; 1060 *parg = current_exp;
1061 free(token);
1061 return PEVENT_ERRNO__UNBALANCED_PAREN; 1062 return PEVENT_ERRNO__UNBALANCED_PAREN;
1062 } 1063 }
1063 break; 1064 break;
@@ -1168,6 +1169,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
1168 1169
1169 *parg = current_op; 1170 *parg = current_op;
1170 1171
1172 free(token);
1171 return 0; 1173 return 0;
1172 1174
1173 fail_alloc: 1175 fail_alloc:
diff --git a/tools/lib/traceevent/trace-seq.c b/tools/lib/traceevent/trace-seq.c
index ec3bd16a5488..292dc9f1d233 100644
--- a/tools/lib/traceevent/trace-seq.c
+++ b/tools/lib/traceevent/trace-seq.c
@@ -231,19 +231,24 @@ void trace_seq_terminate(struct trace_seq *s)
231 s->buffer[s->len] = 0; 231 s->buffer[s->len] = 0;
232} 232}
233 233
234int trace_seq_do_printf(struct trace_seq *s) 234int trace_seq_do_fprintf(struct trace_seq *s, FILE *fp)
235{ 235{
236 TRACE_SEQ_CHECK(s); 236 TRACE_SEQ_CHECK(s);
237 237
238 switch (s->state) { 238 switch (s->state) {
239 case TRACE_SEQ__GOOD: 239 case TRACE_SEQ__GOOD:
240 return printf("%.*s", s->len, s->buffer); 240 return fprintf(fp, "%.*s", s->len, s->buffer);
241 case TRACE_SEQ__BUFFER_POISONED: 241 case TRACE_SEQ__BUFFER_POISONED:
242 puts("Usage of trace_seq after it was destroyed"); 242 fprintf(fp, "%s\n", "Usage of trace_seq after it was destroyed");
243 break; 243 break;
244 case TRACE_SEQ__MEM_ALLOC_FAILED: 244 case TRACE_SEQ__MEM_ALLOC_FAILED:
245 puts("Can't allocate trace_seq buffer memory"); 245 fprintf(fp, "%s\n", "Can't allocate trace_seq buffer memory");
246 break; 246 break;
247 } 247 }
248 return -1; 248 return -1;
249} 249}
250
251int trace_seq_do_printf(struct trace_seq *s)
252{
253 return trace_seq_do_fprintf(s, stdout);
254}