Merge branch 'bugfix/heap_tracing_newlib_allocations' into 'master'

heap tracing: Fix tracing of newlib internal allocations

See merge request idf/esp-idf!1992
This commit is contained in:
Angus Gratton 2018-04-18 12:07:15 +08:00
commit fe907bde60
3 changed files with 54 additions and 3 deletions

View file

@ -14,7 +14,7 @@ endif
ifdef CONFIG_HEAP_TRACING 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= WRAP_ARGUMENT := -Wl,--wrap=
COMPONENT_ADD_LDFLAGS = -l$(COMPONENT_NAME) $(addprefix $(WRAP_ARGUMENT),$(WRAP_FUNCTIONS)) 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(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 */ /* trace any 'malloc' event */
static IRAM_ATTR __attribute__((noinline)) void *trace_malloc(size_t size, uint32_t caps, trace_malloc_mode_t mode) 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 ) { if ( mode == TRACE_MALLOC_CAPS ) {
p = __real_heap_caps_malloc(size, caps); p = __real_heap_caps_malloc(size, caps);
} else { //TRACE_MALLOC_DEFAULT } else { //TRACE_MALLOC_DEFAULT
p = heap_caps_malloc_default(size); p = __real_heap_caps_malloc_default(size);
} }
if (tracing && p != NULL) { 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 ) { if (mode == TRACE_MALLOC_CAPS ) {
r = __real_heap_caps_realloc(p, size, caps); r = __real_heap_caps_realloc(p, size, caps);
} else { //TRACE_MALLOC_DEFAULT } else { //TRACE_MALLOC_DEFAULT
r = heap_caps_realloc_default(p, size); r = __real_heap_caps_realloc_default(p, size);
} }
if (tracing && r != NULL) { if (tracing && r != NULL) {
get_call_stack(callers); 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); 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 "sdkconfig.h"
#include "unity.h" #include "unity.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#ifdef CONFIG_HEAP_TRACING #ifdef CONFIG_HEAP_TRACING
// only compile in heap tracing tests if tracing is enabled // 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(); 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 #endif