mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-07-18 23:29:57 +02:00
perf annotate-data: Add get_global_var_type()
Accessing global variable is common when it tracks execution later. Factor out the common code into a function for later use. It adds thread and cpumode to struct data_loc_info to find (global) symbols if needed. Also remove var_name as it's retrieved in the helper function. Signed-off-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: https://lore.kernel.org/r/20240319055115.4063940-12-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
4f903455be
commit
1ebb5e17ef
|
@ -22,6 +22,7 @@
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
#include "symbol.h"
|
#include "symbol.h"
|
||||||
#include "symbol_conf.h"
|
#include "symbol_conf.h"
|
||||||
|
#include "thread.h"
|
||||||
|
|
||||||
#define pr_debug_dtp(fmt, ...) \
|
#define pr_debug_dtp(fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -382,6 +383,50 @@ static struct type_state_stack *findnew_stack_state(struct type_state *state,
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool get_global_var_type(Dwarf_Die *cu_die, struct data_loc_info *dloc,
|
||||||
|
u64 ip, u64 var_addr, int *var_offset,
|
||||||
|
Dwarf_Die *type_die)
|
||||||
|
{
|
||||||
|
u64 pc, mem_addr;
|
||||||
|
int offset;
|
||||||
|
bool is_pointer = false;
|
||||||
|
const char *var_name = NULL;
|
||||||
|
Dwarf_Die var_die;
|
||||||
|
struct addr_location al;
|
||||||
|
struct symbol *sym;
|
||||||
|
|
||||||
|
/* Try to get the variable by address first */
|
||||||
|
if (die_find_variable_by_addr(cu_die, var_addr, &var_die, &offset) &&
|
||||||
|
check_variable(&var_die, type_die, offset, is_pointer) == 0) {
|
||||||
|
*var_offset = offset;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Kernel symbols might be relocated */
|
||||||
|
mem_addr = var_addr + map__reloc(dloc->ms->map);
|
||||||
|
|
||||||
|
addr_location__init(&al);
|
||||||
|
sym = thread__find_symbol_fb(dloc->thread, dloc->cpumode,
|
||||||
|
mem_addr, &al);
|
||||||
|
if (sym) {
|
||||||
|
var_name = sym->name;
|
||||||
|
/* Calculate type offset from the start of variable */
|
||||||
|
*var_offset = mem_addr - map__unmap_ip(al.map, sym->start);
|
||||||
|
}
|
||||||
|
addr_location__exit(&al);
|
||||||
|
if (var_name == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pc = map__rip_2objdump(dloc->ms->map, ip);
|
||||||
|
|
||||||
|
/* Try to get the name of global variable */
|
||||||
|
if (die_find_variable_at(cu_die, var_name, pc, &var_die) &&
|
||||||
|
check_variable(&var_die, type_die, *var_offset, is_pointer) == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* update_var_state - Update type state using given variables
|
* update_var_state - Update type state using given variables
|
||||||
* @state: type state table
|
* @state: type state table
|
||||||
|
@ -637,24 +682,14 @@ static int find_data_type_die(struct data_loc_info *dloc, Dwarf_Die *type_die)
|
||||||
pr_debug_dtp("CU die offset: %#lx\n", (long)dwarf_dieoffset(&cu_die));
|
pr_debug_dtp("CU die offset: %#lx\n", (long)dwarf_dieoffset(&cu_die));
|
||||||
|
|
||||||
if (reg == DWARF_REG_PC) {
|
if (reg == DWARF_REG_PC) {
|
||||||
if (die_find_variable_by_addr(&cu_die, dloc->var_addr, &var_die,
|
if (get_global_var_type(&cu_die, dloc, dloc->ip, dloc->var_addr,
|
||||||
&offset)) {
|
&offset, type_die)) {
|
||||||
ret = check_variable(&var_die, type_die, offset,
|
|
||||||
/*is_pointer=*/false);
|
|
||||||
dloc->type_offset = offset;
|
dloc->type_offset = offset;
|
||||||
|
|
||||||
pr_debug_dtp("found PC-rel by addr=%#"PRIx64" offset=%#x\n",
|
pr_debug_dtp("found PC-rel by addr=%#"PRIx64" offset=%#x\n",
|
||||||
dloc->var_addr, offset);
|
dloc->var_addr, offset);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dloc->var_name &&
|
|
||||||
die_find_variable_at(&cu_die, dloc->var_name, pc, &var_die)) {
|
|
||||||
ret = check_variable(&var_die, type_die, dloc->type_offset,
|
|
||||||
/*is_pointer=*/false);
|
|
||||||
/* dloc->type_offset was updated by the caller */
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a list of nested scopes - i.e. (inlined) functions and blocks. */
|
/* Get a list of nested scopes - i.e. (inlined) functions and blocks. */
|
||||||
|
@ -769,7 +804,6 @@ struct annotated_data_type *find_data_type(struct data_loc_info *dloc)
|
||||||
* The type offset is the same as instruction offset by default.
|
* The type offset is the same as instruction offset by default.
|
||||||
* But when finding a global variable, the offset won't be valid.
|
* But when finding a global variable, the offset won't be valid.
|
||||||
*/
|
*/
|
||||||
if (dloc->var_name == NULL)
|
|
||||||
dloc->type_offset = dloc->op->offset;
|
dloc->type_offset = dloc->op->offset;
|
||||||
|
|
||||||
dloc->fbreg = -1;
|
dloc->fbreg = -1;
|
||||||
|
|
|
@ -11,6 +11,7 @@ struct annotated_op_loc;
|
||||||
struct debuginfo;
|
struct debuginfo;
|
||||||
struct evsel;
|
struct evsel;
|
||||||
struct map_symbol;
|
struct map_symbol;
|
||||||
|
struct thread;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct annotated_member - Type of member field
|
* struct annotated_member - Type of member field
|
||||||
|
@ -76,10 +77,11 @@ extern struct annotated_data_type stackop_type;
|
||||||
/**
|
/**
|
||||||
* struct data_loc_info - Data location information
|
* struct data_loc_info - Data location information
|
||||||
* @arch: CPU architecture info
|
* @arch: CPU architecture info
|
||||||
|
* @thread: Thread info
|
||||||
* @ms: Map and Symbol info
|
* @ms: Map and Symbol info
|
||||||
* @ip: Instruction address
|
* @ip: Instruction address
|
||||||
* @var_addr: Data address (for global variables)
|
* @var_addr: Data address (for global variables)
|
||||||
* @var_name: Variable name (for global variables)
|
* @cpumode: CPU execution mode
|
||||||
* @op: Instruction operand location (regs and offset)
|
* @op: Instruction operand location (regs and offset)
|
||||||
* @di: Debug info
|
* @di: Debug info
|
||||||
* @fbreg: Frame base register
|
* @fbreg: Frame base register
|
||||||
|
@ -89,10 +91,11 @@ extern struct annotated_data_type stackop_type;
|
||||||
struct data_loc_info {
|
struct data_loc_info {
|
||||||
/* These are input field, should be filled by caller */
|
/* These are input field, should be filled by caller */
|
||||||
struct arch *arch;
|
struct arch *arch;
|
||||||
|
struct thread *thread;
|
||||||
struct map_symbol *ms;
|
struct map_symbol *ms;
|
||||||
u64 ip;
|
u64 ip;
|
||||||
u64 var_addr;
|
u64 var_addr;
|
||||||
const char *var_name;
|
u8 cpumode;
|
||||||
struct annotated_op_loc *op;
|
struct annotated_op_loc *op;
|
||||||
|
|
||||||
/* These are used internally */
|
/* These are used internally */
|
||||||
|
|
|
@ -3873,9 +3873,11 @@ retry:
|
||||||
for_each_insn_op_loc(&loc, i, op_loc) {
|
for_each_insn_op_loc(&loc, i, op_loc) {
|
||||||
struct data_loc_info dloc = {
|
struct data_loc_info dloc = {
|
||||||
.arch = arch,
|
.arch = arch,
|
||||||
|
.thread = he->thread,
|
||||||
.ms = ms,
|
.ms = ms,
|
||||||
/* Recalculate IP for LOCK prefix or insn fusion */
|
/* Recalculate IP for LOCK prefix or insn fusion */
|
||||||
.ip = ms->sym->start + dl->al.offset,
|
.ip = ms->sym->start + dl->al.offset,
|
||||||
|
.cpumode = he->cpumode,
|
||||||
.op = op_loc,
|
.op = op_loc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3887,23 +3889,8 @@ retry:
|
||||||
|
|
||||||
/* PC-relative addressing */
|
/* PC-relative addressing */
|
||||||
if (op_loc->reg1 == DWARF_REG_PC) {
|
if (op_loc->reg1 == DWARF_REG_PC) {
|
||||||
struct addr_location al;
|
dloc.var_addr = annotate_calc_pcrel(ms, dloc.ip,
|
||||||
struct symbol *var;
|
op_loc->offset, dl);
|
||||||
u64 map_addr;
|
|
||||||
|
|
||||||
dloc.var_addr = annotate_calc_pcrel(ms, ip, op_loc->offset, dl);
|
|
||||||
/* Kernel symbols might be relocated */
|
|
||||||
map_addr = dloc.var_addr + map__reloc(ms->map);
|
|
||||||
|
|
||||||
addr_location__init(&al);
|
|
||||||
var = thread__find_symbol_fb(he->thread, he->cpumode,
|
|
||||||
map_addr, &al);
|
|
||||||
if (var) {
|
|
||||||
dloc.var_name = var->name;
|
|
||||||
/* Calculate type offset from the start of variable */
|
|
||||||
dloc.type_offset = map_addr - map__unmap_ip(al.map, var->start);
|
|
||||||
}
|
|
||||||
addr_location__exit(&al);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_type = find_data_type(&dloc);
|
mem_type = find_data_type(&dloc);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user