]> granicus.if.org Git - esp-idf/commitdiff
heap tracing: Fix tracing of newlib internal allocations
authorAngus Gratton <angus@espressif.com>
Wed, 28 Feb 2018 00:00:45 +0000 (11:00 +1100)
committerAngus Gratton <gus@projectgus.com>
Tue, 20 Mar 2018 01:03:46 +0000 (12:03 +1100)
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
components/heap/heap_trace.c
components/heap/test/test_heap_trace.c

index 8c57271d4a25c0946d7e1c827e1b1085f8c545e0..77fd7997170186981deb955f05b0f85b37ade4d6 100644 (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))
index b7ef48514e71d264fc3c2d2b58896d5cb3039306..04ae69431c27d3beedde744b44f29733906a74db 100644 (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);
+}
index ccec5daf7c45940adf834d286879d261e9161d7a..909aa31b5cdd53e79222d2232b693d59a7ff170b 100644 (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