diff --git a/cores/esp8266/abi.cpp b/cores/esp8266/abi.cpp index 2670ec989..8001c185a 100644 --- a/cores/esp8266/abi.cpp +++ b/cores/esp8266/abi.cpp @@ -24,14 +24,28 @@ using __cxxabiv1::__guard; +// Debugging helper, last allocation which returned NULL +extern void *umm_last_fail_alloc_addr; +extern int umm_last_fail_alloc_size; + void *operator new(size_t size) { - return malloc(size); + void *ret = malloc(size); + if (0 != size && 0 == ret) { + umm_last_fail_alloc_addr = __builtin_return_address(0); + umm_last_fail_alloc_size = size; + } + return ret; } void *operator new[](size_t size) { - return malloc(size); + void *ret = malloc(size); + if (0 != size && 0 == ret) { + umm_last_fail_alloc_addr = __builtin_return_address(0); + umm_last_fail_alloc_size = size; + } + return ret; } void operator delete(void * ptr) diff --git a/cores/esp8266/core_esp8266_postmortem.c b/cores/esp8266/core_esp8266_postmortem.c index 971242979..fc47f4f03 100644 --- a/cores/esp8266/core_esp8266_postmortem.c +++ b/cores/esp8266/core_esp8266_postmortem.c @@ -45,6 +45,11 @@ static void uart_write_char_d(char c); static void uart0_write_char_d(char c); static void uart1_write_char_d(char c); static void print_stack(uint32_t start, uint32_t end); + +// From UMM, the last caller of a malloc/realloc/calloc which failed: +extern void *umm_last_fail_alloc_addr; +extern int umm_last_fail_alloc_size; + static void raise_exception() __attribute__((noreturn)); extern void __custom_crash_callback( struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) { @@ -137,6 +142,11 @@ void __wrap_system_restart_local() { print_stack(sp + offset, stack_end); + // Use cap-X formatting to ensure the standard EspExceptionDecoder doesn't match the address + if (umm_last_fail_alloc_addr) { + ets_printf("\nlast failed alloc call: %08X(%d)\n", (uint32_t)umm_last_fail_alloc_addr, umm_last_fail_alloc_size); + } + custom_crash_callback( &rst_info, sp + offset, stack_end ); delayMicroseconds(10000); diff --git a/cores/esp8266/heap.c b/cores/esp8266/heap.c index 49b6f1258..5f5aaef79 100644 --- a/cores/esp8266/heap.c +++ b/cores/esp8266/heap.c @@ -8,10 +8,19 @@ #include #include +// Debugging helper, last allocation which returned NULL +void *umm_last_fail_alloc_addr = NULL; +int umm_last_fail_alloc_size = 0; + void* _malloc_r(struct _reent* unused, size_t size) { (void) unused; - return malloc(size); + void *ret = malloc(size); + if (0 != size && 0 == ret) { + umm_last_fail_alloc_addr = __builtin_return_address(0); + umm_last_fail_alloc_size = size; + } + return ret; } void _free_r(struct _reent* unused, void* ptr) @@ -23,13 +32,23 @@ void _free_r(struct _reent* unused, void* ptr) void* _realloc_r(struct _reent* unused, void* ptr, size_t size) { (void) unused; - return realloc(ptr, size); + void *ret = realloc(ptr, size); + if (0 != size && 0 == ret) { + umm_last_fail_alloc_addr = __builtin_return_address(0); + umm_last_fail_alloc_size = size; + } + return ret; } void* _calloc_r(struct _reent* unused, size_t count, size_t size) { (void) unused; - return calloc(count, size); + void *ret = calloc(count, size); + if (0 != (count * size) && 0 == ret) { + umm_last_fail_alloc_addr = __builtin_return_address(0); + umm_last_fail_alloc_size = count * size; + } + return ret; } void ICACHE_RAM_ATTR vPortFree(void *ptr, const char* file, int line) diff --git a/cores/esp8266/umm_malloc/umm_malloc.c b/cores/esp8266/umm_malloc/umm_malloc.c index ac249b643..d65eac781 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.c +++ b/cores/esp8266/umm_malloc/umm_malloc.c @@ -499,6 +499,10 @@ #include "umm_malloc_cfg.h" /* user-dependent */ +// From UMM, the last caller of a malloc/realloc/calloc which failed: +extern void *umm_last_fail_alloc_addr; +extern int umm_last_fail_alloc_size; + #ifndef UMM_FIRST_FIT # ifndef UMM_BEST_FIT # define UMM_BEST_FIT @@ -1661,6 +1665,10 @@ void *umm_malloc( size_t size ) { size += POISON_SIZE(size); ret = _umm_malloc( size ); + if (0 != size && 0 == ret) { + umm_last_fail_alloc_addr = __builtin_return_address(0); + umm_last_fail_alloc_size = size; + } ret = GET_POISONED(ret, size); @@ -1688,6 +1696,10 @@ void *umm_calloc( size_t num, size_t item_size ) { if (ret) { memset(ret, 0x00, size); } + if (0 != size && 0 == ret) { + umm_last_fail_alloc_addr = __builtin_return_address(0); + umm_last_fail_alloc_size = size; + } ret = GET_POISONED(ret, size); @@ -1713,6 +1725,10 @@ void *umm_realloc( void *ptr, size_t size ) { size += POISON_SIZE(size); ret = _umm_realloc( ptr, size ); + if (0 != size && 0 == ret) { + umm_last_fail_alloc_addr = __builtin_return_address(0); + umm_last_fail_alloc_size = size; + } ret = GET_POISONED(ret, size);