@@ -48,7 +48,7 @@ static const char* s_unhandled_exception = NULL;
48
48
49
49
// Common way to notify about where the stack smashing happened
50
50
// (but, **only** if caller uses our handler function)
51
- static uint32_t s_stacksmash_addr = 0 ;
51
+ static uint32_t s_stack_chk_addr = 0 ;
52
52
53
53
void abort () __attribute__((noreturn));
54
54
static void uart_write_char_d (char c);
@@ -59,6 +59,7 @@ static void print_stack(uint32_t start, uint32_t end);
59
59
// using numbers different from "REASON_" in user_interface.h (=0..6)
60
60
enum rst_reason_sw
61
61
{
62
+ REASON_USER_STACK_OVERFLOW = 252 ,
62
63
REASON_USER_STACK_SMASH = 253 ,
63
64
REASON_USER_SWEXCEPTION_RST = 254
64
65
};
@@ -188,7 +189,7 @@ static void postmortem_report(uint32_t sp_dump) {
188
189
}
189
190
else if (rst_info.reason == REASON_SOFT_WDT_RST) {
190
191
ets_printf_P (PSTR (" \n Soft WDT reset" ));
191
- const char infinite_loop[] = { 0x06 , 0xff , 0xff }; // loop: j loop
192
+ const uint8_t infinite_loop[] = { 0x06 , 0xff , 0xff }; // loop: j loop
192
193
if (is_pc_valid (rst_info.epc1 ) && 0 == memcmp_P (infinite_loop, (PGM_VOID_P)rst_info.epc1 , 3u )) {
193
194
// The SDK is riddled with these. They are usually preceded by an ets_printf.
194
195
ets_printf_P (PSTR (" - deliberate infinite loop detected" ));
@@ -198,17 +199,23 @@ static void postmortem_report(uint32_t sp_dump) {
198
199
rst_info.exccause , /* Address executing at time of Soft WDT level-1 interrupt */ rst_info.epc1 , 0 , 0 , 0 , 0 );
199
200
}
200
201
else if (rst_info.reason == REASON_USER_STACK_SMASH) {
201
- ets_printf_P (PSTR (" \n Stack smashing detected.\n " ));
202
- ets_printf_P (PSTR (" \n Exception (%d):\n epc1=0x%08x epc2=0x%08x epc3=0x%08x excvaddr=0x%08x depc=0x%08x\n " ),
203
- 5 /* Alloca exception, closest thing to stack fault*/ , s_stacksmash_addr, 0 , 0 , 0 , 0 );
204
- }
202
+ ets_printf_P (PSTR (" \n Stack smashing detected at 0x%08x\n " ), s_stack_chk_addr);
203
+ }
204
+ else if (rst_info.reason == REASON_USER_STACK_OVERFLOW) {
205
+ ets_printf_P (PSTR (" \n Stack overflow detected\n " ));
206
+ }
205
207
else {
206
208
ets_printf_P (PSTR (" \n Generic Reset\n " ));
207
209
}
208
210
209
- uint32_t cont_stack_start = (uint32_t ) &(g_pcont->stack );
210
- uint32_t cont_stack_end = (uint32_t ) g_pcont->stack_end ;
211
- uint32_t stack_end;
211
+ uint32_t cont_stack_start;
212
+ if (rst_info.reason == REASON_USER_STACK_SMASH) {
213
+ cont_stack_start = s_stack_chk_addr;
214
+ } else {
215
+ cont_stack_start = (uint32_t ) (&g_pcont->stack [0 ]);
216
+ }
217
+
218
+ uint32_t cont_stack_end = cont_stack_start + CONT_STACKSIZE;
212
219
213
220
// amount of stack taken by interrupt or exception handler
214
221
// and everything up to __wrap_system_restart_local
@@ -249,15 +256,23 @@ static void postmortem_report(uint32_t sp_dump) {
249
256
sp_dump = stack_thunk_get_cont_sp ();
250
257
}
251
258
252
- if (sp_dump > cont_stack_start && sp_dump < cont_stack_end) {
259
+ uint32_t stack_end;
260
+
261
+ // above and inside of cont, dump from the sp to the bottom of the stack
262
+ if (rst_info.reason == REASON_USER_STACK_OVERFLOW) {
263
+ ets_printf_P (PSTR (" \n ctx: cont\n " ));
264
+ stack_end = cont_stack_end;
265
+ }
266
+ else if (sp_dump > cont_stack_start && sp_dump < cont_stack_end) {
253
267
ets_printf_P (PSTR (" \n ctx: cont\n " ));
254
268
stack_end = cont_stack_end;
255
269
}
270
+ // in system, reposition to a known address
271
+ // it's actually 0x3ffffff0, but the stuff below ets_run
272
+ // is likely not really relevant to the crash
256
273
else {
257
274
ets_printf_P (PSTR (" \n ctx: sys\n " ));
258
275
stack_end = 0x3fffffb0 ;
259
- // it's actually 0x3ffffff0, but the stuff below ets_run
260
- // is likely not really relevant to the crash
261
276
}
262
277
263
278
ets_printf_P (PSTR (" sp: %08x end: %08x offset: %04x\n " ), sp_dump, stack_end, offset);
@@ -296,11 +311,20 @@ static void print_stack(uint32_t start, uint32_t end) {
296
311
for (uint32_t pos = start; pos < end; pos += 0x10 ) {
297
312
uint32_t * values = (uint32_t *)(pos);
298
313
314
+ // avoid printing irrelevant data
315
+ if ((values[0 ] == CONT_STACKGUARD)
316
+ && (values[0 ] == values[1 ])
317
+ && (values[1 ] == values[2 ])
318
+ && (values[2 ] == values[3 ]))
319
+ {
320
+ continue ;
321
+ }
322
+
299
323
// rough indicator: stack frames usually have SP saved as the second word
300
- bool looksLikeStackFrame = (values[2 ] == pos + 0x10 );
324
+ const bool looksLikeStackFrame = (values[2 ] == pos + 0x10 );
301
325
302
326
ets_printf_P (PSTR (" %08x: %08x %08x %08x %08x %c\n " ),
303
- pos, values[0 ], values[1 ], values[2 ], values[3 ], (looksLikeStackFrame)? ' <' : ' ' );
327
+ pos, values[0 ], values[1 ], values[2 ], values[3 ], (looksLikeStackFrame) ? ' <' : ' ' );
304
328
}
305
329
}
306
330
@@ -370,7 +394,7 @@ void __panic_func(const char* file, int line, const char* func) {
370
394
uintptr_t __stack_chk_guard = 0x08675309 ^ RANDOM_REG32;
371
395
void __stack_chk_fail (void ) {
372
396
s_user_reset_reason = REASON_USER_STACK_SMASH;
373
- s_stacksmash_addr = (uint32_t )__builtin_return_address (0 );
397
+ s_stack_chk_addr = (uint32_t )__builtin_return_address (0 );
374
398
375
399
if (gdb_present ())
376
400
__asm__ __volatile__ (" syscall" ); // triggers GDB when enabled
@@ -382,4 +406,16 @@ void __stack_chk_fail(void) {
382
406
__builtin_unreachable (); // never reached, needed to satisfy "noreturn" attribute
383
407
}
384
408
409
+ void __stack_overflow (cont_t * cont, uint32_t * sp) {
410
+ s_user_reset_reason = REASON_USER_STACK_OVERFLOW;
411
+ s_stack_chk_addr = (uint32_t )&cont->stack [0 ];
412
+
413
+ if (gdb_present ())
414
+ __asm__ __volatile__ (" syscall" ); // triggers GDB when enabled
415
+
416
+ postmortem_report ((uint32_t )sp);
417
+
418
+ __builtin_unreachable (); // never reached, needed to satisfy "noreturn" attribute
419
+ }
420
+
385
421
} // extern "C"
0 commit comments