summaryrefslogtreecommitdiff
path: root/tools/perf/util/probe-finder.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/probe-finder.c')
-rw-r--r--tools/perf/util/probe-finder.c248
1 files changed, 72 insertions, 176 deletions
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index ffb657f..f069273 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -115,7 +115,7 @@ static const Dwfl_Callbacks offline_callbacks = {
};
/* Get a Dwarf from offline image */
-static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
+static int debuginfo__init_offline_dwarf(struct debuginfo *self,
const char *path)
{
int fd;
@@ -124,25 +124,25 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
if (fd < 0)
return fd;
- dbg->dwfl = dwfl_begin(&offline_callbacks);
- if (!dbg->dwfl)
+ self->dwfl = dwfl_begin(&offline_callbacks);
+ if (!self->dwfl)
goto error;
- dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
- if (!dbg->mod)
+ self->mod = dwfl_report_offline(self->dwfl, "", "", fd);
+ if (!self->mod)
goto error;
- dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
- if (!dbg->dbg)
+ self->dbg = dwfl_module_getdwarf(self->mod, &self->bias);
+ if (!self->dbg)
goto error;
return 0;
error:
- if (dbg->dwfl)
- dwfl_end(dbg->dwfl);
+ if (self->dwfl)
+ dwfl_end(self->dwfl);
else
close(fd);
- memset(dbg, 0, sizeof(*dbg));
+ memset(self, 0, sizeof(*self));
return -ENOENT;
}
@@ -180,24 +180,24 @@ static const Dwfl_Callbacks kernel_callbacks = {
};
/* Get a Dwarf from live kernel image */
-static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
+static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
Dwarf_Addr addr)
{
- dbg->dwfl = dwfl_begin(&kernel_callbacks);
- if (!dbg->dwfl)
+ self->dwfl = dwfl_begin(&kernel_callbacks);
+ if (!self->dwfl)
return -EINVAL;
/* Load the kernel dwarves: Don't care the result here */
- dwfl_linux_kernel_report_kernel(dbg->dwfl);
- dwfl_linux_kernel_report_modules(dbg->dwfl);
+ dwfl_linux_kernel_report_kernel(self->dwfl);
+ dwfl_linux_kernel_report_modules(self->dwfl);
- dbg->dbg = dwfl_addrdwarf(dbg->dwfl, addr, &dbg->bias);
+ self->dbg = dwfl_addrdwarf(self->dwfl, addr, &self->bias);
/* Here, check whether we could get a real dwarf */
- if (!dbg->dbg) {
+ if (!self->dbg) {
pr_debug("Failed to find kernel dwarf at %lx\n",
(unsigned long)addr);
- dwfl_end(dbg->dwfl);
- memset(dbg, 0, sizeof(*dbg));
+ dwfl_end(self->dwfl);
+ memset(self, 0, sizeof(*self));
return -ENOENT;
}
@@ -205,7 +205,7 @@ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
}
#else
/* With older elfutils, this just support kernel module... */
-static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
+static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
Dwarf_Addr addr __maybe_unused)
{
const char *path = kernel_get_module_path("kernel");
@@ -216,45 +216,44 @@ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
}
pr_debug2("Use file %s for debuginfo\n", path);
- return debuginfo__init_offline_dwarf(dbg, path);
+ return debuginfo__init_offline_dwarf(self, path);
}
#endif
struct debuginfo *debuginfo__new(const char *path)
{
- struct debuginfo *dbg = zalloc(sizeof(*dbg));
- if (!dbg)
+ struct debuginfo *self = zalloc(sizeof(struct debuginfo));
+ if (!self)
return NULL;
- if (debuginfo__init_offline_dwarf(dbg, path) < 0) {
- free(dbg);
- dbg = NULL;
+ if (debuginfo__init_offline_dwarf(self, path) < 0) {
+ free(self);
+ self = NULL;
}
- return dbg;
+ return self;
}
struct debuginfo *debuginfo__new_online_kernel(unsigned long addr)
{
- struct debuginfo *dbg = zalloc(sizeof(*dbg));
-
- if (!dbg)
+ struct debuginfo *self = zalloc(sizeof(struct debuginfo));
+ if (!self)
return NULL;
- if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) {
- free(dbg);
- dbg = NULL;
+ if (debuginfo__init_online_kernel_dwarf(self, (Dwarf_Addr)addr) < 0) {
+ free(self);
+ self = NULL;
}
- return dbg;
+ return self;
}
-void debuginfo__delete(struct debuginfo *dbg)
+void debuginfo__delete(struct debuginfo *self)
{
- if (dbg) {
- if (dbg->dwfl)
- dwfl_end(dbg->dwfl);
- free(dbg);
+ if (self) {
+ if (self->dwfl)
+ dwfl_end(self->dwfl);
+ free(self);
}
}
@@ -274,15 +273,12 @@ static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
/*
* Convert a location into trace_arg.
* If tvar == NULL, this just checks variable can be converted.
- * If fentry == true and vr_die is a parameter, do huristic search
- * for the location fuzzed by function entry mcount.
*/
static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
- Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
+ Dwarf_Op *fb_ops,
struct probe_trace_arg *tvar)
{
Dwarf_Attribute attr;
- Dwarf_Addr tmp = 0;
Dwarf_Op *op;
size_t nops;
unsigned int regn;
@@ -295,29 +291,12 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
goto static_var;
/* TODO: handle more than 1 exprs */
- if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
- return -EINVAL; /* Broken DIE ? */
- if (dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0) {
- ret = dwarf_entrypc(sp_die, &tmp);
- if (ret || addr != tmp ||
- dwarf_tag(vr_die) != DW_TAG_formal_parameter ||
- dwarf_highpc(sp_die, &tmp))
- return -ENOENT;
- /*
- * This is fuzzed by fentry mcount. We try to find the
- * parameter location at the earliest address.
- */
- for (addr += 1; addr <= tmp; addr++) {
- if (dwarf_getlocation_addr(&attr, addr, &op,
- &nops, 1) > 0)
- goto found;
- }
- return -ENOENT;
- }
-found:
- if (nops == 0)
+ if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL ||
+ dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0 ||
+ nops == 0) {
/* TODO: Support const_value */
return -ENOENT;
+ }
if (op->atom == DW_OP_addr) {
static_var:
@@ -584,7 +563,7 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
}
if (die_find_member(&type, field->name, die_mem) == NULL) {
- pr_warning("%s(type:%s) has no member %s.\n", varname,
+ pr_warning("%s(tyep:%s) has no member %s.\n", varname,
dwarf_diename(&type), field->name);
return -EINVAL;
}
@@ -621,7 +600,7 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
dwarf_diename(vr_die));
ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
- &pf->sp_die, pf->tvar);
+ pf->tvar);
if (ret == -ENOENT)
pr_err("Failed to find the location of %s at this address.\n"
" Perhaps, it has been optimized out.\n", pf->pvar->var);
@@ -1084,7 +1063,7 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
}
/* Find probe points from debuginfo */
-static int debuginfo__find_probes(struct debuginfo *dbg,
+static int debuginfo__find_probes(struct debuginfo *self,
struct probe_finder *pf)
{
struct perf_probe_point *pp = &pf->pev->point;
@@ -1095,7 +1074,7 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
#if _ELFUTILS_PREREQ(0, 142)
/* Get the call frame information from this dwarf */
- pf->cfi = dwarf_getcfi(dbg->dbg);
+ pf->cfi = dwarf_getcfi(self->dbg);
#endif
off = 0;
@@ -1114,7 +1093,7 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
.data = pf,
};
- dwarf_getpubnames(dbg->dbg, pubname_search_cb,
+ dwarf_getpubnames(self->dbg, pubname_search_cb,
&pubname_param, 0);
if (pubname_param.found) {
ret = probe_point_search_cb(&pf->sp_die, &probe_param);
@@ -1124,9 +1103,9 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
}
/* Loop on CUs (Compilation Unit) */
- while (!dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
+ while (!dwarf_nextcu(self->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
/* Get the DIE(Debugging Information Entry) of this CU */
- diep = dwarf_offdie(dbg->dbg, off + cuhl, &pf->cu_die);
+ diep = dwarf_offdie(self->dbg, off + cuhl, &pf->cu_die);
if (!diep)
continue;
@@ -1157,80 +1136,12 @@ found:
return ret;
}
-struct local_vars_finder {
- struct probe_finder *pf;
- struct perf_probe_arg *args;
- int max_args;
- int nargs;
- int ret;
-};
-
-/* Collect available variables in this scope */
-static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
-{
- struct local_vars_finder *vf = data;
- struct probe_finder *pf = vf->pf;
- int tag;
-
- tag = dwarf_tag(die_mem);
- if (tag == DW_TAG_formal_parameter ||
- tag == DW_TAG_variable) {
- if (convert_variable_location(die_mem, vf->pf->addr,
- vf->pf->fb_ops, &pf->sp_die,
- NULL) == 0) {
- vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
- if (vf->args[vf->nargs].var == NULL) {
- vf->ret = -ENOMEM;
- return DIE_FIND_CB_END;
- }
- pr_debug(" %s", vf->args[vf->nargs].var);
- vf->nargs++;
- }
- }
-
- if (dwarf_haspc(die_mem, vf->pf->addr))
- return DIE_FIND_CB_CONTINUE;
- else
- return DIE_FIND_CB_SIBLING;
-}
-
-static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf,
- struct perf_probe_arg *args)
-{
- Dwarf_Die die_mem;
- int i;
- int n = 0;
- struct local_vars_finder vf = {.pf = pf, .args = args,
- .max_args = MAX_PROBE_ARGS, .ret = 0};
-
- for (i = 0; i < pf->pev->nargs; i++) {
- /* var never be NULL */
- if (strcmp(pf->pev->args[i].var, "$vars") == 0) {
- pr_debug("Expanding $vars into:");
- vf.nargs = n;
- /* Special local variables */
- die_find_child(sc_die, copy_variables_cb, (void *)&vf,
- &die_mem);
- pr_debug(" (%d)\n", vf.nargs - n);
- if (vf.ret < 0)
- return vf.ret;
- n = vf.nargs;
- } else {
- /* Copy normal argument */
- args[n] = pf->pev->args[i];
- n++;
- }
- }
- return n;
-}
-
/* Add a found probe point into trace event list */
static int add_probe_trace_event(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;
/* Check number of tevs */
@@ -1250,45 +1161,31 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
tev->point.offset);
- /* 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;
-
- 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];
+ tev->nargs = pf->pev->nargs;
+ tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
+ if (tev->args == NULL)
+ return -ENOMEM;
+ for (i = 0; i < pf->pev->nargs; i++) {
+ pf->pvar = &pf->pev->args[i];
pf->tvar = &tev->args[i];
/* Variable should be found from scope DIE */
ret = find_variable(sc_die, pf);
if (ret != 0)
- break;
+ return ret;
}
-end:
- free(args);
- return ret;
+ return 0;
}
/* Find probe_trace_events specified by perf_probe_event from debuginfo */
-int debuginfo__find_trace_events(struct debuginfo *dbg,
+int debuginfo__find_trace_events(struct debuginfo *self,
struct perf_probe_event *pev,
struct probe_trace_event **tevs, int max_tevs)
{
struct trace_event_finder tf = {
.pf = {.pev = pev, .callback = add_probe_trace_event},
- .mod = dbg->mod, .max_tevs = max_tevs};
+ .mod = self->mod, .max_tevs = max_tevs};
int ret;
/* Allocate result tevs array */
@@ -1299,7 +1196,7 @@ int debuginfo__find_trace_events(struct debuginfo *dbg,
tf.tevs = *tevs;
tf.ntevs = 0;
- ret = debuginfo__find_probes(dbg, &tf.pf);
+ ret = debuginfo__find_probes(self, &tf.pf);
if (ret < 0) {
free(*tevs);
*tevs = NULL;
@@ -1325,8 +1222,7 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
if (tag == DW_TAG_formal_parameter ||
tag == DW_TAG_variable) {
ret = convert_variable_location(die_mem, af->pf.addr,
- af->pf.fb_ops, &af->pf.sp_die,
- NULL);
+ af->pf.fb_ops, NULL);
if (ret == 0) {
ret = die_get_varname(die_mem, buf, MAX_VAR_LEN);
pr_debug2("Add new var: %s\n", buf);
@@ -1390,14 +1286,14 @@ out:
}
/* Find available variables at given probe point */
-int debuginfo__find_available_vars_at(struct debuginfo *dbg,
+int debuginfo__find_available_vars_at(struct debuginfo *self,
struct perf_probe_event *pev,
struct variable_list **vls,
int max_vls, bool externs)
{
struct available_var_finder af = {
.pf = {.pev = pev, .callback = add_available_vars},
- .mod = dbg->mod,
+ .mod = self->mod,
.max_vls = max_vls, .externs = externs};
int ret;
@@ -1409,7 +1305,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg,
af.vls = *vls;
af.nvls = 0;
- ret = debuginfo__find_probes(dbg, &af.pf);
+ ret = debuginfo__find_probes(self, &af.pf);
if (ret < 0) {
/* Free vlist for error */
while (af.nvls--) {
@@ -1427,7 +1323,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg,
}
/* Reverse search */
-int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
+int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,
struct perf_probe_point *ppt)
{
Dwarf_Die cudie, spdie, indie;
@@ -1436,10 +1332,10 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
int baseline = 0, lineno = 0, ret = 0;
/* Adjust address with bias */
- addr += dbg->bias;
+ addr += self->bias;
/* Find cu die */
- if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr - dbg->bias, &cudie)) {
+ if (!dwarf_addrdie(self->dbg, (Dwarf_Addr)addr - self->bias, &cudie)) {
pr_warning("Failed to find debug information for address %lx\n",
addr);
ret = -EINVAL;
@@ -1640,7 +1536,7 @@ static int find_line_range_by_func(struct line_finder *lf)
return param.retval;
}
-int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr)
+int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr)
{
struct line_finder lf = {.lr = lr, .found = 0};
int ret = 0;
@@ -1657,7 +1553,7 @@ int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr)
struct dwarf_callback_param line_range_param = {
.data = (void *)&lf, .retval = 0};
- dwarf_getpubnames(dbg->dbg, pubname_search_cb,
+ dwarf_getpubnames(self->dbg, pubname_search_cb,
&pubname_param, 0);
if (pubname_param.found) {
line_range_search_cb(&lf.sp_die, &line_range_param);
@@ -1668,12 +1564,12 @@ int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr)
/* Loop on CUs (Compilation Unit) */
while (!lf.found && ret >= 0) {
- if (dwarf_nextcu(dbg->dbg, off, &noff, &cuhl,
+ if (dwarf_nextcu(self->dbg, off, &noff, &cuhl,
NULL, NULL, NULL) != 0)
break;
/* Get the DIE(Debugging Information Entry) of this CU */
- diep = dwarf_offdie(dbg->dbg, off + cuhl, &lf.cu_die);
+ diep = dwarf_offdie(self->dbg, off + cuhl, &lf.cu_die);
if (!diep)
continue;