Commit bebd23a2 authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo' of...

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

New features:

  - Allow passing C language eBPF scriptlets via --event in all tools,
    so that it gets built using clang and then pass it to the kernel via
    sys_bpf(). (Wang Nan)

  - Wire up the loaded ebpf object file with associated kprobes, so that
    it can determine if the kprobes will be filtered or not. (Wang Nan)

User visible changes:

  - Add cmd string table to decode sys_bpf first arg in 'trace'. (Arnaldo Carvalho de Melo)

  - Enable printing of branch stack in 'perf script'. (Stephane Eranian)

  - Pass the right file with debug info to libunwind. (Rabin Vincent)

Build Fixes:

  - Make sure fixdep is built before libbpf, fixing a race. (Jiri Olsa)

  - Fix libiberty feature detection. (Rabin Vincent)
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 66a565c2 7ed4915a
...@@ -132,10 +132,10 @@ test-libbfd.bin: ...@@ -132,10 +132,10 @@ test-libbfd.bin:
$(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl $(BUILD) -DPACKAGE='"perf"' -lbfd -lz -liberty -ldl
test-liberty.bin: test-liberty.bin:
$(CC) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty
test-liberty-z.bin: test-liberty-z.bin:
$(CC) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' -lbfd -ldl -liberty -lz $(CC) $(CFLAGS) -Wall -Werror -o $(OUTPUT)$@ test-libbfd.c -DPACKAGE='"perf"' $(LDFLAGS) -lbfd -ldl -liberty -lz
test-cplus-demangle.bin: test-cplus-demangle.bin:
$(BUILD) -liberty $(BUILD) -liberty
......
...@@ -314,6 +314,12 @@ This option sets the time out limit. The default value is 500 ms. ...@@ -314,6 +314,12 @@ This option sets the time out limit. The default value is 500 ms.
Record context switch events i.e. events of type PERF_RECORD_SWITCH or Record context switch events i.e. events of type PERF_RECORD_SWITCH or
PERF_RECORD_SWITCH_CPU_WIDE. PERF_RECORD_SWITCH_CPU_WIDE.
--clang-path::
Path to clang binary to use for compiling BPF scriptlets.
--clang-opt::
Options passed to clang when compiling BPF scriptlets.
SEE ALSO SEE ALSO
-------- --------
linkperf:perf-stat[1], linkperf:perf-list[1] linkperf:perf-stat[1], linkperf:perf-list[1]
...@@ -112,11 +112,11 @@ OPTIONS ...@@ -112,11 +112,11 @@ OPTIONS
--debug-mode:: --debug-mode::
Do various checks like samples ordering and lost events. Do various checks like samples ordering and lost events.
-f:: -F::
--fields:: --fields::
Comma separated list of fields to print. Options are: Comma separated list of fields to print. Options are:
comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
srcline, period, iregs, flags. srcline, period, iregs, brstack, brstacksym, flags.
Field list can be prepended with the type, trace, sw or hw, Field list can be prepended with the type, trace, sw or hw,
to indicate to which event type the field list applies. to indicate to which event type the field list applies.
e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
...@@ -175,6 +175,16 @@ OPTIONS ...@@ -175,6 +175,16 @@ OPTIONS
Finally, a user may not set fields to none for all event types. Finally, a user may not set fields to none for all event types.
i.e., -f "" is not allowed. i.e., -f "" is not allowed.
The brstack output includes branch related information with raw addresses using the
/v/v/v/v/ syntax in the following order:
FROM: branch source instruction
TO : branch target instruction
M/P/-: M=branch target mispredicted or branch direction was mispredicted, P=target predicted or direction predicted, -=not supported
X/- : X=branch inside a transactional region, -=not in transaction region or not supported
A/- : A=TSX abort entry, -=not aborted region or not supported
The brstacksym is identical to brstack, except that the FROM and TO addresses are printed in a symbolic form if possible.
-k:: -k::
--vmlinux=<file>:: --vmlinux=<file>::
vmlinux pathname vmlinux pathname
......
...@@ -430,7 +430,7 @@ $(LIBAPI)-clean: ...@@ -430,7 +430,7 @@ $(LIBAPI)-clean:
$(call QUIET_CLEAN, libapi) $(call QUIET_CLEAN, libapi)
$(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null $(Q)$(MAKE) -C $(LIB_DIR) O=$(OUTPUT) clean >/dev/null
$(LIBBPF): FORCE $(LIBBPF): fixdep FORCE
$(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) $(OUTPUT)libbpf.a $(Q)$(MAKE) -C $(BPF_DIR) O=$(OUTPUT) $(OUTPUT)libbpf.a
$(LIBBPF)-clean: $(LIBBPF)-clean:
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "util/auxtrace.h" #include "util/auxtrace.h"
#include "util/parse-branch-options.h" #include "util/parse-branch-options.h"
#include "util/parse-regs-options.h" #include "util/parse-regs-options.h"
#include "util/llvm-utils.h"
#include <unistd.h> #include <unistd.h>
#include <sched.h> #include <sched.h>
...@@ -1112,6 +1113,12 @@ struct option __record_options[] = { ...@@ -1112,6 +1113,12 @@ struct option __record_options[] = {
"per thread proc mmap processing timeout in ms"), "per thread proc mmap processing timeout in ms"),
OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events, OPT_BOOLEAN(0, "switch-events", &record.opts.record_switch_events,
"Record context switch events"), "Record context switch events"),
#ifdef HAVE_LIBBPF_SUPPORT
OPT_STRING(0, "clang-path", &llvm_param.clang_path, "clang path",
"clang binary to use for compiling BPF scriptlets"),
OPT_STRING(0, "clang-opt", &llvm_param.clang_opt, "clang options",
"options passed to clang when compiling BPF scriptlets"),
#endif
OPT_END() OPT_END()
}; };
......
...@@ -51,6 +51,8 @@ enum perf_output_field { ...@@ -51,6 +51,8 @@ enum perf_output_field {
PERF_OUTPUT_SRCLINE = 1U << 12, PERF_OUTPUT_SRCLINE = 1U << 12,
PERF_OUTPUT_PERIOD = 1U << 13, PERF_OUTPUT_PERIOD = 1U << 13,
PERF_OUTPUT_IREGS = 1U << 14, PERF_OUTPUT_IREGS = 1U << 14,
PERF_OUTPUT_BRSTACK = 1U << 15,
PERF_OUTPUT_BRSTACKSYM = 1U << 16,
}; };
struct output_option { struct output_option {
...@@ -72,6 +74,8 @@ struct output_option { ...@@ -72,6 +74,8 @@ struct output_option {
{.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, {.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
{.str = "period", .field = PERF_OUTPUT_PERIOD}, {.str = "period", .field = PERF_OUTPUT_PERIOD},
{.str = "iregs", .field = PERF_OUTPUT_IREGS}, {.str = "iregs", .field = PERF_OUTPUT_IREGS},
{.str = "brstack", .field = PERF_OUTPUT_BRSTACK},
{.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM},
}; };
/* default set to maintain compatibility with current format */ /* default set to maintain compatibility with current format */
...@@ -425,6 +429,77 @@ static void print_sample_start(struct perf_sample *sample, ...@@ -425,6 +429,77 @@ static void print_sample_start(struct perf_sample *sample,
} }
} }
static inline char
mispred_str(struct branch_entry *br)
{
if (!(br->flags.mispred || br->flags.predicted))
return '-';
return br->flags.predicted ? 'P' : 'M';
}
static void print_sample_brstack(union perf_event *event __maybe_unused,
struct perf_sample *sample,
struct thread *thread __maybe_unused,
struct perf_event_attr *attr __maybe_unused)
{
struct branch_stack *br = sample->branch_stack;
u64 i;
if (!(br && br->nr))
return;
for (i = 0; i < br->nr; i++) {
printf(" 0x%"PRIx64"/0x%"PRIx64"/%c/%c/%c/%d ",
br->entries[i].from,
br->entries[i].to,
mispred_str( br->entries + i),
br->entries[i].flags.in_tx? 'X' : '-',
br->entries[i].flags.abort? 'A' : '-',
br->entries[i].flags.cycles);
}
}
static void print_sample_brstacksym(union perf_event *event __maybe_unused,
struct perf_sample *sample,
struct thread *thread __maybe_unused,
struct perf_event_attr *attr __maybe_unused)
{
struct branch_stack *br = sample->branch_stack;
struct addr_location alf, alt;
u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
u64 i, from, to;
if (!(br && br->nr))
return;
for (i = 0; i < br->nr; i++) {
memset(&alf, 0, sizeof(alf));
memset(&alt, 0, sizeof(alt));
from = br->entries[i].from;
to = br->entries[i].to;
thread__find_addr_map(thread, cpumode, MAP__FUNCTION, from, &alf);
if (alf.map)
alf.sym = map__find_symbol(alf.map, alf.addr, NULL);
thread__find_addr_map(thread, cpumode, MAP__FUNCTION, to, &alt);
if (alt.map)
alt.sym = map__find_symbol(alt.map, alt.addr, NULL);
symbol__fprintf_symname_offs(alf.sym, &alf, stdout);
putchar('/');
symbol__fprintf_symname_offs(alt.sym, &alt, stdout);
printf("/%c/%c/%c/%d ",
mispred_str( br->entries + i),
br->entries[i].flags.in_tx? 'X' : '-',
br->entries[i].flags.abort? 'A' : '-',
br->entries[i].flags.cycles);
}
}
static void print_sample_addr(union perf_event *event, static void print_sample_addr(union perf_event *event,
struct perf_sample *sample, struct perf_sample *sample,
struct thread *thread, struct thread *thread,
...@@ -560,6 +635,11 @@ static void process_event(union perf_event *event, struct perf_sample *sample, ...@@ -560,6 +635,11 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
if (PRINT_FIELD(IREGS)) if (PRINT_FIELD(IREGS))
print_sample_iregs(event, sample, thread, attr); print_sample_iregs(event, sample, thread, attr);
if (PRINT_FIELD(BRSTACK))
print_sample_brstack(event, sample, thread, attr);
else if (PRINT_FIELD(BRSTACKSYM))
print_sample_brstacksym(event, sample, thread, attr);
printf("\n"); printf("\n");
} }
...@@ -1681,7 +1761,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -1681,7 +1761,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
"comma separated output fields prepend with 'type:'. " "comma separated output fields prepend with 'type:'. "
"Valid types: hw,sw,trace,raw. " "Valid types: hw,sw,trace,raw. "
"Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
"addr,symoff,period,iregs,flags", parse_output_fields), "addr,symoff,period,iregs,brstack,brstacksym,flags", parse_output_fields),
OPT_BOOLEAN('a', "all-cpus", &system_wide, OPT_BOOLEAN('a', "all-cpus", &system_wide,
"system-wide collection from all CPUs"), "system-wide collection from all CPUs"),
OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
......
...@@ -585,6 +585,12 @@ static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct sysc ...@@ -585,6 +585,12 @@ static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct sysc
#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op #define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
static const char *bpf_cmd[] = {
"MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
"MAP_GET_NEXT_KEY", "PROG_LOAD",
};
static DEFINE_STRARRAY(bpf_cmd);
static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", }; static const char *epoll_ctl_ops[] = { "ADD", "DEL", "MOD", };
static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1); static DEFINE_STRARRAY_OFFSET(epoll_ctl_ops, 1);
...@@ -1011,6 +1017,7 @@ static struct syscall_fmt { ...@@ -1011,6 +1017,7 @@ static struct syscall_fmt {
.arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */
[1] = SCA_ACCMODE, /* mode */ }, }, [1] = SCA_ACCMODE, /* mode */ }, },
{ .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
{ .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
{ .name = "brk", .hexret = true, { .name = "brk", .hexret = true,
.arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
{ .name = "chdir", .errmsg = true, { .name = "chdir", .errmsg = true,
......
#ifndef LINUX_VERSION_CODE
# error Need LINUX_VERSION_CODE
# error Example: for 4.2 kernel, put 'clang-opt="-DLINUX_VERSION_CODE=0x40200" into llvm section of ~/.perfconfig'
#endif
#define BPF_ANY 0
#define BPF_MAP_TYPE_ARRAY 2
#define BPF_FUNC_map_lookup_elem 1
#define BPF_FUNC_map_update_elem 2
static void *(*bpf_map_lookup_elem)(void *map, void *key) =
(void *) BPF_FUNC_map_lookup_elem;
static void *(*bpf_map_update_elem)(void *map, void *key, void *value, int flags) =
(void *) BPF_FUNC_map_update_elem;
struct bpf_map_def {
unsigned int type;
unsigned int key_size;
unsigned int value_size;
unsigned int max_entries;
};
#define SEC(NAME) __attribute__((section(NAME), used))
struct bpf_map_def SEC("maps") flip_table = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(int),
.max_entries = 1,
};
SEC("func=sys_epoll_pwait")
int bpf_func__sys_epoll_pwait(void *ctx)
{
int ind =0;
int *flag = bpf_map_lookup_elem(&flip_table, &ind);
int new_flag;
if (!flag)
return 0;
/* flip flag and store back */
new_flag = !*flag;
bpf_map_update_elem(&flip_table, &ind, &new_flag, BPF_ANY);
return new_flag;
}
char _license[] SEC("license") = "GPL";
int _version SEC("version") = LINUX_VERSION_CODE;
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "bpf-loader.h" #include "bpf-loader.h"
#include "probe-event.h" #include "probe-event.h"
#include "probe-finder.h" // for MAX_PROBES #include "probe-finder.h" // for MAX_PROBES
#include "llvm-utils.h"
#define DEFINE_PRINT_FN(name, level) \ #define DEFINE_PRINT_FN(name, level) \
static int libbpf_##name(const char *fmt, ...) \ static int libbpf_##name(const char *fmt, ...) \
...@@ -33,7 +34,7 @@ struct bpf_prog_priv { ...@@ -33,7 +34,7 @@ struct bpf_prog_priv {
struct perf_probe_event pev; struct perf_probe_event pev;
}; };
struct bpf_object *bpf__prepare_load(const char *filename) struct bpf_object *bpf__prepare_load(const char *filename, bool source)
{ {
struct bpf_object *obj; struct bpf_object *obj;
static bool libbpf_initialized; static bool libbpf_initialized;
...@@ -45,7 +46,19 @@ struct bpf_object *bpf__prepare_load(const char *filename) ...@@ -45,7 +46,19 @@ struct bpf_object *bpf__prepare_load(const char *filename)
libbpf_initialized = true; libbpf_initialized = true;
} }
obj = bpf_object__open(filename); if (source) {
int err;
void *obj_buf;
size_t obj_buf_sz;
err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz);
if (err)
return ERR_PTR(err);
obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
free(obj_buf);
} else
obj = bpf_object__open(filename);
if (!obj) { if (!obj) {
pr_debug("bpf: failed to load %s\n", filename); pr_debug("bpf: failed to load %s\n", filename);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
......
...@@ -18,7 +18,7 @@ typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev, ...@@ -18,7 +18,7 @@ typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev,
int fd, void *arg); int fd, void *arg);
#ifdef HAVE_LIBBPF_SUPPORT #ifdef HAVE_LIBBPF_SUPPORT
struct bpf_object *bpf__prepare_load(const char *filename); struct bpf_object *bpf__prepare_load(const char *filename, bool source);
void bpf__clear(void); void bpf__clear(void);
...@@ -34,7 +34,8 @@ int bpf__foreach_tev(struct bpf_object *obj, ...@@ -34,7 +34,8 @@ int bpf__foreach_tev(struct bpf_object *obj,
bpf_prog_iter_callback_t func, void *arg); bpf_prog_iter_callback_t func, void *arg);
#else #else
static inline struct bpf_object * static inline struct bpf_object *
bpf__prepare_load(const char *filename __maybe_unused) bpf__prepare_load(const char *filename __maybe_unused,
bool source __maybe_unused)
{ {
pr_debug("ERROR: eBPF object loading is disabled during compiling.\n"); pr_debug("ERROR: eBPF object loading is disabled during compiling.\n");
return ERR_PTR(-ENOTSUP); return ERR_PTR(-ENOTSUP);
......
...@@ -208,6 +208,7 @@ void perf_evsel__init(struct perf_evsel *evsel, ...@@ -208,6 +208,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
evsel->unit = ""; evsel->unit = "";
evsel->scale = 1.0; evsel->scale = 1.0;
evsel->evlist = NULL; evsel->evlist = NULL;
evsel->bpf_fd = -1;
INIT_LIST_HEAD(&evsel->node); INIT_LIST_HEAD(&evsel->node);
INIT_LIST_HEAD(&evsel->config_terms); INIT_LIST_HEAD(&evsel->config_terms);
perf_evsel__object.init(evsel); perf_evsel__object.init(evsel);
...@@ -1356,6 +1357,22 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, ...@@ -1356,6 +1357,22 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
err); err);
goto try_fallback; goto try_fallback;
} }
if (evsel->bpf_fd >= 0) {
int evt_fd = FD(evsel, cpu, thread);
int bpf_fd = evsel->bpf_fd;
err = ioctl(evt_fd,
PERF_EVENT_IOC_SET_BPF,
bpf_fd);
if (err && errno != EEXIST) {
pr_err("failed to attach bpf fd %d: %s\n",
bpf_fd, strerror(errno));
err = -EINVAL;
goto out_close;
}
}
set_rlimit = NO_CHANGE; set_rlimit = NO_CHANGE;
/* /*
......
...@@ -123,6 +123,7 @@ struct perf_evsel { ...@@ -123,6 +123,7 @@ struct perf_evsel {
char *group_name; char *group_name;
bool cmdline_group_boundary; bool cmdline_group_boundary;
struct list_head config_terms; struct list_head config_terms;
int bpf_fd;
}; };
union u64_swap { union u64_swap {
......
...@@ -542,6 +542,7 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd, ...@@ -542,6 +542,7 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd,
struct __add_bpf_event_param *param = _param; struct __add_bpf_event_param *param = _param;
struct parse_events_evlist *evlist = param->data; struct parse_events_evlist *evlist = param->data;
struct list_head *list = param->list; struct list_head *list = param->list;
struct perf_evsel *pos;
int err; int err;
pr_debug("add bpf event %s:%s and attach bpf program %d\n", pr_debug("add bpf event %s:%s and attach bpf program %d\n",
...@@ -562,6 +563,11 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd, ...@@ -562,6 +563,11 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd,
} }
pr_debug("adding %s:%s\n", tev->group, tev->event); pr_debug("adding %s:%s\n", tev->group, tev->event);
list_for_each_entry(pos, &new_evsels, node) {
pr_debug("adding %s:%s to %p\n",
tev->group, tev->event, pos);
pos->bpf_fd = fd;
}
list_splice(&new_evsels, list); list_splice(&new_evsels, list);
return 0; return 0;
} }
...@@ -620,11 +626,12 @@ int parse_events_load_bpf_obj(struct parse_events_evlist *data, ...@@ -620,11 +626,12 @@ int parse_events_load_bpf_obj(struct parse_events_evlist *data,
int parse_events_load_bpf(struct parse_events_evlist *data, int parse_events_load_bpf(struct parse_events_evlist *data,
struct list_head *list, struct list_head *list,
char *bpf_file_name) char *bpf_file_name,
bool source)
{ {
struct bpf_object *obj; struct bpf_object *obj;
obj = bpf__prepare_load(bpf_file_name); obj = bpf__prepare_load(bpf_file_name, source);
if (IS_ERR(obj) || !obj) { if (IS_ERR(obj) || !obj) {
char errbuf[BUFSIZ]; char errbuf[BUFSIZ];
int err; int err;
......
...@@ -125,7 +125,8 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx, ...@@ -125,7 +125,8 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx,
struct list_head *head_config); struct list_head *head_config);
int parse_events_load_bpf(struct parse_events_evlist *data, int parse_events_load_bpf(struct parse_events_evlist *data,
struct list_head *list, struct list_head *list,
char *bpf_file_name); char *bpf_file_name,
bool source);
/* Provide this function for perf test */ /* Provide this function for perf test */
struct bpf_object; struct bpf_object;
int parse_events_load_bpf_obj(struct parse_events_evlist *data, int parse_events_load_bpf_obj(struct parse_events_evlist *data,
......
...@@ -116,6 +116,7 @@ group [^,{}/]*[{][^}]*[}][^,{}/]* ...@@ -116,6 +116,7 @@ group [^,{}/]*[{][^}]*[}][^,{}/]*
event_pmu [^,{}/]+[/][^/]*[/][^,{}/]* event_pmu [^,{}/]+[/][^/]*[/][^,{}/]*
event [^,{}/]+ event [^,{}/]+
bpf_object .*\.(o|bpf) bpf_object .*\.(o|bpf)
bpf_source .*\.c
num_dec [0-9]+ num_dec [0-9]+
num_hex 0x[a-fA-F0-9]+ num_hex 0x[a-fA-F0-9]+
...@@ -161,6 +162,7 @@ modifier_bp [rwx]{1,3} ...@@ -161,6 +162,7 @@ modifier_bp [rwx]{1,3}
{event_pmu} | {event_pmu} |
{bpf_object} | {bpf_object} |
{bpf_source} |
{event} { {event} {
BEGIN(INITIAL); BEGIN(INITIAL);
REWIND(1); REWIND(1);
...@@ -269,6 +271,7 @@ r{num_raw_hex} { return raw(yyscanner); } ...@@ -269,6 +271,7 @@ r{num_raw_hex} { return raw(yyscanner); }
{modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); } {modifier_event} { return str(yyscanner, PE_MODIFIER_EVENT); }
{bpf_object} { return str(yyscanner, PE_BPF_OBJECT); } {bpf_object} { return str(yyscanner, PE_BPF_OBJECT); }
{bpf_source} { return str(yyscanner, PE_BPF_SOURCE); }
{name} { return pmu_str_check(yyscanner); } {name} { return pmu_str_check(yyscanner); }
"/" { BEGIN(config); return '/'; } "/" { BEGIN(config); return '/'; }
- { return '-'; } - { return '-'; }
......
...@@ -42,7 +42,7 @@ static inc_group_count(struct list_head *list, ...@@ -42,7 +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_BPF_OBJECT PE_BPF_SOURCE
%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
...@@ -55,6 +55,7 @@ static inc_group_count(struct list_head *list, ...@@ -55,6 +55,7 @@ static inc_group_count(struct list_head *list,
%type <num> PE_TERM %type <num> PE_TERM
%type <str> PE_NAME %type <str> PE_NAME
%type <str> PE_BPF_OBJECT %type <str> PE_BPF_OBJECT
%type <str> PE_BPF_SOURCE
%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
...@@ -461,7 +462,17 @@ PE_BPF_OBJECT ...@@ -461,7 +462,17 @@ PE_BPF_OBJECT
struct list_head *list; struct list_head *list;
ALLOC_LIST(list); ALLOC_LIST(list);
ABORT_ON(parse_events_load_bpf(data, list, $1)); ABORT_ON(parse_events_load_bpf(data, list, $1, false));
$$ = list;
}
|
PE_BPF_SOURCE
{
struct parse_events_evlist *data = _data;
struct list_head *list;
ALLOC_LIST(list);
ABORT_ON(parse_events_load_bpf(data, list, $1, true));
$$ = list; $$ = list;
} }
......
...@@ -360,12 +360,15 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, ...@@ -360,12 +360,15 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
int fd = dso__data_get_fd(map->dso, ui->machine); int fd = dso__data_get_fd(map->dso, ui->machine);
int is_exec = elf_is_exec(fd, map->dso->name); int is_exec = elf_is_exec(fd, map->dso->name);
unw_word_t base = is_exec ? 0 : map->start; unw_word_t base = is_exec ? 0 : map->start;
const char *symfile;
if (fd >= 0) if (fd >= 0)
dso__data_put_fd(map->dso); dso__data_put_fd(map->dso);
symfile = map->dso->symsrc_filename ?: map->dso->name;
memset(&di, 0, sizeof(di)); memset(&di, 0, sizeof(di));
if (dwarf_find_debug_frame(0, &di, ip, base, map->dso->name, if (dwarf_find_debug_frame(0, &di, ip, base, symfile,
map->start, map->end)) map->start, map->end))
return dwarf_search_unwind_table(as, ip, &di, pi, return dwarf_search_unwind_table(as, ip, &di, pi,
need_unwind_info, arg); need_unwind_info, arg);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment