perf annotate-data: Show typedef names properly
The die_get_typename() would resolve typedef and get to the original
type. But sometimes the original type is a struct without name and it
makes the output confusing and hard to read.
This is a diff of perf report -s type before and after the change.
New types such as atomic{,64}_t and sigset_t appeared and the portion
of unnamed struct was reduced. Also u32, u64 and size_t were splitted
from the base types.
--- b 2024-08-01 17:02:34.307809952 -0700
+++ a 2024-08-07 14:17:05.245853999 -0700
- 2.40% long unsigned int
+ 2.26% long unsigned int
- 1.56% unsigned int
+ 1.27% unsigned int
- 0.98% struct
- 0.79% long long unsigned int
+ 0.58% long long unsigned int
+ 0.36% struct
+ 0.27% atomic64_t
+ 0.22% u32
+ 0.21% u64
+ 0.19% atomic_t
+ 0.13% size_t
- 0.08% struct seqcount_spinlock
+ 0.08% seqcount_spinlock_t
+ 0.08% sigset_t
+ 0.08% __poll_t
Let's use the typedef name directly and the resolved to get the size of
the type.
Committer testing:
root@x1:~# diff -u before after | head -30
--- before 2024-08-08 09:35:13.917325041 -0300
+++ after 2024-08-08 09:37:35.312257905 -0300
@@ -10,25 +10,27 @@
# ........ .........
#
79.40% (unknown)
- 2.28% union
1.96% (stack operation)
- 1.24% struct
+ 1.87% pthread_mutex_t
0.99% u32[]
- 0.92% unsigned int
0.77% struct task_struct
+ 0.75% U32
0.75% struct pcpu_hot
0.63% struct qspinlock
+ 0.61% atomic_t
0.59% struct list_head
- 0.58% int
0.53% struct cfs_rq
0.51% BYTE*
- 0.48% unsigned char
+ 0.48% BYTE
0.48% long unsigned int
0.46% struct rq
0.41% struct worker
0.41% struct memcg_vmstats_percpu
+ 0.41% pthread_cond_t
0.37% _Bool
+ 0.36% int
root@x1:~#
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
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: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20240807223129.1738004-1-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
committed by
Arnaldo Carvalho de Melo
parent
037f1b67e8
commit
90d78e7b8e
@@ -217,8 +217,13 @@ static int __add_member_cb(Dwarf_Die *die, void *arg)
|
||||
strbuf_init(&sb, 32);
|
||||
die_get_typename(die, &sb);
|
||||
|
||||
die_get_real_type(die, &member_type);
|
||||
if (dwarf_aggregate_size(&member_type, &size) < 0)
|
||||
__die_get_real_type(die, &member_type);
|
||||
if (dwarf_tag(&member_type) == DW_TAG_typedef)
|
||||
die_get_real_type(&member_type, &die_mem);
|
||||
else
|
||||
die_mem = member_type;
|
||||
|
||||
if (dwarf_aggregate_size(&die_mem, &size) < 0)
|
||||
size = 0;
|
||||
|
||||
if (!dwarf_attr_integrate(die, DW_AT_data_member_location, &attr))
|
||||
@@ -235,11 +240,11 @@ static int __add_member_cb(Dwarf_Die *die, void *arg)
|
||||
INIT_LIST_HEAD(&member->children);
|
||||
list_add_tail(&member->node, &parent->children);
|
||||
|
||||
tag = dwarf_tag(&member_type);
|
||||
tag = dwarf_tag(&die_mem);
|
||||
switch (tag) {
|
||||
case DW_TAG_structure_type:
|
||||
case DW_TAG_union_type:
|
||||
die_find_child(&member_type, __add_member_cb, member, &die_mem);
|
||||
die_find_child(&die_mem, __add_member_cb, member, &die_mem);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -281,6 +286,10 @@ static struct annotated_data_type *dso__findnew_data_type(struct dso *dso,
|
||||
if (die_get_typename_from_type(type_die, &sb) < 0)
|
||||
strbuf_add(&sb, "(unknown type)", 14);
|
||||
type_name = strbuf_detach(&sb, NULL);
|
||||
|
||||
if (dwarf_tag(type_die) == DW_TAG_typedef)
|
||||
die_get_real_type(type_die, type_die);
|
||||
|
||||
dwarf_aggregate_size(type_die, &size);
|
||||
|
||||
/* Check existing nodes in dso->data_types tree */
|
||||
@@ -342,6 +351,7 @@ static int check_variable(struct data_loc_info *dloc, Dwarf_Die *var_die,
|
||||
{
|
||||
Dwarf_Word size;
|
||||
bool is_pointer = true;
|
||||
Dwarf_Die sized_type;
|
||||
|
||||
if (reg == DWARF_REG_PC)
|
||||
is_pointer = false;
|
||||
@@ -351,7 +361,7 @@ static int check_variable(struct data_loc_info *dloc, Dwarf_Die *var_die,
|
||||
is_pointer = false;
|
||||
|
||||
/* Get the type of the variable */
|
||||
if (die_get_real_type(var_die, type_die) == NULL) {
|
||||
if (__die_get_real_type(var_die, type_die) == NULL) {
|
||||
pr_debug_dtp("variable has no type\n");
|
||||
ann_data_stat.no_typeinfo++;
|
||||
return -1;
|
||||
@@ -365,15 +375,20 @@ static int check_variable(struct data_loc_info *dloc, Dwarf_Die *var_die,
|
||||
if (is_pointer) {
|
||||
if ((dwarf_tag(type_die) != DW_TAG_pointer_type &&
|
||||
dwarf_tag(type_die) != DW_TAG_array_type) ||
|
||||
die_get_real_type(type_die, type_die) == NULL) {
|
||||
__die_get_real_type(type_die, type_die) == NULL) {
|
||||
pr_debug_dtp("no pointer or no type\n");
|
||||
ann_data_stat.no_typeinfo++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dwarf_tag(type_die) == DW_TAG_typedef)
|
||||
die_get_real_type(type_die, &sized_type);
|
||||
else
|
||||
sized_type = *type_die;
|
||||
|
||||
/* Get the size of the actual type */
|
||||
if (dwarf_aggregate_size(type_die, &size) < 0) {
|
||||
if (dwarf_aggregate_size(&sized_type, &size) < 0) {
|
||||
pr_debug_dtp("type size is unknown\n");
|
||||
ann_data_stat.invalid_size++;
|
||||
return -1;
|
||||
@@ -846,6 +861,7 @@ static int check_matching_type(struct type_state *state,
|
||||
|
||||
if (state->regs[reg].ok && state->regs[reg].kind == TSR_KIND_TYPE) {
|
||||
int tag = dwarf_tag(&state->regs[reg].type);
|
||||
Dwarf_Die sized_type;
|
||||
|
||||
/*
|
||||
* Normal registers should hold a pointer (or array) to
|
||||
@@ -862,13 +878,18 @@ static int check_matching_type(struct type_state *state,
|
||||
pr_debug_dtp("\n");
|
||||
|
||||
/* Remove the pointer and get the target type */
|
||||
if (die_get_real_type(&state->regs[reg].type, type_die) == NULL)
|
||||
if (__die_get_real_type(&state->regs[reg].type, type_die) == NULL)
|
||||
return -1;
|
||||
|
||||
dloc->type_offset = dloc->op->offset;
|
||||
|
||||
if (dwarf_tag(type_die) == DW_TAG_typedef)
|
||||
die_get_real_type(type_die, &sized_type);
|
||||
else
|
||||
sized_type = *type_die;
|
||||
|
||||
/* Get the size of the actual type */
|
||||
if (dwarf_aggregate_size(type_die, &size) < 0 ||
|
||||
if (dwarf_aggregate_size(&sized_type, &size) < 0 ||
|
||||
(unsigned)dloc->type_offset >= size)
|
||||
return -1;
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@ Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
|
||||
}
|
||||
|
||||
/* Get a type die, but skip qualifiers */
|
||||
static Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
|
||||
Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
|
||||
{
|
||||
int tag;
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ const char *die_get_decl_file(Dwarf_Die *dw_die);
|
||||
/* Get type die */
|
||||
Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem);
|
||||
|
||||
/* Get a type die, but skip qualifiers */
|
||||
Dwarf_Die *__die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem);
|
||||
/* Get a type die, but skip qualifiers and typedef */
|
||||
Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user