[PATCH v3 06/18] perf cs-etm: Don't drop previous target for kernel samples

From: James Clark

Date: Mon Nov 02 2026 - 07:27:13 EST


The branch target of the previous sample is used as the start of the
range to disassemble, but if that sample's DSO is "[unknown]" then we'll
drop it even though it's useful information. This happens when recording
userspace only. Save the address earlier for "Trace On" samples, before
we get to the early exit condition for unknown DSOs.

In a later commit to change the default timestamp interval, trace will
be collected that triggers this issue, so fix it now.

Signed-off-by: James Clark <james.clark@xxxxxxxxxx>
---
tools/perf/python/arm-cs-trace-disasm.py | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/tools/perf/python/arm-cs-trace-disasm.py b/tools/perf/python/arm-cs-trace-disasm.py
index 1812ccaf4b20..5a7daf927bea 100755
--- a/tools/perf/python/arm-cs-trace-disasm.py
+++ b/tools/perf/python/arm-cs-trace-disasm.py
@@ -52,6 +52,7 @@ DISASM_CACHE: Dict[str, List[str]] = {}
DISASM_RE = re.compile(r"^\s*([0-9a-fA-F]+):")
DISASM_FUNC_RE = re.compile(r"^\s*([0-9a-fA-F]+)\s.*:")
CACHE_SIZE = 1024
+PERF_IP_FLAG_TRACE_BEGIN = 1 << 8
class _State:
sample_idx: int = -1
source_file_name: Optional[str] = None
@@ -252,12 +253,12 @@ class TraceDisasm:
print(f"Event type: {ev_name}")
print_sample(sample)

- # Initialize CPU data if it's empty, and directly return back
- # if this is the first tracing event for this CPU. This must happen
- # before the dso == '[unknown]' check because the initial
- # CS_ETM_TRACE_ON sample has ip == 0 (dso == '[unknown]') and
- # carries the starting target address in sample.sample_addr.
- if self.cpu_data.get(f"{sample.sample_cpu}addr") is None:
+ # Initialize CPU data on the first event and whenever tracing resumes.
+ # Trace-start samples may have no source DSO map, but carry the next
+ # range's starting address in sample.sample_addr. Instruction samples
+ # in the first range also have TRACE_BEGIN set, so only check branches.
+ if (self.cpu_data.get(f"{sample.sample_cpu}addr") is None or
+ ("branches" in ev_name and sample.flags & PERF_IP_FLAG_TRACE_BEGIN)):
self.cpu_data[f"{sample.sample_cpu}addr"] = sample.sample_addr
return


--
2.43.0