@@ -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 }
189190else if (rst_info.reason == REASON_SOFT_WDT_RST) {
190191ets_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
192193if (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.
194195ets_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 }
200201else 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+ }
205207else {
206208ets_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+ {
253265ets_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
256271else {
257272ets_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
263276ets_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) {
296309for (uint32_t pos = start; pos < end; pos +=0x10 ) {
297310uint32_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
302324ets_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
375397if (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"