[llvm] [llvm-profgen] Guard unwindReturn against zero call address (PR #211381)
Kunal Pathak via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 29 08:29:18 PDT 2026
================
@@ -0,0 +1,12 @@
+PERF_RECORD_MMAP2 2854748/2854748: [0x400000(0x1000) @ 0 00:1d 123291722 526021]: r-xp /home/noinline-cs-noprobe.perfbin
+// The 5th LBR entry 0x4005e9/0x400637 is a return (0x4005e9 is `retq` in bar)
----------------
kunalspathak wrote:
The LBR here is intentionally invalid. This is a hand-crafted synthetic sample whose whole purpose is to exercise the new guard against a corrupted/invalid return, so it isn't meant to be a self consistent physical trace.
The only entry that matters is `0x4005e9/0x400637`: bar's ret (at `0x4005e9`) "returns" to `0x400637`, which is not the address after a `call`, the real return site of call bar (at `0x40062f`) is `0x400634` (a mov), while `0x400637` is a `jmp`. So `getCallAddrFromFrameAddr(0x400637)` returns 0, which is exactly the case the guard handles (without it, switchToFrame(0) trips "Address can't be zero!").
It is not a specific HW bug, but call-less return targets show up in real captures for several reasons, which is why the unwinder should tolerate them defensively:
- the LBR is a fixed-depth hardware ring buffer, so a return's paired call can be truncated off the top of the sampling window;
- perf's software branch synthesis (`perf script --itrace`, and the Arm CoreSight/CS-ETM decoder) can emit unpaired/standalone entries at trace-window seams, interrupts, or context switches;
https://github.com/llvm/llvm-project/pull/211381
More information about the llvm-commits
mailing list