From d3b8f1f92746e9b9474275141aef510156e3f51d Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 28 Feb 2018 11:00:45 +1100 Subject: [PATCH] heap tracing: Fix tracing of newlib internal allocations Newlib internal allocations (from newlib ROM code) were not being included in the heap trace. Ref https://github.com/espressif/esp-idf/issues/1652 --- components/heap/component.mk | 2 +- components/heap/heap_trace.c | 16 +++++++++-- components/heap/test/test_heap_trace.c | 39 ++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/components/heap/component.mk b/components/heap/component.mk index 8c57271d4a..77fd799717 100644 --- a/components/heap/component.mk +++ b/components/heap/component.mk @@ -14,7 +14,7 @@ endif ifdef CONFIG_HEAP_TRACING -WRAP_FUNCTIONS = calloc malloc free realloc heap_caps_malloc heap_caps_free heap_caps_realloc +WRAP_FUNCTIONS = calloc malloc free realloc heap_caps_malloc heap_caps_free heap_caps_realloc heap_caps_malloc_default heap_caps_realloc_default WRAP_ARGUMENT := -Wl,--wrap= COMPONENT_ADD_LDFLAGS = -l$(COMPONENT_NAME) $(addprefix $(WRAP_ARGUMENT),$(WRAP_FUNCTIONS)) diff --git a/components/heap/heap_trace.c b/components/heap/heap_trace.c index b7ef48514e..04ae69431c 100644 --- a/components/heap/heap_trace.c +++ b/components/heap/heap_trace.c @@ -312,6 +312,8 @@ typedef enum { void *__real_heap_caps_malloc(size_t size, uint32_t caps); +void *__real_heap_caps_malloc_default( size_t size ); +void *__real_heap_caps_realloc_default( void *ptr, size_t size ); /* trace any 'malloc' event */ static IRAM_ATTR __attribute__((noinline)) void *trace_malloc(size_t size, uint32_t caps, trace_malloc_mode_t mode) @@ -321,7 +323,7 @@ static IRAM_ATTR __attribute__((noinline)) void *trace_malloc(size_t size, uint3 if ( mode == TRACE_MALLOC_CAPS ) { p = __real_heap_caps_malloc(size, caps); } else { //TRACE_MALLOC_DEFAULT - p = heap_caps_malloc_default(size); + p = __real_heap_caps_malloc_default(size); } if (tracing && p != NULL) { @@ -364,7 +366,7 @@ static IRAM_ATTR __attribute__((noinline)) void *trace_realloc(void *p, size_t s if (mode == TRACE_MALLOC_CAPS ) { r = __real_heap_caps_realloc(p, size, caps); } else { //TRACE_MALLOC_DEFAULT - r = heap_caps_realloc_default(p, size); + r = __real_heap_caps_realloc_default(p, size); } if (tracing && r != NULL) { get_call_stack(callers); @@ -423,3 +425,13 @@ IRAM_ATTR void *__wrap_heap_caps_realloc(void *p, size_t size, uint32_t caps) { return trace_realloc(p, size, caps, TRACE_MALLOC_CAPS); } + +IRAM_ATTR void *__wrap_heap_caps_malloc_default( size_t size ) +{ + return trace_malloc(size, 0, TRACE_MALLOC_DEFAULT); +} + +IRAM_ATTR void *__wrap_heap_caps_realloc_default( void *ptr, size_t size ) +{ + return trace_realloc(ptr, size, 0, TRACE_MALLOC_DEFAULT); +} diff --git a/components/heap/test/test_heap_trace.c b/components/heap/test/test_heap_trace.c index ccec5daf7c..909aa31b5c 100644 --- a/components/heap/test/test_heap_trace.c +++ b/components/heap/test/test_heap_trace.c @@ -11,6 +11,9 @@ #include "sdkconfig.h" #include "unity.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + #ifdef CONFIG_HEAP_TRACING // only compile in heap tracing tests if tracing is enabled @@ -120,6 +123,42 @@ TEST_CASE("heap trace wrapped buffer check", "[heap]") heap_trace_stop(); } +static void print_floats_task(void *ignore) +{ + heap_trace_start(HEAP_TRACE_ALL); + char buf[16] = { }; + volatile float f = 12.3456; + sprintf(buf, "%.4f", f); + TEST_ASSERT_EQUAL_STRING("12.3456", buf); + heap_trace_stop(); + + vTaskDelete(NULL); +} + +TEST_CASE("can trace allocations made by newlib", "[heap]") +{ + const size_t N = 8; + heap_trace_record_t recs[N]; + heap_trace_init_standalone(recs, N); + + /* Verifying that newlib code performs an allocation is very fiddly: + + - Printing a float allocates data associated with the task, but only the + first time a task prints a float of this length. So we do it in a one-shot task + to avoid possibility it already happened. + + - If newlib is updated this test may start failing if the printf() implementation + changes. (This version passes for both nano & regular formatting in newlib 2.2.0) + + - We also do the tracing in the task so we only capture things directly related to it. + */ + + xTaskCreate(print_floats_task, "print_float", 4096, NULL, 5, NULL); + vTaskDelay(10); + + /* has to be at least a few as newlib allocates via multiple different function calls */ + TEST_ASSERT(heap_trace_get_count() > 3); +} #endif