Message ID | 20200312195610.346362-14-jolsa@kernel.org |
---|---|
State | Awaiting Upstream |
Delegated to: | BPF Maintainers |
Headers | show |
Series | bpf: Add trampoline and dispatcher to /proc/kallsyms | expand |
Em Thu, Mar 12, 2020 at 08:56:08PM +0100, Jiri Olsa escreveu: > +static int > +process_bpf_image(char *name, u64 addr, struct kallsyms_parse *data) > +{ > + struct machine *machine = data->machine; > + union perf_event *event = data->event; > + struct perf_record_ksymbol *ksymbol; > + > + ksymbol = &event->ksymbol; > + > + *ksymbol = (struct perf_record_ksymbol) { > + .header = { > + .type = PERF_RECORD_KSYMBOL, > + .size = offsetof(struct perf_record_ksymbol, name), > + }, > + .addr = addr, > + .len = page_size, > + .ksym_type = PERF_RECORD_KSYMBOL_TYPE_BPF, > + .flags = 0, > + }; > + > + strncpy(ksymbol->name, name, KSYM_NAME_LEN); > + ksymbol->header.size += PERF_ALIGN(strlen(name) + 1, sizeof(u64)); > + memset((void *) event + event->header.size, 0, machine->id_hdr_size); > + event->header.size += machine->id_hdr_size; > + > + return perf_tool__process_synth_event(data->tool, event, machine, > + data->process); This explodes in fedora 32 and rawhide and in openmandriva:cooker: GEN /tmp/build/perf/python/perf.so CC /tmp/build/perf/util/bpf-event.o In file included from /usr/include/string.h:495, from /git/perf/tools/lib/bpf/libbpf_common.h:12, from /git/perf/tools/lib/bpf/bpf.h:31, from util/bpf-event.c:4: In function ‘strncpy’, inlined from ‘process_bpf_image’ at util/bpf-event.c:323:2, inlined from ‘kallsyms_process_symbol’ at util/bpf-event.c:358:9: /usr/include/bits/string_fortified.h:106:10: error: ‘__builtin_strncpy’ specified bound 256 equals destination size [-Werror=stringop-truncation] 106 | return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors mv: cannot stat '/tmp/build/perf/util/.bpf-event.o.tmp': No such file or directory make[4]: *** [/git/perf/tools/build/Makefile.build:97: /tmp/build/perf/util/bpf-event.o] Error 1 make[3]: *** [/git/perf/tools/build/Makefile.build:139: util] Error 2 make[2]: *** [Makefile.perf:617: /tmp/build/perf/perf-in.o] Error 2 make[1]: *** [Makefile.perf:225: sub-make] Error 2 make: *** [Makefile:70: all] Error 2 make: Leaving directory '/git/perf/tools/perf' [perfbuilder@fc58e82bfba4 ~]$ So I patched it a bit, please ack: diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index 3728db98981e..0cd41a862952 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -306,6 +306,7 @@ process_bpf_image(char *name, u64 addr, struct kallsyms_parse *data) struct machine *machine = data->machine; union perf_event *event = data->event; struct perf_record_ksymbol *ksymbol; + int len; ksymbol = &event->ksymbol; @@ -320,8 +321,8 @@ process_bpf_image(char *name, u64 addr, struct kallsyms_parse *data) .flags = 0, }; - strncpy(ksymbol->name, name, KSYM_NAME_LEN); - ksymbol->header.size += PERF_ALIGN(strlen(name) + 1, sizeof(u64)); + len = scnprintf(ksymbol->name, KSYM_NAME_LEN, "%s", name); + ksymbol->header.size += PERF_ALIGN(len + 1, sizeof(u64)); memset((void *) event + event->header.size, 0, machine->id_hdr_size); event->header.size += machine->id_hdr_size;
On Mon, Apr 06, 2020 at 09:54:12AM -0300, Arnaldo Carvalho de Melo wrote: > Em Thu, Mar 12, 2020 at 08:56:08PM +0100, Jiri Olsa escreveu: > > +static int > > +process_bpf_image(char *name, u64 addr, struct kallsyms_parse *data) > > +{ > > + struct machine *machine = data->machine; > > + union perf_event *event = data->event; > > + struct perf_record_ksymbol *ksymbol; > > + > > + ksymbol = &event->ksymbol; > > + > > + *ksymbol = (struct perf_record_ksymbol) { > > + .header = { > > + .type = PERF_RECORD_KSYMBOL, > > + .size = offsetof(struct perf_record_ksymbol, name), > > + }, > > + .addr = addr, > > + .len = page_size, > > + .ksym_type = PERF_RECORD_KSYMBOL_TYPE_BPF, > > + .flags = 0, > > + }; > > + > > + strncpy(ksymbol->name, name, KSYM_NAME_LEN); > > + ksymbol->header.size += PERF_ALIGN(strlen(name) + 1, sizeof(u64)); > > + memset((void *) event + event->header.size, 0, machine->id_hdr_size); > > + event->header.size += machine->id_hdr_size; > > + > > + return perf_tool__process_synth_event(data->tool, event, machine, > > + data->process); > > This explodes in fedora 32 and rawhide and in openmandriva:cooker: > > GEN /tmp/build/perf/python/perf.so > CC /tmp/build/perf/util/bpf-event.o > In file included from /usr/include/string.h:495, > from /git/perf/tools/lib/bpf/libbpf_common.h:12, > from /git/perf/tools/lib/bpf/bpf.h:31, > from util/bpf-event.c:4: > In function ‘strncpy’, > inlined from ‘process_bpf_image’ at util/bpf-event.c:323:2, > inlined from ‘kallsyms_process_symbol’ at util/bpf-event.c:358:9: > /usr/include/bits/string_fortified.h:106:10: error: ‘__builtin_strncpy’ specified bound 256 equals destination size [-Werror=stringop-truncation] > 106 | return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest)); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > cc1: all warnings being treated as errors > mv: cannot stat '/tmp/build/perf/util/.bpf-event.o.tmp': No such file or directory > make[4]: *** [/git/perf/tools/build/Makefile.build:97: /tmp/build/perf/util/bpf-event.o] Error 1 > make[3]: *** [/git/perf/tools/build/Makefile.build:139: util] Error 2 > make[2]: *** [Makefile.perf:617: /tmp/build/perf/perf-in.o] Error 2 > make[1]: *** [Makefile.perf:225: sub-make] Error 2 > make: *** [Makefile:70: all] Error 2 > make: Leaving directory '/git/perf/tools/perf' > [perfbuilder@fc58e82bfba4 ~]$ > > So I patched it a bit, please ack: perfect, thanks Acked-by: Jiri Olsa <jolsa@redhat.com> jirka > > > diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c > index 3728db98981e..0cd41a862952 100644 > --- a/tools/perf/util/bpf-event.c > +++ b/tools/perf/util/bpf-event.c > @@ -306,6 +306,7 @@ process_bpf_image(char *name, u64 addr, struct kallsyms_parse *data) > struct machine *machine = data->machine; > union perf_event *event = data->event; > struct perf_record_ksymbol *ksymbol; > + int len; > > ksymbol = &event->ksymbol; > > @@ -320,8 +321,8 @@ process_bpf_image(char *name, u64 addr, struct kallsyms_parse *data) > .flags = 0, > }; > > - strncpy(ksymbol->name, name, KSYM_NAME_LEN); > - ksymbol->header.size += PERF_ALIGN(strlen(name) + 1, sizeof(u64)); > + len = scnprintf(ksymbol->name, KSYM_NAME_LEN, "%s", name); > + ksymbol->header.size += PERF_ALIGN(len + 1, sizeof(u64)); > memset((void *) event + event->header.size, 0, machine->id_hdr_size); > event->header.size += machine->id_hdr_size; > >
diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c index a3207d900339..3728db98981e 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -6,6 +6,9 @@ #include <bpf/libbpf.h> #include <linux/btf.h> #include <linux/err.h> +#include <linux/string.h> +#include <internal/lib.h> +#include <symbol/kallsyms.h> #include "bpf-event.h" #include "debug.h" #include "dso.h" @@ -290,11 +293,81 @@ static int perf_event__synthesize_one_bpf_prog(struct perf_session *session, return err ? -1 : 0; } +struct kallsyms_parse { + union perf_event *event; + perf_event__handler_t process; + struct machine *machine; + struct perf_tool *tool; +}; + +static int +process_bpf_image(char *name, u64 addr, struct kallsyms_parse *data) +{ + struct machine *machine = data->machine; + union perf_event *event = data->event; + struct perf_record_ksymbol *ksymbol; + + ksymbol = &event->ksymbol; + + *ksymbol = (struct perf_record_ksymbol) { + .header = { + .type = PERF_RECORD_KSYMBOL, + .size = offsetof(struct perf_record_ksymbol, name), + }, + .addr = addr, + .len = page_size, + .ksym_type = PERF_RECORD_KSYMBOL_TYPE_BPF, + .flags = 0, + }; + + strncpy(ksymbol->name, name, KSYM_NAME_LEN); + ksymbol->header.size += PERF_ALIGN(strlen(name) + 1, sizeof(u64)); + memset((void *) event + event->header.size, 0, machine->id_hdr_size); + event->header.size += machine->id_hdr_size; + + return perf_tool__process_synth_event(data->tool, event, machine, + data->process); +} + +static int +kallsyms_process_symbol(void *data, const char *_name, + char type __maybe_unused, u64 start) +{ + char disp[KSYM_NAME_LEN]; + char *module, *name; + unsigned long id; + int err = 0; + + module = strchr(_name, '\t'); + if (!module) + return 0; + + /* We are going after [bpf] module ... */ + if (strcmp(module + 1, "[bpf]")) + return 0; + + name = memdup(_name, (module - _name) + 1); + if (!name) + return -ENOMEM; + + name[module - _name] = 0; + + /* .. and only for trampolines and dispatchers */ + if ((sscanf(name, "bpf_trampoline_%lu", &id) == 1) || + (sscanf(name, "bpf_dispatcher_%s", disp) == 1)) + err = process_bpf_image(name, start, data); + + free(name); + return err; +} + int perf_event__synthesize_bpf_events(struct perf_session *session, perf_event__handler_t process, struct machine *machine, struct record_opts *opts) { + const char *kallsyms_filename = "/proc/kallsyms"; + struct kallsyms_parse arg; union perf_event *event; __u32 id = 0; int err; @@ -303,6 +376,8 @@ int perf_event__synthesize_bpf_events(struct perf_session *session, event = malloc(sizeof(event->bpf) + KSYM_NAME_LEN + machine->id_hdr_size); if (!event) return -1; + + /* Synthesize all the bpf programs in system. */ while (true) { err = bpf_prog_get_next_id(id, &id); if (err) { @@ -335,6 +410,23 @@ int perf_event__synthesize_bpf_events(struct perf_session *session, break; } } + + /* Synthesize all the bpf images - trampolines/dispatchers. */ + if (symbol_conf.kallsyms_name != NULL) + kallsyms_filename = symbol_conf.kallsyms_name; + + arg = (struct kallsyms_parse) { + .event = event, + .process = process, + .machine = machine, + .tool = session->tool, + }; + + if (kallsyms__parse(kallsyms_filename, &arg, kallsyms_process_symbol)) { + pr_err("%s: failed to synthesize bpf images: %s\n", + __func__, strerror(errno)); + } + free(event); return err; }