From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Namhyung Kim <namhyung@kernel.org>
Cc: Ingo Molnar <mingo@kernel.org>,
Thomas Gleixner <tglx@linutronix.de>,
James Clark <james.clark@linaro.org>,
Jiri Olsa <jolsa@kernel.org>, Ian Rogers <irogers@google.com>,
Adrian Hunter <adrian.hunter@intel.com>,
Clark Williams <williams@redhat.com>,
linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org,
Arnaldo Carvalho de Melo <acme@redhat.com>
Subject: [PATCH v2 04/11] perf annotate-data: Count flexible array accesses for the whole struct
Date: Fri, 13 Nov 2026 17:08:42 -0300 [thread overview]
Message-ID: <20261113200850.2803460-5-acme@kernel.org> (raw)
In-Reply-To: <20261113200850.2803460-1-acme@kernel.org>
From: Arnaldo Carvalho de Melo <acme@redhat.com>
The per-member percentage sums the histogram entries in the member's
own [offset, offset + size) range. A flexible array member is resolved
past the end of its struct, so the struct row only covered its declared
size and showed 0.00% while the member row showed 100.00% and the
header said N samples.
Take a member's extent as the end of its last child as well, so the
struct counts what was resolved past it. Union members all start at
offset 0, so a plain union keeps its size; a member that is itself a
struct with a flexible array extends the union too. The TUI browser
accounts the members the same way, use the extent there as well.
Extend tests/shell/data_type_flex_array.sh to check that the accesses
count for the struct in the percent, samples and period columns.
Fixes: aaca646915a1bb53 ("perf annotate-data: Adjust type offset for flex-array")
Cc: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
.../perf/tests/shell/data_type_flex_array.sh | 40 ++++++++++++++++++-
tools/perf/ui/browsers/annotate-data.c | 7 ++--
tools/perf/util/annotate-data.c | 24 ++++++++++-
tools/perf/util/annotate-data.h | 3 ++
4 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/tools/perf/tests/shell/data_type_flex_array.sh b/tools/perf/tests/shell/data_type_flex_array.sh
index 983cde2b3c7d2b29..7a7a782320afee23 100755
--- a/tools/perf/tests/shell/data_type_flex_array.sh
+++ b/tools/perf/tests/shell/data_type_flex_array.sh
@@ -100,5 +100,43 @@ if ! grep -Fq "# data-type: struct flex +0x4 (data)" "$perfout"; then
exit 1
fi
-echo "flexible array member resolved"
+# The accesses to the flexible array are resolved past the end of the
+# struct: they must count for the struct, not only for the member.
+if ! perf annotate --data-type -i "$perfdata" --stdio > "$perfout" 2>/dev/null; then
+ echo "FAIL: perf annotate --data-type"
+ cleanup
+ exit 1
+fi
+
+if ! awk '
+ $1 + 0 == 100.00 && /struct flex/ { struct_ok = 1 }
+ $1 + 0 == 100.00 && /char\[\]/ && /data;/ { data_ok = 1 }
+ $1 + 0 == 0.00 && /int/ && /len;/ { len_ok = 1 }
+ END { exit !(struct_ok && data_ok && len_ok) }
+' <(sed -n "/^Annotate type: 'struct flex' in/,/^Annotate type: /p" "$perfout"); then
+ echo "FAIL: --data-type does not count the flexible array accesses"
+ cleanup
+ exit 1
+fi
+
+# Same with the samples and period columns, the other two display modes.
+for mode in --show-nr-samples --show-total-period; do
+ if ! perf annotate --data-type -i "$perfdata" --stdio "$mode" > "$perfout" 2>/dev/null; then
+ echo "FAIL: perf annotate --data-type $mode"
+ cleanup
+ exit 1
+ fi
+
+ if ! awk '
+ $1 + 0 > 0 && /struct flex/ { total = $1 + 0 }
+ /char\[\]/ && /data;/ { data = $1 + 0 }
+ END { exit !(total > 0 && total == data) }
+ ' <(sed -n "/^Annotate type: 'struct flex' in/,/^Annotate type: /p" "$perfout"); then
+ echo "FAIL: --data-type $mode does not count the flexible array accesses"
+ cleanup
+ exit 1
+ fi
+done
+
+echo "flexible array member resolved and counted"
cleanup
diff --git a/tools/perf/ui/browsers/annotate-data.c b/tools/perf/ui/browsers/annotate-data.c
index 0f778788df4a934b..0e1e06acf2b231a7 100644
--- a/tools/perf/ui/browsers/annotate-data.c
+++ b/tools/perf/ui/browsers/annotate-data.c
@@ -53,12 +53,11 @@ static int get_member_overhead(struct annotated_data_type *adt,
struct evsel *leader)
{
struct annotated_member *member = entry->data;
- int i, k;
+ int i, k, end = annotated_member_extent(member);
- for (i = 0; i < member->size; i++) {
+ for (i = member->offset; i < end; i++) {
struct type_hist *h;
struct evsel *evsel;
- int offset = member->offset + i;
k = 0;
for_each_group_evsel(evsel, leader) {
@@ -69,7 +68,7 @@ static int get_member_overhead(struct annotated_data_type *adt,
continue;
h = &adt->histograms[evsel->core.idx];
- if (hashmap__find(&h->samples, offset, &hist))
+ if (hashmap__find(&h->samples, i, &hist))
update_hist_entry(&entry->hists[k], hist);
k++;
}
diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c
index dd9c1d7b2da8be8a..75a0906b4df0b9e2 100644
--- a/tools/perf/util/annotate-data.c
+++ b/tools/perf/util/annotate-data.c
@@ -2233,6 +2233,25 @@ static void print_annotated_data_value(struct type_hist *h, u64 period, int nr_s
color_fprintf(stdout, color, " %7.2f", percent);
}
+/*
+ * A flexible array member is resolved past the end of its parent, so the
+ * parent's samples are not bounded by its size.
+ */
+int annotated_member_extent(struct annotated_member *member)
+{
+ struct annotated_member *child;
+ int end = member->offset + member->size;
+
+ list_for_each_entry(child, &member->children, node) {
+ int child_end = annotated_member_extent(child);
+
+ if (child_end > end)
+ end = child_end;
+ }
+
+ return end;
+}
+
static void print_annotated_data_type(struct annotated_data_type *mem_type,
struct annotated_member *member,
struct evsel *evsel, int indent)
@@ -2240,6 +2259,7 @@ static void print_annotated_data_type(struct annotated_data_type *mem_type,
struct annotated_member *child;
struct type_hist *h;
int i, nr_events = 0, samples = 0;
+ int end = annotated_member_extent(member);
u64 period = 0;
int width = symbol_conf.show_total_period ? 11 : 7;
struct evsel *pos;
@@ -2253,10 +2273,10 @@ static void print_annotated_data_type(struct annotated_data_type *mem_type,
samples = 0;
period = 0;
- for (i = 0; i < member->size; i++) {
+ for (i = member->offset; i < end; i++) {
struct type_hist_entry *entry;
- if (!hashmap__find(&h->samples, member->offset + i, &entry))
+ if (!hashmap__find(&h->samples, i, &entry))
continue;
samples += entry->nr_samples;
diff --git a/tools/perf/util/annotate-data.h b/tools/perf/util/annotate-data.h
index 184262c7356213fa..880b11849a9329c7 100644
--- a/tools/perf/util/annotate-data.h
+++ b/tools/perf/util/annotate-data.h
@@ -260,6 +260,9 @@ void global_var_type__tree_delete(struct rb_root *root);
/* Print data type annotation (including members) on stdout */
int hist_entry__annotate_data_tty(struct hist_entry *he, struct evsel *evsel);
+/* End offset of a member, including a flexible array's children */
+int annotated_member_extent(struct annotated_member *member);
+
/* Get name of member field at the given offset in the data type */
int annotated_data_type__get_member_name(struct annotated_data_type *adt,
char *buf, size_t sz, int member_offset);
--
2.56.0
next prev parent reply other threads:[~2026-11-13 20:09 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-13 20:08 [PATCH v2 0/11] perf coverage: A harness for perf, and the fixes it found Arnaldo Carvalho de Melo
2026-11-13 20:08 ` [PATCH v2 01/11] perf scripts: Add a coverage harness for perf Arnaldo Carvalho de Melo
2026-11-13 20:26 ` sashiko-bot
2026-11-13 20:08 ` [PATCH v2 02/11] perf annotate-data: Resolve DW_OP_addrx global variables Arnaldo Carvalho de Melo
2026-11-13 20:31 ` sashiko-bot
2026-11-13 20:08 ` [PATCH v2 03/11] perf tests: Exercise the flexible array member path Arnaldo Carvalho de Melo
2026-11-13 20:25 ` sashiko-bot
2026-11-13 20:08 ` Arnaldo Carvalho de Melo [this message]
2026-11-13 20:26 ` [PATCH v2 04/11] perf annotate-data: Count flexible array accesses for the whole struct sashiko-bot
2026-11-13 20:08 ` [PATCH v2 05/11] perf tests: Exercise data type resolution from a register Arnaldo Carvalho de Melo
2026-11-13 20:26 ` sashiko-bot
2026-11-13 20:08 ` [PATCH v2 06/11] perf annotate: Print the stats after the annotations Arnaldo Carvalho de Melo
2026-11-13 20:24 ` sashiko-bot
2026-11-13 20:08 ` [PATCH v2 07/11] perf tests: Silence the libbfd probe in build-test Arnaldo Carvalho de Melo
2026-11-13 20:18 ` sashiko-bot
2026-11-13 20:08 ` [PATCH v2 08/11] perf build: Record the display-only features in FEATURE-DUMP Arnaldo Carvalho de Melo
2026-11-13 20:24 ` sashiko-bot
2026-11-13 20:08 ` [PATCH v2 09/11] perf tests: Fix the Intel PT virtual LBR check Arnaldo Carvalho de Melo
2026-11-13 20:35 ` sashiko-bot
2026-11-13 20:08 ` [PATCH v2 10/11] perf test: Drop samples without an IP in the dlfilter test Arnaldo Carvalho de Melo
2026-11-13 20:26 ` sashiko-bot
2026-11-13 20:08 ` [PATCH v2 11/11] perf test: Skip the LBR inline unwinding check when unsupported Arnaldo Carvalho de Melo
2026-11-13 20:26 ` sashiko-bot
2026-11-13 22:16 ` [PATCH v2 0/11] perf coverage: A harness for perf, and the fixes it found Ian Rogers
2026-11-13 23:58 ` Arnaldo Melo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261113200850.2803460-5-acme@kernel.org \
--to=acme@kernel.org \
--cc=acme@redhat.com \
--cc=adrian.hunter@intel.com \
--cc=irogers@google.com \
--cc=james.clark@linaro.org \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=namhyung@kernel.org \
--cc=tglx@linutronix.de \
--cc=williams@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.