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
This commit is contained in:
Angus Gratton 2018-02-28 11:00:45 +11:00 committed by Angus Gratton
parent b626c1b365
commit d3b8f1f927
3 changed files with 54 additions and 3 deletions

View file

@ -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))

View file

@ -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);
}

View file

@ -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