* [PATCH] perf annotate-data: Show typedef names properly
@ 2024-08-07 22:31 Namhyung Kim
2024-08-08 12:40 ` Arnaldo Carvalho de Melo
0 siblings, 1 reply; 2+ messages in thread
From: Namhyung Kim @ 2024-08-07 22:31 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo, Ian Rogers, Kan Liang
Cc: Jiri Olsa, Adrian Hunter, Peter Zijlstra, Ingo Molnar, LKML,
linux-perf-users, Athira Rajeev, Masami Hiramatsu
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.
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/util/annotate-data.c | 39 +++++++++++++++++++++++++--------
tools/perf/util/dwarf-aux.c | 2 +-
tools/perf/util/dwarf-aux.h | 2 ++
3 files changed, 33 insertions(+), 10 deletions(-)
diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c
index 734acdd8c4b7..092809bb92f5 100644
--- a/tools/perf/util/annotate-data.c
+++ b/tools/perf/util/annotate-data.c
@@ -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;
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index 44ef968a7ad3..5e080d7e22c2 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -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;
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index 24446412b869..336a3a183a78 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -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);
--
2.46.0.rc2.264.g509ed76dc8-goog
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH] perf annotate-data: Show typedef names properly
2024-08-07 22:31 [PATCH] perf annotate-data: Show typedef names properly Namhyung Kim
@ 2024-08-08 12:40 ` Arnaldo Carvalho de Melo
0 siblings, 0 replies; 2+ messages in thread
From: Arnaldo Carvalho de Melo @ 2024-08-08 12:40 UTC (permalink / raw)
To: Namhyung Kim
Cc: Ian Rogers, Kan Liang, Jiri Olsa, Adrian Hunter, Peter Zijlstra,
Ingo Molnar, LKML, linux-perf-users, Athira Rajeev,
Masami Hiramatsu
On Wed, Aug 07, 2024 at 03:31:29PM -0700, Namhyung Kim wrote:
> 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.
Great improvement! Tested and applied.
- Arnaldo
> Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
> Cc: Masami Hiramatsu <mhiramat@kernel.org>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
> tools/perf/util/annotate-data.c | 39 +++++++++++++++++++++++++--------
> tools/perf/util/dwarf-aux.c | 2 +-
> tools/perf/util/dwarf-aux.h | 2 ++
> 3 files changed, 33 insertions(+), 10 deletions(-)
>
> diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c
> index 734acdd8c4b7..092809bb92f5 100644
> --- a/tools/perf/util/annotate-data.c
> +++ b/tools/perf/util/annotate-data.c
> @@ -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;
>
> diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
> index 44ef968a7ad3..5e080d7e22c2 100644
> --- a/tools/perf/util/dwarf-aux.c
> +++ b/tools/perf/util/dwarf-aux.c
> @@ -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;
>
> diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
> index 24446412b869..336a3a183a78 100644
> --- a/tools/perf/util/dwarf-aux.h
> +++ b/tools/perf/util/dwarf-aux.h
> @@ -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);
>
> --
> 2.46.0.rc2.264.g509ed76dc8-goog
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2024-08-08 12:41 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-07 22:31 [PATCH] perf annotate-data: Show typedef names properly Namhyung Kim
2024-08-08 12:40 ` Arnaldo Carvalho de Melo
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.