Commit 83bfa06d authored by Namhyung Kim's avatar Namhyung Kim

perf annotate-data: Handle PC-relative addressing

Extend find_data_type_die() to find data type from PC-relative address
using die_find_variable_by_addr().  Users need to pass the address for
the (global) variable.

The offset for the variable should be updated after finding the type
because the offset in the instruction is just to calcuate the address
for the variable.  So it changed to pass a pointer to offset and renamed
it to 'poffset'.

First it searches variables in the CU DIE as it's likely that the global
variables are defined in the file level.  And then it iterates the scope
DIEs to find a local (static) variable.
Reviewed-by: default avatarIan Rogers <irogers@google.com>
Cc: Stephane Eranian <eranian@google.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Link: https://lore.kernel.org/r/20240117062657.985479-6-namhyung@kernel.orgSigned-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
parent 7a54f1d8
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "debuginfo.h" #include "debuginfo.h"
#include "debug.h" #include "debug.h"
#include "dso.h" #include "dso.h"
#include "dwarf-regs.h"
#include "evsel.h" #include "evsel.h"
#include "evlist.h" #include "evlist.h"
#include "map.h" #include "map.h"
...@@ -193,7 +194,8 @@ static bool find_cu_die(struct debuginfo *di, u64 pc, Dwarf_Die *cu_die) ...@@ -193,7 +194,8 @@ static bool find_cu_die(struct debuginfo *di, u64 pc, Dwarf_Die *cu_die)
} }
/* The type info will be saved in @type_die */ /* The type info will be saved in @type_die */
static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset) static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset,
bool is_pointer)
{ {
Dwarf_Word size; Dwarf_Word size;
...@@ -205,15 +207,18 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset) ...@@ -205,15 +207,18 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset)
} }
/* /*
* It expects a pointer type for a memory access. * Usually it expects a pointer type for a memory access.
* Convert to a real type it points to. * Convert to a real type it points to. But global variables
* are accessed directly without a pointer.
*/ */
if ((dwarf_tag(type_die) != DW_TAG_pointer_type && if (is_pointer) {
dwarf_tag(type_die) != DW_TAG_array_type) || if ((dwarf_tag(type_die) != DW_TAG_pointer_type &&
die_get_real_type(type_die, type_die) == NULL) { dwarf_tag(type_die) != DW_TAG_array_type) ||
pr_debug("no pointer or no type\n"); die_get_real_type(type_die, type_die) == NULL) {
ann_data_stat.no_typeinfo++; pr_debug("no pointer or no type\n");
return -1; ann_data_stat.no_typeinfo++;
return -1;
}
} }
/* Get the size of the actual type */ /* Get the size of the actual type */
...@@ -234,7 +239,7 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset) ...@@ -234,7 +239,7 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset)
} }
/* The result will be saved in @type_die */ /* The result will be saved in @type_die */
static int find_data_type_die(struct debuginfo *di, u64 pc, static int find_data_type_die(struct debuginfo *di, u64 pc, u64 addr,
struct annotated_op_loc *loc, Dwarf_Die *type_die) struct annotated_op_loc *loc, Dwarf_Die *type_die)
{ {
Dwarf_Die cu_die, var_die; Dwarf_Die cu_die, var_die;
...@@ -250,21 +255,36 @@ static int find_data_type_die(struct debuginfo *di, u64 pc, ...@@ -250,21 +255,36 @@ static int find_data_type_die(struct debuginfo *di, u64 pc,
return -1; return -1;
} }
/* Get a list of nested scopes - i.e. (inlined) functions and blocks. */
nr_scopes = die_get_scopes(&cu_die, pc, &scopes);
reg = loc->reg1; reg = loc->reg1;
offset = loc->offset; offset = loc->offset;
if (reg == DWARF_REG_PC &&
die_find_variable_by_addr(&cu_die, pc, addr, &var_die, &offset)) {
ret = check_variable(&var_die, type_die, offset,
/*is_pointer=*/false);
goto out;
}
/* Get a list of nested scopes - i.e. (inlined) functions and blocks. */
nr_scopes = die_get_scopes(&cu_die, pc, &scopes);
retry: retry:
/* Search from the inner-most scope to the outer */ /* Search from the inner-most scope to the outer */
for (i = nr_scopes - 1; i >= 0; i--) { for (i = nr_scopes - 1; i >= 0; i--) {
/* Look up variables/parameters in this scope */ if (reg == DWARF_REG_PC) {
if (!die_find_variable_by_reg(&scopes[i], pc, reg, &var_die)) if (!die_find_variable_by_addr(&scopes[i], pc, addr,
continue; &var_die, &offset))
continue;
} else {
/* Look up variables/parameters in this scope */
if (!die_find_variable_by_reg(&scopes[i], pc, reg,
&var_die))
continue;
}
/* Found a variable, see if it's correct */ /* Found a variable, see if it's correct */
ret = check_variable(&var_die, type_die, offset); ret = check_variable(&var_die, type_die, offset,
reg != DWARF_REG_PC);
goto out; goto out;
} }
...@@ -312,7 +332,7 @@ struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip, ...@@ -312,7 +332,7 @@ struct annotated_data_type *find_data_type(struct map_symbol *ms, u64 ip,
* a file address for DWARF processing. * a file address for DWARF processing.
*/ */
pc = map__rip_2objdump(ms->map, ip); pc = map__rip_2objdump(ms->map, ip);
if (find_data_type_die(di, pc, loc, &type_die) < 0) if (find_data_type_die(di, pc, 0, loc, &type_die) < 0)
goto out; goto out;
result = dso__findnew_data_type(dso, &type_die); result = dso__findnew_data_type(dso, &type_die);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment