perf tools: Enable passing bpf object file to --event

By introducing new rules in tools/perf/util/parse-events.[ly], this
patch enables 'perf record --event bpf_file.o' to select events by an
eBPF object file. It calls parse_events_load_bpf() to load that file,
which uses bpf__prepare_load() and finally calls bpf_object__open() for
the object files.

After applying this patch, commands like:

 # perf record --event foo.o sleep

become possible.

However, at this point it is unable to link any useful things onto the
evsel list because the creating of probe points and BPF program
attaching have not been implemented.  Before real events are possible to
be extracted, to avoid perf report error because of empty evsel list,
this patch link a dummy evsel. The dummy event related code will be
removed when probing and extracting code is ready.

Commiter notes:

Using it:

  $ ls -la foo.o
  ls: cannot access foo.o: No such file or directory
  $ perf record --event foo.o sleep
  libbpf: failed to open foo.o: No such file or directory
  event syntax error: 'foo.o'
                       \___ BPF object file 'foo.o' is invalid

  (add -v to see detail)
  Run 'perf list' for a list of valid events

   Usage: perf record [<options>] [<command>]
      or: perf record [<options>] -- <command> [<options>]

      -e, --event <event>   event selector. use 'perf list' to list available events
  $

  $ file /tmp/build/perf/perf.o
  /tmp/build/perf/perf.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
  $ perf record --event /tmp/build/perf/perf.o sleep
  libbpf: /tmp/build/perf/perf.o is not an eBPF object file
  event syntax error: '/tmp/build/perf/perf.o'
                       \___ BPF object file '/tmp/build/perf/perf.o' is invalid

  (add -v to see detail)
  Run 'perf list' for a list of valid events

   Usage: perf record [<options>] [<command>]
      or: perf record [<options>] -- <command> [<options>]

      -e, --event <event>   event selector. use 'perf list' to list available events
  $

  $ file /tmp/foo.o
  /tmp/foo.o: ELF 64-bit LSB relocatable, no machine, version 1 (SYSV), not stripped
  $ perf record --event /tmp/foo.o sleep 1
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.013 MB perf.data ]
  $ perf evlist
  /tmp/foo.o
  $ perf evlist  -v
  /tmp/foo.o: type: 1, size: 112, config: 0x9, { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|PERIOD, disabled: 1, inherit: 1, mmap: 1, comm: 1, freq: 1, enable_on_exec: 1, task: 1, sample_id_all: 1, exclude_guest: 1, mmap2: 1, comm_exec: 1
  $

So, type 1 is PERF_TYPE_SOFTWARE, config 0x9 is PERF_COUNT_SW_DUMMY, ok.

  $ perf report --stdio
  Error:
  The perf.data file has no samples!
  # To display the perf.data header info, please use --header/--header-only options.
  #
  $

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1444826502-49291-4-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Wang Nan 2015-10-14 12:41:14 +00:00 коммит произвёл Arnaldo Carvalho de Melo
Родитель 69d262a93a
Коммит 84c86ca12b
6 изменённых файлов: 88 добавлений и 1 удалений

Просмотреть файл

@ -15,6 +15,7 @@
#include "util/run-command.h" #include "util/run-command.h"
#include "util/parse-events.h" #include "util/parse-events.h"
#include "util/parse-options.h" #include "util/parse-options.h"
#include "util/bpf-loader.h"
#include "util/debug.h" #include "util/debug.h"
#include <api/fs/tracing_path.h> #include <api/fs/tracing_path.h>
#include <pthread.h> #include <pthread.h>
@ -385,6 +386,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
status = p->fn(argc, argv, prefix); status = p->fn(argc, argv, prefix);
exit_browser(status); exit_browser(status);
perf_env__exit(&perf_env); perf_env__exit(&perf_env);
bpf__clear();
if (status) if (status)
return status & 0xff; return status & 0xff;

Просмотреть файл

@ -87,6 +87,7 @@ libperf-$(CONFIG_AUXTRACE) += intel-bts.o
libperf-y += parse-branch-options.o libperf-y += parse-branch-options.o
libperf-y += parse-regs-options.o libperf-y += parse-regs-options.o
libperf-$(CONFIG_LIBBPF) += bpf-loader.o
libperf-$(CONFIG_LIBELF) += symbol-elf.o libperf-$(CONFIG_LIBELF) += symbol-elf.o
libperf-$(CONFIG_LIBELF) += probe-file.o libperf-$(CONFIG_LIBELF) += probe-file.o
libperf-$(CONFIG_LIBELF) += probe-event.o libperf-$(CONFIG_LIBELF) += probe-event.o

Просмотреть файл

@ -11,6 +11,7 @@
#include "symbol.h" #include "symbol.h"
#include "cache.h" #include "cache.h"
#include "header.h" #include "header.h"
#include "bpf-loader.h"
#include "debug.h" #include "debug.h"
#include <api/fs/tracing_path.h> #include <api/fs/tracing_path.h>
#include "parse-events-bison.h" #include "parse-events-bison.h"
@ -529,6 +530,62 @@ static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
return ret; return ret;
} }
int parse_events_load_bpf_obj(struct parse_events_evlist *data,
struct list_head *list,
struct bpf_object *obj)
{
int err;
char errbuf[BUFSIZ];
if (IS_ERR(obj) || !obj) {
snprintf(errbuf, sizeof(errbuf),
"Internal error: load bpf obj with NULL");
err = -EINVAL;
goto errout;
}
/*
* Temporary add a dummy event here so we can check whether
* basic bpf loader works. Following patches will replace
* dummy event by useful evsels.
*/
return parse_events_add_numeric(data, list, PERF_TYPE_SOFTWARE,
PERF_COUNT_SW_DUMMY, NULL);
errout:
data->error->help = strdup("(add -v to see detail)");
data->error->str = strdup(errbuf);
return err;
}
int parse_events_load_bpf(struct parse_events_evlist *data,
struct list_head *list,
char *bpf_file_name)
{
struct bpf_object *obj;
obj = bpf__prepare_load(bpf_file_name);
if (IS_ERR(obj) || !obj) {
char errbuf[BUFSIZ];
int err;
err = obj ? PTR_ERR(obj) : -EINVAL;
if (err == -ENOTSUP)
snprintf(errbuf, sizeof(errbuf),
"BPF support is not compiled");
else
snprintf(errbuf, sizeof(errbuf),
"BPF object file '%s' is invalid",
bpf_file_name);
data->error->help = strdup("(add -v to see detail)");
data->error->str = strdup(errbuf);
return err;
}
return parse_events_load_bpf_obj(data, list, obj);
}
static int static int
parse_breakpoint_type(const char *type, struct perf_event_attr *attr) parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
{ {

Просмотреть файл

@ -123,6 +123,14 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx,
char *sys, char *event, char *sys, char *event,
struct parse_events_error *error, struct parse_events_error *error,
struct list_head *head_config); struct list_head *head_config);
int parse_events_load_bpf(struct parse_events_evlist *data,
struct list_head *list,
char *bpf_file_name);
/* Provide this function for perf test */
struct bpf_object;
int parse_events_load_bpf_obj(struct parse_events_evlist *data,
struct list_head *list,
struct bpf_object *obj);
int parse_events_add_numeric(struct parse_events_evlist *data, int parse_events_add_numeric(struct parse_events_evlist *data,
struct list_head *list, struct list_head *list,
u32 type, u64 config, u32 type, u64 config,

Просмотреть файл

@ -115,6 +115,7 @@ do { \
group [^,{}/]*[{][^}]*[}][^,{}/]* group [^,{}/]*[{][^}]*[}][^,{}/]*
event_pmu [^,{}/]+[/][^/]*[/][^,{}/]* event_pmu [^,{}/]+[/][^/]*[/][^,{}/]*
event [^,{}/]+ event [^,{}/]+
bpf_object .*\.(o|bpf)
num_dec [0-9]+ num_dec [0-9]+
num_hex 0x[a-fA-F0-9]+ num_hex 0x[a-fA-F0-9]+
@ -159,6 +160,7 @@ modifier_bp [rwx]{1,3}
} }
{event_pmu} | {event_pmu} |
{bpf_object} |
{event} { {event} {
BEGIN(INITIAL); BEGIN(INITIAL);
REWIND(1); REWIND(1);
@ -266,6 +268,7 @@ r{num_raw_hex} { return raw(yyscanner); }
{num_hex} { return value(yyscanner, 16); } {num_hex} { return value(yyscanner, 16); }
{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } {modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
{bpf_object} { return str(yyscanner, PE_BPF_OBJECT); }
{name} { return pmu_str_check(yyscanner); } {name} { return pmu_str_check(yyscanner); }
"/" { BEGIN(config); return '/'; } "/" { BEGIN(config); return '/'; }
- { return '-'; } - { return '-'; }

Просмотреть файл

@ -42,6 +42,7 @@ static inc_group_count(struct list_head *list,
%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM %token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
%token PE_EVENT_NAME %token PE_EVENT_NAME
%token PE_NAME %token PE_NAME
%token PE_BPF_OBJECT
%token PE_MODIFIER_EVENT PE_MODIFIER_BP %token PE_MODIFIER_EVENT PE_MODIFIER_BP
%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP %token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
@ -53,6 +54,7 @@ static inc_group_count(struct list_head *list,
%type <num> PE_RAW %type <num> PE_RAW
%type <num> PE_TERM %type <num> PE_TERM
%type <str> PE_NAME %type <str> PE_NAME
%type <str> PE_BPF_OBJECT
%type <str> PE_NAME_CACHE_TYPE %type <str> PE_NAME_CACHE_TYPE
%type <str> PE_NAME_CACHE_OP_RESULT %type <str> PE_NAME_CACHE_OP_RESULT
%type <str> PE_MODIFIER_EVENT %type <str> PE_MODIFIER_EVENT
@ -70,6 +72,7 @@ static inc_group_count(struct list_head *list,
%type <tracepoint_name> tracepoint_name %type <tracepoint_name> tracepoint_name
%type <head> event_legacy_numeric %type <head> event_legacy_numeric
%type <head> event_legacy_raw %type <head> event_legacy_raw
%type <head> event_bpf_file
%type <head> event_def %type <head> event_def
%type <head> event_mod %type <head> event_mod
%type <head> event_name %type <head> event_name
@ -203,7 +206,8 @@ event_def: event_pmu |
event_legacy_mem | event_legacy_mem |
event_legacy_tracepoint sep_dc | event_legacy_tracepoint sep_dc |
event_legacy_numeric sep_dc | event_legacy_numeric sep_dc |
event_legacy_raw sep_dc event_legacy_raw sep_dc |
event_bpf_file
event_pmu: event_pmu:
PE_NAME '/' event_config '/' PE_NAME '/' event_config '/'
@ -449,6 +453,18 @@ PE_RAW
$$ = list; $$ = list;
} }
event_bpf_file:
PE_BPF_OBJECT
{
struct parse_events_evlist *data = _data;
struct parse_events_error *error = data->error;
struct list_head *list;
ALLOC_LIST(list);
ABORT_ON(parse_events_load_bpf(data, list, $1));
$$ = list;
}
start_terms: event_config start_terms: event_config
{ {
struct parse_events_terms *data = _data; struct parse_events_terms *data = _data;