From: Ian Rogers <irogers@google.com>
To: "Peter Zijlstra" <peterz@infradead.org>,
"Ingo Molnar" <mingo@redhat.com>,
"Arnaldo Carvalho de Melo" <acme@kernel.org>,
"Namhyung Kim" <namhyung@kernel.org>,
"Jiri Olsa" <jolsa@kernel.org>, "Ian Rogers" <irogers@google.com>,
"Adrian Hunter" <adrian.hunter@intel.com>,
"James Clark" <james.clark@linaro.org>,
"John Garry" <john.g.garry@oracle.com>,
"Will Deacon" <will@kernel.org>, "Leo Yan" <leo.yan@linux.dev>,
"Guo Ren" <guoren@kernel.org>, "Paul Walmsley" <pjw@kernel.org>,
"Palmer Dabbelt" <palmer@dabbelt.com>,
"Albert Ou" <aou@eecs.berkeley.edu>,
"Alexandre Ghiti" <alex@ghiti.fr>,
"Shimin Guo" <shimin.guo@skydio.com>,
"Athira Rajeev" <atrajeev@linux.ibm.com>,
"Stephen Brennan" <stephen.s.brennan@oracle.com>,
"Howard Chu" <howardchu95@gmail.com>,
"Thomas Falcon" <thomas.falcon@intel.com>,
"Andi Kleen" <ak@linux.intel.com>,
"Dr. David Alan Gilbert" <linux@treblig.org>,
"Dmitry Vyukov" <dvyukov@google.com>,
"Krzysztof Łopatowski" <krzysztof.m.lopatowski@gmail.com>,
"Chun-Tse Shao" <ctshao@google.com>,
"Aditya Bodkhe" <aditya.b1@linux.ibm.com>,
"Haibo Xu" <haibo1.xu@intel.com>,
"Sergei Trofimovich" <slyich@gmail.com>,
linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, linux-csky@vger.kernel.org,
linux-riscv@lists.infradead.org, "Mark Wielaard" <mark@klomp.org>
Subject: [PATCH v1 23/23] perf machine: Add inline information to frame pointer and LBR callchains
Date: Fri, 16 Jan 2026 21:28:49 -0800 [thread overview]
Message-ID: <20260117052849.2205545-24-irogers@google.com> (raw)
In-Reply-To: <20260117052849.2205545-1-irogers@google.com>
Use append_inlines in frame pointer and LBR cases. Update the
addr2line test to also test frame pointers. LBR is also updated but
inaccuracy in the branched to IP means the inline information is
missing in the leaf. Leave LBR callchains untested for now.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/tests/shell/addr2line_inlines.sh | 31 +++++-
tools/perf/util/machine.c | 104 +++++++++++---------
2 files changed, 86 insertions(+), 49 deletions(-)
diff --git a/tools/perf/tests/shell/addr2line_inlines.sh b/tools/perf/tests/shell/addr2line_inlines.sh
index 4a5b6f5be23d..ce30d9c7e0bf 100755
--- a/tools/perf/tests/shell/addr2line_inlines.sh
+++ b/tools/perf/tests/shell/addr2line_inlines.sh
@@ -21,8 +21,28 @@ trap_cleanup() {
}
trap trap_cleanup EXIT TERM INT
-test_inlinedloop() {
- echo "Inline unwinding verification test"
+test_fp() {
+ echo "Inline unwinding fp verification test"
+ # Record data. Currently only dwarf callchains support inlined functions.
+ perf record --call-graph fp -e task-clock:u -o "${perf_data}" -- perf test -w inlineloop 1
+
+ # Check output with inline (default) and srcline
+ perf script -i "${perf_data}" --fields +srcline > "${perf_script_txt}"
+
+ # Expect the leaf and middle functions to occur on lines in the 20s, with
+ # the non-inlined parent function on a line in the 30s.
+ if grep -q "inlineloop.c:2. (inlined)" "${perf_script_txt}" &&
+ grep -q "inlineloop.c:3.$" "${perf_script_txt}"
+ then
+ echo "Inline unwinding fp verification test [Success]"
+ else
+ echo "Inline unwinding fp verification test [Failed missing inlined functions]"
+ err=1
+ fi
+}
+
+test_dwarf() {
+ echo "Inline unwinding dwarf verification test"
# Record data. Currently only dwarf callchains support inlined functions.
perf record --call-graph dwarf -e task-clock:u -o "${perf_data}" -- perf test -w inlineloop 1
@@ -34,14 +54,15 @@ test_inlinedloop() {
if grep -q "inlineloop.c:2. (inlined)" "${perf_script_txt}" &&
grep -q "inlineloop.c:3.$" "${perf_script_txt}"
then
- echo "Inline unwinding verification test [Success]"
+ echo "Inline unwinding dwarf verification test [Success]"
else
- echo "Inline unwinding verification test [Failed missing inlined functions]"
+ echo "Inline unwinding dwarf verification test [Failed missing inlined functions]"
err=1
fi
}
-test_inlinedloop
+test_fp
+test_dwarf
cleanup
exit $err
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 841b711d970e..30d606fbf040 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -2090,6 +2090,59 @@ struct iterations {
u64 cycles;
};
+static int append_inlines(struct callchain_cursor *cursor, struct map_symbol *ms, u64 ip,
+ bool branch, struct branch_flags *flags, int nr_loop_iter,
+ u64 iter_cycles, u64 branch_from)
+{
+ struct symbol *sym = ms->sym;
+ struct map *map = ms->map;
+ struct inline_node *inline_node;
+ struct inline_list *ilist;
+ struct dso *dso;
+ u64 addr;
+ int ret = 1;
+ struct map_symbol ilist_ms;
+ bool first = true;
+
+ if (!symbol_conf.inline_name || !map || !sym)
+ return ret;
+
+ addr = map__dso_map_ip(map, ip);
+ addr = map__rip_2objdump(map, addr);
+ dso = map__dso(map);
+
+ inline_node = inlines__tree_find(dso__inlined_nodes(dso), addr);
+ if (!inline_node) {
+ inline_node = dso__parse_addr_inlines(dso, addr, sym);
+ if (!inline_node)
+ return ret;
+ inlines__tree_insert(dso__inlined_nodes(dso), inline_node);
+ }
+
+ ilist_ms = (struct map_symbol) {
+ .maps = maps__get(ms->maps),
+ .map = map__get(map),
+ };
+ list_for_each_entry(ilist, &inline_node->val, list) {
+ ilist_ms.sym = ilist->symbol;
+ if (first) {
+ ret = callchain_cursor_append(cursor, ip, &ilist_ms,
+ branch, flags, nr_loop_iter,
+ iter_cycles, branch_from, ilist->srcline);
+ } else {
+ ret = callchain_cursor_append(cursor, ip, &ilist_ms, false,
+ NULL, 0, 0, 0, ilist->srcline);
+ }
+ first = false;
+
+ if (ret != 0)
+ return ret;
+ }
+ map_symbol__exit(&ilist_ms);
+
+ return ret;
+}
+
static int add_callchain_ip(struct thread *thread,
struct callchain_cursor *cursor,
struct symbol **parent,
@@ -2170,6 +2223,11 @@ static int add_callchain_ip(struct thread *thread,
ms.maps = maps__get(al.maps);
ms.map = map__get(al.map);
ms.sym = al.sym;
+
+ if (append_inlines(cursor, &ms, ip, branch, flags, nr_loop_iter,
+ iter_cycles, branch_from) == 0)
+ goto out;
+
srcline = callchain_srcline(&ms, al.addr);
err = callchain_cursor_append(cursor, ip, &ms,
branch, flags, nr_loop_iter,
@@ -2888,49 +2946,6 @@ static int thread__resolve_callchain_sample(struct thread *thread,
return 0;
}
-static int append_inlines(struct callchain_cursor *cursor, struct map_symbol *ms, u64 ip)
-{
- struct symbol *sym = ms->sym;
- struct map *map = ms->map;
- struct inline_node *inline_node;
- struct inline_list *ilist;
- struct dso *dso;
- u64 addr;
- int ret = 1;
- struct map_symbol ilist_ms;
-
- if (!symbol_conf.inline_name || !map || !sym)
- return ret;
-
- addr = map__dso_map_ip(map, ip);
- addr = map__rip_2objdump(map, addr);
- dso = map__dso(map);
-
- inline_node = inlines__tree_find(dso__inlined_nodes(dso), addr);
- if (!inline_node) {
- inline_node = dso__parse_addr_inlines(dso, addr, sym);
- if (!inline_node)
- return ret;
- inlines__tree_insert(dso__inlined_nodes(dso), inline_node);
- }
-
- ilist_ms = (struct map_symbol) {
- .maps = maps__get(ms->maps),
- .map = map__get(map),
- };
- list_for_each_entry(ilist, &inline_node->val, list) {
- ilist_ms.sym = ilist->symbol;
- ret = callchain_cursor_append(cursor, ip, &ilist_ms, false,
- NULL, 0, 0, 0, ilist->srcline);
-
- if (ret != 0)
- return ret;
- }
- map_symbol__exit(&ilist_ms);
-
- return ret;
-}
-
static int unwind_entry(struct unwind_entry *entry, void *arg)
{
struct callchain_cursor *cursor = arg;
@@ -2940,7 +2955,8 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
if (symbol_conf.hide_unresolved && entry->ms.sym == NULL)
return 0;
- if (append_inlines(cursor, &entry->ms, entry->ip) == 0)
+ if (append_inlines(cursor, &entry->ms, entry->ip, /*branch=*/false, /*branch_flags=*/NULL,
+ /*nr_loop_iter=*/0, /*iter_cycles=*/0, /*branch_from=*/0) == 0)
return 0;
/*
--
2.52.0.457.g6b5491de43-goog
prev parent reply other threads:[~2026-01-17 5:31 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-17 5:28 [PATCH v1 00/23] perf dwarf/libdw extra support, speed and clean ups Ian Rogers
2026-01-17 5:28 ` [PATCH v1 01/23] perf symbol-elf: Fix leak of ELF files with GNU debugdata Ian Rogers
2026-01-17 5:28 ` [PATCH v1 02/23] perf dso: Extra validity checks that e_machine is valid Ian Rogers
2026-01-17 5:28 ` [PATCH v1 03/23] perf record: Disable inline frames when marking build IDs Ian Rogers
2026-01-17 5:28 ` [PATCH v1 04/23] perf unwind-libdw: fix a cross-arch unwinding bug Ian Rogers
2026-01-20 16:02 ` Arnaldo Carvalho de Melo
2026-01-20 17:53 ` Ian Rogers
2026-01-17 5:28 ` [PATCH v1 05/23] perf libdw_addr2line: Fixes to srcline memory allocation Ian Rogers
2026-01-17 5:28 ` [PATCH v1 06/23] perf unwind-libdw: Correct argument to dwfl_attach_state Ian Rogers
2026-01-17 5:28 ` [PATCH v1 07/23] perf powerpc: Unify the skip-callchain-idx libdw with that for addr2line Ian Rogers
2026-01-17 5:28 ` [PATCH v1 08/23] perf perf_regs: Switch from arch string to int e_machine Ian Rogers
2026-01-20 18:49 ` Arnaldo Carvalho de Melo
2026-01-21 6:58 ` Mi, Dapeng
2026-01-21 7:10 ` Ian Rogers
2026-01-17 5:28 ` [PATCH v1 09/23] perf dwarf-regs: Add util/dwarf-regs-arch for consistency with perf-regs Ian Rogers
2026-01-17 5:28 ` [PATCH v1 10/23] perf dwarf-regs: Remove get_arch_regnum Ian Rogers
2026-01-17 5:28 ` [PATCH v1 11/23] perf dwarf-regs: Clean up x86 dwarf_regnum code Ian Rogers
2026-01-17 5:28 ` [PATCH v1 12/23] perf dwarf-regs: Add get_dwarf_regnum_for_perf_regnum and use for x86 unwinding Ian Rogers
2026-01-17 5:42 ` Ian Rogers
2026-01-17 5:28 ` [PATCH v1 13/23] perf dwarf-regs: Add basic get_dwarf_regnum for most architectures Ian Rogers
2026-01-17 5:28 ` [PATCH v1 14/23] perf dwarf-regs: Add ARM perf to dwarf register number mapping functions Ian Rogers
2026-01-17 5:28 ` [PATCH v1 15/23] perf dwarf-regs: Add csky " Ian Rogers
2026-01-17 5:28 ` [PATCH v1 16/23] perf dwarf-regs: Add loongarch " Ian Rogers
2026-01-17 5:28 ` [PATCH v1 17/23] perf dwarf-regs: Add powerpc " Ian Rogers
2026-01-17 5:28 ` [PATCH v1 18/23] perf dwarf-regs: Add RISC-V " Ian Rogers
2026-01-17 5:28 ` [PATCH v1 19/23] perf dwarf-regs: Add S390 " Ian Rogers
2026-01-17 5:28 ` [PATCH v1 20/23] perf dwarf-regs: Add MIPS " Ian Rogers
2026-01-17 5:28 ` [PATCH v1 21/23] perf build: Remove NO_LIBDW_DWARF_UNWIND option Ian Rogers
2026-01-17 5:28 ` [PATCH v1 22/23] perf unwind-libdw: Don't discard loaded ELF/Dwarf after every unwind Ian Rogers
2026-01-27 17:42 ` Serhei Makarov
2026-01-27 18:08 ` Ian Rogers
2026-01-17 5:28 ` Ian Rogers [this message]
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=20260117052849.2205545-24-irogers@google.com \
--to=irogers@google.com \
--cc=acme@kernel.org \
--cc=aditya.b1@linux.ibm.com \
--cc=adrian.hunter@intel.com \
--cc=ak@linux.intel.com \
--cc=alex@ghiti.fr \
--cc=aou@eecs.berkeley.edu \
--cc=atrajeev@linux.ibm.com \
--cc=ctshao@google.com \
--cc=dvyukov@google.com \
--cc=guoren@kernel.org \
--cc=haibo1.xu@intel.com \
--cc=howardchu95@gmail.com \
--cc=james.clark@linaro.org \
--cc=john.g.garry@oracle.com \
--cc=jolsa@kernel.org \
--cc=krzysztof.m.lopatowski@gmail.com \
--cc=leo.yan@linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-csky@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=linux-riscv@lists.infradead.org \
--cc=linux@treblig.org \
--cc=mark@klomp.org \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=palmer@dabbelt.com \
--cc=peterz@infradead.org \
--cc=pjw@kernel.org \
--cc=shimin.guo@skydio.com \
--cc=slyich@gmail.com \
--cc=stephen.s.brennan@oracle.com \
--cc=thomas.falcon@intel.com \
--cc=will@kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox