From 1e0cdcbd132ab284187f62ca346de68ba4aba439 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Thu, 12 Sep 2024 16:24:33 +0800 Subject: [PATCH] feat(heap): enable heap tracing for the RISC-V targets When the frame pointer is enabled, it is possible for RISC-V targets to now possible to enable and generate heap call traces. --- components/app_trace/CMakeLists.txt | 6 +-- components/app_trace/heap_trace_tohost.c | 8 ++-- components/heap/Kconfig | 9 ++-- components/heap/heap_trace_standalone.c | 8 +--- components/heap/include/esp_heap_trace.h | 4 -- components/heap/include/heap_trace.inc | 46 +++++++++++-------- .../heap/test_apps/heap_tests/pytest_heap.py | 14 +++--- .../heap_tests/sdkconfig.ci.heap_trace | 3 -- ... => sdkconfig.ci.heap_trace_hashmap_esp32} | 0 .../sdkconfig.ci.heap_trace_hashmap_esp32c3 | 5 ++ .../main/sysview_heap_log.c | 4 +- .../sdkconfig.defaults | 2 + 12 files changed, 54 insertions(+), 55 deletions(-) delete mode 100644 components/heap/test_apps/heap_tests/sdkconfig.ci.heap_trace rename components/heap/test_apps/heap_tests/{sdkconfig.ci.heap_trace_hashmap => sdkconfig.ci.heap_trace_hashmap_esp32} (100%) create mode 100644 components/heap/test_apps/heap_tests/sdkconfig.ci.heap_trace_hashmap_esp32c3 diff --git a/components/app_trace/CMakeLists.txt b/components/app_trace/CMakeLists.txt index 353b3dc14c..11dc85b869 100644 --- a/components/app_trace/CMakeLists.txt +++ b/components/app_trace/CMakeLists.txt @@ -60,9 +60,9 @@ endif() if(CONFIG_HEAP_TRACING_TOHOST) list(APPEND srcs "heap_trace_tohost.c") - set_source_files_properties(heap_trace_tohost.c - PROPERTIES COMPILE_FLAGS - -Wno-frame-address) + if(CONFIG_IDF_TARGET_ARCH_XTENSA) + set_source_files_properties(heap_trace_tohost.c PROPERTIES COMPILE_FLAGS -Wno-frame-address) + endif() endif() idf_component_register(SRCS "${srcs}" diff --git a/components/app_trace/heap_trace_tohost.c b/components/app_trace/heap_trace_tohost.c index 7a52294f5c..3175932a71 100644 --- a/components/app_trace/heap_trace_tohost.c +++ b/components/app_trace/heap_trace_tohost.c @@ -1,13 +1,11 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ -#include +#include "sdkconfig.h" -#define HEAP_TRACE_SRCFILE /* don't warn on inclusion here */ #include "esp_heap_trace.h" -#undef HEAP_TRACE_SRCFILE #include "esp_heap_caps.h" #if CONFIG_APPTRACE_SV_ENABLE #include "esp_app_trace.h" @@ -16,7 +14,7 @@ #define STACK_DEPTH CONFIG_HEAP_TRACING_STACK_DEPTH -#ifdef CONFIG_HEAP_TRACING_TOHOST +#if CONFIG_HEAP_TRACING_TOHOST #if !CONFIG_APPTRACE_SV_ENABLE #error None of the heap tracing backends is enabled! You must enable SystemView compatible tracing to use this feature. diff --git a/components/heap/Kconfig b/components/heap/Kconfig index 6bcc7ab7d1..d40b64fcee 100644 --- a/components/heap/Kconfig +++ b/components/heap/Kconfig @@ -31,15 +31,14 @@ menu "Heap memory debugging" bool "Disabled" config HEAP_TRACING_STANDALONE bool "Standalone" - select HEAP_TRACING config HEAP_TRACING_TOHOST bool "Host-based" - select HEAP_TRACING endchoice config HEAP_TRACING bool - default F + default n if HEAP_TRACING_OFF + default y if !HEAP_TRACING_OFF help Enables/disables heap tracing API. @@ -76,8 +75,8 @@ menu "Heap memory debugging" config HEAP_TRACING_STACK_DEPTH int "Heap tracing stack depth" - range 0 0 if IDF_TARGET_ARCH_RISCV # Disabled for RISC-V due to `__builtin_return_address` limitation - default 0 if IDF_TARGET_ARCH_RISCV + range 0 0 if IDF_TARGET_ARCH_RISCV && !ESP_SYSTEM_USE_FRAME_POINTER + default 0 if IDF_TARGET_ARCH_RISCV && !ESP_SYSTEM_USE_FRAME_POINTER range 0 32 default 2 depends on HEAP_TRACING diff --git a/components/heap/heap_trace_standalone.c b/components/heap/heap_trace_standalone.c index 00c66162a1..01e7607bfc 100644 --- a/components/heap/heap_trace_standalone.c +++ b/components/heap/heap_trace_standalone.c @@ -4,13 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ #include -#include +#include "sdkconfig.h" #include #include "esp_log.h" -#define HEAP_TRACE_SRCFILE /* don't warn on inclusion here */ #include "esp_heap_trace.h" -#undef HEAP_TRACE_SRCFILE #include "esp_heap_caps.h" #include "esp_attr.h" #include "freertos/FreeRTOS.h" @@ -22,8 +20,6 @@ static __attribute__((unused)) const char* TAG = "heaptrace"; #define STACK_DEPTH CONFIG_HEAP_TRACING_STACK_DEPTH -#if CONFIG_HEAP_TRACING_STANDALONE - typedef enum { TRACING_STARTED, // start recording allocs and free TRACING_STOPPED, // stop recording allocs and free @@ -672,5 +668,3 @@ static HEAP_IRAM_ATTR void list_find_and_remove(void* p) } #include "heap_trace.inc" - -#endif // CONFIG_HEAP_TRACING_STANDALONE diff --git a/components/heap/include/esp_heap_trace.h b/components/heap/include/esp_heap_trace.h index d6a4431074..d6430a1fb2 100644 --- a/components/heap/include/esp_heap_trace.h +++ b/components/heap/include/esp_heap_trace.h @@ -15,10 +15,6 @@ extern "C" { #endif -#if !defined(CONFIG_HEAP_TRACING) && !defined(HEAP_TRACE_SRCFILE) -#warning "esp_heap_trace.h is included but heap tracing is disabled in menuconfig, functions are no-ops" -#endif - #ifndef CONFIG_HEAP_TRACING_STACK_DEPTH #define CONFIG_HEAP_TRACING_STACK_DEPTH 0 #endif diff --git a/components/heap/include/heap_trace.inc b/components/heap/include/heap_trace.inc index 6ac08a034e..d409ee8329 100644 --- a/components/heap/include/heap_trace.inc +++ b/components/heap/include/heap_trace.inc @@ -1,18 +1,10 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include -#include +#include "sdkconfig.h" #include "soc/soc_memory_layout.h" #include "esp_attr.h" #include "esp_cpu.h" @@ -31,11 +23,8 @@ inline static uint32_t get_ccount(void) /* Architecture-specific return value of __builtin_return_address which * should be interpreted as an invalid address. */ -#ifdef __XTENSA__ +#if CONFIG_IDF_TARGET_ARCH_XTENSA #define HEAP_ARCH_INVALID_PC 0x40000000 -#else -#define HEAP_ARCH_INVALID_PC 0x00000000 -#endif // Caller is 2 stack frames deeper than we care about #define STACK_OFFSET 2 @@ -94,6 +83,27 @@ static HEAP_IRAM_ATTR __attribute__((noinline)) void get_call_stack(void **calle TEST_STACK(31); } +#else // !CONFIG_IDF_TARGET_ARCH_XTENSA + +extern uint32_t esp_fp_get_callers(uint32_t frame, void** callers, void** stacks, uint32_t depth); + +static HEAP_IRAM_ATTR __attribute__((noinline)) void get_call_stack(void **callers) +{ + uint32_t fp = (uint32_t) __builtin_frame_address(0); + memset(callers, 0, sizeof(void *) * STACK_DEPTH); + +#if CONFIG_ESP_SYSTEM_USE_FRAME_POINTER + /* We can skip the current return address since this function won't be inlined */ + esp_fp_get_callers(fp, callers, NULL, STACK_DEPTH); +#else + /* RISC-V compiler doesn't support `__builtin_frame_address` with a parameter bigger than 0 */ + callers[0] = (void*) fp; +#endif +} + +#endif + + ESP_STATIC_ASSERT(STACK_DEPTH >= 0 && STACK_DEPTH <= 32, "CONFIG_HEAP_TRACING_STACK_DEPTH must be in range 0-32"); typedef enum { diff --git a/components/heap/test_apps/heap_tests/pytest_heap.py b/components/heap/test_apps/heap_tests/pytest_heap.py index 6f0c710bc2..36f0f07e74 100644 --- a/components/heap/test_apps/heap_tests/pytest_heap.py +++ b/components/heap/test_apps/heap_tests/pytest_heap.py @@ -94,17 +94,15 @@ def test_heap_misc_options(dut: Dut) -> None: @pytest.mark.generic -@pytest.mark.parametrize( - 'target', - [ - 'esp32', - ] -) +@pytest.mark.esp32 +@pytest.mark.esp32c3 @pytest.mark.parametrize( 'config', [ - 'heap_trace', - 'heap_trace_hashmap' + pytest.param('heap_trace_esp32', marks=[pytest.mark.esp32]), + pytest.param('heap_trace_hashmap_esp32', marks=[pytest.mark.esp32]), + pytest.param('heap_trace_esp32c3', marks=[pytest.mark.esp32c3]), + pytest.param('heap_trace_hashmap_esp32c3', marks=[pytest.mark.esp32c3]) ] ) def test_heap_trace_dump(dut: Dut) -> None: diff --git a/components/heap/test_apps/heap_tests/sdkconfig.ci.heap_trace b/components/heap/test_apps/heap_tests/sdkconfig.ci.heap_trace deleted file mode 100644 index f14177fa36..0000000000 --- a/components/heap/test_apps/heap_tests/sdkconfig.ci.heap_trace +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_IDF_TARGET="esp32" -CONFIG_SPIRAM=y -CONFIG_HEAP_TRACING_STANDALONE=y diff --git a/components/heap/test_apps/heap_tests/sdkconfig.ci.heap_trace_hashmap b/components/heap/test_apps/heap_tests/sdkconfig.ci.heap_trace_hashmap_esp32 similarity index 100% rename from components/heap/test_apps/heap_tests/sdkconfig.ci.heap_trace_hashmap rename to components/heap/test_apps/heap_tests/sdkconfig.ci.heap_trace_hashmap_esp32 diff --git a/components/heap/test_apps/heap_tests/sdkconfig.ci.heap_trace_hashmap_esp32c3 b/components/heap/test_apps/heap_tests/sdkconfig.ci.heap_trace_hashmap_esp32c3 new file mode 100644 index 0000000000..a1a6476d86 --- /dev/null +++ b/components/heap/test_apps/heap_tests/sdkconfig.ci.heap_trace_hashmap_esp32c3 @@ -0,0 +1,5 @@ +CONFIG_IDF_TARGET="esp32c3" +CONFIG_ESP_SYSTEM_USE_FRAME_POINTER=y +CONFIG_HEAP_TRACING_STANDALONE=y +CONFIG_HEAP_TRACE_HASH_MAP=y +CONFIG_HEAP_TRACE_HASH_MAP_SIZE=10 diff --git a/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c b/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c index f07b6c821b..87b0031d07 100644 --- a/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c +++ b/examples/system/sysview_tracing_heap_log/main/sysview_heap_log.c @@ -53,7 +53,7 @@ static void alloc_task(void *p) snprintf(task_name, sizeof(task_name), "free%d", task_args->idx); xTaskCreatePinnedToCore(free_task, task_name, 2500, queue, 5, NULL, CONFIG_FREERTOS_NUMBER_OF_CORES-1); - // here GDB will stop at brekpoint and execute OpenOCD command to start tracing + // here GDB will stop at breakpoint and execute OpenOCD command to start tracing for(int i = 1; i < 10; i++) { uint32_t sz = 2*i*(task_args->idx + 1); void *p = malloc(sz/2); @@ -100,6 +100,6 @@ void app_main(void) uint32_t val = ulTaskNotifyTake(pdFALSE, portMAX_DELAY); ESP_LOGI(TAG, "Got notify val %"PRIu32, val); } - // here GDB will stop at brekpoint and execute OpenOCD command to stop tracing + // here GDB will stop at breakpoint and execute OpenOCD command to stop tracing heap_trace_stop(); } diff --git a/examples/system/sysview_tracing_heap_log/sdkconfig.defaults b/examples/system/sysview_tracing_heap_log/sdkconfig.defaults index 140b5dbac7..0d2f661c0e 100644 --- a/examples/system/sysview_tracing_heap_log/sdkconfig.defaults +++ b/examples/system/sysview_tracing_heap_log/sdkconfig.defaults @@ -24,3 +24,5 @@ CONFIG_APPTRACE_SV_EVT_TIMER_EXIT_ENABLE=y CONFIG_LOG_COLORS=n # Enable heap tracing to host CONFIG_HEAP_TRACING_TOHOST=y +# For RISC-V targets +CONFIG_ESP_SYSTEM_USE_FRAME_POINTER=y