perf/core improvements and fixes
Subsystems (4)
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling,
I've added building objtool to most of the containers in my build test setup:
[root@jouet ~]# perf stat dm
alpine:3.4: Ok
centos:5: Ok
centos:6: Ok
centos:7: Ok
debian:7: Ok
debian:8: Ok
debian:experimental: Ok
fedora:21: Ok
fedora:22: Ok
fedora:23: Ok
fedora:24: Ok
fedora:rawhide: Ok
mageia:5: Ok
opensuse:13.2: Ok
opensuse:42.1: Ok
ubuntu:12.04.5: Ok
ubuntu:14.04.4: Ok
ubuntu:15.10: Ok
ubuntu:16.04: Ok
Performance counter stats for 'dm':
2601.121782 task-clock (msec) # 0.002 CPUs utilized
86,368 context-switches # 0.033 M/sec
5,740 cpu-migrations # 0.002 M/sec
53,962 page-faults # 0.021 M/sec
7,217,605,183 cycles # 2.775 GHz
6,534,540,119 instructions # 0.91 insn per cycle
1,408,715,184 branches # 541.580 M/sec
18,523,459 branch-misses # 1.31% of all branches 1541.746171526 seconds time elapsed
[root@jouet ~]#
- Arnaldo
The following changes since commit 7b39cafb7aa68ef8e32a9f51fbe737d96084ca74:
tools: Work around BITS_PER_LONG related build failure in objtool (2016-07-13 09:37:43 +0200)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-20160713
for you to fetch changes up to 8e5dc848356ecf6ea8d27d641c4d7ad8d42fe92b:
perf test: Add a test case for SDT event (2016-07-13 23:09:10 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
User visible:
- Finish merging initial SDT (Statically Defined Traces) support, see cset comments for details about how it all works (Masami Hiramatsu)
- Support attaching eBPF programs to tracepoints (Wang Nan)
Infrastructure:
- Fix up BITS_PER_LONG setting (Arnaldo Carvalho de Melo)
- Add fallback from ELF_C_READ_MMAP to ELF_C_READ in objtool, fixing the build in libelf implementations lacking that elf_begin() cmd, such as Alpine Linux's (Arnaldo Carvalho de Melo)
- Avoid checking code drift on busybox's diff in objtool (Arnaldo Carvalho de Melo)
----------------------------------------------------------------
Arnaldo Carvalho de Melo (3):
tools: Fix up BITS_PER_LONG setting
objtool: Add fallback from ELF_C_READ_MMAP to ELF_C_READ
objtool: Avoid checking code drift on busybox's diff
Masami Hiramatsu (11):
perf probe: Fix to show correct error message for $vars and $params perf probe: Accept %sdt and %cached event name
perf probe: Make --list show only available cached events perf probe-cache: Add for_each_probe_cache_entry() wrapper perf probe: Allow wildcard for cached events
perf probe: Search SDT/cached event from all probe caches perf list: Show SDT and pre-cached events
perf probe: Support @BUILDID or @FILE suffix for SDT events perf probe: Support a special SDT probe format
perf build: Add sdt feature detection
perf test: Add a test case for SDT event
Wang Nan (5):
tools lib bpf: New API to adjust type of a BPF program tools lib bpf: Report error when kernel doesn't support program type perf event parser: Add const qualifier to evt_name and sys_name perf bpf: Rename bpf__foreach_tev() to bpf__foreach_event() perf bpf: Support BPF program attach to tracepoints
tools/build/Makefile.feature | 3 +- tools/build/feature/Makefile | 6 +- tools/build/feature/test-all.c | 5 + tools/build/feature/test-sdt.c | 7 + tools/include/asm-generic/bitsperlong.h | 24 ++- tools/lib/bpf/libbpf.c | 80 +++++++-- tools/lib/bpf/libbpf.h | 10 ++ tools/objtool/Makefile | 5 +- tools/objtool/elf.c | 7 + tools/perf/Documentation/perf-probe.txt | 11 +- tools/perf/Makefile.perf | 3 + tools/perf/builtin-list.c | 6 +- tools/perf/builtin-probe.c | 2 +- tools/perf/config/Makefile | 10 ++ tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 + tools/perf/tests/make | 3 +- tools/perf/tests/sdt.c | 115 ++++++++++++ tools/perf/tests/tests.h | 1 + tools/perf/util/bpf-loader.c | 73 +++++++- tools/perf/util/bpf-loader.h | 12 +- tools/perf/util/build-id.c | 76 +++++++- tools/perf/util/build-id.h | 3 +- tools/perf/util/parse-events.c | 110 ++++++++++-- tools/perf/util/parse-events.h | 4 +- tools/perf/util/probe-event.c | 309 +++++++++++++++++++++++++++----- tools/perf/util/probe-event.h | 1 + tools/perf/util/probe-file.c | 57 ++++-- tools/perf/util/probe-file.h | 14 ++ 29 files changed, 850 insertions(+), 112 deletions(-) create mode 100644 tools/build/feature/test-sdt.c create mode 100644 tools/perf/tests/sdt.c
Arnaldo Carvalho de Melo
maintainerPATCH 1/19 tools: Fix up BITS_PER_LONG setting
From: Arnaldo Carvalho de Melo <[email protected]>
It was set based on CONFIG_64BIT, that is available only when using Kconfig, which we're working towards but not to the point of having this CONFIG variable set, so synthesize it from available compiler defined defines, __SIZEOF_LONG__ or, lacking that, __WORDSIZE.
--- tools/include/asm-generic/bitsperlong.h | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)
tools/include/asm-generic/bitsperlong.h +19 -5
@@ -3,6 +3,24 @@#include <uapi/asm-generic/bitsperlong.h> +/* +* In the kernel, where this file comes from, we can rely on CONFIG_64BIT, +* here we have to make amends with what the various compilers provides us +* to figure out if we're on a 64-bit machine... +*/ +#ifdef __SIZEOF_LONG__ +# if __SIZEOF_LONG__ ==8 +# define CONFIG_64BIT +# endif +#else +# ifdef __WORDSIZE +# if __WORDSIZE ==64 +# define CONFIG_64BIT +# endif +# else +# error Failed to determine BITS_PER_LONG value +# endif +#endif #ifdef CONFIG_64BIT #define BITS_PER_LONG 64
@@ -10,11 +28,7 @@#define BITS_PER_LONG 32#endif /* CONFIG_64BIT */ -/* -* FIXME: The check currently breaks x86-64 build, so it's -* temporarily disabled. Please fix x86-64 and reenable -*/ -#if 0 &&BITS_PER_LONG != __BITS_PER_LONG +#if BITS_PER_LONG != __BITS_PER_LONG#error Inconsistent word size. Check asm/bitsperlong.h#endif
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 2/19 objtool: Add fallback from ELF_C_READ_MMAP to ELF_C_READ
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Not all libelf implementations have this "Please, ELF_C_READ, but use mmap if possible" elf_begin() cmd, so provide a fallback to plain old ELF_C_READ.
Case in point: Alpine Linux 3.4.
--- tools/objtool/elf.c | 7 +++++++ 1 file changed, 7 insertions(+)
tools/objtool/elf.c +7 -0
@@ -30,6 +30,13 @@#include "elf.h" #include "warn.h" +/* +* Fallback for systems without this "read, mmaping if possible" cmd. +*/ +#ifndef ELF_C_READ_MMAP +#define ELF_C_READ_MMAP ELF_C_READ +#endif +struct section *find_section_by_name (struct elf *elf,const char *name) {struct section *sec;
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 3/19 objtool: Avoid checking code drift on busybox's diff
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
That doesn't have -I to match lines.
--- tools/objtool/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
tools/objtool/Makefile +4 -1
@@ -41,8 +41,11 @@ include $(srctree)/tools/build/Makefile.include $(OBJTOOL_IN): fixdep FORCE @$(MAKE) $(build)=objtool +# Busybox's diff doesn't have -I, avoid warning in that case +# $(OBJTOOL): $(LIBSUBCMD) $(OBJTOOL_IN) - @(test -d ../../kernel -a -d ../../tools -a -d ../objtool && (( \ + @(diff -I 2>&1 | grep -q 'option requires an argument' && \ + test -d ../../kernel -a -d ../../tools -a -d ../objtool && (( \ diff -I'^#include' arch/x86/insn/insn.c ../../arch/x86/lib/insn.c >/dev/null && \ diff -I'^#include' arch/x86/insn/inat.c ../../arch/x86/lib/inat.c >/dev/null && \ diff arch/x86/insn/x86-opcode-map.txt ../../arch/x86/lib/x86-opcode-map.txt >/dev/null && \
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 4/19 tools lib bpf: New API to adjust type of a BPF program
In reply to Arnaldo Carvalho de MeloFrom: Wang Nan <[email protected]>
Add 4 new APIs to adjust and query the type of a BPF program. Load program according to type set by caller. Default is set to BPF_PROG_TYPE_KPROBE.
--- tools/lib/bpf/libbpf.c | 53 +++++++++++++++++++++++++++++++++++++++++++------- tools/lib/bpf/libbpf.h | 9 +++++++++ 2 files changed, 55 insertions(+), 7 deletions(-)
tools/lib/bpf/libbpf.c +46 -7
@@ -158,6 +158,7 @@ struct bpf_program {char *section_name;struct bpf_insn *insns;size_t insns_cnt; +enum bpf_prog_type type;struct {int insn_idx;
@@ -299,6 +300,7 @@ bpf_program__init(void *data, size_t size, char *name, int idx, prog->idx = idx; prog->instances.fds =NULL ; prog->instances.nr =-1 ; + prog->type =BPF_PROG_TYPE_KPROBE ;return 0 ; errout:
@@ -894,8 +896,8 @@ static int bpf_object__collect_reloc(struct bpf_object *obj) }static int -load_program (struct bpf_insn *insns,int insns_cnt, -char *license,u32 kern_version,int *pfd) +load_program (enum bpf_prog_type type,struct bpf_insn *insns, +int insns_cnt,char *license,u32 kern_version,int *pfd) {int ret;char *log_buf;
@@ -907,9 +909,8 @@ load_program(struct bpf_insn *insns, int insns_cnt,if (!log_buf)pr_warning ("Alloc log buffer for bpf loader error, continue without log\n" ); - ret =bpf_load_program (BPF_PROG_TYPE_KPROBE , insns, - insns_cnt, license, kern_version, - log_buf,BPF_LOG_BUF_SIZE ); + ret =bpf_load_program (type, insns, insns_cnt, license, + kern_version, log_buf,BPF_LOG_BUF_SIZE );if (ret >=0 ) { *pfd = ret;
@@ -968,7 +969,7 @@ bpf_program__load(struct bpf_program *prog,pr_warning ("Program '%s' is inconsistent: nr(%d) != 1\n" , prog->section_name, prog->instances.nr); } - err =load_program (prog->insns, prog->insns_cnt, + err =load_program (prog->type, prog->insns, prog->insns_cnt, license, kern_version, &fd);if (!err) prog->instances.fds[0 ] = fd;
@@ -997,7 +998,7 @@ bpf_program__load(struct bpf_program *prog,continue ; } - err =load_program (result.new_insn_ptr, + err =load_program (prog->type, result.new_insn_ptr, result.new_insn_cnt, license, kern_version, &fd);
@@ -1316,6 +1317,44 @@ int bpf_program__nth_fd(struct bpf_program *prog, int n)return fd; } +static void bpf_program__set_type (struct bpf_program *prog, +enum bpf_prog_type type) +{ + prog->type = type; +} + +int bpf_program__set_tracepoint (struct bpf_program *prog) +{ +if (!prog) +return -EINVAL ; +bpf_program__set_type (prog,BPF_PROG_TYPE_TRACEPOINT ); +return 0 ; +} + +int bpf_program__set_kprobe (struct bpf_program *prog) +{ +if (!prog) +return -EINVAL ; +bpf_program__set_type (prog,BPF_PROG_TYPE_KPROBE ); +return 0 ; +} + +static bool bpf_program__is_type (struct bpf_program *prog, +enum bpf_prog_type type) +{ +return prog ? (prog->type == type) : false; +} + +bool bpf_program__is_tracepoint (struct bpf_program *prog) +{ +return bpf_program__is_type (prog,BPF_PROG_TYPE_TRACEPOINT ); +} + +bool bpf_program__is_kprobe (struct bpf_program *prog) +{ +return bpf_program__is_type (prog,BPF_PROG_TYPE_KPROBE ); +} +int bpf_map__fd (struct bpf_map *map) {return map ? map->fd : -EINVAL ;
tools/lib/bpf/libbpf.h +9 -0
@@ -165,6 +165,15 @@ int bpf_program__set_prep(struct bpf_program *prog, int nr_instance,int bpf_program__nth_fd (struct bpf_program *prog,int n);/* +* Adjust type of bpf program. Default is kprobe. +*/ +int bpf_program__set_tracepoint (struct bpf_program *prog); +int bpf_program__set_kprobe (struct bpf_program *prog); + +bool bpf_program__is_tracepoint (struct bpf_program *prog); +bool bpf_program__is_kprobe (struct bpf_program *prog); + +/* * We don't need __attribute__((packed)) now since it is * unnecessary for 'bpf_map_def' because they are all aligned. * In addition, using it will trigger -Wpacked warning message,
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 5/19 tools lib bpf: Report error when kernel doesn't support program type
In reply to Arnaldo Carvalho de MeloFrom: Wang Nan <[email protected]>
Now libbpf support tracepoint program type. Report meaningful error when kernel version is less than 4.7.
--- tools/lib/bpf/libbpf.c | 27 ++++++++++++++++++++------- tools/lib/bpf/libbpf.h | 1 + 2 files changed, 21 insertions(+), 7 deletions(-)
tools/lib/bpf/libbpf.c +20 -7
@@ -90,6 +90,7 @@ static const char *libbpf_strerror_table[NR_ERRNO] = { [ERRCODE_OFFSET(VERIFY)] = "Kernel verifier blocks program loading", [ERRCODE_OFFSET(PROG2BIG)] = "Program too big", [ERRCODE_OFFSET(KVER)] = "Incorrect kernel version", + [ERRCODE_OFFSET(PROGTYPE)] = "Kernel doesn't support this program type", };int libbpf_strerror (int err,char *buf,size_t size)
@@ -926,15 +927,27 @@ load_program(enum bpf_prog_type type, struct bpf_insn *insns,pr_warning ("-- BEGIN DUMP LOG ---\n" );pr_warning ("\n%s\n" , log_buf);pr_warning ("-- END LOG --\n" ); + }else if (insns_cnt >=BPF_MAXINSNS ) { +pr_warning ("Program too large (%d insns), at most %d insns\n" , + insns_cnt,BPF_MAXINSNS ); + ret = -LIBBPF_ERRNO__PROG2BIG ; }else { -if (insns_cnt >=BPF_MAXINSNS ) { -pr_warning ("Program too large (%d insns), at most %d insns\n" , - insns_cnt,BPF_MAXINSNS ); - ret = -LIBBPF_ERRNO__PROG2BIG ; - }else if (log_buf) { -pr_warning ("log buffer is empty\n" ); - ret = -LIBBPF_ERRNO__KVER ; +/* Wrong program type? */ +if (type !=BPF_PROG_TYPE_KPROBE ) { +int fd; + + fd =bpf_load_program (BPF_PROG_TYPE_KPROBE , insns, + insns_cnt, license, kern_version, +NULL ,0 ); +if (fd >=0 ) { +close (fd); + ret = -LIBBPF_ERRNO__PROGTYPE ; + goto out; + } } + +if (log_buf) + ret = -LIBBPF_ERRNO__KVER ; } out:
tools/lib/bpf/libbpf.h +1 -0
@@ -39,6 +39,7 @@ enum libbpf_errno {LIBBPF_ERRNO__VERIFY ,/* Kernel verifier blocks program loading */ LIBBPF_ERRNO__PROG2BIG ,/* Program too big */ LIBBPF_ERRNO__KVER ,/* Incorrect kernel version */ +LIBBPF_ERRNO__PROGTYPE ,/* Kernel doesn't support this program type */ __LIBBPF_ERRNO__END, };
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 6/19 perf event parser: Add const qualifier to evt_name and sys_name
In reply to Arnaldo Carvalho de MeloFrom: Wang Nan <[email protected]>
Add missing 'const' qualifiers so following commits are able to create tracepoints using const strings.
--- tools/perf/util/parse-events.c | 12 ++++++------ tools/perf/util/parse-events.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-)
tools/perf/util/parse-events.c +6 -6
@@ -436,7 +436,7 @@ int parse_events_add_cache(struct list_head *list, int *idx, }static void tracepoint_error (struct parse_events_error *e,int err, -char *sys,char *name) +const char *sys,const char *name) {char help[BUFSIZ ];
@@ -466,7 +466,7 @@ static void tracepoint_error(struct parse_events_error *e, int err, }static int add_tracepoint (struct list_head *list,int *idx, -char *sys_name,char *evt_name, +const char *sys_name,const char *evt_name,struct parse_events_error *err,struct list_head *head_config) {
@@ -491,7 +491,7 @@ static int add_tracepoint(struct list_head *list, int *idx, }static int add_tracepoint_multi_event (struct list_head *list,int *idx, -char *sys_name,char *evt_name, +const char *sys_name,const char *evt_name,struct parse_events_error *err,struct list_head *head_config) {
@@ -533,7 +533,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx, }static int add_tracepoint_event (struct list_head *list,int *idx, -char *sys_name,char *evt_name, +const char *sys_name,const char *evt_name,struct parse_events_error *err,struct list_head *head_config) {
@@ -545,7 +545,7 @@ static int add_tracepoint_event(struct list_head *list, int *idx, }static int add_tracepoint_multi_sys (struct list_head *list,int *idx, -char *sys_name,char *evt_name, +const char *sys_name,const char *evt_name,struct parse_events_error *err,struct list_head *head_config) {
@@ -1126,7 +1126,7 @@ do { \ }int parse_events_add_tracepoint (struct list_head *list,int *idx, -char *sys,char *event, +const char *sys,const char *event,struct parse_events_error *err,struct list_head *head_config) {
tools/perf/util/parse-events.h +1 -1
@@ -134,7 +134,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add);int parse_events__modifier_group (struct list_head *list,char *event_mod);int parse_events_name (struct list_head *list,char *name);int parse_events_add_tracepoint (struct list_head *list,int *idx, -char *sys,char *event, +const char *sys,const char *event,struct parse_events_error *error,struct list_head *head_config); int parse_events_load_bpf(struct parse_events_evlist *data,
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 7/19 perf bpf: Rename bpf__foreach_tev() to bpf__foreach_event()
In reply to Arnaldo Carvalho de MeloFrom: Wang Nan <[email protected]>
Following commit will allow BPF script attach to tracepoints. bpf__foreach_tev() will iterate over all events, not only kprobes. Rename it to bpf__foreach_event().
Since only group and event are used by caller, there's no need to pass full 'struct probe_trace_event' to bpf_prog_iter_callback_t. Pass only these two strings. After this patch bpf_prog_iter_callback_t natually support tracepoints.
--- tools/perf/util/bpf-loader.c | 8 ++++---- tools/perf/util/bpf-loader.h | 12 ++++++------ tools/perf/util/parse-events.c | 16 ++++++++-------- 3 files changed, 18 insertions(+), 18 deletions(-)
tools/perf/util/bpf-loader.c +4 -4
@@ -693,9 +693,9 @@ int bpf__load(struct bpf_object *obj)return 0 ; } -int bpf__foreach_tev (struct bpf_object *obj, -bpf_prog_iter_callback_t func, -void *arg) +int bpf__foreach_event (struct bpf_object *obj, +bpf_prog_iter_callback_t func, +void *arg) {struct bpf_program *prog;int err;
@@ -728,7 +728,7 @@ int bpf__foreach_tev(struct bpf_object *obj,return fd; } - err = (*func)(tev, fd, arg); + err = (*func)(tev->group, tev->event, fd, arg);if (err) {pr_debug ("bpf: call back failed, stop iterate\n" );return err;
tools/perf/util/bpf-loader.h +6 -6
@@ -46,7 +46,7 @@ struct bpf_object;struct parse_events_term ;#define PERF_BPF_PROBE_GROUP "perf_bpf_probe" -typedef int (*bpf_prog_iter_callback_t )(struct probe_trace_event *tev, +typedef int (*bpf_prog_iter_callback_t )(const char *group,const char *event,int fd,void *arg);#ifdef HAVE_LIBBPF_SUPPORT
@@ -67,8 +67,8 @@ int bpf__strerror_probe(struct bpf_object *obj, int err,int bpf__load (struct bpf_object *obj);int bpf__strerror_load (struct bpf_object *obj,int err,char *buf,size_t size); -int bpf__foreach_tev (struct bpf_object *obj, -bpf_prog_iter_callback_t func,void *arg); +int bpf__foreach_event (struct bpf_object *obj, +bpf_prog_iter_callback_t func,void *arg);int bpf__config_obj (struct bpf_object *obj,struct parse_events_term *term,struct perf_evlist *evlist,int *error_pos);
@@ -107,9 +107,9 @@ static inline int bpf__unprobe(struct bpf_object *obj __maybe_unused) { return 0static inline int bpf__load (struct bpf_object *obj__maybe_unused ) {return 0 ; }static inline int -bpf__foreach_tev (struct bpf_object *obj__maybe_unused , -bpf_prog_iter_callback_t func__maybe_unused , -void *arg__maybe_unused ) +bpf__foreach_event (struct bpf_object *obj__maybe_unused , +bpf_prog_iter_callback_t func__maybe_unused , +void *arg__maybe_unused ) {return 0 ; }
tools/perf/util/parse-events.c +8 -8
@@ -584,7 +584,7 @@ struct __add_bpf_event_param {struct list_head *head_config; }; -static int add_bpf_event (struct probe_trace_event *tev,int fd, +static int add_bpf_event (const char *group,const char *event,int fd,void *_param) {LIST_HEAD (new_evsels);
@@ -595,27 +595,27 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd,int err;pr_debug ("add bpf event %s:%s and attach bpf program %d\n" , - tev->group, tev->event, fd); + group, event, fd); - err =parse_events_add_tracepoint (&new_evsels, &evlist->idx, tev->group, - tev->event, evlist->error, + err =parse_events_add_tracepoint (&new_evsels, &evlist->idx, group, + event, evlist->error, param->head_config);if (err) {struct perf_evsel *evsel, *tmp;pr_debug ("Failed to add BPF event %s:%s\n" , - tev->group, tev->event); + group, event);list_for_each_entry_safe (evsel, tmp, &new_evsels, node) {list_del (&evsel->node);perf_evsel__delete (evsel); }return err; } -pr_debug ("adding %s:%s\n" , tev->group, tev->event); +pr_debug ("adding %s:%s\n" , group, event);list_for_each_entry (pos, &new_evsels, node) {pr_debug ("adding %s:%s to %p\n" , - tev->group, tev->event, pos); + group, event, pos); pos->bpf_fd = fd; }list_splice (&new_evsels, list);
@@ -661,7 +661,7 @@ int parse_events_load_bpf_obj(struct parse_events_evlist *data, goto errout; } - err =bpf__foreach_tev (obj, add_bpf_event, ¶m); + err =bpf__foreach_event (obj, add_bpf_event, ¶m);if (err) {snprintf (errbuf,sizeof (errbuf),"Attach events in BPF object failed" );
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 8/19 perf bpf: Support BPF program attach to tracepoints
In reply to Arnaldo Carvalho de MeloFrom: Wang Nan <[email protected]>
To support 98b5c2c65c29 ("perf, bpf: allow bpf programs attach to tracepoints"), this patch allows BPF scripts to select tracepoints in their section name.
Example:
# cat test_tracepoint.c
/*********************************************/
#include <uapi/linux/bpf.h>
#define SEC(NAME) __attribute__((section(NAME), used))
SEC("raw_syscalls:sys_enter")
int func(void *ctx)
{
/*
* /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/format:
* ...
* field:long id; offset:8; size:8; signed:1;
* ...
* ctx + 8 select 'id'
*/
u64 id = *((u64 *)(ctx + 8));
if (id == 1)
return 1;
return 0;
}
SEC("_write=sys_write")
int _write(void *ctx)
{
return 1;
}
char _license[] SEC("license") = "GPL";
int _version SEC("version") = LINUX_VERSION_CODE;
/*********************************************/
# perf record -e ./test_tracepoint.c dd if=/dev/zero of=/dev/null count=5
5+0 records in
5+0 records out
2560 bytes (2.6 kB) copied, 6.2281e-05 s, 41.1 MB/s
[ perf record: Woken up 1 times to write data ]
# perf script
dd 13436 [005] 1596.490869: raw_syscalls:sys_enter: NR 1 (1, 178d000, 200, 7ffe82470d60, ffffffffffffe020, fffff
dd 13436 [005] 1596.490871: perf_bpf_probe:_write: (ffffffff812351e0)
dd 13436 [005] 1596.490873: raw_syscalls:sys_enter: NR 1 (1, 178d000, 200, ffffffffffffe000, ffffffffffffe020, f
dd 13436 [005] 1596.490874: perf_bpf_probe:_write: (ffffffff812351e0)
dd 13436 [005] 1596.490876: raw_syscalls:sys_enter: NR 1 (1, 178d000, 200, ffffffffffffe000, ffffffffffffe020, f
dd 13436 [005] 1596.490876: perf_bpf_probe:_write: (ffffffff812351e0)
dd 13436 [005] 1596.490878: raw_syscalls:sys_enter: NR 1 (1, 178d000, 200, ffffffffffffe000, ffffffffffffe020, f
dd 13436 [005] 1596.490879: perf_bpf_probe:_write: (ffffffff812351e0)
dd 13436 [005] 1596.490881: raw_syscalls:sys_enter: NR 1 (1, 178d000, 200, ffffffffffffe000, ffffffffffffe020, f
dd 13436 [005] 1596.490882: perf_bpf_probe:_write: (ffffffff812351e0)
dd 13436 [005] 1596.490900: raw_syscalls:sys_enter: NR 1 (2, 7ffe8246e640, 1f, 40acb8, 7f44bac74700, 7f44baa4fba
dd 13436 [005] 1596.490901: perf_bpf_probe:_write: (ffffffff812351e0)
dd 13436 [005] 1596.490917: raw_syscalls:sys_enter: NR 1 (2, 7ffe8246e640, 1a, fffffffa, 7f44bac74700, 7f44baa4f
dd 13436 [005] 1596.490918: perf_bpf_probe:_write: (ffffffff812351e0)
dd 13436 [005] 1596.490932: raw_syscalls:sys_enter: NR 1 (2, 7ffe8246e640, 1a, fffffff9, 7f44bac74700, 7f44baa4f
dd 13436 [005] 1596.490933: perf_bpf_probe:_write: (ffffffff812351e0)Committer note:
Further testing:
# trace --no-sys --event /home/acme/bpf/tracepoint.c cat /etc/passwd > /dev/null
0.000 raw_syscalls:sys_enter:NR 1 (1, 7f0490504000, c48, 7f0490503010, ffffffffffffffff, 0))
0.006 perf_bpf_probe:_write:(ffffffff81241bc0))
#--- tools/perf/util/bpf-loader.c | 65 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 5 deletions(-)
tools/perf/util/bpf-loader.c +60 -5
@@ -37,6 +37,9 @@ DEFINE_PRINT_FN(info, 1) DEFINE_PRINT_FN(debug, 1)struct bpf_prog_priv { +bool is_tp; +char *sys_name; +char *evt_name;struct perf_probe_event pev;bool need_prologue;struct bpf_insn *insns_buf;
@@ -118,6 +121,8 @@ clear_prog_priv(struct bpf_program *prog __maybe_unused,cleanup_perf_probe_events (&priv->pev,1 );zfree (&priv->insns_buf);zfree (&priv->type_mapping); +zfree (&priv->sys_name); +zfree (&priv->evt_name);free (priv); }
@@ -269,7 +274,8 @@ nextline: }static int -parse_prog_config (const char *config_str,struct perf_probe_event *pev) +parse_prog_config (const char *config_str,const char **p_main_str, +bool *is_tp,struct perf_probe_event *pev) {int err;const char *main_str =parse_prog_config_kvpair (config_str, pev);
@@ -277,6 +283,22 @@ parse_prog_config(const char *config_str, struct perf_probe_event *pev)if (IS_ERR (main_str))return PTR_ERR (main_str); + *p_main_str = main_str; +if (!strchr (main_str,'=' )) { +/* Is a tracepoint event? */ +const char *s =strchr (main_str,':' ); + +if (!s) { +pr_debug ("bpf: '%s' is not a valid tracepoint\n" , + config_str); +return -BPF_LOADER_ERRNO__CONFIG ; + } + + *is_tp = true; +return 0 ; + } + + *is_tp = false; err =parse_perf_probe_command (main_str, pev);if (err <0 ) { pr_debug("bpf: '%s' is not a valid config string\n",
@@ -292,7 +314,8 @@ config_bpf_program(struct bpf_program *prog) {struct perf_probe_event *pev =NULL ;struct bpf_prog_priv *priv =NULL ; -const char *config_str; +const char *config_str, *main_str; +bool is_tp = false;int err;/* Initialize per-program probing setting */
@@ -313,10 +336,19 @@ config_bpf_program(struct bpf_program *prog) pev = &priv->pev;pr_debug ("bpf: config program '%s'\n" , config_str); - err =parse_prog_config (config_str, pev); + err =parse_prog_config (config_str, &main_str, &is_tp, pev);if (err) goto errout; +if (is_tp) { +char *s =strchr (main_str,':' ); + + priv->is_tp = true; + priv->sys_name =strndup (main_str, s - main_str); + priv->evt_name =strdup (s +1 ); + goto set_priv; + } +if (pev->group &&strcmp (pev->group,PERF_BPF_PROBE_GROUP )) {pr_debug ("bpf: '%s': group for event is set and not '%s'.\n" , config_str,PERF_BPF_PROBE_GROUP );
@@ -339,6 +371,7 @@ config_bpf_program(struct bpf_program *prog) }pr_debug ("bpf: config '%s' is ok\n" , config_str); +set_priv: err =bpf_program__set_priv (prog, priv, clear_prog_priv);if (err) {pr_debug ("Failed to set priv for program '%s'\n" , config_str);
@@ -387,7 +420,7 @@ preproc_gen_prologue(struct bpf_program *prog, int n,size_t prologue_cnt =0 ;int i, err; -if (IS_ERR (priv) || !priv) +if (IS_ERR (priv) || !priv || priv->is_tp) goto errout; pev = &priv->pev;
@@ -544,6 +577,11 @@ static int hook_load_preprocessor(struct bpf_program *prog)return -BPF_LOADER_ERRNO__INTERNAL ; } +if (priv->is_tp) { + priv->need_prologue = false; +return 0 ; + } + pev = &priv->pev;for (i =0 ; i < pev->ntevs; i++) {struct probe_trace_event *tev = &pev->tevs[i];
@@ -610,6 +648,13 @@ int bpf__probe(struct bpf_object *obj) err =PTR_ERR (priv); goto out; } + +if (priv->is_tp) { +bpf_program__set_tracepoint (prog); +continue ; + } + +bpf_program__set_kprobe (prog); pev = &priv->pev; err =convert_perf_probe_events (pev,1 );
@@ -650,7 +695,7 @@ int bpf__unprobe(struct bpf_object *obj)struct bpf_prog_priv *priv =bpf_program__priv (prog);int i; -if (IS_ERR (priv) || !priv) +if (IS_ERR (priv) || !priv || priv->is_tp)continue ;for (i =0 ; i < priv->pev.ntevs; i++) {
@@ -711,6 +756,16 @@ int bpf__foreach_event(struct bpf_object *obj,return -BPF_LOADER_ERRNO__INTERNAL ; } +if (priv->is_tp) { + fd =bpf_program__fd (prog); + err = (*func)(priv->sys_name, priv->evt_name, fd, arg); +if (err) { +pr_debug ("bpf: tracepoint call back failed, stop iterate\n" ); +return err; + } +continue ; + } + pev = &priv->pev;for (i =0 ; i < pev->ntevs; i++) { tev = &pev->tevs[i];
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 9/19 perf probe: Fix to show correct error message for $vars and $params
In reply to Arnaldo Carvalho de MeloFrom: Masami Hiramatsu <[email protected]>
Fix to show correct error messages for $vars and $params because those special variables requires debug information to find the real variables or function parameters.
E.g. without this fix;
----
# perf probe -x /lib64/libc-2.23.so getaddrinfo \$params
Failed to write event: Invalid argument
Please upgrade your kernel to at least 3.14 to have access to feature $params
Error: Failed to add events.
----Perf ends up with an error, but the message is not correct. With this fix, perf shows correct error message as below.
----
# perf probe -x /lib64/libc-2.23.so getaddrinfo \$params
The /usr/lib64/libc-2.23.so file has no debug information.
Rebuild with -g, or install an appropriate debuginfo package.
Error: Failed to add events.
------- tools/perf/util/probe-event.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
tools/perf/util/probe-event.c +3 -1
@@ -1547,7 +1547,9 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)return true;for (i =0 ; i < pev->nargs; i++) -if (is_c_varname (pev->args[i].var)) +if (is_c_varname (pev->args[i].var) || + !strcmp (pev->args[i].var,"$params" ) || + !strcmp (pev->args[i].var,"$vars" ))return true;return false;
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 10/19 perf probe: Accept %sdt and %cached event name
In reply to Arnaldo Carvalho de MeloFrom: Masami Hiramatsu <[email protected]>
To improve usability, support %[PROVIDER:]SDTEVENT format to add new probes on SDT and cached events.
e.g.
----
# perf probe -x /lib/libc-2.17.so %lll_lock_wait_private
Added new event:
sdt_libc:lll_lock_wait_private (on %lll_lock_wait_private in /usr/lib/libc-2.17.so)You can now use it in all perf tools, such as:
perf record -e sdt_libc:lll_lock_wait_private -aR sleep 1
# perf probe -l | more
sdt_libc:lll_lock_wait_private (on __lll_lock_wait_private+21 in /usr/lib/libc-2.17.so)
----Note that this is not only for SDT events, but also normal events with event-name.
e.g. define "myevent" on cache (-n doesn't add the real probe)
----
# perf probe -x ./perf --cache -n --add 'myevent=dso__load $params' ---- Reuse the "myevent" from cache as below. ---- # perf probe -x ./perf %myevent ----
--- tools/perf/Documentation/perf-probe.txt | 9 +++- tools/perf/util/probe-event.c | 82 +++++++++++++++++++++++---------- tools/perf/util/probe-event.h | 1 + tools/perf/util/probe-file.c | 9 ++++ 4 files changed, 76 insertions(+), 25 deletions(-)
tools/perf/Documentation/perf-probe.txt +8 -1
@@ -151,6 +151,8 @@ Probe points are defined by following syntax. 3) Define event based on source file with lazy pattern [[GROUP:]EVENT=]SRC;PTN [ARG ...] + 4) Pre-defined SDT events or cached event with name + %[PROVIDER:]SDTEVENT 'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. You can also specify a group name by 'GROUP', if omitted, set 'probe' is used for kprobe and 'probe_<bin>' is used for uprobe. Note that using existing group name can conflict with other events. Especially, using the group name reserved for kernel modules can hide embedded events in the
@@ -158,6 +160,11 @@ modules. 'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, ':RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. And ';PTN' means lazy matching pattern (see LAZY MATCHING). Note that ';PTN' must be the end of the probe point definition. In addition, '@SRC' specifies a source file which has that function. It is also possible to specify a probe point by the source line number or lazy matching by using 'SRC:ALN' or 'SRC;PTN' syntax, where 'SRC' is the source file path, ':ALN' is the line number and ';PTN' is the lazy matching pattern. 'ARG' specifies the arguments of this probe point, (see PROBE ARGUMENT). +'SDTEVENT' and 'PROVIDER' is the pre-defined event name which is defined by user SDT (Statically Defined Tracing) or the pre-cached probes with event name. +Note that before using the SDT event, the target binary (on which SDT events are defined) must be scanned by linkperf:perf-buildid-cache[1] to make SDT events as cached events. + +For details of the SDT, see below. +https://sourceware.org/gdb/onlinedocs/gdb/Static-Probe-Points.html PROBE ARGUMENT --------------
@@ -237,4 +244,4 @@ Add probes at malloc() function on libc SEE ALSO -------- -linkperf:perf-trace[1], linkperf:perf-record[1] +linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1]
tools/perf/util/probe-event.c +58 -24
124 lines not on this page · raw message
tools/perf/util/probe-event.h +1 -0
@@ -85,6 +85,7 @@ struct perf_probe_event {char *group;/* Group name */ struct perf_probe_point point;/* Probe point */ int nargs;/* Number of arguments */ +bool sdt;/* SDT/cached event flag */ bool uprobes;/* Uprobe event flag */ char *target;/* Target binary */ struct perf_probe_arg *args;/* Arguments */
tools/perf/util/probe-file.c +9 -0
@@ -547,6 +547,15 @@ probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)return NULL ;list_for_each_entry (entry, &pcache->entries, node) { +if (pev->sdt) { +if (entry->pev.event && +streql (entry->pev.event, pev->event) && + (!pev->group || +streql (entry->pev.group, pev->group))) + goto found; + +continue ; + }/* Hit if same event name or same command-string */ if ((pev->event && (streql(entry->pev.group, pev->group) &&
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 11/19 perf probe: Make --list show only available cached events
In reply to Arnaldo Carvalho de MeloFrom: Masami Hiramatsu <[email protected]>
Make "perf probe --cache --list" show only available cached events by checking build-id validity.
E.g. without this patch:
----
$ ./perf probe --cache --add oldevent=cmd_probe $ make #(to update ./perf) $ ./perf probe --cache --add newevent=cmd_probe $ ./perf probe --cache --list /home/mhiramat/ksrc/linux/tools/perf/perf (061e90539bac69 probe_perf:newevent=cmd_probe /home/mhiramat/ksrc/linux/tools/perf/perf (c2e44d614e33e1 probe_perf:oldevent=cmd_probe ---- It shows both of old and new events but user can not use old one. With this; ---- $ ./perf probe --cache -l /home/mhiramat/ksrc/linux/tools/perf/perf (061e90539bac69 probe_perf:newevent=cmd_probe ----
This shows only new events which are on the existing binary.
--- tools/perf/builtin-probe.c | 2 +- tools/perf/util/build-id.c | 33 ++++++++++++++++++++++++++++++++- tools/perf/util/build-id.h | 2 +- tools/perf/util/probe-file.c | 2 +- 4 files changed, 35 insertions(+), 4 deletions(-)
tools/perf/builtin-probe.c +1 -1
@@ -370,7 +370,7 @@ static int del_perf_probe_caches(struct strfilter *filter)struct str_node *nd;int ret; - bidlist =build_id_cache__list_all (); + bidlist =build_id_cache__list_all (false);if (!bidlist) { ret = -errno;pr_debug ("Failed to get buildids: %d\n" , ret);
tools/perf/util/build-id.c +32 -1
@@ -206,6 +206,31 @@ out:return ret; } +/* Check if the given build_id cache is valid on current running system */ +static bool build_id_cache__valid_id (char *sbuild_id) +{ +char real_sbuild_id[SBUILD_ID_SIZE ] ="" ; +char *pathname; +int ret =0 ; +bool result = false; + + pathname =build_id_cache__origname (sbuild_id); +if (!pathname) +return false; + +if (!strcmp (pathname,DSO__NAME_KALLSYMS )) + ret =sysfs__sprintf_build_id ("/" , real_sbuild_id); +else if (pathname[0 ] =='/' ) + ret =filename__sprintf_build_id (pathname, real_sbuild_id); +else + ret = -EINVAL ;/* Should we support other special DSO cache? */ +if (ret >=0 ) + result = (strcmp (sbuild_id, real_sbuild_id) ==0 ); +free (pathname); + +return result; +} +static const char *build_id_cache__basename (bool is_kallsyms,bool is_vdso) {return is_kallsyms ?"kallsyms" : (is_vdso ?"vdso" :"elf" );
@@ -433,13 +458,17 @@ static bool lsdir_bid_tail_filter(const char *name __maybe_unused,return (i ==SBUILD_ID_SIZE -3 ) && (d->d_name[i] =='\0' ); } -struct strlist *build_id_cache__list_all (void ) +struct strlist *build_id_cache__list_all (bool validonly) {struct strlist *toplist, *linklist =NULL , *bidlist;struct str_node *nd, *nd2;char *topdir, *linkdir =NULL ;char sbuild_id[SBUILD_ID_SIZE ]; +/* for filename__ functions */ +if (validonly) +symbol__init (NULL ); +/* Open the top-level directory */ if (asprintf (&topdir,"%s/.build-id/" , buildid_dir) <0 )return NULL ;
@@ -470,6 +499,8 @@ struct strlist *build_id_cache__list_all(void)if (snprintf (sbuild_id,SBUILD_ID_SIZE ,"%s%s" , nd->s, nd2->s) !=SBUILD_ID_SIZE -1 ) goto err_out; +if (validonly && !build_id_cache__valid_id (sbuild_id)) +continue ;if (strlist__add (bidlist, sbuild_id) <0 ) goto err_out; }
tools/perf/util/build-id.h +1 -1
@@ -34,7 +34,7 @@ char *build_id_cache__origname(const char *sbuild_id);char *build_id_cache__linkname (const char *sbuild_id,char *bf,size_t size);char *build_id_cache__cachedir (const char *sbuild_id,const char *name,bool is_kallsyms,bool is_vdso); -struct strlist *build_id_cache__list_all (void ); +struct strlist *build_id_cache__list_all (bool validonly);int build_id_cache__list_build_ids (const char *pathname,struct strlist **result);bool build_id_cache__cached (const char *sbuild_id);
tools/perf/util/probe-file.c +1 -1
@@ -808,7 +808,7 @@ int probe_cache__show_all_caches(struct strfilter *filter)pr_debug ("list cache with filter: %s\n" , buf);free (buf); - bidlist =build_id_cache__list_all (); + bidlist =build_id_cache__list_all (true);if (!bidlist) {pr_debug ("Failed to get buildids: %d\n" , errno);return -EINVAL ;
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 12/19 perf probe-cache: Add for_each_probe_cache_entry() wrapper
In reply to Arnaldo Carvalho de MeloFrom: Masami Hiramatsu <[email protected]>
Add for_each_probe_cache_entry() wrapper macro for hiding list in probe_cache.
--- tools/perf/util/probe-file.c | 8 ++++---- tools/perf/util/probe-file.h | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-)
tools/perf/util/probe-file.c +4 -4
@@ -546,7 +546,7 @@ probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)if (!cmd)return NULL ; -list_for_each_entry (entry, &pcache->entries, node) { +for_each_probe_cache_entry (entry, pcache) {if (pev->sdt) { if (entry->pev.event && streql(entry->pev.event, pev->event) &&
@@ -576,7 +576,7 @@ probe_cache__find_by_name(struct probe_cache *pcache, {struct probe_cache_entry *entry =NULL ; -list_for_each_entry (entry, &pcache->entries, node) { +for_each_probe_cache_entry (entry, pcache) {/* Hit if same event name or same command-string */ if (streql (entry->pev.group, group) &&streql (entry->pev.event, event))
@@ -748,7 +748,7 @@ int probe_cache__commit(struct probe_cache *pcache)if (ret <0 ) goto out; -list_for_each_entry (entry, &pcache->entries, node) { +for_each_probe_cache_entry (entry, pcache) { ret =probe_cache_entry__write (entry, pcache->fd);pr_debug ("Cache committed: %d\n" , ret);if (ret <0 )
@@ -790,7 +790,7 @@ static int probe_cache__show_entries(struct probe_cache *pcache, {struct probe_cache_entry *entry; -list_for_each_entry (entry, &pcache->entries, node) { +for_each_probe_cache_entry (entry, pcache) {if (probe_cache_entry__compare (entry, filter))printf ("%s\n" , entry->spev); }
tools/perf/util/probe-file.h +2 -0
@@ -21,6 +21,8 @@ struct probe_cache {#define PF_FL_UPROBE 1#define PF_FL_RW 2 +#define for_each_probe_cache_entry (entry, pcache) \ + list_for_each_entry(entry, &pcache->entries, node)int probe_file__open (int flag);int probe_file__open_both (int *kfd,int *ufd,int flag);
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 13/19 perf probe: Allow wildcard for cached events
In reply to Arnaldo Carvalho de MeloFrom: Masami Hiramatsu <[email protected]>
Allo glob wildcard for reusing cached/SDT events. E.g.
# perf probe -x /usr/lib64/libc-2.20.so -a %sdt_libc:\*
This example adds probes for all SDT in libc.
Note that the SDTs must have been scanned by perf buildid-cache.
Committer note:
Using it to check what of those SDT probes would take place when doing a cargo run (rust):
# trace --no-sys --event sdt_libc:* cargo run
0.000 sdt_libc:setjmp:(7f326b69c4d1))
28.423 sdt_libc:setjmp:(7f4b0a5364d1))
29.000 sdt_libc:setjmp:(7f4b0a5364d1))
88.597 sdt_libc:setjmp:(7fc01fd414d1))
89.220 sdt_libc:setjmp:(7fc01fd414d1))
95.501 sdt_libc:setjmp:(7f326b69c4d1))
Running `target/debug/hello_world`
97.110 sdt_libc:setjmp:(7f95e09234d1))
Hello, world!
#--- tools/perf/util/probe-event.c | 107 ++++++++++++++++++++++++++++++++++++++++-- tools/perf/util/probe-file.c | 38 ++++++++++++--- tools/perf/util/probe-file.h | 3 ++ 3 files changed, 138 insertions(+), 10 deletions(-)
tools/perf/util/probe-event.c +103 -4
@@ -1204,7 +1204,7 @@ static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev) ptr =strchr (*arg,':' );if (ptr) { *ptr ='\0' ; -if (!is_c_func_name (*arg)) +if (!pev->sdt && !is_c_func_name (*arg)) goto ng_name; pev->group =strdup (*arg);if (!pev->group)
@@ -1212,7 +1212,7 @@ static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev) *arg = ptr +1 ; }else pev->group =NULL ; -if (!is_c_func_name (*arg)) { +if (!pev->sdt && !is_c_func_name (*arg)) { ng_name:semantic_error ("%s is bad for event name -it must " "follow C symbol-naming rule.\n" , *arg);
@@ -1644,6 +1644,7 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev) ret = -ENOMEM ; goto out; } + tev->uprobes = (tp->module[0 ] =='/' ); p++; }else p = argv[1 ];
@@ -2518,7 +2519,7 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,int ret;/* If probe_event or trace_event already have the name, reuse it */ -if (pev->event) +if (pev->event && !pev->sdt) event = pev->event;else if (tev->event) event = tev->event;
@@ -2531,7 +2532,7 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,else event = tev->point.realname; } -if (pev->group) +if (pev->group && !pev->sdt) group = pev->group;else if (tev->group) group = tev->group;
@@ -2894,6 +2895,100 @@ errout:bool __weak arch__prefers_symtab (void ) {return false; } +/* Concatinate two arrays */ +static void *memcat (void *a,size_t sz_a,void *b,size_t sz_b) +{ +void *ret; + + ret =malloc (sz_a + sz_b); +if (ret) { +memcpy (ret, a, sz_a); +memcpy (ret + sz_a, b, sz_b); + } +return ret; +} + +static int +concat_probe_trace_events (struct probe_trace_event **tevs,int *ntevs, +struct probe_trace_event **tevs2,int ntevs2) +{ +struct probe_trace_event *new_tevs; +int ret =0 ; + +if (ntevs ==0 ) { + *tevs = *tevs2; + *ntevs = ntevs2; + *tevs2 =NULL ; +return 0 ; + } + +if (*ntevs + ntevs2 > probe_conf.max_probes) + ret = -E2BIG ; +else { +/* Concatinate the array of probe_trace_event */ + new_tevs =memcat (*tevs, (*ntevs) *sizeof (**tevs), + *tevs2, ntevs2 *sizeof (**tevs2)); +if (!new_tevs) + ret = -ENOMEM ; +else { +free (*tevs); + *tevs = new_tevs; + *ntevs += ntevs2; + } + } +if (ret <0 ) +clear_probe_trace_events (*tevs2, ntevs2); +zfree (tevs2); + +return ret; +} + +/* +* Try to find probe_trace_event from given probe caches. Return the number +* of cached events found, if an error occurs return the error. +*/ +static int find_cached_events (struct perf_probe_event *pev, +struct probe_trace_event **tevs, +const char *target) +{ +struct probe_cache *cache; +struct probe_cache_entry *entry; +struct probe_trace_event *tmp_tevs =NULL ; +int ntevs =0 ; +int ret =0 ; + + cache =probe_cache__new (target); +/* Return 0 ("not found") if the target has no probe cache. */ +if (!cache) +return 0 ; + +for_each_probe_cache_entry (entry, cache) { +/* Skip the cache entry which has no name */ +if (!entry->pev.event || !entry->pev.group) +continue ; +if ((!pev->group ||strglobmatch (entry->pev.group, pev->group)) && +strglobmatch (entry->pev.event, pev->event)) { + ret =probe_cache_entry__get_event (entry, &tmp_tevs); +if (ret >0 ) + ret =concat_probe_trace_events (tevs, &ntevs, + &tmp_tevs, ret); +if (ret <0 ) +break ; + } + } +probe_cache__delete (cache); +if (ret <0 ) { +clear_probe_trace_events (*tevs, ntevs); +zfree (tevs); + }else { + ret = ntevs; +if (ntevs >0 && target && target[0 ] =='/' ) + pev->uprobes = true; + } + +return ret; +} +static int find_probe_trace_events_from_cache (struct perf_probe_event *pev,struct probe_trace_event **tevs) {
@@ -2903,6 +2998,10 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,struct str_node *node;int ret, i; +if (pev->sdt) +/* For SDT/cached events, we use special search functions */ +return find_cached_events (pev, tevs, pev->target); + cache =probe_cache__new (pev->target);if (!cache)return 0 ;
tools/perf/util/probe-file.c +32 -6
@@ -362,13 +362,38 @@ probe_cache_entry__new(struct perf_probe_event *pev)return entry; } -/* For the kernel probe caches, pass target = NULL */ +int probe_cache_entry__get_event (struct probe_cache_entry *entry, +struct probe_trace_event **tevs) +{ +struct probe_trace_event *tev; +struct str_node *node; +int ret, i; + + ret =strlist__nr_entries (entry->tevlist); +if (ret > probe_conf.max_probes) +return -E2BIG ; + + *tevs =zalloc (ret *sizeof (*tev)); +if (!*tevs) +return -ENOMEM ; + + i =0 ; +strlist__for_each_entry (node, entry->tevlist) { + tev = &(*tevs)[i++]; + ret =parse_probe_trace_command (node->s, tev); +if (ret <0 ) +break ; + } +return i; +} + +/* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */ static int probe_cache__open (struct probe_cache *pcache,const char *target) {char cpath[PATH_MAX ];char sbuildid[SBUILD_ID_SIZE ];char *dir_name =NULL ; -bool is_kallsyms = !target; +bool is_kallsyms = false;int ret, fd;if (target &&build_id_cache__cached (target)) {
@@ -378,12 +403,13 @@ static int probe_cache__open(struct probe_cache *pcache, const char *target) goto found; } -if (target) - ret =filename__sprintf_build_id (target, sbuildid); -else { +if (!target || !strcmp (target,DSO__NAME_KALLSYMS )) { target =DSO__NAME_KALLSYMS ; + is_kallsyms = true; ret =sysfs__sprintf_build_id ("/" , sbuildid); - } + }else + ret =filename__sprintf_build_id (target, sbuildid); +if (ret <0 ) {pr_debug ("Failed to get build-id from %s.\n" , target);return ret;
tools/perf/util/probe-file.h +3 -0
@@ -34,6 +34,9 @@ int probe_file__get_events(int fd, struct strfilter *filter, struct strlist *plist);int probe_file__del_strlist (int fd,struct strlist *namelist); +int probe_cache_entry__get_event (struct probe_cache_entry *entry, +struct probe_trace_event **tevs); +struct probe_cache *probe_cache__new (const char *target); int probe_cache__add_entry(struct probe_cache *pcache, struct perf_probe_event *pev,
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 14/19 perf probe: Search SDT/cached event from all probe caches
In reply to Arnaldo Carvalho de MeloFrom: Masami Hiramatsu <[email protected]>
Search SDT/cached event from all probe caches if user doesn't pass any binary. With this, we don't have to specify target binary for SDT and named cached events (which start with %).
E.g. without this, a target binary must be passed with -x.
# perf probe -x /usr/lib64/libc-2.20.so -a %sdt_libc:\*
With this change, we don't need it anymore.
# perf probe -a %sdt_libc:\*
--- tools/perf/util/probe-event.c | 105 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 86 insertions(+), 19 deletions(-)
tools/perf/util/probe-event.c +86 -19
@@ -2557,41 +2557,60 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,return 0 ; } -static int __add_probe_trace_events (struct perf_probe_event *pev, -struct probe_trace_event *tevs, -int ntevs,bool allow_suffix) +static int __open_probe_file_and_namelist (bool uprobe, +struct strlist **namelist) { -int i, fd, ret; -struct probe_trace_event *tev =NULL ; -struct probe_cache *cache =NULL ; -struct strlist *namelist; +int fd; - fd =probe_file__open (PF_FL_RW | (pev->uprobes ?PF_FL_UPROBE :0 )); + fd =probe_file__open (PF_FL_RW | (uprobe ?PF_FL_UPROBE :0 ));if (fd <0 )return fd;/* Get current event names */ - namelist =probe_file__get_namelist (fd); -if (!namelist) { + *namelist =probe_file__get_namelist (fd); +if (!(*namelist)) {pr_debug ("Failed to get current event list.\n" ); - ret = -ENOMEM ; - goto close_out; +close (fd); +return -ENOMEM ; } +return fd; +} + +static int __add_probe_trace_events (struct perf_probe_event *pev, +struct probe_trace_event *tevs, +int ntevs,bool allow_suffix) +{ +int i, fd[2 ] = {-1 ,-1 }, up, ret; +struct probe_trace_event *tev =NULL ; +struct probe_cache *cache =NULL ; +struct strlist *namelist[2 ] = {NULL ,NULL }; + + up = pev->uprobes ?1 :0 ; + fd[up] =__open_probe_file_and_namelist (up, &namelist[up]); +if (fd[up] <0 ) +return fd[up]; ret =0 ;for (i =0 ; i < ntevs; i++) { tev = &tevs[i]; + up = tev->uprobes ?1 :0 ; +if (fd[up] ==-1 ) {/* Open the kprobe/uprobe_events */ + fd[up] =__open_probe_file_and_namelist (up, + &namelist[up]); +if (fd[up] <0 ) + goto close_out; + }/* Skip if the symbol is out of .text or blacklisted */ if (!tev->point.symbol && !pev->uprobes)continue ;/* Set new name for tev (and update namelist) */ - ret =probe_trace_event__set_name (tev, pev, namelist, + ret =probe_trace_event__set_name (tev, pev, namelist[up], allow_suffix);if (ret <0 )break ; - ret =probe_file__add_event (fd, tev); + ret =probe_file__add_event (fd[up], tev);if (ret <0 )break ;
@@ -2614,9 +2633,12 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,probe_cache__delete (cache); } -strlist__delete (namelist); close_out: -close (fd); +for (up =0 ; up <2 ; up++) { +strlist__delete (namelist[up]); +if (fd[up] >=0 ) +close (fd[up]); + }return ret; }
@@ -2989,6 +3011,48 @@ static int find_cached_events(struct perf_probe_event *pev,return ret; } +/* Try to find probe_trace_event from all probe caches */ +static int find_cached_events_all (struct perf_probe_event *pev, +struct probe_trace_event **tevs) +{ +struct probe_trace_event *tmp_tevs =NULL ; +struct strlist *bidlist; +struct str_node *nd; +char *pathname; +int ntevs =0 ; +int ret; + +/* Get the buildid list of all valid caches */ + bidlist =build_id_cache__list_all (true); +if (!bidlist) { + ret = -errno; +pr_debug ("Failed to get buildids: %d\n" , ret); +return ret; + } + + ret =0 ; +strlist__for_each_entry (nd, bidlist) { + pathname =build_id_cache__origname (nd->s); + ret =find_cached_events (pev, &tmp_tevs, pathname); +/* In the case of cnt == 0, we just skip it */ +if (ret >0 ) + ret =concat_probe_trace_events (tevs, &ntevs, + &tmp_tevs, ret); +free (pathname); +if (ret <0 ) +break ; + } +strlist__delete (bidlist); + +if (ret <0 ) { +clear_probe_trace_events (*tevs, ntevs); +zfree (tevs); + }else + ret = ntevs; + +return ret; +} +static int find_probe_trace_events_from_cache (struct perf_probe_event *pev,struct probe_trace_event **tevs) {
@@ -2998,10 +3062,13 @@ static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,struct str_node *node;int ret, i; -if (pev->sdt) +if (pev->sdt) {/* For SDT/cached events, we use special search functions */ -return find_cached_events (pev, tevs, pev->target); - +if (!pev->target) +return find_cached_events_all (pev, tevs); +else +return find_cached_events (pev, tevs, pev->target); + } cache =probe_cache__new (pev->target);if (!cache)return 0 ;
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 15/19 perf list: Show SDT and pre-cached events
In reply to Arnaldo Carvalho de MeloFrom: Masami Hiramatsu <[email protected]>
Show SDT and pre-cached events by perf-list with "sdt". This also shows the binary and build-id where the events are placed only when there are same name events on different binaries.
e.g.:
# perf list sdt
List of pre-defined events (to be used in -e):
sdt_libc:lll_futex_wake [SDT event]
sdt_libc:lll_lock_wait_private [SDT event]
sdt_libc:longjmp [SDT event]
sdt_libc:longjmp_target [SDT event]
...
sdt_libstdcxx:rethrow@/usr/bin/gcc(0cc207fc4b27) [SDT event]
sdt_libstdcxx:rethrow@/usr/lib64/libstdc++.so.6.0.20(91c7a88fdf49)
sdt_libstdcxx:throw@/usr/bin/gcc(0cc207fc4b27) [SDT event]
sdt_libstdcxx:throw@/usr/lib64/libstdc++.so.6.0.20(91c7a88fdf49)The binary path and build-id are shown in below format;
<GROUP>:<EVENT>@<PATH>(<BUILD-ID>)
--- tools/perf/builtin-list.c | 6 +++- tools/perf/util/parse-events.c | 82 ++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/parse-events.h | 2 ++ tools/perf/util/probe-file.h | 9 +++++ 4 files changed, 98 insertions(+), 1 deletion(-)
tools/perf/builtin-list.c +5 -1
@@ -25,7 +25,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) OPT_END() };const char *const list_usage[] = { -"perf list [hw|sw|cache|tracepoint|pmu|event_glob]" , +"perf list [hw|sw|cache|tracepoint|pmu|sdt|event_glob]" ,NULL };
@@ -62,6 +62,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)print_hwcache_events (NULL , raw_dump); else if (strcmp(argv[i], "pmu") == 0) print_pmu_events(NULL, raw_dump); + else if (strcmp(argv[i], "sdt") == 0) + print_sdt_events(NULL, NULL, raw_dump); else if ((sep = strchr(argv[i], ':')) != NULL) {int sep_idx;
@@ -76,6 +78,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) s[sep_idx] ='\0' ;print_tracepoint_events (s, s + sep_idx +1 , raw_dump); +print_sdt_events (s, s + sep_idx +1 , raw_dump);free (s); }else {if (asprintf (&s,"*%s*" , argv[i]) <0 ) {
@@ -89,6 +92,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)print_hwcache_events (s, raw_dump);print_pmu_events (s, raw_dump);print_tracepoint_events (NULL , s, raw_dump); +print_sdt_events (NULL , s, raw_dump);free (s); } }
tools/perf/util/parse-events.c +82 -0
100 lines not on this page · raw message
tools/perf/util/parse-events.h +2 -0
@@ -183,6 +183,8 @@ void print_symbol_events(const char *event_glob, unsigned type,void print_tracepoint_events (const char *subsys_glob,const char *event_glob,bool name_only);int print_hwcache_events (const char *event_glob,bool name_only); +void print_sdt_events (const char *subsys_glob,const char *event_glob, +bool name_only);int is_valid_tracepoint (const char *event_string);int valid_event_mount (const char *eventfs);
tools/perf/util/probe-file.h +9 -0
@@ -24,6 +24,8 @@ struct probe_cache {#define for_each_probe_cache_entry (entry, pcache) \ list_for_each_entry(entry, &pcache->entries, node) +/* probe-file.c depends on libelf */ +#ifdef HAVE_LIBELF_SUPPORT int probe_file__open (int flag);int probe_file__open_both (int *kfd,int *ufd,int flag);struct strlist *probe_file__get_namelist (int fd);
@@ -52,4 +54,11 @@ struct probe_cache_entry *probe_cache__find(struct probe_cache *pcache,struct probe_cache_entry *probe_cache__find_by_name (struct probe_cache *pcache,const char *group,const char *event);int probe_cache__show_all_caches (struct strfilter *filter); +#else /* ! HAVE_LIBELF_SUPPORT */ +static inline struct probe_cache *probe_cache__new (const char *tgt__maybe_unused ) +{ +return NULL ; +} +#define probe_cache__delete (pcache) do {} while (0) +#endif #endif
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 16/19 perf probe: Support @BUILDID or @FILE suffix for SDT events
In reply to Arnaldo Carvalho de MeloFrom: Masami Hiramatsu <[email protected]>
Support @BUILDID or @FILE suffix for SDT events. This allows perf to add probes on SDTs/pre-cached events on given FILE or the file which has given BUILDID (also, this complements BUILDID.)
For example, both gcc and libstdc++ has same SDTs as below. If you would like to add a probe on sdt_libstdcxx:catch on gcc, you can do as below.
----
# perf list sdt | tail -n 6
sdt_libstdcxx:catch@/usr/bin/gcc(0cc207fc4b27) [SDT event]
sdt_libstdcxx:catch@/usr/lib64/libstdc++.so.6.0.20(91c7a88fdf49)
sdt_libstdcxx:rethrow@/usr/bin/gcc(0cc207fc4b27) [SDT event]
sdt_libstdcxx:rethrow@/usr/lib64/libstdc++.so.6.0.20(91c7a88fdf49)
sdt_libstdcxx:throw@/usr/bin/gcc(0cc207fc4b27) [SDT event]
sdt_libstdcxx:throw@/usr/lib64/libstdc++.so.6.0.20(91c7a88fdf49)
# perf probe -a %sdt_libstdcxx:catch@0cc
Added new event:
sdt_libstdcxx:catch (on %catch in /usr/bin/gcc)You can now use it in all perf tools, such as:
perf record -e sdt_libstdcxx:catch -aR sleep 1
----
Committer note:
Doing the full sequence of steps to get the results above:
With a clean build-id cache:
[root@jouet ~]# rm -rf ~/.debug/
[root@jouet ~]# perf list sdt
List of pre-defined events (to be used in -e):
[root@jouet ~]#
No events whatsoever, then, we can add all events in gcc to the build-id cache, doing a --add + --dry-run:
[root@jouet ~]# perf probe --dry-run --cache -x /usr/bin/gcc --add %sdt_libstdcxx:\*
Added new events:
sdt_libstdcxx:throw (on %* in /usr/bin/gcc)
sdt_libstdcxx:rethrow (on %* in /usr/bin/gcc)
sdt_libstdcxx:catch (on %* in /usr/bin/gcc)You can now use it in all perf tools, such as:
perf record -e sdt_libstdcxx:catch -aR sleep 1
[root@jouet ~]#
It really didn't add any events, it just cached them:
[root@jouet ~]# perf probe -l
[root@jouet ~]#
We can see that it was cached as:
[root@jouet ~]# ls -la ~/.debug/usr/bin/gcc/9a0730e2bcc6d2a2003d21ac46807e8ee6bcb7c2/
total 976
drwxr-xr-x. 2 root root 4096 Jul 13 21:47 .
drwxr-xr-x. 3 root root 4096 Jul 13 21:47 ..
-rwxr-xr-x. 4 root root 985912 Jun 22 18:52 elf
-rw-r--r--. 1 root root 303 Jul 13 21:47 probes
[root@jouet ~]# file ~/.debug/usr/bin/gcc/9a0730e2bcc6d2a2003d21ac46807e8ee6bcb7c2/elf
/root/.debug/usr/bin/gcc/9a0730e2bcc6d2a2003d21ac46807e8ee6bcb7c2/elf: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=9a0730e2bcc6d2a2003d21ac46807e8ee6bcb7c2, stripped [root@jouet ~]# cat ~/.debug/usr/bin/gcc/9a0730e2bcc6d2a2003d21ac46807e8ee6bcb7c2/probes
%sdt_libstdcxx:throw=throw
p:sdt_libstdcxx/throw /usr/bin/gcc:0x71ffd
%sdt_libstdcxx:rethrow=rethrow
p:sdt_libstdcxx/rethrow /usr/bin/gcc:0x720b8
%sdt_libstdcxx:catch=catch
p:sdt_libstdcxx/catch /usr/bin/gcc:0x7307f
%sdt_libgcc:unwind=unwind
p:sdt_libgcc/unwind /usr/bin/gcc:0x7eec0
#sdt_libstdcxx:*=%*
[root@jouet ~]#
Ok, now we can use 'perf probe' to refer to those cached entries as:
Humm, nope, doing as above we end up with:
[root@jouet ~]# perf probe -a %sdt_libstdcxx:catch
Semantic error :* is bad for event name -it must follow C symbol-naming rule.
Error: Failed to add events.
[root@jouet ~]#
But it worked at some point, lets try not using --dry-run:
Resetting everything:
# rm -rf ~/.debug/ # perf probe -d *:* # perf probe -l # perf list sdt
List of pre-defined events (to be used in -e):
#
Ok, now it cached everything, even things we haven't asked it to (sdt_libgcc:unwind):
[root@jouet ~]# perf probe -x /usr/bin/gcc --add %sdt_libstdcxx:\*
Added new events:
sdt_libstdcxx:throw (on %* in /usr/bin/gcc)
sdt_libstdcxx:rethrow (on %* in /usr/bin/gcc)
sdt_libstdcxx:catch (on %* in /usr/bin/gcc)You can now use it in all perf tools, such as:
perf record -e sdt_libstdcxx:catch -aR sleep 1
[root@jouet ~]# perf list sdt
List of pre-defined events (to be used in -e):
sdt_libgcc:unwind [SDT event]
sdt_libstdcxx:catch [SDT event]
sdt_libstdcxx:rethrow [SDT event]
sdt_libstdcxx:throw [SDT event][root@jouet ~]#
And we have the events in place:
[root@jouet ~]# perf probe -l
sdt_libstdcxx:catch (on execute_cfa_program+1551@../../../libgcc/unwind-dw2.c in /usr/bin/gcc) sdt_libstdcxx:rethrow (on d_print_subexpr+280@libsupc++/cp-demangle.c in /usr/bin/gcc) sdt_libstdcxx:throw (on d_print_subexpr+93@libsupc++/cp-demangle.c in /usr/bin/gcc)
[root@jouet ~]#
And trying to use them at least has 'perf trace --event sdt*:*' working.
Then, if we try to add the ones in libstdc++:
[root@jouet ~]# perf probe -x /usr/lib64/libstdc++.so.6 -a %sdt_libstdcxx:\*
Error: event "catch" already exists.
Hint: Remove existing event by 'perf probe -d'
or force duplicates by 'perf probe -f'
or set 'force=yes' in BPF source.
Error: Failed to add events.
[root@jouet ~]#
Doesn't work, dups, but at least this served to, unbeknownst to the user, add the SDT probes in /usr/lib64/libstdc++.so.6!
[root@jouet ~]# perf list sdt
List of pre-defined events (to be used in -e):
sdt_libgcc:unwind [SDT event]
sdt_libstdcxx:catch@/usr/bin/gcc(9a0730e2bcc6) [SDT event]
sdt_libstdcxx:catch@/usr/lib64/libstdc++.so.6.0.22(ef2b7066559a) [SDT event]
sdt_libstdcxx:rethrow@/usr/bin/gcc(9a0730e2bcc6) [SDT event]
sdt_libstdcxx:rethrow@/usr/lib64/libstdc++.so.6.0.22(ef2b7066559a) [SDT event]
sdt_libstdcxx:throw@/usr/bin/gcc(9a0730e2bcc6) [SDT event]
sdt_libstdcxx:throw@/usr/lib64/libstdc++.so.6.0.22(ef2b7066559a) [SDT event][root@jouet ~]#
Now we should be able to get to the original cset comment, if we remove all SDTs events in place, not from the cache, from the kernel, where it was set up as:
[root@jouet ~]# ls -la /sys/kernel/debug/tracing/events/sdt_libstdcxx/ total 0
drwxr-xr-x. 5 root root 0 Jul 13 22:00 .
drwxr-xr-x. 80 root root 0 Jul 13 21:56 ..
drwxr-xr-x. 2 root root 0 Jul 13 22:00 catch -rw-r--r--. 1 root root 0 Jul 13 22:00 enable -rw-r--r--. 1 root root 0 Jul 13 22:00 filter drwxr-xr-x. 2 root root 0 Jul 13 22:00 rethrow drwxr-xr-x. 2 root root 0 Jul 13 22:00 throw
[root@jouet ~]#
[root@jouet ~]# head -2 /sys/kernel/debug/tracing/events/sdt_libstdcxx/throw/format
name: throw
ID: 2059
[root@jouet ~]#
Now to remove it:
[root@jouet ~]# perf probe -d sdt_libstdc*:*
Removed event: sdt_libstdcxx:catch
Removed event: sdt_libstdcxx:rethrow
Removed event: sdt_libstdcxx:throw
[root@jouet ~]#
Which caused:
[root@jouet ~]# ls -la /sys/kernel/debug/tracing/events/sdt_libstdcxx/
ls: cannot access '/sys/kernel/debug/tracing/events/sdt_libstdcxx/': No such file or directory [root@jouet ~]#
Ok, now we can do:
[root@jouet ~]# perf list sdt_libstdcxx:catch
List of pre-defined events (to be used in -e):
sdt_libstdcxx:catch@/usr/bin/gcc(9a0730e2bcc6) [SDT event]
sdt_libstdcxx:catch@/usr/lib64/libstdc++.so.6.0.22(ef2b7066559a) [SDT event][root@jouet ~]#
So, these are not really 'pre-defined events', i.e. we can't use them with 'perf record --event':
[root@jouet ~]# perf record --event sdt_libstdcxx:catch*
event syntax error: 'sdt_libstdcxx:catch*'
\___ unknown tracepoint Error: File /sys/kernel/debug/tracing/events/sdt_libstdcxx/catch* not found.
Hint: Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
<SNIP>
[root@jouet ~]#
To have it really pre-defined we must use perf probe to get its definition from the cache and set it up in the kernel, creating the tracepoint to _then_ use it with 'perf record --event':
[root@jouet ~]# perf probe -a sdt_libstdcxx:catch Semantic error :There is non-digit char in line number. <SNIP>
Oops, there is another gotcha here, we need that pesky '%' character:
[root@jouet ~]# perf probe -a %sdt_libstdcxx:catch
Added new events:
sdt_libstdcxx:catch (on %catch in /usr/bin/gcc) sdt_libstdcxx:catch_1 (on %catch in /usr/lib64/libstdc++.so.6.0.22)
You can now use it in all perf tools, such as:
perf record -e sdt_libstdcxx:catch_1 -aR sleep 1
[root@jouet ~]#
But then we added _two_ events, one with the name we expected, the other one with a _ added, when doing the analysis we need to pay attention to who maps to who.
And here is where we get to the point of this patch, which is to be able to disambiguate those definitions for 'catch' in the build-id cache, but first we need remove those events we just added:
[root@jouet ~]# perf probe -d %sdt_libstdcxx:catch
Oops, that didn't remove anything, we need to _remove_ that % char in this case:
[root@jouet ~]# perf probe -d sdt_libstdcxx:catch Removed event: sdt_libstdcxx:catch
And we need to remove the other event added, i.e. I forgot to add a * at the end:
[root@jouet ~]# perf probe -d sdt_libstdcxx:catch* Removed event: sdt_libstdcxx:catch_1 [root@jouet ~]#
Ok, disambiguating it using what is in this patch:
[root@jouet ~]# perf list sdt_libstdcxx:catch
List of pre-defined events (to be used in -e):
sdt_libstdcxx:catch@/usr/bin/gcc(9a0730e2bcc6) [SDT event]
sdt_libstdcxx:catch@/usr/lib64/libstdc++.so.6.0.22(ef2b7066559a) [SDT event] [root@jouet ~]#
[root@jouet ~]# perf probe -a %sdt_libstdcxx:catch@9a07 Added new event:
sdt_libstdcxx:catch (on %catch in /usr/bin/gcc)
You can now use it in all perf tools, such as:
perf record -e sdt_libstdcxx:catch -aR sleep 1
[root@jouet ~]# perf probe -l
sdt_libstdcxx:catch (on execute_cfa_program+1551@../../../libgcc/unwind-dw2.c in /usr/bin/gcc)
[root@jouet ~]#
Yeah, it works! But we need to try and simplify this :-)
Update: Some aspects of this simplification take place in the following
patches.
--- tools/perf/util/build-id.c | 43 +++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/build-id.h | 1 + tools/perf/util/probe-event.c | 17 +++++++++++++++-- 3 files changed, 59 insertions(+), 2 deletions(-)
tools/perf/util/build-id.c +43 -0
@@ -523,6 +523,49 @@ err_out: goto out_free; } +static bool str_is_build_id (const char *maybe_sbuild_id,size_t len) +{ +size_t i; + +for (i =0 ; i < len; i++) { +if (!isxdigit (maybe_sbuild_id[i])) +return false; + } +return true; +} + +/* Return the valid complete build-id */ +char *build_id_cache__complement (const char *incomplete_sbuild_id) +{ +struct strlist *bidlist; +struct str_node *nd, *cand =NULL ; +char *sbuild_id =NULL ; +size_t len =strlen (incomplete_sbuild_id); + +if (len >=SBUILD_ID_SIZE || + !str_is_build_id (incomplete_sbuild_id, len)) +return NULL ; + + bidlist =build_id_cache__list_all (true); +if (!bidlist) +return NULL ; + +strlist__for_each_entry (nd, bidlist) { +if (strncmp (nd->s, incomplete_sbuild_id, len) !=0 ) +continue ; +if (cand) {/* Error: There are more than 2 candidates. */ + cand =NULL ; +break ; + } + cand = nd; + } +if (cand) + sbuild_id =strdup (cand->s); +strlist__delete (bidlist); + +return sbuild_id; +} +char *build_id_cache__cachedir (const char *sbuild_id,const char *name,bool is_kallsyms,bool is_vdso) {
tools/perf/util/build-id.h +1 -0
@@ -35,6 +35,7 @@ char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size);char *build_id_cache__cachedir (const char *sbuild_id,const char *name,bool is_kallsyms,bool is_vdso);struct strlist *build_id_cache__list_all (bool validonly); +char *build_id_cache__complement (const char *incomplete_sbuild_id);int build_id_cache__list_build_ids (const char *pathname,struct strlist **result);bool build_id_cache__cached (const char *sbuild_id);
tools/perf/util/probe-event.c +15 -2
@@ -1251,8 +1251,21 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) ptr =strpbrk (arg,";=@+%" );if (pev->sdt) {if (ptr) { -semantic_error ("%s must contain only an SDT event name.\n" , arg); -return -EINVAL ; +if (*ptr !='@' ) { +semantic_error ("%s must be an SDT name.\n" , + arg); +return -EINVAL ; + } +/* This must be a target file name or build id */ + tmp =build_id_cache__complement (ptr +1 ); +if (tmp) { + pev->target =build_id_cache__origname (tmp); +free (tmp); + }else + pev->target =strdup (ptr +1 ); +if (!pev->target) +return -ENOMEM ; + *ptr ='\0' ; } ret =parse_perf_probe_event_name (&arg, pev);if (ret ==0 ) {
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 17/19 perf probe: Support a special SDT probe format
In reply to Arnaldo Carvalho de MeloFrom: Masami Hiramatsu <[email protected]>
Support a special SDT probe format which can omit the '%' prefix only if the SDT group name starts with "sdt_". So, for example both of "%sdt_libc:setjump" and "sdt_libc:setjump" are acceptable for perf probe --add.
E.g. without this:
# perf probe -a sdt_libc:setjmp Semantic error :There is non-digit char in line number. ...
With this:
# perf probe -a sdt_libc:setjmp
Added new event:
sdt_libc:setjmp (on %setjmp in /usr/lib64/libc-2.20.so)You can now use it in all perf tools, such as:
perf record -e sdt_libc:setjmp -aR sleep 1
--- tools/perf/Documentation/perf-probe.txt | 4 +++- tools/perf/util/probe-event.c | 12 ++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-)
tools/perf/Documentation/perf-probe.txt +3 -1
@@ -152,7 +152,9 @@ Probe points are defined by following syntax. [[GROUP:]EVENT=]SRC;PTN [ARG ...] 4) Pre-defined SDT events or cached event with name - %[PROVIDER:]SDTEVENT + %[sdt_PROVIDER:]SDTEVENT + or, + sdt_PROVIDER:SDTEVENT 'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. You can also specify a group name by 'GROUP', if omitted, set 'probe' is used for kprobe and 'probe_<bin>' is used for uprobe. Note that using existing group name can conflict with other events. Especially, using the group name reserved for kernel modules can hide embedded events in the
tools/perf/util/probe-event.c +10 -2
@@ -1243,9 +1243,17 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)if (!arg)return -EINVAL ; -if (arg[0 ] =='%' ) { +/* +* If the probe point starts with '%', +* or starts with "sdt_" and has a ':' but no '=', +* then it should be a SDT/cached probe point. +*/ +if (arg[0 ] =='%' || + (!strncmp (arg,"sdt_" ,4 ) && + !!strchr (arg,':' ) && !strchr (arg,'=' ))) { pev->sdt = true; - arg++; +if (arg[0 ] =='%' ) + arg++; } ptr =strpbrk (arg,";=@+%" );
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 18/19 perf build: Add sdt feature detection
In reply to Arnaldo Carvalho de MeloFrom: Masami Hiramatsu <[email protected]>
This checks whether sys/sdt.h is available or not, which is required for DTRACE_PROBE().
We can disable this feature by passing NO_SDT=1 when building.
This flag will be used for SDT test case and further SDT events in perftools.
--- tools/build/Makefile.feature | 3 ++- tools/build/feature/Makefile | 6 +++++- tools/build/feature/test-all.c | 5 +++++ tools/build/feature/test-sdt.c | 7 +++++++ tools/perf/Makefile.perf | 3 +++ tools/perf/config/Makefile | 10 ++++++++++ tools/perf/tests/make | 3 ++- 7 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 tools/build/feature/test-sdt.c
tools/build/Makefile.feature +2 -1
@@ -62,7 +62,8 @@ FEATURE_TESTS_BASIC := \ zlib \ lzma \ get_cpuid \ - bpf + bpf \ + sdt # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list # of all feature tests
tools/build/feature/Makefile +5 -1
@@ -45,7 +45,8 @@ FILES= \ test-zlib.bin \ test-lzma.bin \ test-bpf.bin \ - test-get_cpuid.bin + test-get_cpuid.bin \ + test-sdt.bin FILES := $(addprefix $(OUTPUT),$(FILES))
@@ -213,6 +214,9 @@ $(OUTPUT)test-get_cpuid.bin: $(OUTPUT)test-bpf.bin: $(BUILD) +$(OUTPUT)test-sdt.bin: + $(BUILD) + -include $(OUTPUT)*.d ###############################
tools/build/feature/test-all.c +5 -0
@@ -145,6 +145,10 @@# include "test-libcrypto.c" #undef main +#define main main_test_sdt +# include "test-sdt.c" +#undef main +int main (int argc,char *argv[]) {main_test_libpython ();
@@ -178,6 +182,7 @@ int main(int argc, char *argv[])main_test_get_cpuid ();main_test_bpf ();main_test_libcrypto (); +main_test_sdt ();return 0 ; }
tools/build/feature/test-sdt.c new file +7 -0
@@ -0,0 +1,7 @@ +#include <sys/sdt.h> + +int main (void ) +{ +DTRACE_PROBE (provider, name); +return 0 ; +}
tools/perf/Makefile.perf +3 -0
@@ -81,6 +81,9 @@ include ../scripts/utilities.mak # # Define NO_LIBBPF if you do not want BPF support # +# Define NO_SDT if you do not want to define SDT event in perf tools, +# note that it doesn't disable SDT scanning support. +# # Define FEATURES_DUMP to provide features detection dump file # and bypass the feature detection
tools/perf/config/Makefile +10 -0
@@ -355,6 +355,16 @@ ifndef NO_LIBELF endif # NO_LIBBPF endif # NO_LIBELF +ifndef NO_SDT + ifneq ($(feature-sdt), 1) + msg := $(warning No sys/sdt.h found, no SDT events are defined, please install systemtap-sdt-devel or systemtap-sdt-dev); + NO_SDT := 1; + else + CFLAGS += -DHAVE_SDT_EVENT + $(call detected,CONFIG_SDT_EVENT) + endif +endif + ifdef PERF_HAVE_JITDUMP ifndef NO_DWARF $(call detected,CONFIG_JITDUMP)
tools/perf/tests/make +2 -1
@@ -82,6 +82,7 @@ make_no_auxtrace := NO_AUXTRACE=1 make_no_libbpf := NO_LIBBPF=1 make_no_libcrypto := NO_LIBCRYPTO=1 make_with_babeltrace:= LIBBABELTRACE=1 +make_no_sdt := NO_SDT=1 make_tags := tags make_cscope := cscope make_help := help
@@ -105,7 +106,7 @@ make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1 make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 -make_minimal += NO_LIBCRYPTO=1 +make_minimal += NO_LIBCRYPTO=1 NO_SDT=1 # $(run) contains all available tests run := make_pure
Signature · 1 line
2.7.4
Arnaldo Carvalho de Melo
maintainerPATCH 19/19 perf test: Add a test case for SDT event
In reply to Arnaldo Carvalho de MeloFrom: Masami Hiramatsu <[email protected]>
Add a basic test case for SDT event support. This test scans an SDT event in perftools and check whether the SDT event is correctly stored into the buildid cache.
Here is an example:
----
$ perf test sdt -v 47: Test SDT event probing : --- start --- test child forked, pid 20732 Found 72 SDTs in /home/mhiramat/ksrc/linux/tools/perf/perf Writing cache: %sdt_perf:test_target=test_target Cache committed: 0 symbol:test_target file:(null) line:0 offset:0 return:0 lazy:(null) test child finished with 0 ---- end ---- Test SDT event probing: Ok ----
--- tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 ++ tools/perf/tests/sdt.c | 115 ++++++++++++++++++++++++++++++++++++++++ tools/perf/tests/tests.h | 1 + 4 files changed, 121 insertions(+) create mode 100644 tools/perf/tests/sdt.c
tools/perf/tests/Build +1 -0
@@ -39,6 +39,7 @@ perf-y += stat.o perf-y += event_update.o perf-y += event-times.o perf-y += backward-ring-buffer.o +perf-y += sdt.o $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build $(call rule_mkdir)
tools/perf/tests/builtin-test.c +4 -0
@@ -218,6 +218,10 @@ static struct test generic_tests[] = { .func = test__cpu_map_print, }, { + .desc = "Test SDT event probing", + .func = test__sdt_event, + }, + { .func = NULL, }, };
tools/perf/tests/sdt.c new file +115 -0
115 lines not on this page · raw message
tools/perf/tests/tests.h +1 -0
@@ -88,6 +88,7 @@ int test__event_update(int subtest);int test__event_times (int subtest);int test__backward_ring_buffer (int subtest);int test__cpu_map_print (int subtest); +int test__sdt_event (int subtest);#if defined(__arm__) || defined(__aarch64__)#ifdef HAVE_DWARF_UNWIND_SUPPORT
Signature · 1 line
2.7.4
Quoted 128 lines · Arnaldo Carvalho de Melo
Hi Ingo,
Please consider pulling,
I've added building objtool to most of the containers in my build test setup:
[root@jouet ~]# perf stat dm
alpine:3.4: Ok
centos:5: Ok
centos:6: Ok
centos:7: Ok
debian:7: Ok
debian:8: Ok
debian:experimental: Ok
fedora:21: Ok
fedora:22: Ok
fedora:23: Ok
fedora:24: Ok
fedora:rawhide: Ok
mageia:5: Ok
opensuse:13.2: Ok
opensuse:42.1: Ok
ubuntu:12.04.5: Ok
ubuntu:14.04.4: Ok
ubuntu:15.10: Ok
ubuntu:16.04: OkPerformance counter stats for 'dm':
2601.121782 task-clock (msec) # 0.002 CPUs utilized 86,368 context-switches # 0.033 M/sec 5,740 cpu-migrations # 0.002 M/sec 53,962 page-faults # 0.021 M/sec 7,217,605,183 cycles # 2.775 GHz 6,534,540,119 instructions # 0.91 insn per cycle 1,408,715,184 branches # 541.580 M/sec 18,523,459 branch-misses # 1.31% of all branches1541.746171526 seconds time elapsed[root@jouet ~]#
- Arnaldo
The following changes since commit
7b39cafb7aa68ef8e32a9f51fbe737d96084ca74:tools: Work around
BITS_PER_LONGrelated build failure in objtool (2016-07-13 09:37:43 +0200)are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gittags/perf-core-for-mingo-20160713for you to fetch changes up to
8e5dc848356ecf6ea8d27d641c4d7ad8d42fe92b:perf test: Add a test case for SDT event (2016-07-13 23:09:10 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:User visible:
- Finish merging initial SDT (Statically Defined Traces) support, see cset comments for details about how it all works (Masami Hiramatsu)
- Support attaching eBPF programs to tracepoints (Wang Nan)
Infrastructure:
- Fix up
BITS_PER_LONGsetting (Arnaldo Carvalho de Melo)- Add fallback from
ELF_C_READ_MMAPtoELF_C_READin objtool, fixing the build in libelf implementations lacking thatelf_begin()cmd, such as Alpine Linux's (Arnaldo Carvalho de Melo)- Avoid checking code drift on busybox's diff in objtool (Arnaldo Carvalho de Melo)
Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Arnaldo Carvalho de Melo (3):
tools: Fix upBITS_PER_LONGsetting
objtool: Add fallback fromELF_C_READ_MMAPtoELF_C_READ
objtool: Avoid checking code drift on busybox's diffMasami Hiramatsu (11):
perf probe: Fix to show correct error message for $vars and $params perf probe: Accept %sdt and %cached event name
perf probe: Make --list show only available cached events perf probe-cache: Addfor_each_probe_cache_entry()wrapper perf probe: Allow wildcard for cached events
perf probe: Search SDT/cached event from all probe caches perf list: Show SDT and pre-cached events
perf probe: Support @BUILDID or @FILE suffix for SDT events perf probe: Support a special SDT probe format
perf build: Add sdt feature detection
perf test: Add a test case for SDT eventWang Nan (5):
tools lib bpf: New API to adjust type of a BPF program tools lib bpf: Report error when kernel doesn't support program type perf event parser: Add const qualifier toevt_nameandsys_nameperf bpf: Renamebpf__foreach_tev()tobpf__foreach_event()perf bpf: Support BPF program attach to tracepointstools/build/Makefile.feature | 3 +- tools/build/feature/Makefile | 6 +- tools/build/feature/test-all.c | 5 + tools/build/feature/test-sdt.c | 7 + tools/include/asm-generic/bitsperlong.h | 24 ++- tools/lib/bpf/libbpf.c | 80 +++++++-- tools/lib/bpf/libbpf.h | 10 ++ tools/objtool/Makefile | 5 +- tools/objtool/elf.c | 7 + tools/perf/Documentation/perf-probe.txt | 11 +- tools/perf/Makefile.perf | 3 + tools/perf/builtin-list.c | 6 +- tools/perf/builtin-probe.c | 2 +- tools/perf/config/Makefile | 10 ++ tools/perf/tests/Build | 1 + tools/perf/tests/builtin-test.c | 4 + tools/perf/tests/make | 3 +- tools/perf/tests/sdt.c | 115 ++++++++++++ tools/perf/tests/tests.h | 1 + tools/perf/util/bpf-loader.c | 73 +++++++- tools/perf/util/bpf-loader.h | 12 +- tools/perf/util/build-id.c | 76 +++++++- tools/perf/util/build-id.h | 3 +- tools/perf/util/parse-events.c | 110 ++++++++++--
Quoted 8 lines
tools/perf/util/parse-events.h | 4 +- tools/perf/util/probe-event.c | 309 +++++++++++++++++++++++++++----- tools/perf/util/probe-event.h | 1 + tools/perf/util/probe-file.c | 57 ++++-- tools/perf/util/probe-file.h | 14 ++ 29 files changed, 850 insertions(+), 112 deletions(-) create mode 100644 tools/build/feature/test-sdt.c create mode 100644 tools/perf/tests/sdt.c
Pulled, thanks a lot Arnaldo!
Ingo