Messages in this thread Patch in this message | | | From | He Kuang <> | Subject | [RFC PATCH 5/6] perf bpf: Process debuginfo for generating bpf prologue | Date | Tue, 5 May 2015 10:10:11 +0000 |
| |
Process debuginfo for bpf prologue, the process function is copied and modified from debuginfo__find_trace_events(), but use 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 | 90 ++++++++++++++++++++++++++++++++++++++++++ tools/perf/util/probe-finder.h | 4 ++ 4 files changed, 123 insertions(+)
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index c307cd7..fbdda4d 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -906,6 +906,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 3b6c284..5a6b86e 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h @@ -115,6 +115,8 @@ extern int synthesize_probe_trace_arg_bpf(struct probe_trace_arg *arg, extern int synthesize_probe_trace_arg_bpf_begin(struct strbuf *buf); extern int synthesize_probe_trace_arg_bpf_end(struct probe_trace_arg *arg, struct strbuf *buf, int num); +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 249e6cb..bfb7625 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -1164,6 +1164,71 @@ static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf, return n; } +#define BPF_PROLOGUE_MAX_LEN (1024) +static int generate_bpf_prologue(Dwarf_Die *sc_die, struct probe_finder *pf) +{ + struct perf_probe_arg *args; + int ret = 0, i; + Dwarf_Die vr_die; + struct strbuf buf; + int narg; + + if (pf->tvar) + return -ERANGE; + + pf->tvar = (struct probe_trace_arg *) + malloc(sizeof(struct probe_trace_arg)); + if (pf->tvar == NULL) + return -ENOMEM; + + /* Expand special probe argument if exist */ + args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS); + if (args == NULL) + return -ENOMEM; + + narg = expand_probe_args(sc_die, pf, args); + if (narg <= 0) + goto end; + + strbuf_init(&buf, BPF_PROLOGUE_MAX_LEN); + synthesize_probe_trace_arg_bpf_begin(&buf); + + /* Find each argument */ + for (i = 0; i < narg; i++) { + pf->pvar = &args[i]; + + memset(pf->tvar, 0, sizeof(struct probe_trace_arg)); + /* 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; + + ret = synthesize_probe_trace_arg_bpf(pf->tvar, &buf, i); + if (ret) + goto end; + } + + synthesize_probe_trace_arg_bpf_end(pf->tvar, &buf, narg); + + pr_debug("bpf_prologue: insn num=%d\n", pf->tvar->insns_cnt); + +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) { @@ -1248,6 +1313,31 @@ int debuginfo__find_trace_events(struct debuginfo *dbg, return (ret < 0) ? ret : tf.ntevs; } +int debuginfo__find_bpf_prologue(struct debuginfo *dbg, + struct perf_probe_event *pev, + char **result, int *count) +{ + struct probe_finder pf = {.pev = pev, + .callback = generate_bpf_prologue}; + int ret; + + pf.tvar = NULL; + ret = debuginfo__find_probes(dbg, &pf); + if (ret == -ERANGE) + ret = 0; + + if (pf.tvar) { + *result = pf.tvar->insns; + *count = pf.tvar->insns_cnt; + free(pf.tvar); + } else { + *result = NULL; + *count = 0; + } + + 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 ebf8c8c..28437978 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h @@ -40,6 +40,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
| |