[PATCH v2 03/11] perf dwarf-aux: Skip check_variable for variable lookup

From: Zecheng Li

Date: Mon Mar 09 2026 - 14:04:19 EST


From: Zecheng Li <zecheng@xxxxxxxxxx>

Both die_find_variable_by_reg and die_find_variable_by_addr call
match_var_offset which already performs sufficient checking and type
matching. The additional check_variable call is redundant, and its
need_pointer logic is only a heuristic. Since DWARF encodes accurate
type information, which match_var_offset verifies, skipping
check_variable improves both coverage and accuracy.

Return the matched type from die_find_variable_by_reg and
die_find_variable_by_addr via the existing `type` field in
find_var_data, removing the need for check_variable in
find_data_type_die.

Signed-off-by: Zecheng Li <zecheng@xxxxxxxxxx>
Signed-off-by: Zecheng Li <zli94@xxxxxxxx>
---
tools/perf/util/annotate-data.c | 42 ++++++++++++++-------------------
tools/perf/util/dwarf-aux.c | 13 ++++++----
tools/perf/util/dwarf-aux.h | 5 ++--
3 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c
index cda020ea18d5..23a09bf58f86 100644
--- a/tools/perf/util/annotate-data.c
+++ b/tools/perf/util/annotate-data.c
@@ -814,9 +814,8 @@ bool get_global_var_type(Dwarf_Die *cu_die, struct data_loc_info *dloc,
}

/* Try to get the variable by address first */
- if (die_find_variable_by_addr(cu_die, var_addr, &var_die, &offset) &&
- check_variable(dloc, &var_die, type_die, DWARF_REG_PC, offset,
- /*is_fbreg=*/false) == PERF_TMR_OK) {
+ if (die_find_variable_by_addr(cu_die, var_addr, &var_die, type_die,
+ &offset)) {
var_name = dwarf_diename(&var_die);
*var_offset = offset;
goto ok;
@@ -1606,12 +1605,13 @@ static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die)

if (reg == DWARF_REG_PC) {
if (!die_find_variable_by_addr(&scopes[i], dloc->var_addr,
- &var_die, &type_offset))
+ &var_die, &mem_die,
+ &type_offset))
continue;
} else {
/* Look up variables/parameters in this scope */
if (!die_find_variable_by_reg(&scopes[i], pc, reg,
- &type_offset, is_fbreg, &var_die))
+ &mem_die, &type_offset, is_fbreg, &var_die))
continue;
}

@@ -1619,26 +1619,20 @@ static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die)
dwarf_diename(&var_die), (long)dwarf_dieoffset(&var_die),
i+1, nr_scopes, (long)dwarf_dieoffset(&scopes[i]));

- /* Found a variable, see if it's correct */
- result = check_variable(dloc, &var_die, &mem_die, reg, type_offset, is_fbreg);
- if (result == PERF_TMR_OK) {
- if (reg == DWARF_REG_PC) {
- pr_debug_dtp("addr=%#"PRIx64" type_offset=%#x\n",
- dloc->var_addr, type_offset);
- } else if (reg == DWARF_REG_FB || is_fbreg) {
- pr_debug_dtp("stack_offset=%#x type_offset=%#x\n",
- fb_offset, type_offset);
- } else {
- pr_debug_dtp("type_offset=%#x\n", type_offset);
- }
-
- if (!found || is_better_type(type_die, &mem_die)) {
- *type_die = mem_die;
- dloc->type_offset = type_offset;
- found = true;
- }
+ if (reg == DWARF_REG_PC) {
+ pr_debug_dtp("addr=%#"PRIx64" type_offset=%#x\n",
+ dloc->var_addr, type_offset);
+ } else if (reg == DWARF_REG_FB || is_fbreg) {
+ pr_debug_dtp("stack_offset=%#x type_offset=%#x\n",
+ fb_offset, type_offset);
} else {
- pr_debug_dtp("failed: %s\n", match_result_str(result));
+ pr_debug_dtp("type_offset=%#x\n", type_offset);
+ }
+
+ if (!found || is_better_type(type_die, &mem_die)) {
+ *type_die = mem_die;
+ dloc->type_offset = type_offset;
+ found = true;
}

pr_debug_location(&var_die, pc, reg);
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index 3b0fc9038f19..1484aa756826 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -1560,7 +1560,7 @@ static int __die_find_var_reg_cb(Dwarf_Die *die_mem, void *arg)
* when the variable is in the stack.
*/
Dwarf_Die *die_find_variable_by_reg(Dwarf_Die *sc_die, Dwarf_Addr pc, int reg,
- int *poffset, bool is_fbreg,
+ Dwarf_Die *type_die, int *poffset, bool is_fbreg,
Dwarf_Die *die_mem)
{
struct find_var_data data = {
@@ -1572,8 +1572,10 @@ Dwarf_Die *die_find_variable_by_reg(Dwarf_Die *sc_die, Dwarf_Addr pc, int reg,
Dwarf_Die *result;

result = die_find_child(sc_die, __die_find_var_reg_cb, &data, die_mem);
- if (result)
+ if (result) {
*poffset = data.offset;
+ *type_die = data.type;
+ }
return result;
}

@@ -1617,7 +1619,8 @@ static int __die_find_var_addr_cb(Dwarf_Die *die_mem, void *arg)
* This is usually for global variables.
*/
Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die, Dwarf_Addr addr,
- Dwarf_Die *die_mem, int *offset)
+ Dwarf_Die *die_mem, Dwarf_Die *type_die,
+ int *offset)
{
struct find_var_data data = {
.addr = addr,
@@ -1625,8 +1628,10 @@ Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die, Dwarf_Addr addr,
Dwarf_Die *result;

result = die_find_child(sc_die, __die_find_var_addr_cb, &data, die_mem);
- if (result)
+ if (result) {
*offset = data.offset;
+ *type_die = data.type;
+ }
return result;
}

diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index 99d2735122d5..939a59c91796 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -165,12 +165,13 @@ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf);

/* Find a variable saved in the 'reg' at given address */
Dwarf_Die *die_find_variable_by_reg(Dwarf_Die *sc_die, Dwarf_Addr pc, int reg,
- int *poffset, bool is_fbreg,
+ Dwarf_Die *type_die, int *poffset, bool is_fbreg,
Dwarf_Die *die_mem);

/* Find a (global) variable located in the 'addr' */
Dwarf_Die *die_find_variable_by_addr(Dwarf_Die *sc_die, Dwarf_Addr addr,
- Dwarf_Die *die_mem, int *offset);
+ Dwarf_Die *die_mem, Dwarf_Die *type_die,
+ int *offset);

/* Save all variables and parameters in this scope */
void die_collect_vars(Dwarf_Die *sc_die, struct die_var_type **var_types);
--
2.53.0