Skip to content

Commit 2fb4fa3

Browse files
committed
Spill registers before scanning the stack.
From the change: // xtensa has more registers than an instruction can address. The 16 that // can be addressed are called the "window". When a function is called or // returns the window rotates. This allows for more efficient function calls // because ram doesn't need to be used. It's only used if the window wraps // around onto itself. At that point values are "spilled" to empty spots in // the stack that were set aside. When the window rotates back around (on // function return), the values are restored into the register from ram. // So, in order to read the values in the stack scan we must make sure all // of the register values we care about have been spilled to RAM. Luckily, // there is a HAL call to do it. There is a bit of a race condition here // because the register value could change after it's been restored but that // is unlikely to happen with a heap pointer while we do a GC. Fixes #2907
1 parent d98151a commit 2fb4fa3

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

ports/esp32s2/mphalport.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,24 @@ void mp_hal_delay_us(mp_uint_t delay) {
3737
mp_hal_delay_ms(delay / 1000);
3838
}
3939

40-
mp_uint_t cpu_get_regs_and_sp(mp_uint_t *regs) {
40+
// This is provided by the esp-idf/components/xtensa/esp32s2/libhal.a binary
41+
// blob.
42+
extern void xthal_window_spill(void);
43+
44+
mp_uint_t cpu_get_regs_and_sp(mp_uint_t *regs, uint8_t reg_count) {
45+
// xtensa has more registers than an instruction can address. The 16 that
46+
// can be addressed are called the "window". When a function is called or
47+
// returns the window rotates. This allows for more efficient function calls
48+
// because ram doesn't need to be used. It's only used if the window wraps
49+
// around onto itself. At that point values are "spilled" to empty spots in
50+
// the stack that were set aside. When the window rotates back around (on
51+
// function return), the values are restored into the register from ram.
52+
53+
// So, in order to read the values in the stack scan we must make sure all
54+
// of the register values we care about have been spilled to RAM. Luckily,
55+
// there is a HAL call to do it. There is a bit of a race condition here
56+
// because the register value could change after it's been restored but that
57+
// is unlikely to happen with a heap pointer while we do a GC.
58+
xthal_window_spill();
4159
return (mp_uint_t) __builtin_frame_address(0);
4260
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""Simple script that translates "Backtrace:" lines from the ESP output to files
2+
and line numbers.
3+
4+
Run with: python3 tools/decode_backtrace.py <board>
5+
6+
Enter the backtrace line at the "? " prompt. CTRL-C to exit the script.
7+
"""
8+
9+
import subprocess
10+
import sys
11+
12+
board = sys.argv[1]
13+
print(board)
14+
15+
while True:
16+
addresses = input("? ")
17+
if addresses.startswith("Backtrace:"):
18+
addresses = addresses[len("Backtrace:"):]
19+
addresses = addresses.strip().split()
20+
addresses = [address.split(":")[0] for address in addresses]
21+
print('got', addresses)
22+
subprocess.run(["xtensa-esp32s2-elf-addr2line",
23+
"-e", "build-{}/firmware.elf".format(board)] + addresses)

0 commit comments

Comments
 (0)