Skip to content

Ultra-low overhead record last failed memory allocation, dump on a panic #4220

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions cores/esp8266/abi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 10 additions & 0 deletions cores/esp8266/core_esp8266_postmortem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) {
Expand Down Expand Up @@ -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);
Expand Down
25 changes: 22 additions & 3 deletions cores/esp8266/heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,19 @@
#include <c_types.h>
#include <sys/reent.h>

// 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)
Expand All @@ -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)
Expand Down
16 changes: 16 additions & 0 deletions cores/esp8266/umm_malloc/umm_malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);

Expand All @@ -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);

Expand Down