Skip to content

Commit 61a9741

Browse files
namhyungacmel
authored andcommitted
perf annotate: Add --type-stat option for debugging
The --type-stat option is to be used with --data-type and to print detailed failure reasons for the data type annotation. $ perf annotate --data-type --type-stat Annotate data type stats: total 294, ok 116 (39.5%), bad 178 (60.5%) ----------------------------------------------------------- 30 : no_sym 40 : no_insn_ops 33 : no_mem_ops 63 : no_var 4 : no_typeinfo 8 : bad_offset Signed-off-by: Namhyung Kim <[email protected]> Tested-by: Arnaldo Carvalho de Melo <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Ian Rogers <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Masami Hiramatsu <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Stephane Eranian <[email protected]> Cc: [email protected] Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 227ad32 commit 61a9741

File tree

5 files changed

+108
-7
lines changed

5 files changed

+108
-7
lines changed

tools/perf/Documentation/perf-annotate.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ include::itrace.txt[]
162162
that case it'd show annotation for the type only, otherwise it'd show
163163
all data types it finds.
164164

165+
--type-stat::
166+
Show stats for the data type annotation.
167+
165168

166169
SEE ALSO
167170
--------

tools/perf/builtin-annotate.c

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ struct perf_annotate {
5757
bool has_br_stack;
5858
bool group_set;
5959
bool data_type;
60+
bool type_stat;
6061
float min_percent;
6162
const char *sym_hist_filter;
6263
const char *cpu_list;
@@ -396,13 +397,53 @@ static void print_annotated_data_type(struct annotated_data_type *mem_type,
396397
printf(";\n");
397398
}
398399

400+
static void print_annotate_data_stat(struct annotated_data_stat *s)
401+
{
402+
#define PRINT_STAT(fld) if (s->fld) printf("%10d : %s\n", s->fld, #fld)
403+
404+
int bad = s->no_sym +
405+
s->no_insn +
406+
s->no_insn_ops +
407+
s->no_mem_ops +
408+
s->no_reg +
409+
s->no_dbginfo +
410+
s->no_cuinfo +
411+
s->no_var +
412+
s->no_typeinfo +
413+
s->invalid_size +
414+
s->bad_offset;
415+
int ok = s->total - bad;
416+
417+
printf("Annotate data type stats:\n");
418+
printf("total %d, ok %d (%.1f%%), bad %d (%.1f%%)\n",
419+
s->total, ok, 100.0 * ok / (s->total ?: 1), bad, 100.0 * bad / (s->total ?: 1));
420+
printf("-----------------------------------------------------------\n");
421+
PRINT_STAT(no_sym);
422+
PRINT_STAT(no_insn);
423+
PRINT_STAT(no_insn_ops);
424+
PRINT_STAT(no_mem_ops);
425+
PRINT_STAT(no_reg);
426+
PRINT_STAT(no_dbginfo);
427+
PRINT_STAT(no_cuinfo);
428+
PRINT_STAT(no_var);
429+
PRINT_STAT(no_typeinfo);
430+
PRINT_STAT(invalid_size);
431+
PRINT_STAT(bad_offset);
432+
printf("\n");
433+
434+
#undef PRINT_STAT
435+
}
436+
399437
static void hists__find_annotations(struct hists *hists,
400438
struct evsel *evsel,
401439
struct perf_annotate *ann)
402440
{
403441
struct rb_node *nd = rb_first_cached(&hists->entries), *next;
404442
int key = K_RIGHT;
405443

444+
if (ann->type_stat)
445+
print_annotate_data_stat(&ann_data_stat);
446+
406447
while (nd) {
407448
struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
408449
struct annotation *notes;
@@ -749,7 +790,8 @@ int cmd_annotate(int argc, const char **argv)
749790
OPT_CALLBACK_OPTARG(0, "data-type", &annotate, NULL, "name",
750791
"Show data type annotate for the memory accesses",
751792
parse_data_type),
752-
793+
OPT_BOOLEAN(0, "type-stat", &annotate.type_stat,
794+
"Show stats for the data type annotation"),
753795
OPT_END()
754796
};
755797
int ret;

tools/perf/util/annotate-data.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset)
199199
/* Get the type of the variable */
200200
if (die_get_real_type(var_die, type_die) == NULL) {
201201
pr_debug("variable has no type\n");
202+
ann_data_stat.no_typeinfo++;
202203
return -1;
203204
}
204205

@@ -209,18 +210,21 @@ static int check_variable(Dwarf_Die *var_die, Dwarf_Die *type_die, int offset)
209210
if (dwarf_tag(type_die) != DW_TAG_pointer_type ||
210211
die_get_real_type(type_die, type_die) == NULL) {
211212
pr_debug("no pointer or no type\n");
213+
ann_data_stat.no_typeinfo++;
212214
return -1;
213215
}
214216

215217
/* Get the size of the actual type */
216218
if (dwarf_aggregate_size(type_die, &size) < 0) {
217219
pr_debug("type size is unknown\n");
220+
ann_data_stat.invalid_size++;
218221
return -1;
219222
}
220223

221224
/* Minimal sanity check */
222225
if ((unsigned)offset >= size) {
223226
pr_debug("offset: %d is bigger than size: %" PRIu64 "\n", offset, size);
227+
ann_data_stat.bad_offset++;
224228
return -1;
225229
}
226230

@@ -239,6 +243,7 @@ static int find_data_type_die(struct debuginfo *di, u64 pc,
239243
/* Get a compile_unit for this address */
240244
if (!find_cu_die(di, pc, &cu_die)) {
241245
pr_debug("cannot find CU for address %" PRIx64 "\n", pc);
246+
ann_data_stat.no_cuinfo++;
242247
return -1;
243248
}
244249

@@ -253,9 +258,12 @@ static int find_data_type_die(struct debuginfo *di, u64 pc,
253258

254259
/* Found a variable, see if it's correct */
255260
ret = check_variable(&var_die, type_die, offset);
256-
break;
261+
goto out;
257262
}
263+
if (ret < 0)
264+
ann_data_stat.no_var++;
258265

266+
out:
259267
free(scopes);
260268
return ret;
261269
}

tools/perf/util/annotate-data.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,37 @@ struct annotated_data_type {
7070

7171
extern struct annotated_data_type unknown_type;
7272

73+
/**
74+
* struct annotated_data_stat - Debug statistics
75+
* @total: Total number of entry
76+
* @no_sym: No symbol or map found
77+
* @no_insn: Failed to get disasm line
78+
* @no_insn_ops: The instruction has no operands
79+
* @no_mem_ops: The instruction has no memory operands
80+
* @no_reg: Failed to extract a register from the operand
81+
* @no_dbginfo: The binary has no debug information
82+
* @no_cuinfo: Failed to find a compile_unit
83+
* @no_var: Failed to find a matching variable
84+
* @no_typeinfo: Failed to get a type info for the variable
85+
* @invalid_size: Failed to get a size info of the type
86+
* @bad_offset: The access offset is out of the type
87+
*/
88+
struct annotated_data_stat {
89+
int total;
90+
int no_sym;
91+
int no_insn;
92+
int no_insn_ops;
93+
int no_mem_ops;
94+
int no_reg;
95+
int no_dbginfo;
96+
int no_cuinfo;
97+
int no_var;
98+
int no_typeinfo;
99+
int invalid_size;
100+
int bad_offset;
101+
};
102+
extern struct annotated_data_stat ann_data_stat;
103+
73104
#ifdef HAVE_DWARF_SUPPORT
74105

75106
/* Returns data type at the location (ip, reg, offset) */

tools/perf/util/annotate.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ static struct ins_ops nop_ops;
103103
static struct ins_ops lock_ops;
104104
static struct ins_ops ret_ops;
105105

106+
/* Data type collection debug statistics */
107+
struct annotated_data_stat ann_data_stat;
108+
106109
static int arch__grow_instructions(struct arch *arch)
107110
{
108111
struct ins *new_instructions;
@@ -3683,14 +3686,22 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he)
36833686
u64 ip = he->ip;
36843687
int i;
36853688

3686-
if (ms->map == NULL || ms->sym == NULL)
3689+
ann_data_stat.total++;
3690+
3691+
if (ms->map == NULL || ms->sym == NULL) {
3692+
ann_data_stat.no_sym++;
36873693
return NULL;
3694+
}
36883695

3689-
if (!symbol_conf.init_annotation)
3696+
if (!symbol_conf.init_annotation) {
3697+
ann_data_stat.no_sym++;
36903698
return NULL;
3699+
}
36913700

3692-
if (evsel__get_arch(evsel, &arch) < 0)
3701+
if (evsel__get_arch(evsel, &arch) < 0) {
3702+
ann_data_stat.no_insn++;
36933703
return NULL;
3704+
}
36943705

36953706
/* Make sure it runs objdump to get disasm of the function */
36963707
symbol__ensure_annotate(ms, evsel);
@@ -3700,11 +3711,15 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he)
37003711
* This is too slow...
37013712
*/
37023713
dl = find_disasm_line(ms->sym, ip);
3703-
if (dl == NULL)
3714+
if (dl == NULL) {
3715+
ann_data_stat.no_insn++;
37043716
return NULL;
3717+
}
37053718

3706-
if (annotate_get_insn_location(arch, dl, &loc) < 0)
3719+
if (annotate_get_insn_location(arch, dl, &loc) < 0) {
3720+
ann_data_stat.no_insn_ops++;
37073721
return NULL;
3722+
}
37083723

37093724
for_each_insn_op_loc(&loc, i, op_loc) {
37103725
if (!op_loc->mem_ref)
@@ -3721,5 +3736,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he)
37213736
he->mem_type_off = op_loc->offset;
37223737
return mem_type;
37233738
}
3739+
3740+
ann_data_stat.no_mem_ops++;
37243741
return NULL;
37253742
}

0 commit comments

Comments
 (0)