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:
commit
fe907bde60
3 changed files with 54 additions and 3 deletions
|
@ -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))
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue