@@ -48,7 +48,7 @@ static const char* s_unhandled_exception = NULL;
4848
4949// Common way to notify about where the stack smashing happened
5050// (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 ;
5252
5353void abort () __attribute__((noreturn));
5454static void uart_write_char_d (char c);
@@ -59,6 +59,7 @@ static void print_stack(uint32_t start, uint32_t end);
5959// using numbers different from "REASON_" in user_interface.h (=0..6)
6060enum rst_reason_sw
6161{
62+ REASON_USER_STACK_OVERFLOW = 252 ,
6263 REASON_USER_STACK_SMASH = 253 ,
6364 REASON_USER_SWEXCEPTION_RST = 254
6465};
@@ -188,7 +189,7 @@ static void postmortem_report(uint32_t sp_dump) {
188189 }
189190 else if (rst_info.reason == REASON_SOFT_WDT_RST) {
190191 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
192193 if (is_pc_valid (rst_info.epc1 ) && 0 == memcmp_P (infinite_loop, (PGM_VOID_P)rst_info.epc1 , 3u )) {
193194 // The SDK is riddled with these. They are usually preceded by an ets_printf.
194195 ets_printf_P (PSTR (" - deliberate infinite loop detected" ));
@@ -198,17 +199,23 @@ static void postmortem_report(uint32_t sp_dump) {
198199 rst_info.exccause , /* Address executing at time of Soft WDT level-1 interrupt */ rst_info.epc1 , 0 , 0 , 0 , 0 );
199200 }
200201 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+ }
205207 else {
206208 ets_printf_P (PSTR (" \n Generic Reset\n " ));
207209 }
208210
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;
212219
213220 // amount of stack taken by interrupt or exception handler
214221 // and everything up to __wrap_system_restart_local
@@ -249,15 +256,21 @@ static void postmortem_report(uint32_t sp_dump) {
249256 sp_dump = stack_thunk_get_cont_sp ();
250257 }
251258
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+ || ((sp_dump > cont_stack_start) && (sp_dump < cont_stack_end)))
264+ {
253265 ets_printf_P (PSTR (" \n ctx: cont\n " ));
254266 stack_end = cont_stack_end;
255267 }
268+ // in system, reposition to a known address
269+ // it's actually 0x3ffffff0, but the stuff below ets_run
270+ // is likely not really relevant to the crash
256271 else {
257272 ets_printf_P (PSTR (" \n ctx: sys\n " ));
258273 stack_end = 0x3fffffb0 ;
259- // it's actually 0x3ffffff0, but the stuff below ets_run
260- // is likely not really relevant to the crash
261274 }
262275
263276 ets_printf_P (PSTR (" sp: %08x end: %08x offset: %04x\n " ), sp_dump, stack_end, offset);
@@ -296,11 +309,20 @@ static void print_stack(uint32_t start, uint32_t end) {
296309 for (uint32_t pos = start; pos < end; pos += 0x10 ) {
297310 uint32_t * values = (uint32_t *)(pos);
298311
312+ // avoid printing irrelevant data
313+ if ((values[0 ] == CONT_STACKGUARD)
314+ && (values[0 ] == values[1 ])
315+ && (values[1 ] == values[2 ])
316+ && (values[2 ] == values[3 ]))
317+ {
318+ continue ;
319+ }
320+
299321 // rough indicator: stack frames usually have SP saved as the second word
300- bool looksLikeStackFrame = (values[2 ] == pos + 0x10 );
322+ const bool looksLikeStackFrame = (values[2 ] == pos + 0x10 );
301323
302324 ets_printf_P (PSTR (" %08x: %08x %08x %08x %08x %c\n " ),
303- pos, values[0 ], values[1 ], values[2 ], values[3 ], (looksLikeStackFrame)? ' <' : ' ' );
325+ pos, values[0 ], values[1 ], values[2 ], values[3 ], (looksLikeStackFrame) ? ' <' : ' ' );
304326 }
305327}
306328
@@ -370,7 +392,7 @@ void __panic_func(const char* file, int line, const char* func) {
370392uintptr_t __stack_chk_guard = 0x08675309 ^ RANDOM_REG32;
371393void __stack_chk_fail (void ) {
372394 s_user_reset_reason = REASON_USER_STACK_SMASH;
373- s_stacksmash_addr = (uint32_t )__builtin_return_address (0 );
395+ s_stack_chk_addr = (uint32_t )__builtin_return_address (0 );
374396
375397 if (gdb_present ())
376398 __asm__ __volatile__ (" syscall" ); // triggers GDB when enabled
@@ -382,4 +404,16 @@ void __stack_chk_fail(void) {
382404 __builtin_unreachable (); // never reached, needed to satisfy "noreturn" attribute
383405}
384406
407+ void __stack_overflow (cont_t * cont, uint32_t * sp) {
408+ s_user_reset_reason = REASON_USER_STACK_OVERFLOW;
409+ s_stack_chk_addr = (uint32_t )&cont->stack [0 ];
410+
411+ if (gdb_present ())
412+ __asm__ __volatile__ (" syscall" ); // triggers GDB when enabled
413+
414+ postmortem_report ((uint32_t )sp);
415+
416+ __builtin_unreachable (); // never reached, needed to satisfy "noreturn" attribute
417+ }
418+
385419} // extern "C"
0 commit comments