From: Ian Rogers <irogers@google.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Namhyung Kim <namhyung@kernel.org>, Jiri Olsa <jolsa@kernel.org>,
Adrian Hunter <adrian.hunter@intel.com>,
James Clark <james.clark@linaro.org>,
Zecheng Li <zli94@ncsu.edu>,
Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>,
linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Ian Rogers <irogers@google.com>
Subject: [PATCH v2 4/6] perf probe-finder: Fix libdw API contract violations
Date: Sat, 2 May 2026 08:56:54 -0700 [thread overview]
Message-ID: <20260502155656.478642-5-irogers@google.com> (raw)
In-Reply-To: <20260502155656.478642-1-irogers@google.com>
Check return values of `dwarf_formsdata`, `dwarf_entrypc`,
`dwarf_highpc`, `dwarf_bytesize`, `dwarf_attr`, `dwarf_decl_line`,
`dwarf_getfuncs`, and `dwarf_formref_die`. Validate `dwarf_diename` and
`dwarf_diecu` results to prevent potential crashes. Fix C90 mixed
declarations.
Fixes: 66f69b219716 ("perf probe: Support DW_AT_const_value constant value")
Fixes: 3d918a12a1b3 ("perf probe: Find fentry mcount fuzzed parameter location")
Fixes: bcfc082150c6 ("perf probe: Remove redundant dwarf functions")
Fixes: 221d061182b8 ("perf probe: Fix to search local variables in appropriate scope")
Fixes: b55a87ade383 ("perf probe: Remove die() from probe-finder code")
Fixes: 4c859351226c ("perf probe: Support glob wildcards for function name")
Assisted-by: Gemini-CLI:Google Gemini 3
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/probe-finder.c | 84 ++++++++++++++++++++++------------
1 file changed, 56 insertions(+), 28 deletions(-)
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 64328abeef8b..069f0d83d0b7 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -93,7 +93,8 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
if (!tvar)
return 0;
- dwarf_formsdata(&attr, &snum);
+ if (dwarf_formsdata(&attr, &snum) != 0)
+ return -ENOENT;
ret = asprintf(&tvar->value, "\\%ld", (long)snum);
return ret < 0 ? -ENOMEM : 0;
@@ -103,8 +104,7 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
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)
+ if (dwarf_entrypc(sp_die, &tmp) != 0)
return -ENOENT;
if (probe_conf.show_location_range &&
@@ -115,8 +115,7 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
return -ENOENT;
}
- ret = dwarf_highpc(sp_die, &tmp);
- if (ret)
+ if (dwarf_highpc(sp_die, &tmp) != 0)
return -ENOENT;
/*
* This is fuzzed by fentry mcount. We try to find the
@@ -138,15 +137,21 @@ static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
static_var:
if (!tvar)
return ret2;
- /* Static variables on memory (not stack), make @varname */
- ret = strlen(dwarf_diename(vr_die));
- tvar->value = zalloc(ret + 2);
- if (tvar->value == NULL)
- return -ENOMEM;
- snprintf(tvar->value, ret + 2, "@%s", dwarf_diename(vr_die));
- tvar->ref = alloc_trace_arg_ref((long)offs);
- if (tvar->ref == NULL)
- return -ENOMEM;
+ {
+ /* Static variables on memory (not stack), make @varname */
+ const char *name = dwarf_diename(vr_die);
+
+ if (!name)
+ return -ENOENT;
+ ret = strlen(name);
+ tvar->value = zalloc(ret + 2);
+ if (tvar->value == NULL)
+ return -ENOMEM;
+ snprintf(tvar->value, ret + 2, "@%s", name);
+ tvar->ref = alloc_trace_arg_ref((long)offs);
+ if (tvar->ref == NULL)
+ return -ENOMEM;
+ }
return ret2;
}
@@ -234,8 +239,9 @@ static int convert_variable_type(Dwarf_Die *vr_die,
}
if (die_get_real_type(vr_die, &type) == NULL) {
+ const char *name = dwarf_diename(vr_die);
pr_warning("Failed to get a type information of %s.\n",
- dwarf_diename(vr_die));
+ name ? name : "<unknown>");
return -ENOENT;
}
@@ -291,7 +297,7 @@ static int convert_variable_type(Dwarf_Die *vr_die,
probe_type_is_available(PROBE_TYPE_X) ? 'x' : 'u';
ret = dwarf_bytesize(&type);
- if (ret <= 0)
+ if (ret < 0)
/* No size ... try to use default type */
return 0;
ret = BYTES_TO_BITS(ret);
@@ -357,7 +363,13 @@ static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname,
else
*ref_ptr = ref;
}
- ref->offset += dwarf_bytesize(&type) * field->index;
+ {
+ int bsize = dwarf_bytesize(&type);
+
+ if (bsize < 0)
+ return -EINVAL;
+ ref->offset += bsize * field->index;
+ }
ref->user_access = user_access;
goto next;
} else if (tag == DW_TAG_pointer_type) {
@@ -611,10 +623,16 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf)
memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die));
/* Get the frame base attribute/ops from subprogram */
- dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr);
- ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
- if (ret <= 0 || nops == 0) {
+ if (dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr) == NULL) {
pf->fb_ops = NULL;
+ } else {
+ ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1);
+ if (ret <= 0 || nops == 0)
+ pf->fb_ops = NULL;
+ }
+
+ if (pf->fb_ops == NULL) {
+ /* Not supported */
} else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
(pf->cfi_eh != NULL || pf->cfi_dbg != NULL)) {
if ((dwarf_cfi_addrframe(pf->cfi_eh, pf->addr, &frame) != 0 &&
@@ -667,8 +685,8 @@ static int find_best_scope_cb(Dwarf_Die *fn_die, void *data)
}
} else {
/* With the line number, find the nearest declared DIE */
- dwarf_decl_line(fn_die, &lno);
- if (lno < fsp->line && fsp->diff > fsp->line - lno) {
+ if (dwarf_decl_line(fn_die, &lno) == 0 &&
+ lno < fsp->line && fsp->diff > fsp->line - lno) {
/* Keep a candidate and continue */
fsp->diff = fsp->line - lno;
memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die));
@@ -1018,7 +1036,8 @@ static int find_probe_point_by_func(struct probe_finder *pf)
{
struct dwarf_callback_param _param = {.data = (void *)pf,
.retval = 0};
- dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0);
+ if (dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0) < 0)
+ return -ENOENT;
return _param.retval;
}
@@ -1207,7 +1226,8 @@ static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
* points to correct die.
*/
if (dwarf_attr(die_mem, DW_AT_abstract_origin, &attr)) {
- dwarf_formref_die(&attr, &var_die);
+ if (dwarf_formref_die(&attr, &var_die) == NULL)
+ goto out;
if (pf->abstrace_dieoffset != dwarf_dieoffset(&var_die))
goto out;
}
@@ -1270,6 +1290,8 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
struct probe_trace_event *tev;
struct perf_probe_arg *args = NULL;
int ret, i;
+ const char *realname;
+ Dwarf_Die cu_die_mem;
/*
* For some reason (e.g. different column assigned to same address)
@@ -1293,13 +1315,17 @@ static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf)
if (ret < 0)
goto end;
- tev->point.realname = strdup(dwarf_diename(sc_die));
+ realname = dwarf_diename(sc_die);
+ tev->point.realname = strdup(realname ?: "unknown");
if (!tev->point.realname) {
ret = -ENOMEM;
goto end;
}
- tev->lang = dwarf_srclang(dwarf_diecu(sc_die, &pf->cu_die, NULL, NULL));
+ if (dwarf_diecu(sc_die, &cu_die_mem, NULL, NULL) != NULL)
+ tev->lang = dwarf_srclang(&cu_die_mem);
+ else
+ tev->lang = DW_LANG_C; // Fallback
pr_debug("Probe point found: %s+%lu\n", tev->point.symbol,
tev->point.offset);
@@ -1794,7 +1820,8 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
if (die_match_name(sp_die, lr->function) && die_is_func_def(sp_die)) {
lf->fname = die_get_decl_file(sp_die);
- dwarf_decl_line(sp_die, &lr->offset);
+ if (dwarf_decl_line(sp_die, &lr->offset) != 0)
+ return DWARF_CB_OK; // Skip if no line info
pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
lf->lno_s = lr->offset + lr->start;
if (lf->lno_s < 0) /* Overflow */
@@ -1818,7 +1845,8 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
static int find_line_range_by_func(struct line_finder *lf)
{
struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0};
- dwarf_getfuncs(&lf->cu_die, line_range_search_cb, ¶m, 0);
+ if (dwarf_getfuncs(&lf->cu_die, line_range_search_cb, ¶m, 0) < 0)
+ return -ENOENT;
return param.retval;
}
--
2.54.0.545.g6539524ca2-goog
next prev parent reply other threads:[~2026-05-02 15:57 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-02 6:48 [PATCH v1] perf dwarf-aux: Fix libdw segmentation fault in cu_walk_functions_at Ian Rogers
2026-05-02 15:56 ` [PATCH v2 0/6] perf DWARF: Fix libdw API contract violations and crashes Ian Rogers
2026-05-02 15:56 ` [PATCH v2 1/6] perf dwarf-aux: Fix libdw segmentation fault in cu_walk_functions_at Ian Rogers
2026-05-02 15:56 ` [PATCH v2 2/6] perf dwarf-aux: Fix libdw API contract violations Ian Rogers
2026-05-02 15:56 ` [PATCH v2 3/6] perf libdw: " Ian Rogers
2026-05-02 15:56 ` Ian Rogers [this message]
2026-05-02 15:56 ` [PATCH v2 5/6] perf annotate-data: " Ian Rogers
2026-05-02 15:56 ` [PATCH v2 6/6] perf debuginfo: " Ian Rogers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260502155656.478642-5-irogers@google.com \
--to=irogers@google.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=james.clark@linaro.org \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=masami.hiramatsu.pt@hitachi.com \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
--cc=zli94@ncsu.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox