Skip to content

Commit 326be35

Browse files
authored
Postmortem improvements (#8839)
* divide by 0 reporting to point back at the divide function caller * stack offset adjustments to be independent of __wrap_system_restart_local()'s stack frame size.
1 parent 1beca6f commit 326be35

File tree

1 file changed

+55
-13
lines changed

1 file changed

+55
-13
lines changed

cores/esp8266/core_esp8266_postmortem.cpp

+55-13
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,26 @@ static void cut_here() {
110110
ets_putc('\n');
111111
}
112112

113-
void __wrap_system_restart_local() {
114-
register uint32_t sp asm("a1");
115-
uint32_t sp_dump = sp;
116-
113+
/*
114+
Add some assembly to grab the stack pointer and pass it as an argument before
115+
it grows for the target function. Should stabilize the stack offsets, used to
116+
find the relevant stack content for dumping.
117+
*/
118+
extern "C" void __wrap_system_restart_local(void);
119+
asm(
120+
".section .text.__wrap_system_restart_local,\"ax\",@progbits\n\t"
121+
".literal_position\n\t"
122+
".align 4\n\t"
123+
".global __wrap_system_restart_local\n\t"
124+
".type __wrap_system_restart_local, @function\n\t"
125+
"\n"
126+
"__wrap_system_restart_local:\n\t"
127+
"mov a2, a1\n\t"
128+
"j postmortem_report\n\t"
129+
".size __wrap_system_restart_local, .-__wrap_system_restart_local\n\t"
130+
);
131+
132+
static void postmortem_report(uint32_t sp_dump) {
117133
struct rst_info rst_info;
118134
memset(&rst_info, 0, sizeof(rst_info));
119135
if (s_user_reset_reason == REASON_DEFAULT_RST)
@@ -152,9 +168,17 @@ void __wrap_system_restart_local() {
152168
else if (rst_info.reason == REASON_EXCEPTION_RST) {
153169
// The GCC divide routine in ROM jumps to the address below and executes ILL (00 00 00) on div-by-zero
154170
// In that case, print the exception as (6) which is IntegerDivZero
155-
bool div_zero = (rst_info.exccause == 0) && (rst_info.epc1 == 0x4000dce5);
171+
uint32_t epc1 = rst_info.epc1;
172+
uint32_t exccause = rst_info.exccause;
173+
bool div_zero = (exccause == 0) && (epc1 == 0x4000dce5u);
174+
if (div_zero) {
175+
exccause = 6;
176+
// In place of the detached 'ILL' instruction., redirect attention
177+
// back to the code that called the ROM divide function.
178+
__asm__ __volatile__("rsr.excsave1 %0\n\t" : "=r"(epc1) :: "memory");
179+
}
156180
ets_printf_P(PSTR("\nException (%d):\nepc1=0x%08x epc2=0x%08x epc3=0x%08x excvaddr=0x%08x depc=0x%08x\n"),
157-
div_zero ? 6 : rst_info.exccause, rst_info.epc1, rst_info.epc2, rst_info.epc3, rst_info.excvaddr, rst_info.depc);
181+
exccause, epc1, rst_info.epc2, rst_info.epc3, rst_info.excvaddr, rst_info.depc);
158182
}
159183
else if (rst_info.reason == REASON_SOFT_WDT_RST) {
160184
ets_printf_P(PSTR("\nSoft WDT reset\n"));
@@ -174,16 +198,31 @@ void __wrap_system_restart_local() {
174198

175199
// amount of stack taken by interrupt or exception handler
176200
// and everything up to __wrap_system_restart_local
177-
// (determined empirically, might break)
201+
// ~(determined empirically, might break)~
178202
uint32_t offset = 0;
179203
if (rst_info.reason == REASON_SOFT_WDT_RST) {
180-
offset = 0x1a0;
204+
// Stack Tally
205+
// 256 User Exception vector handler reserves stack space
206+
// directed to _xtos_l1int_handler function in Boot ROM
207+
// 48 wDev_ProcessFiq - its address appears in a vector table at 0x3FFFC27C
208+
// 16 ?unnamed? - index into a table, pull out pointer, and call if non-zero
209+
// appears near near wDev_ProcessFiq
210+
// 32 pp_soft_wdt_feed_local - gather the specifics and call __wrap_system_restart_local
211+
offset = 32 + 16 + 48 + 256;
181212
}
182213
else if (rst_info.reason == REASON_EXCEPTION_RST) {
183-
offset = 0x190;
214+
// Stack Tally
215+
// 256 Exception vector reserves stack space
216+
// filled in by "C" wrapper handler
217+
// 16 Handler level 1 - enable icache
218+
// 64 Handler level 2 - exception report
219+
offset = 64 + 16 + 256;
184220
}
185221
else if (rst_info.reason == REASON_WDT_RST) {
186-
offset = 0x10;
222+
offset = 16;
223+
}
224+
else if (rst_info.reason == REASON_USER_SWEXCEPTION_RST) {
225+
offset = 16;
187226
}
188227

189228
ets_printf_P(PSTR("\n>>>stack>>>\n"));
@@ -280,8 +319,9 @@ static void raise_exception() {
280319

281320
s_user_reset_reason = REASON_USER_SWEXCEPTION_RST;
282321
ets_printf_P(PSTR("\nUser exception (panic/abort/assert)"));
283-
__wrap_system_restart_local();
284-
322+
uint32_t sp;
323+
__asm__ __volatile__ ("mov %0, a1\n\t" : "=r"(sp) :: "memory");
324+
postmortem_report(sp);
285325
while (1); // never reached, needed to satisfy "noreturn" attribute
286326
}
287327

@@ -321,7 +361,9 @@ void __stack_chk_fail(void) {
321361
if (gdb_present())
322362
__asm__ __volatile__ ("syscall"); // triggers GDB when enabled
323363

324-
__wrap_system_restart_local();
364+
uint32_t sp;
365+
__asm__ __volatile__ ("mov %0, a1\n\t" : "=r"(sp) :: "memory");
366+
postmortem_report(sp);
325367

326368
__builtin_unreachable(); // never reached, needed to satisfy "noreturn" attribute
327369
}

0 commit comments

Comments
 (0)