diff options
author | Namhyung Kim <namhyung@kernel.org> | 2024-08-17 02:58:35 +0300 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2024-08-19 17:37:52 +0300 |
commit | 69e2c78425c92361f0ab01cbbb8f3a44fc94341f (patch) | |
tree | 187340f796fea251d1960815a19e2f363583a76b /tools | |
parent | 653185d808ea6f5e3e6247087b793fcd8510bb26 (diff) | |
download | linux-69e2c78425c92361f0ab01cbbb8f3a44fc94341f.tar.xz |
perf annotate-data: Change return type of find_data_type_block()
So that it can return enum variable_match_type to be propagated to the
find_data_type_die(). Also update the debug message to show the result
of the check_matching_type().
chk [dd] reg0 offset=0 ok=1 kind=1 : Good!
or
chk [177] reg4 offset=0x138 ok=0 kind=0 cfa : no type information
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20240816235840.2754937-6-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/util/annotate-data.c | 117 |
1 files changed, 58 insertions, 59 deletions
diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c index 332254da49be..5548cd8e84ba 100644 --- a/tools/perf/util/annotate-data.c +++ b/tools/perf/util/annotate-data.c @@ -352,6 +352,7 @@ enum type_match_result { PERF_TMR_NO_POINTER, PERF_TMR_NO_SIZE, PERF_TMR_BAD_OFFSET, + PERF_TMR_BAIL_OUT, }; static const char *match_result_str(enum type_match_result tmr) @@ -368,6 +369,7 @@ static const char *match_result_str(enum type_match_result tmr) case PERF_TMR_BAD_OFFSET: return "offset bigger than size"; case PERF_TMR_UNKNOWN: + case PERF_TMR_BAIL_OUT: default: return "invalid state"; } @@ -868,19 +870,19 @@ static void setup_stack_canary(struct data_loc_info *dloc) /* * It's at the target address, check if it has a matching type. - * It returns 1 if found, 0 if not or -1 if not found but no need to - * repeat the search. The last case is for per-cpu variables which + * It returns PERF_TMR_BAIL_OUT when it looks up per-cpu variables which * are similar to global variables and no additional info is needed. */ -static int check_matching_type(struct type_state *state, - struct data_loc_info *dloc, - Dwarf_Die *cu_die, Dwarf_Die *type_die) +static enum type_match_result check_matching_type(struct type_state *state, + struct data_loc_info *dloc, + Dwarf_Die *cu_die, + Dwarf_Die *type_die) { Dwarf_Word size; u32 insn_offset = dloc->ip - dloc->ms->sym->start; int reg = dloc->op->reg1; - pr_debug_dtp("chk [%x] reg%d offset=%#x ok=%d kind=%d", + pr_debug_dtp("chk [%x] reg%d offset=%#x ok=%d kind=%d ", insn_offset, reg, dloc->op->offset, state->regs[reg].ok, state->regs[reg].kind); @@ -896,15 +898,12 @@ static int check_matching_type(struct type_state *state, if (dloc->op->offset < 0 && reg != state->stack_reg) goto check_kernel; - pr_debug_dtp("\n"); - return -1; + return PERF_TMR_NO_POINTER; } - pr_debug_dtp("\n"); - /* Remove the pointer and get the target type */ if (__die_get_real_type(&state->regs[reg].type, type_die) == NULL) - return -1; + return PERF_TMR_NO_POINTER; dloc->type_offset = dloc->op->offset; @@ -916,33 +915,33 @@ static int check_matching_type(struct type_state *state, /* Get the size of the actual type */ if (dwarf_aggregate_size(&sized_type, &size) < 0 || (unsigned)dloc->type_offset >= size) - return -1; + return PERF_TMR_BAD_OFFSET; - return 1; + return PERF_TMR_OK; } if (reg == dloc->fbreg) { struct type_state_stack *stack; - pr_debug_dtp(" fbreg\n"); + pr_debug_dtp("fbreg"); stack = find_stack_state(state, dloc->type_offset); if (stack == NULL) - return 0; + return PERF_TMR_NO_TYPE; if (stack->kind == TSR_KIND_CANARY) { setup_stack_canary(dloc); - return -1; + return PERF_TMR_BAIL_OUT; } if (stack->kind != TSR_KIND_TYPE) - return 0; + return PERF_TMR_NO_TYPE; *type_die = stack->type; /* Update the type offset from the start of slot */ dloc->type_offset -= stack->offset; - return 1; + return PERF_TMR_OK; } if (dloc->fb_cfa) { @@ -950,38 +949,38 @@ static int check_matching_type(struct type_state *state, u64 pc = map__rip_2objdump(dloc->ms->map, dloc->ip); int fbreg, fboff; - pr_debug_dtp(" cfa\n"); + pr_debug_dtp("cfa"); if (die_get_cfa(dloc->di->dbg, pc, &fbreg, &fboff) < 0) fbreg = -1; if (reg != fbreg) - return 0; + return PERF_TMR_NO_TYPE; stack = find_stack_state(state, dloc->type_offset - fboff); if (stack == NULL) - return 0; + return PERF_TMR_NO_TYPE; if (stack->kind == TSR_KIND_CANARY) { setup_stack_canary(dloc); - return -1; + return PERF_TMR_BAIL_OUT; } if (stack->kind != TSR_KIND_TYPE) - return 0; + return PERF_TMR_NO_TYPE; *type_die = stack->type; /* Update the type offset from the start of slot */ dloc->type_offset -= fboff + stack->offset; - return 1; + return PERF_TMR_OK; } if (state->regs[reg].kind == TSR_KIND_PERCPU_BASE) { u64 var_addr = dloc->op->offset; int var_offset; - pr_debug_dtp(" percpu var\n"); + pr_debug_dtp("percpu var"); if (dloc->op->multi_regs) { int reg2 = dloc->op->reg2; @@ -997,14 +996,14 @@ static int check_matching_type(struct type_state *state, if (get_global_var_type(cu_die, dloc, dloc->ip, var_addr, &var_offset, type_die)) { dloc->type_offset = var_offset; - return 1; + return PERF_TMR_OK; } /* No need to retry per-cpu (global) variables */ - return -1; + return PERF_TMR_BAIL_OUT; } if (state->regs[reg].ok && state->regs[reg].kind == TSR_KIND_POINTER) { - pr_debug_dtp(" percpu ptr\n"); + pr_debug_dtp("percpu ptr"); /* * It's actaully pointer but the address was calculated using @@ -1017,13 +1016,13 @@ static int check_matching_type(struct type_state *state, /* Get the size of the actual type */ if (dwarf_aggregate_size(type_die, &size) < 0 || (unsigned)dloc->type_offset >= size) - return -1; + return PERF_TMR_BAIL_OUT; - return 1; + return PERF_TMR_OK; } if (state->regs[reg].ok && state->regs[reg].kind == TSR_KIND_CANARY) { - pr_debug_dtp(" stack canary\n"); + pr_debug_dtp("stack canary"); /* * This is a saved value of the stack canary which will be handled @@ -1032,7 +1031,7 @@ static int check_matching_type(struct type_state *state, */ setup_stack_canary(dloc); - return -1; + return PERF_TMR_BAIL_OUT; } check_kernel: @@ -1043,16 +1042,16 @@ check_kernel: /* Direct this-cpu access like "%gs:0x34740" */ if (dloc->op->segment == INSN_SEG_X86_GS && dloc->op->imm && arch__is(dloc->arch, "x86")) { - pr_debug_dtp(" this-cpu var\n"); + pr_debug_dtp("this-cpu var"); addr = dloc->op->offset; if (get_global_var_type(cu_die, dloc, dloc->ip, addr, &offset, type_die)) { dloc->type_offset = offset; - return 1; + return PERF_TMR_OK; } - return -1; + return PERF_TMR_BAIL_OUT; } /* Access to global variable like "-0x7dcf0500(,%rdx,8)" */ @@ -1061,31 +1060,30 @@ check_kernel: if (get_global_var_type(cu_die, dloc, dloc->ip, addr, &offset, type_die)) { - pr_debug_dtp(" global var\n"); + pr_debug_dtp("global var"); dloc->type_offset = offset; - return 1; + return PERF_TMR_OK; } - pr_debug_dtp(" negative offset\n"); - return -1; + return PERF_TMR_BAIL_OUT; } } - pr_debug_dtp("\n"); - return 0; + return PERF_TMR_UNKNOWN; } /* Iterate instructions in basic blocks and update type table */ -static int find_data_type_insn(struct data_loc_info *dloc, - struct list_head *basic_blocks, - struct die_var_type *var_types, - Dwarf_Die *cu_die, Dwarf_Die *type_die) +static enum type_match_result find_data_type_insn(struct data_loc_info *dloc, + struct list_head *basic_blocks, + struct die_var_type *var_types, + Dwarf_Die *cu_die, + Dwarf_Die *type_die) { struct type_state state; struct symbol *sym = dloc->ms->sym; struct annotation *notes = symbol__annotation(sym); struct annotated_basic_block *bb; - int ret = 0; + enum type_match_result ret = PERF_TMR_UNKNOWN; init_type_state(&state, dloc->arch); @@ -1111,6 +1109,7 @@ static int find_data_type_insn(struct data_loc_info *dloc, if (this_ip == dloc->ip) { ret = check_matching_type(&state, dloc, cu_die, type_die); + pr_debug_dtp(" : %s\n", match_result_str(ret)); goto out; } @@ -1137,24 +1136,25 @@ static int arch_supports_insn_tracking(struct data_loc_info *dloc) * Construct a list of basic blocks for each scope with variables and try to find * the data type by updating a type state table through instructions. */ -static int find_data_type_block(struct data_loc_info *dloc, - Dwarf_Die *cu_die, Dwarf_Die *scopes, - int nr_scopes, Dwarf_Die *type_die) +static enum type_match_result find_data_type_block(struct data_loc_info *dloc, + Dwarf_Die *cu_die, + Dwarf_Die *scopes, + int nr_scopes, + Dwarf_Die *type_die) { LIST_HEAD(basic_blocks); struct die_var_type *var_types = NULL; u64 src_ip, dst_ip, prev_dst_ip; - int ret = -1; + enum type_match_result ret = PERF_TMR_UNKNOWN; /* TODO: other architecture support */ if (!arch_supports_insn_tracking(dloc)) - return -1; + return PERF_TMR_BAIL_OUT; prev_dst_ip = dst_ip = dloc->ip; for (int i = nr_scopes - 1; i >= 0; i--) { Dwarf_Addr base, start, end; LIST_HEAD(this_blocks); - int found; if (dwarf_ranges(&scopes[i], 0, &base, &start, &end) < 0) break; @@ -1185,9 +1185,9 @@ again: fixup_var_address(var_types, start); /* Find from start of this scope to the target instruction */ - found = find_data_type_insn(dloc, &basic_blocks, var_types, + ret = find_data_type_insn(dloc, &basic_blocks, var_types, cu_die, type_die); - if (found > 0) { + if (ret == PERF_TMR_OK) { char buf[64]; if (dloc->op->multi_regs) @@ -1199,11 +1199,10 @@ again: pr_debug_dtp("found by insn track: %#x(%s) type-offset=%#x\n", dloc->op->offset, buf, dloc->type_offset); pr_debug_type_name(type_die, TSR_KIND_TYPE); - ret = 0; break; } - if (found < 0) + if (ret == PERF_TMR_BAIL_OUT) break; /* Go up to the next scope and find blocks to the start */ @@ -1357,11 +1356,11 @@ retry: } if (reg != DWARF_REG_PC) { - ret = find_data_type_block(dloc, &cu_die, scopes, + result = find_data_type_block(dloc, &cu_die, scopes, nr_scopes, type_die); - if (ret == 0) { + if (result == PERF_TMR_OK) { ann_data_stat.insn_track++; - goto out; + ret = 0; } } |