Messages in this thread Patch in this message | | | From | He Kuang <> | Subject | [RFC PATCH v2 10/15] perf bpf: Process debuginfo for generating bpf prologue | Date | Sun, 24 May 2015 08:28:06 +0000 |
| |
Process debuginfo for bpf prologue, the process function is copied and modified from debuginfo__find_trace_events(), with a different callback function for generating bpf prologue bytecode.
Signed-off-by: He Kuang <hekuang@huawei.com> --- tools/perf/util/probe-event.c | 27 ++++++++++++ tools/perf/util/probe-event.h | 2 + tools/perf/util/probe-finder.c | 93 ++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/probe-finder.h | 4 ++ 4 files changed, 126 insertions(+)
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 7f9f431..ccbf4d9 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -914,6 +914,33 @@ out: return ret; } +int get_bpf_prologue(struct perf_probe_event *pev, char **result, int *count) +{ + int ret; + struct debuginfo *dinfo; + bool need_dwarf; + + ret = init_symbol_maps(false); + if (ret < 0) + return ret; + + need_dwarf = perf_probe_event_need_dwarf(pev); + + dinfo = open_debuginfo(NULL, !need_dwarf); + + if (!dinfo) { + if (need_dwarf) + return -ENOENT; + pr_debug("Could not open debuginfo. Try to use symbols.\n"); + return 0; + } + + pr_debug("Try to generate bpf prologue from debuginfo.\n"); + + ret = debuginfo__find_bpf_prologue(dinfo, pev, result, count); + + return ret; +} #else /* !HAVE_DWARF_SUPPORT */ static int diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 6c19395..3eb0183 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -106,6 +106,8 @@ extern char *synthesize_perf_probe_command(struct perf_probe_event *pev); extern char *synthesize_probe_trace_command(struct probe_trace_event *tev); extern int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len); +extern int get_bpf_prologue(struct perf_probe_event *pev, + char **result, int *count); /* Check the perf_probe_event needs debuginfo */ extern bool perf_probe_event_need_dwarf(struct perf_probe_event *pev); diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 4de7649..6785eab 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -39,6 +39,7 @@ #include "util.h" #include "symbol.h" #include "probe-finder.h" +#include <bpf/libbpf.h> /* Kprobe tracer basic type is up to u64 */ #define MAX_BASIC_TYPE_BITS 64 @@ -1177,6 +1178,70 @@ static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf, return n; } +static int generate_bpf_prologue(Dwarf_Die *sc_die, struct probe_finder *pf) +{ + struct trace_event_finder *tf = + container_of(pf, struct trace_event_finder, pf); + struct probe_trace_event *tev; + struct perf_probe_arg *args; + int ret, i; + Dwarf_Die vr_die; + + /* Check number of tevs */ + if (tf->ntevs == tf->max_tevs) { + pr_warning("Too many( > %d) probe point found.\n", + tf->max_tevs); + return -ERANGE; + } + tev = &tf->tevs[tf->ntevs++]; + + /* Expand special probe argument if exist */ + args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS); + if (args == NULL) + return -ENOMEM; + + ret = expand_probe_args(sc_die, pf, args); + if (ret <= 0) + goto end; + + /* restrict nargs <= BPF_PROLOGUE_NRARGS_MAX */ + if (ret > BPF_PROLOGUE_NRARGS_MAX) + ret = BPF_PROLOGUE_NRARGS_MAX; + + tev->nargs = ret; + tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); + if (tev->args == NULL) { + ret = -ENOMEM; + goto end; + } + + /* Find each argument */ + for (i = 0; i < tev->nargs; i++) { + pf->pvar = &args[i]; + pf->tvar = &tev->args[i]; + + /* Search child die for local variables and parameters. */ + if (!die_find_variable_at(sc_die, pf->pvar->var, + pf->addr, &vr_die)) { + /* Search again in global variables */ + if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, + 0, &vr_die)) { + pr_warning("Failed to find '%s' in this function.\n", + pf->pvar->var); + ret = -ENOENT; + } + } + + if (ret >= 0) + ret = convert_variable(&vr_die, pf); + if (ret != 0) + break; + } +end: + free(args); + return ret; +} + /* Add a found probe point into trace event list */ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) { @@ -1261,6 +1326,34 @@ int debuginfo__find_trace_events(struct debuginfo *dbg, return (ret < 0) ? ret : tf.ntevs; } +#define BPF_MAX_TEVS (1) +int debuginfo__find_bpf_prologue(struct debuginfo *dbg, + struct perf_probe_event *pev, + char **result, int *count) +{ + struct trace_event_finder tf = { + .pf = {.pev = pev, .callback = generate_bpf_prologue}, + .mod = dbg->mod, .max_tevs = BPF_MAX_TEVS}; + struct probe_trace_event *tevs; + int ret; + + /* Allocate result tevs array */ + tevs = zalloc(sizeof(struct probe_trace_event) * BPF_MAX_TEVS); + if (tevs == NULL) + return -ENOMEM; + + tf.tevs = tevs; + tf.ntevs = 0; + + ret = debuginfo__find_probes(dbg, &tf.pf); + + *result = NULL; + *count = 0; + + free(tevs); + return ret; +} + #define MAX_VAR_LEN 64 /* Collect available variables in this scope */ diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index f53553d..f046c63 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h @@ -43,6 +43,10 @@ extern int debuginfo__find_trace_events(struct debuginfo *dbg, struct probe_trace_event **tevs, int max_tevs); +extern int debuginfo__find_bpf_prologue(struct debuginfo *dbg, + struct perf_probe_event *pev, + char **result, int *count); + /* Find a perf_probe_point from debuginfo */ extern int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, -- 1.8.5.2
| |