Commit 90d78e7b authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo

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: default avatarNamhyung Kim <namhyung@kernel.org>
Tested-by: default avatarArnaldo 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.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 037f1b67
...@@ -217,8 +217,13 @@ static int __add_member_cb(Dwarf_Die *die, void *arg) ...@@ -217,8 +217,13 @@ static int __add_member_cb(Dwarf_Die *die, void *arg)
strbuf_init(&sb, 32); strbuf_init(&sb, 32);
die_get_typename(die, &sb); die_get_typename(die, &sb);
die_get_real_type(die, &member_type); __die_get_real_type(die, &member_type);
if (dwarf_aggregate_size(&member_type, &size) < 0) 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; size = 0;
if (!dwarf_attr_integrate(die, DW_AT_data_member_location, &attr)) 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) ...@@ -235,11 +240,11 @@ static int __add_member_cb(Dwarf_Die *die, void *arg)
INIT_LIST_HEAD(&member->children); INIT_LIST_HEAD(&member->children);
list_add_tail(&member->node, &parent->children); list_add_tail(&member->node, &parent->children);
tag = dwarf_tag(&member_type); tag = dwarf_tag(&die_mem);
switch (tag) { switch (tag) {
case DW_TAG_structure_type: case DW_TAG_structure_type:
case DW_TAG_union_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; break;
default: default:
break; break;
...@@ -281,6 +286,10 @@ static struct annotated_data_type *dso__findnew_data_type(struct dso *dso, ...@@ -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) if (die_get_typename_from_type(type_die, &sb) < 0)
strbuf_add(&sb, "(unknown type)", 14); strbuf_add(&sb, "(unknown type)", 14);
type_name = strbuf_detach(&sb, NULL); 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); dwarf_aggregate_size(type_die, &size);
/* Check existing nodes in dso->data_types tree */ /* 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, ...@@ -342,6 +351,7 @@ static int check_variable(struct data_loc_info *dloc, Dwarf_Die *var_die,
{ {
Dwarf_Word size; Dwarf_Word size;
bool is_pointer = true; bool is_pointer = true;
Dwarf_Die sized_type;
if (reg == DWARF_REG_PC) if (reg == DWARF_REG_PC)
is_pointer = false; is_pointer = false;
...@@ -351,7 +361,7 @@ static int check_variable(struct data_loc_info *dloc, Dwarf_Die *var_die, ...@@ -351,7 +361,7 @@ static int check_variable(struct data_loc_info *dloc, Dwarf_Die *var_die,
is_pointer = false; is_pointer = false;
/* Get the type of the variable */ /* 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"); pr_debug_dtp("variable has no type\n");
ann_data_stat.no_typeinfo++; ann_data_stat.no_typeinfo++;
return -1; return -1;
...@@ -365,15 +375,20 @@ static int check_variable(struct data_loc_info *dloc, Dwarf_Die *var_die, ...@@ -365,15 +375,20 @@ static int check_variable(struct data_loc_info *dloc, Dwarf_Die *var_die,
if (is_pointer) { if (is_pointer) {
if ((dwarf_tag(type_die) != DW_TAG_pointer_type && if ((dwarf_tag(type_die) != DW_TAG_pointer_type &&
dwarf_tag(type_die) != DW_TAG_array_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"); pr_debug_dtp("no pointer or no type\n");
ann_data_stat.no_typeinfo++; ann_data_stat.no_typeinfo++;
return -1; 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 */ /* 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"); pr_debug_dtp("type size is unknown\n");
ann_data_stat.invalid_size++; ann_data_stat.invalid_size++;
return -1; return -1;
...@@ -846,6 +861,7 @@ static int check_matching_type(struct type_state *state, ...@@ -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) { if (state->regs[reg].ok && state->regs[reg].kind == TSR_KIND_TYPE) {
int tag = dwarf_tag(&state->regs[reg].type); int tag = dwarf_tag(&state->regs[reg].type);
Dwarf_Die sized_type;
/* /*
* Normal registers should hold a pointer (or array) to * Normal registers should hold a pointer (or array) to
...@@ -862,13 +878,18 @@ static int check_matching_type(struct type_state *state, ...@@ -862,13 +878,18 @@ static int check_matching_type(struct type_state *state,
pr_debug_dtp("\n"); pr_debug_dtp("\n");
/* Remove the pointer and get the target type */ /* 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; return -1;
dloc->type_offset = dloc->op->offset; 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 */ /* 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) (unsigned)dloc->type_offset >= size)
return -1; return -1;
......
...@@ -267,7 +267,7 @@ Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) ...@@ -267,7 +267,7 @@ Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem)
} }
/* Get a type die, but skip qualifiers */ /* 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; int tag;
......
...@@ -56,6 +56,8 @@ const char *die_get_decl_file(Dwarf_Die *dw_die); ...@@ -56,6 +56,8 @@ const char *die_get_decl_file(Dwarf_Die *dw_die);
/* Get type die */ /* Get type die */
Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem); 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 */ /* Get a type die, but skip qualifiers and typedef */
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);
......
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