You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The ghost unwind feature was producing incorrect native stack traces. When `fast_unwind=True`, the captured stack was missing the top frames (like `valloc`) and showed frames shifted by one position.
6
+
7
+
## Root Causes
8
+
9
+
### Bug 1: Returning Return Addresses Instead of Instruction Pointers
10
+
11
+
The `unw_backtrace()` function returns **instruction pointers (IPs)** - the address where each frame is currently executing. However, ghost_stack was returning **return addresses** - the address where each frame will return TO after it completes.
12
+
13
+
These are different values:
14
+
- IP of frame N = where frame N is executing
15
+
- Return address stored in frame N = IP of frame N-1 (the caller)
16
+
17
+
So returning return addresses produces a stack that is shifted by one frame and missing the topmost frame entirely.
18
+
19
+
**Location**: `capture_and_install()` and `copy_cached_frames()` in `ghost_stack.cpp`
20
+
21
+
**Fix**:
22
+
1. Added `ip` field to `StackEntry` struct to store both the IP (for returning to caller) and the return_address (for trampoline restoration)
23
+
2. Changed output buffer to return `entries_[i].ip` instead of `entries_[i].return_address`
24
+
25
+
### Bug 2: Off-by-One Error in Frame Walking Loop
26
+
27
+
The original loop structure was:
28
+
```cpp
29
+
while (unw_step(&cursor) > 0 && frame_idx < raw_count) {
30
+
unw_get_reg(&cursor, UNW_REG_IP, &ip); // Read AFTER stepping
31
+
...
32
+
}
33
+
```
34
+
35
+
This calls `unw_step()` BEFORE reading frame data. After the skip loop positions the cursor at frame 3, the first `unw_step()` moves to frame 4 before we read anything - skipping frame 3 entirely.
36
+
37
+
**Fix**: Changed to read-then-step pattern:
38
+
```cpp
39
+
do {
40
+
unw_get_reg(&cursor, UNW_REG_IP, &ip); // Read FIRST
Both `fast_unwind=False` and `fast_unwind=True` variants now pass and produce correct stack traces with `valloc` and `run_recursive` in the expected positions.
0 commit comments