perf probe: Fix to avoid crashing if DW_AT_decl_file is NULL
Since clang generates DWARF5 which sets DW_AT_decl_file as 0, dwarf_decl_file() thinks that is invalid and returns NULL. In that case 'perf probe' SIGSEGVs because it doesn't expect a NULL decl_file. This adds a dwarf_decl_file() return value check to avoid such SEGV with clang generated DWARF5 info. Without this, 'perf probe' crashes: $ perf probe -k $BIN_PATH/vmlinux -s $SRC_PATH -L vfs_read:10 Segmentation fault $ With this, it just warns about it: $ perf probe -k $BIN_PATH/vmlinux -s $SRC_PATH -L vfs_read:10 Debuginfo analysis failed. Error: Failed to show lines. $ Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Steven Rostedt (VMware) <rostedt@goodmis.org> Link: https://lore.kernel.org/r/166731051077.2100653.15626653369345128302.stgit@devnote3 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
940da138b0
commit
98e4c68ddc
|
@ -137,7 +137,7 @@ int cu_find_lineinfo(Dwarf_Die *cu_die, Dwarf_Addr addr,
|
|||
}
|
||||
|
||||
out:
|
||||
return *lineno ?: -ENOENT;
|
||||
return (*lineno && *fname) ? *lineno : -ENOENT;
|
||||
}
|
||||
|
||||
static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data);
|
||||
|
@ -874,6 +874,11 @@ int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data)
|
|||
cu_die = dwarf_diecu(rt_die, &die_mem, NULL, NULL);
|
||||
dwarf_decl_line(rt_die, &decl);
|
||||
decf = dwarf_decl_file(rt_die);
|
||||
if (!decf) {
|
||||
pr_debug2("Failed to get the declared file name of %s\n",
|
||||
dwarf_diename(rt_die));
|
||||
return -EINVAL;
|
||||
}
|
||||
} else
|
||||
cu_die = rt_die;
|
||||
if (!cu_die) {
|
||||
|
|
|
@ -1063,6 +1063,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
|
|||
struct dwarf_callback_param *param = data;
|
||||
struct probe_finder *pf = param->data;
|
||||
struct perf_probe_point *pp = &pf->pev->point;
|
||||
const char *fname;
|
||||
|
||||
/* Check tag and diename */
|
||||
if (!die_is_func_def(sp_die) ||
|
||||
|
@ -1070,12 +1071,17 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
|
|||
return DWARF_CB_OK;
|
||||
|
||||
/* Check declared file */
|
||||
if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
|
||||
fname = dwarf_decl_file(sp_die);
|
||||
if (!fname) {
|
||||
pr_warning("A function DIE doesn't have decl_line. Maybe broken DWARF?\n");
|
||||
return DWARF_CB_OK;
|
||||
}
|
||||
if (pp->file && fname && strtailcmp(pp->file, fname))
|
||||
return DWARF_CB_OK;
|
||||
|
||||
pr_debug("Matched function: %s [%lx]\n", dwarf_diename(sp_die),
|
||||
(unsigned long)dwarf_dieoffset(sp_die));
|
||||
pf->fname = dwarf_decl_file(sp_die);
|
||||
pf->fname = fname;
|
||||
if (pp->line) { /* Function relative line */
|
||||
dwarf_decl_line(sp_die, &pf->lno);
|
||||
pf->lno += pp->line;
|
||||
|
@ -1134,6 +1140,7 @@ struct pubname_callback_param {
|
|||
static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
|
||||
{
|
||||
struct pubname_callback_param *param = data;
|
||||
const char *fname;
|
||||
|
||||
if (dwarf_offdie(dbg, gl->die_offset, param->sp_die)) {
|
||||
if (dwarf_tag(param->sp_die) != DW_TAG_subprogram)
|
||||
|
@ -1143,9 +1150,11 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
|
|||
if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die))
|
||||
return DWARF_CB_OK;
|
||||
|
||||
if (param->file &&
|
||||
strtailcmp(param->file, dwarf_decl_file(param->sp_die)))
|
||||
return DWARF_CB_OK;
|
||||
if (param->file) {
|
||||
fname = dwarf_decl_file(param->sp_die);
|
||||
if (!fname || strtailcmp(param->file, fname))
|
||||
return DWARF_CB_OK;
|
||||
}
|
||||
|
||||
param->found = 1;
|
||||
return DWARF_CB_ABORT;
|
||||
|
@ -1779,7 +1788,7 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, u64 addr,
|
|||
}
|
||||
/* Verify the lineno and baseline are in a same file */
|
||||
tmp = dwarf_decl_file(&spdie);
|
||||
if (!tmp || strcmp(tmp, fname) != 0)
|
||||
if (!tmp || (fname && strcmp(tmp, fname) != 0))
|
||||
lineno = 0;
|
||||
}
|
||||
|
||||
|
@ -1889,10 +1898,14 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
|
|||
struct dwarf_callback_param *param = data;
|
||||
struct line_finder *lf = param->data;
|
||||
struct line_range *lr = lf->lr;
|
||||
const char *fname;
|
||||
|
||||
/* Check declared file */
|
||||
if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
|
||||
return DWARF_CB_OK;
|
||||
if (lr->file) {
|
||||
fname = dwarf_decl_file(sp_die);
|
||||
if (!fname || strtailcmp(lr->file, fname))
|
||||
return DWARF_CB_OK;
|
||||
}
|
||||
|
||||
if (die_match_name(sp_die, lr->function) && die_is_func_def(sp_die)) {
|
||||
lf->fname = dwarf_decl_file(sp_die);
|
||||
|
|
Loading…
Reference in New Issue