Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757572AbbEEKMU (ORCPT ); Tue, 5 May 2015 06:12:20 -0400 Received: from szxga03-in.huawei.com ([119.145.14.66]:4095 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757473AbbEEKK5 (ORCPT ); Tue, 5 May 2015 06:10:57 -0400 From: He Kuang To: , , , , , , CC: , , , Subject: [RFC PATCH 5/6] perf bpf: Process debuginfo for generating bpf prologue Date: Tue, 5 May 2015 10:10:11 +0000 Message-ID: <1430820612-84443-6-git-send-email-hekuang@huawei.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1430820612-84443-1-git-send-email-hekuang@huawei.com> References: <1430820612-84443-1-git-send-email-hekuang@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.107.197.210] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020206.5548972D.02B6,ss=1,re=0.000,recu=0.000,reip=0.000,cl=1,cld=1,fgs=0, ip=0.0.0.0, so=2013-05-26 15:14:31, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 4d1e744a75d80717b93bce37f3279824 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5561 Lines: 194 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 --- 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 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/