From 5cc69ce12bb028b2e83d511a570dad4ad9e912d9 Mon Sep 17 00:00:00 2001 From: Guillaume Souchere Date: Wed, 14 Feb 2024 13:03:09 +0100 Subject: [PATCH 1/3] feat(heap): Add walker to the heap component Introduce new APIs in essp_heap_caps.h: - heap_caps_walk() - heap_caps_walk_all() Those functions are triggering a callback for all blocks (allocated or free) of memory present in heaps meeting the set of capabilities passed as parameter (or all heaps for heap_caps_walk_all() function) test_walker.c added to test the new functionality in test_apps/heap_test/ --- components/esp_rom/CMakeLists.txt | 11 +++ .../esp_rom/esp32c2/Kconfig.soc_caps.in | 4 + components/esp_rom/esp32c2/esp_rom_caps.h | 1 + .../esp_rom/esp32c5/Kconfig.soc_caps.in | 78 +++++++++++++++++++ .../esp32c5/beta3/esp32c5/esp_rom_caps.h | 1 + .../esp_rom/esp32c6/Kconfig.soc_caps.in | 4 + components/esp_rom/esp32c6/esp_rom_caps.h | 1 + .../esp_rom/esp32h2/Kconfig.soc_caps.in | 4 + components/esp_rom/esp32h2/esp_rom_caps.h | 1 + .../esp_rom/include/esp_rom_multi_heap.h | 40 ++++++++++ .../esp_rom/patches/esp_rom_multi_heap.c | 58 ++++++++++++++ components/heap/heap_caps.c | 49 +++++++++++- components/heap/include/esp_heap_caps.h | 44 ++++++++++- components/heap/include/multi_heap.h | 22 +++++- components/heap/multi_heap.c | 18 +++-- .../test_apps/heap_tests/main/CMakeLists.txt | 3 +- .../test_apps/heap_tests/main/test_walker.c | 55 +++++++++++++ 17 files changed, 384 insertions(+), 10 deletions(-) create mode 100644 components/esp_rom/include/esp_rom_multi_heap.h create mode 100644 components/esp_rom/patches/esp_rom_multi_heap.c create mode 100644 components/heap/test_apps/heap_tests/main/test_walker.c diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index dd4cc19a9a..9b9872b1da 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -49,6 +49,11 @@ else() list(APPEND sources "patches/esp_rom_tlsf.c") endif() + if(CONFIG_HEAP_TLSF_USE_ROM_IMPL AND CONFIG_ESP_ROM_MULTI_HEAP_WALK_PATCH) + # This file shall be included in the build if TLSF in ROM is activated + list(APPEND sources "patches/esp_rom_multi_heap.c") + endif() + list(APPEND private_required_comp soc hal) endif() @@ -64,6 +69,8 @@ if(CONFIG_HAL_WDT_USE_ROM_IMPL) list(APPEND sources "patches/esp_rom_wdt.c") endif() + + if(CONFIG_ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG OR CONFIG_ESP_ROM_HAS_CACHE_WRITEBACK_BUG) list(APPEND sources "patches/esp_rom_cache_esp32s2_esp32s3.c") endif() @@ -216,6 +223,10 @@ else() # Regular app build target_link_libraries(${COMPONENT_LIB} PRIVATE "-u tlsf_set_rom_patches") endif() + if((CONFIG_ESP_ROM_TLSF_CHECK_PATCH OR CONFIG_ESP_ROM_MULTI_HEAP_WALK_PATCH)) + target_link_libraries(${COMPONENT_LIB} PRIVATE "-u esp_rom_include_multi_heap_patch") + endif() + rom_linker_script("heap") endif() diff --git a/components/esp_rom/esp32c2/Kconfig.soc_caps.in b/components/esp_rom/esp32c2/Kconfig.soc_caps.in index ca4d67e28a..19913c950b 100644 --- a/components/esp_rom/esp32c2/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32c2/Kconfig.soc_caps.in @@ -39,6 +39,10 @@ config ESP_ROM_HAS_HEAP_TLSF bool default y +config ESP_ROM_MULTI_HEAP_WALK_PATCH + bool + default y + config ESP_ROM_HAS_LAYOUT_TABLE bool default y diff --git a/components/esp_rom/esp32c2/esp_rom_caps.h b/components/esp_rom/esp32c2/esp_rom_caps.h index eb7284de4c..9c71f9b9e2 100644 --- a/components/esp_rom/esp32c2/esp_rom_caps.h +++ b/components/esp_rom/esp32c2/esp_rom_caps.h @@ -15,6 +15,7 @@ #define ESP_ROM_HAS_HAL_WDT (1) // ROM has the implementation of Watchdog HAL driver #define ESP_ROM_HAS_HAL_SYSTIMER (1) // ROM has the implementation of Systimer HAL driver #define ESP_ROM_HAS_HEAP_TLSF (1) // ROM has the implementation of the tlsf and multi-heap library +#define ESP_ROM_MULTI_HEAP_WALK_PATCH (1) // ROM does not contain the patch of multi_heap_walk() #define ESP_ROM_HAS_LAYOUT_TABLE (1) // ROM has the layout table #define ESP_ROM_HAS_SPI_FLASH (1) // ROM has the implementation of SPI Flash driver #define ESP_ROM_HAS_NEWLIB (1) // ROM has newlib (at least parts of it) functions included diff --git a/components/esp_rom/esp32c5/Kconfig.soc_caps.in b/components/esp_rom/esp32c5/Kconfig.soc_caps.in index 20c519bbcb..4f1584f9b3 100644 --- a/components/esp_rom/esp32c5/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32c5/Kconfig.soc_caps.in @@ -7,6 +7,84 @@ if IDF_TARGET_ESP32C5_BETA3_VERSION source "$IDF_PATH/components/esp_rom/esp32c5/beta3/esp32c5/Kconfig.soc_caps.in" endif +<<<<<<< HEAD if IDF_TARGET_ESP32C5_MP_VERSION source "$IDF_PATH/components/esp_rom/esp32c5/mp/esp32c5/Kconfig.soc_caps.in" endif +======= +config ESP_ROM_HAS_CRC_BE + bool + default y + +config ESP_ROM_HAS_JPEG_DECODE + bool + default y + +config ESP_ROM_UART_CLK_IS_XTAL + bool + default y + +config ESP_ROM_USB_SERIAL_DEVICE_NUM + int + default 3 + +config ESP_ROM_HAS_RETARGETABLE_LOCKING + bool + default y + +config ESP_ROM_GET_CLK_FREQ + bool + default y + +config ESP_ROM_HAS_RVFPLIB + bool + default y + +config ESP_ROM_HAS_HAL_WDT + bool + default y + +config ESP_ROM_HAS_HAL_SYSTIMER + bool + default y + +config ESP_ROM_HAS_HEAP_TLSF + bool + default y + +config ESP_ROM_TLSF_CHECK_PATCH + bool + default y + +config ESP_ROM_MULTI_HEAP_WALK_PATCH + bool + default y + +config ESP_ROM_HAS_LAYOUT_TABLE + bool + default y + +config ESP_ROM_HAS_SPI_FLASH + bool + default y + +config ESP_ROM_WITHOUT_REGI2C + bool + default y + +config ESP_ROM_HAS_NEWLIB_NORMAL_FORMAT + bool + default y + +config ESP_ROM_WDT_INIT_PATCH + bool + default y + +config ESP_ROM_RAM_APP_NEEDS_MMU_INIT + bool + default y + +config ESP_ROM_USB_OTG_NUM + int + default -1 +>>>>>>> 9468f4df09 (feat(heap): Add walker to the heap component) diff --git a/components/esp_rom/esp32c5/beta3/esp32c5/esp_rom_caps.h b/components/esp_rom/esp32c5/beta3/esp32c5/esp_rom_caps.h index 00e7cfed2e..d6ecb2c6a9 100644 --- a/components/esp_rom/esp32c5/beta3/esp32c5/esp_rom_caps.h +++ b/components/esp_rom/esp32c5/beta3/esp32c5/esp_rom_caps.h @@ -18,6 +18,7 @@ #define ESP_ROM_HAS_HAL_SYSTIMER (1) // ROM has the implementation of Systimer HAL driver #define ESP_ROM_HAS_HEAP_TLSF (1) // ROM has the implementation of the tlsf and multi-heap library #define ESP_ROM_TLSF_CHECK_PATCH (1) // ROM does not contain the patch of tlsf_check_pool() +#define ESP_ROM_MULTI_HEAP_WALK_PATCH (1) // ROM does not contain the patch of multi_heap_walk() #define ESP_ROM_HAS_LAYOUT_TABLE (1) // ROM has the layout table #define ESP_ROM_HAS_SPI_FLASH (1) // ROM has the implementation of SPI Flash driver #define ESP_ROM_WITHOUT_REGI2C (1) // ROM has no regi2c APIs diff --git a/components/esp_rom/esp32c6/Kconfig.soc_caps.in b/components/esp_rom/esp32c6/Kconfig.soc_caps.in index 3a2a837056..f117be963f 100644 --- a/components/esp_rom/esp32c6/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32c6/Kconfig.soc_caps.in @@ -51,6 +51,10 @@ config ESP_ROM_TLSF_CHECK_PATCH bool default y +config ESP_ROM_MULTI_HEAP_WALK_PATCH + bool + default y + config ESP_ROM_HAS_LAYOUT_TABLE bool default y diff --git a/components/esp_rom/esp32c6/esp_rom_caps.h b/components/esp_rom/esp32c6/esp_rom_caps.h index 1fb9480849..2b448d3d70 100644 --- a/components/esp_rom/esp32c6/esp_rom_caps.h +++ b/components/esp_rom/esp32c6/esp_rom_caps.h @@ -18,6 +18,7 @@ #define ESP_ROM_HAS_HAL_SYSTIMER (1) // ROM has the implementation of Systimer HAL driver #define ESP_ROM_HAS_HEAP_TLSF (1) // ROM has the implementation of the tlsf and multi-heap library #define ESP_ROM_TLSF_CHECK_PATCH (1) // ROM does not contain the patch of tlsf_check_pool() +#define ESP_ROM_MULTI_HEAP_WALK_PATCH (1) // ROM does not contain the patch of multi_heap_walk() #define ESP_ROM_HAS_LAYOUT_TABLE (1) // ROM has the layout table #define ESP_ROM_HAS_SPI_FLASH (1) // ROM has the implementation of SPI Flash driver #define ESP_ROM_HAS_REGI2C_BUG (1) // ROM has the regi2c bug diff --git a/components/esp_rom/esp32h2/Kconfig.soc_caps.in b/components/esp_rom/esp32h2/Kconfig.soc_caps.in index e6a8376ae5..d43ea1a707 100644 --- a/components/esp_rom/esp32h2/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32h2/Kconfig.soc_caps.in @@ -43,6 +43,10 @@ config ESP_ROM_TLSF_CHECK_PATCH bool default y +config ESP_ROM_MULTI_HEAP_WALK_PATCH + bool + default y + config ESP_ROM_HAS_LAYOUT_TABLE bool default y diff --git a/components/esp_rom/esp32h2/esp_rom_caps.h b/components/esp_rom/esp32h2/esp_rom_caps.h index 186b94a09a..4ff14f74ac 100644 --- a/components/esp_rom/esp32h2/esp_rom_caps.h +++ b/components/esp_rom/esp32h2/esp_rom_caps.h @@ -16,6 +16,7 @@ #define ESP_ROM_HAS_HAL_SYSTIMER (1) // ROM has the implementation of Systimer HAL driver #define ESP_ROM_HAS_HEAP_TLSF (1) // ROM has the implementation of the tlsf and multi-heap library #define ESP_ROM_TLSF_CHECK_PATCH (1) // ROM does not contain the patch of tlsf_check_pool() +#define ESP_ROM_MULTI_HEAP_WALK_PATCH (1) // ROM does not contain the patch of multi_heap_walk() #define ESP_ROM_HAS_LAYOUT_TABLE (1) // ROM has the layout table #define ESP_ROM_HAS_SPI_FLASH (1) // ROM has the implementation of SPI Flash driver #define ESP_ROM_WITHOUT_REGI2C (1) // ROM has no regi2c APIs diff --git a/components/esp_rom/include/esp_rom_multi_heap.h b/components/esp_rom/include/esp_rom_multi_heap.h new file mode 100644 index 0000000000..c7dfa493ae --- /dev/null +++ b/components/esp_rom/include/esp_rom_multi_heap.h @@ -0,0 +1,40 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Opaque handle to a registered heap */ +typedef struct multi_heap_info *multi_heap_handle_t; + +/** + * @brief Callback called when walking the given heap blocks of memory + * + * @param block_ptr Pointer to the block data + * @param block_size The size of the block + * @param block_used Block status. True if free, false if used + * @param user_data Opaque pointer to user defined data + */ +typedef void (*multi_heap_walker_cb_t)(void *block_ptr, size_t block_size, int block_used, void *user_data); + +/** + * @brief Call the tlsf_walk_pool function of the heap given as parameter with + * the walker function passed as parameter + * + * @param heap The heap to traverse + * @param walker_func The walker to trigger on each block of the heap + * @param user_data Opaque pointer to user defined data + */ +void multi_heap_walk(multi_heap_handle_t heap, multi_heap_walker_cb_t walker_func, void *user_data); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_rom/patches/esp_rom_multi_heap.c b/components/esp_rom/patches/esp_rom_multi_heap.c new file mode 100644 index 0000000000..4690bfe4e4 --- /dev/null +++ b/components/esp_rom/patches/esp_rom_multi_heap.c @@ -0,0 +1,58 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This file is a patch for the multi_heap.c file stored in ROM + * - added function multi_heap_walk + * - added function multi_heap_walker + * - added structure walker_data_t + */ + +#include +#include +#include + +#include "esp_rom_multi_heap.h" + +// Hook to force the linker to include this file +void esp_rom_include_multi_heap_patch(void) +{ +} + +/*! + * @brief Opaque types for TLSF implementation + */ +typedef void* tlsf_t; +typedef void* pool_t; +typedef void* tlsf_walker; + +typedef struct multi_heap_info { + void *lock; + size_t free_bytes; + size_t minimum_free_bytes; + size_t pool_size; + void* heap_data; +} heap_t; + +typedef struct walker_data { + void *opaque_ptr; + multi_heap_walker_cb_t walker; + multi_heap_handle_t heap; +} walker_data_t; + +extern void tlsf_walk_pool(pool_t pool, tlsf_walker walker, void* user); +extern pool_t tlsf_get_pool(tlsf_t tlsf); +extern void multi_heap_internal_lock(multi_heap_handle_t heap); +extern void multi_heap_internal_unlock(multi_heap_handle_t heap); + +void multi_heap_walk(multi_heap_handle_t heap, multi_heap_walker_cb_t walker_func, void *user_data) +{ + assert(heap != NULL); + + multi_heap_internal_lock(heap); + tlsf_walk_pool(tlsf_get_pool(heap->heap_data), walker_func, user_data); + multi_heap_internal_unlock(heap); +} diff --git a/components/heap/heap_caps.c b/components/heap/heap_caps.c index ca5ec1338f..72d88ccaa8 100644 --- a/components/heap/heap_caps.c +++ b/components/heap/heap_caps.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,6 +15,10 @@ #include "heap_private.h" #include "esp_system.h" +#if CONFIG_HEAP_TLSF_USE_ROM_IMPL +#include "esp_rom_multi_heap.h" +#endif + #ifdef CONFIG_HEAP_USE_HOOKS #define CALL_HOOK(hook, ...) { \ if (hook != NULL) { \ @@ -860,3 +864,46 @@ void *heap_caps_aligned_calloc(size_t alignment, size_t n, size_t size, uint32_t return ptr; } + +typedef struct walker_data { + void *opaque_ptr; + heap_caps_walker_cb_t cb_func; + heap_t *heap; +} walker_data_t; + +__attribute__((noinline)) static void heap_caps_walker(void* block_ptr, size_t block_size, int block_used, void *user_data) +{ + walker_data_t *walker_data = (walker_data_t*)user_data; + + walker_heap_into_t heap_info = { + (intptr_t)walker_data->heap->start, + (intptr_t)walker_data->heap->end + }; + walker_block_info_t block_info = { + block_ptr, + block_size, + (bool)block_used + }; + + walker_data->cb_func(heap_info, block_info, walker_data->opaque_ptr); +} + +void heap_caps_walk(uint32_t caps, heap_caps_walker_cb_t walker_func, void *user_data) +{ + assert(walker_func != NULL); + + bool all_heaps = caps & MALLOC_CAP_INVALID; + heap_t *heap; + SLIST_FOREACH(heap, ®istered_heaps, next) { + if (heap->heap != NULL + && (all_heaps || (get_all_caps(heap) & caps) == caps)) { + walker_data_t walker_data = {user_data, walker_func, heap}; + multi_heap_walk(heap->heap, heap_caps_walker, &walker_data); + } + } +} + +void heap_caps_walk_all(heap_caps_walker_cb_t walker_func, void *user_data) +{ + heap_caps_walk(MALLOC_CAP_INVALID, walker_func, user_data); +} diff --git a/components/heap/include/esp_heap_caps.h b/components/heap/include/esp_heap_caps.h index ec202359a3..17101424b4 100644 --- a/components/heap/include/esp_heap_caps.h +++ b/components/heap/include/esp_heap_caps.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -444,6 +444,48 @@ void heap_caps_dump_all(void); */ size_t heap_caps_get_allocated_size( void *ptr ); +/** + * @brief Structure used to store heap related data passed to + * the walker callback function + */ +typedef struct walker_heap_info { + intptr_t start; ///< Start address of the heap in which the block is located + intptr_t end; ///< End address of the heap in which the block is located +} walker_heap_into_t; + +/** + * @brief Structure used to store block related data passed to + * the walker callback function + */ +typedef struct walker_block_info { + void *ptr; ///< Pointer to the block data + size_t size; ///< The size of the block + bool used; ///< Block status. True if free, false if used +} walker_block_info_t; + +/** + * @brief Function callback used to walk the heaps + * @see Definition in multi_heap.h + */ +typedef void (*heap_caps_walker_cb_t)(walker_heap_into_t heap_info, walker_block_info_t block_info, void *user_data); + +/** + * @brief Function called to walk through the heaps with the given set of capabilities + * + * @param caps The set of capabilities assigned to the heaps to walk through + * @param walker_func Callback called for each block of the heaps being traversed + * @param user_data Opaque pointer to user defined data + */ +void heap_caps_walk(uint32_t caps, heap_caps_walker_cb_t walker_func, void *user_data); + +/** + * @brief Function called to walk through all heaps defined by the heap component + * + * @param walker_func Callback called for each block of the heaps being traversed + * @param user_data Opaque pointer to user defined data + */ +void heap_caps_walk_all(heap_caps_walker_cb_t walker_func, void *user_data); + #ifdef __cplusplus } #endif diff --git a/components/heap/include/multi_heap.h b/components/heap/include/multi_heap.h index 9fa1e090a2..b7a2170b2f 100644 --- a/components/heap/include/multi_heap.h +++ b/components/heap/include/multi_heap.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -207,6 +207,26 @@ size_t multi_heap_reset_minimum_free_bytes(multi_heap_handle_t heap); */ void multi_heap_restore_minimum_free_bytes(multi_heap_handle_t heap, const size_t new_minimum_free_bytes_value); +/** + * @brief Callback called when walking the given heap blocks of memory + * + * @param block_ptr Pointer to the block data + * @param block_size The size of the block + * @param block_used Block status. 0 if free, else, false + * @param user_data Opaque pointer to user defined data + */ +typedef void (*multi_heap_walker_cb_t)(void *block_ptr, size_t block_size, int block_used, void *user_data); + +/** + * @brief Call the tlsf_walk_pool function of the heap given as parameter with + * the walker function passed as parameter + * + * @param heap The heap to traverse + * @param walker_func The walker to trigger on each block of the heap + * @param user_data Opaque pointer to user defined data + */ +void multi_heap_walk(multi_heap_handle_t heap, multi_heap_walker_cb_t walker_func, void *user_data); + #ifdef __cplusplus } #endif diff --git a/components/heap/multi_heap.c b/components/heap/multi_heap.c index 151113ac05..f112f36a61 100644 --- a/components/heap/multi_heap.c +++ b/components/heap/multi_heap.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -355,13 +355,10 @@ bool multi_heap_check(multi_heap_handle_t heap, bool print_errors) return valid; } -__attribute__((noinline)) static void multi_heap_dump_tlsf(void* ptr, size_t size, int used, void* user) +__attribute__((noinline)) static void multi_heap_dump_tlsf(void *ptr, size_t size, int used, void *user) { (void)user; - MULTI_HEAP_STDERR_PRINTF("Block %p data, size: %d bytes, Free: %s \n", - (void *)ptr, - size, - used ? "No" : "Yes"); + MULTI_HEAP_STDERR_PRINTF("Block %p data, size: %d bytes, Free: %s \n", (void *)ptr, size, used ? "No" : "Yes"); } void multi_heap_dump(multi_heap_handle_t heap) @@ -431,6 +428,15 @@ void multi_heap_get_info_impl(multi_heap_handle_t heap, multi_heap_info_t *info) multi_heap_internal_unlock(heap); } +void multi_heap_walk(multi_heap_handle_t heap, multi_heap_walker_cb_t walker_func, void *user_data) +{ + assert(heap != NULL); + + multi_heap_internal_lock(heap); + tlsf_walk_pool(tlsf_get_pool(heap->heap_data), walker_func, user_data); + multi_heap_internal_unlock(heap); +} + #endif // CONFIG_HEAP_TLSF_USE_ROM_IMPL size_t multi_heap_reset_minimum_free_bytes(multi_heap_handle_t heap) diff --git a/components/heap/test_apps/heap_tests/main/CMakeLists.txt b/components/heap/test_apps/heap_tests/main/CMakeLists.txt index 0ed19610ce..1803d9f193 100644 --- a/components/heap/test_apps/heap_tests/main/CMakeLists.txt +++ b/components/heap/test_apps/heap_tests/main/CMakeLists.txt @@ -8,7 +8,8 @@ set(src_test "test_heap_main.c" "test_malloc.c" "test_realloc.c" "test_runtime_heap_reg.c" - "test_task_tracking.c") + "test_task_tracking.c" + "test_walker.c") idf_component_register(SRCS ${src_test} INCLUDE_DIRS "." diff --git a/components/heap/test_apps/heap_tests/main/test_walker.c b/components/heap/test_apps/heap_tests/main/test_walker.c new file mode 100644 index 0000000000..fdabc5bb85 --- /dev/null +++ b/components/heap/test_apps/heap_tests/main/test_walker.c @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include "unity.h" +#include "stdio.h" + +#include "esp_heap_caps.h" + +#define PASS_CODE 0x9876BAAB +#define ALLOC_SIZE 16 + +static bool block_found = false; +static void heap_walker(walker_heap_into_t heap_info, walker_block_info_t block_info, void* user_data) +{ + TEST_ASSERT(*(uint32_t*)user_data == PASS_CODE); + TEST_ASSERT_NOT_NULL(block_info.ptr); + + uint32_t metadata_size_head = 0; + uint32_t metadata_size_tail = 0; +#if !CONFIG_HEAP_POISONING_DISABLED + metadata_size_head += 8; // sizeof(poison_head_t) + metadata_size_tail += 4; // sizeof(poison_tail_t) +#endif +#if CONFIG_HEAP_TASK_TRACKING + metadata_size_head += 4; // sizeof(TaskHandle_t) +#endif + + /* look for the first 4 bytes pass code to identify the memory allocated in the test */ + const uint32_t pass_code = *((uint32_t*)block_info.ptr + (metadata_size_head / sizeof(uint32_t))); + if (pass_code == PASS_CODE) { + TEST_ASSERT(block_info.size == ALLOC_SIZE + metadata_size_head + metadata_size_tail); + TEST_ASSERT_TRUE(block_info.used); + block_found = true; + } +} + +/* This test assures the proper functioning of heap_caps_walk and heap_caps_walk_all + */ +TEST_CASE("heap walker", "[heap]") +{ + /* Allocate memory using the MALLOC_CAP_DEFAULT capability */ + void *default_ptr = heap_caps_malloc(ALLOC_SIZE, MALLOC_CAP_DEFAULT); + TEST_ASSERT_NOT_NULL(default_ptr); + + /* Write the pass code in the first word of the allocated memory */ + *((uint32_t*)default_ptr) = (uint32_t)PASS_CODE; + + /* call the heap_caps_walker to make sure the hook function is triggered + * and check that the allocated memory is found while walking the heap */ + uint32_t user_code = PASS_CODE; + heap_caps_walk_all(heap_walker, &user_code); + TEST_ASSERT_TRUE(block_found); +} From 34fb83ffbcc2a286ff710a2b8df946cf23d90ccb Mon Sep 17 00:00:00 2001 From: Guillaume Souchere Date: Tue, 27 Feb 2024 12:32:15 +0100 Subject: [PATCH 2/3] feat(heap): Add return value to walker callback This return value is used by the tlsf_walk_pool function to be notified of the need to interrupt the ongoing traversal of the currently traversed heap. --- components/heap/heap_caps.c | 4 +- components/heap/include/esp_heap_caps.h | 14 +++- components/heap/include/multi_heap.h | 5 +- components/heap/multi_heap.c | 6 +- .../test_apps/heap_tests/main/test_walker.c | 67 +++++++++++++++---- components/heap/tlsf | 2 +- 6 files changed, 77 insertions(+), 21 deletions(-) diff --git a/components/heap/heap_caps.c b/components/heap/heap_caps.c index 72d88ccaa8..9dea55673c 100644 --- a/components/heap/heap_caps.c +++ b/components/heap/heap_caps.c @@ -871,7 +871,7 @@ typedef struct walker_data { heap_t *heap; } walker_data_t; -__attribute__((noinline)) static void heap_caps_walker(void* block_ptr, size_t block_size, int block_used, void *user_data) +__attribute__((noinline)) static bool heap_caps_walker(void* block_ptr, size_t block_size, int block_used, void *user_data) { walker_data_t *walker_data = (walker_data_t*)user_data; @@ -885,7 +885,7 @@ __attribute__((noinline)) static void heap_caps_walker(void* block_ptr, size_t b (bool)block_used }; - walker_data->cb_func(heap_info, block_info, walker_data->opaque_ptr); + return walker_data->cb_func(heap_info, block_info, walker_data->opaque_ptr); } void heap_caps_walk(uint32_t caps, heap_caps_walker_cb_t walker_func, void *user_data) diff --git a/components/heap/include/esp_heap_caps.h b/components/heap/include/esp_heap_caps.h index 17101424b4..96e9b88977 100644 --- a/components/heap/include/esp_heap_caps.h +++ b/components/heap/include/esp_heap_caps.h @@ -464,10 +464,18 @@ typedef struct walker_block_info { } walker_block_info_t; /** - * @brief Function callback used to walk the heaps - * @see Definition in multi_heap.h + * @brief Function callback used to get information of memory block + * during calls to heap_caps_walk or heap_caps_walk_all + * + * @param heap_info See walker_heap_into_t + * @param block_info See walker_block_info_t + * @param user_data Opaque pointer to user defined data + * + * @return True to proceed with the heap traversal + * False to stop th traversal of the current heap and continue + * with the traversal of the next heap (if any) */ -typedef void (*heap_caps_walker_cb_t)(walker_heap_into_t heap_info, walker_block_info_t block_info, void *user_data); +typedef bool (*heap_caps_walker_cb_t)(walker_heap_into_t heap_info, walker_block_info_t block_info, void *user_data); /** * @brief Function called to walk through the heaps with the given set of capabilities diff --git a/components/heap/include/multi_heap.h b/components/heap/include/multi_heap.h index b7a2170b2f..f769fa4a7f 100644 --- a/components/heap/include/multi_heap.h +++ b/components/heap/include/multi_heap.h @@ -214,8 +214,11 @@ void multi_heap_restore_minimum_free_bytes(multi_heap_handle_t heap, const size_ * @param block_size The size of the block * @param block_used Block status. 0 if free, else, false * @param user_data Opaque pointer to user defined data + * + * @return True if the walker is expected to continue the heap traversal + * False if the walker is expected to stop the traversal of the heap */ -typedef void (*multi_heap_walker_cb_t)(void *block_ptr, size_t block_size, int block_used, void *user_data); +typedef bool (*multi_heap_walker_cb_t)(void *block_ptr, size_t block_size, int block_used, void *user_data); /** * @brief Call the tlsf_walk_pool function of the heap given as parameter with diff --git a/components/heap/multi_heap.c b/components/heap/multi_heap.c index f112f36a61..a92b4aa564 100644 --- a/components/heap/multi_heap.c +++ b/components/heap/multi_heap.c @@ -355,10 +355,11 @@ bool multi_heap_check(multi_heap_handle_t heap, bool print_errors) return valid; } -__attribute__((noinline)) static void multi_heap_dump_tlsf(void *ptr, size_t size, int used, void *user) +__attribute__((noinline)) static bool multi_heap_dump_tlsf(void *ptr, size_t size, int used, void *user) { (void)user; MULTI_HEAP_STDERR_PRINTF("Block %p data, size: %d bytes, Free: %s \n", (void *)ptr, size, used ? "No" : "Yes"); + return true; } void multi_heap_dump(multi_heap_handle_t heap) @@ -389,7 +390,7 @@ size_t multi_heap_minimum_free_size_impl(multi_heap_handle_t heap) return heap->minimum_free_bytes; } -__attribute__((noinline)) static void multi_heap_get_info_tlsf(void* ptr, size_t size, int used, void* user) +__attribute__((noinline)) static bool multi_heap_get_info_tlsf(void* ptr, size_t size, int used, void* user) { multi_heap_info_t *info = user; @@ -404,6 +405,7 @@ __attribute__((noinline)) static void multi_heap_get_info_tlsf(void* ptr, size_t } info->total_blocks++; + return true; } void multi_heap_get_info_impl(multi_heap_handle_t heap, multi_heap_info_t *info) diff --git a/components/heap/test_apps/heap_tests/main/test_walker.c b/components/heap/test_apps/heap_tests/main/test_walker.c index fdabc5bb85..3a96df7df2 100644 --- a/components/heap/test_apps/heap_tests/main/test_walker.c +++ b/components/heap/test_apps/heap_tests/main/test_walker.c @@ -7,25 +7,39 @@ #include "stdio.h" #include "esp_heap_caps.h" - +#include "esp_rom_sys.h" #define PASS_CODE 0x9876BAAB #define ALLOC_SIZE 16 -static bool block_found = false; -static void heap_walker(walker_heap_into_t heap_info, walker_block_info_t block_info, void* user_data) +static void calculate_block_metadata_size(size_t *header, size_t *footer) { + *header = 0; + *footer = 0; +#if !CONFIG_HEAP_POISONING_DISABLED + *header += 8; // sizeof(poison_head_t) + *footer += 4; // sizeof(poison_tail_t) +#endif +#if CONFIG_HEAP_TASK_TRACKING + *header += 4; // sizeof(TaskHandle_t) +#endif +} + +static bool block_found = false; +static bool heap_corrupted = false; +static bool heap_walker(walker_heap_into_t heap_info, walker_block_info_t block_info, void* user_data) +{ + if ((intptr_t)heap_info.end - (intptr_t)block_info.ptr < block_info.size) + { + heap_corrupted = true; + return false; + } + TEST_ASSERT(*(uint32_t*)user_data == PASS_CODE); TEST_ASSERT_NOT_NULL(block_info.ptr); - uint32_t metadata_size_head = 0; - uint32_t metadata_size_tail = 0; -#if !CONFIG_HEAP_POISONING_DISABLED - metadata_size_head += 8; // sizeof(poison_head_t) - metadata_size_tail += 4; // sizeof(poison_tail_t) -#endif -#if CONFIG_HEAP_TASK_TRACKING - metadata_size_head += 4; // sizeof(TaskHandle_t) -#endif + size_t metadata_size_head = 0; + size_t metadata_size_tail = 0; + calculate_block_metadata_size(&metadata_size_head, &metadata_size_tail); /* look for the first 4 bytes pass code to identify the memory allocated in the test */ const uint32_t pass_code = *((uint32_t*)block_info.ptr + (metadata_size_head / sizeof(uint32_t))); @@ -34,9 +48,14 @@ static void heap_walker(walker_heap_into_t heap_info, walker_block_info_t block_ TEST_ASSERT_TRUE(block_info.used); block_found = true; } + + return true; } /* This test assures the proper functioning of heap_caps_walk and heap_caps_walk_all + * when a corruption occurs in a random heap. The callback which detects the corruption + * returns false to the walker which should result in the interruption of the heap traversal + * by the walker instead of a crash. */ TEST_CASE("heap walker", "[heap]") { @@ -53,3 +72,27 @@ TEST_CASE("heap walker", "[heap]") heap_caps_walk_all(heap_walker, &user_code); TEST_ASSERT_TRUE(block_found); } + +/* This test assures the proper functioning of heap_caps_walk and heap_caps_walk_all + */ +TEST_CASE("heap walker corrupted heap detection", "[heap]") +{ + /* Allocate memory using the MALLOC_CAP_DEFAULT capability */ + void *default_ptr = heap_caps_malloc(ALLOC_SIZE, MALLOC_CAP_DEFAULT); + TEST_ASSERT_NOT_NULL(default_ptr); + + size_t metadata_size_head = 0; + size_t metadata_size_tail = 0; + calculate_block_metadata_size(&metadata_size_head, &metadata_size_tail); + (void)metadata_size_tail; + *((uint32_t*)default_ptr - (metadata_size_head / 4) - 1) = 0xFF000000; + + /* Write the pass code in the first word of the allocated memory */ + *((uint32_t*)default_ptr) = (uint32_t)PASS_CODE; + + /* call the heap_caps_walker to make sure the hook function is triggered + * and check that the allocated memory is found while walking the heap */ + uint32_t user_code = PASS_CODE; + heap_caps_walk_all(heap_walker, &user_code); + TEST_ASSERT_TRUE(heap_corrupted); +} diff --git a/components/heap/tlsf b/components/heap/tlsf index d2e28f8724..e282f0be5a 160000 --- a/components/heap/tlsf +++ b/components/heap/tlsf @@ -1 +1 @@ -Subproject commit d2e28f872472ffc6a704faae65ddee1f24e2dfba +Subproject commit e282f0be5a8488f48bf04cdc74514553c03e3c64 From 39f789df931a2c8e8be6e1f7ed243babf1d6cc08 Mon Sep 17 00:00:00 2001 From: Guillaume Souchere Date: Tue, 19 Mar 2024 13:56:32 +0100 Subject: [PATCH 3/3] feat(esp_rom): patch heap walker to the ROM implementation modify existing patch of TLSF rom and add multi heap patch to add the walker feature to the ROM implementation of the heap component. --- components/esp_rom/CMakeLists.txt | 2 +- .../esp_rom/esp32c2/Kconfig.soc_caps.in | 4 + components/esp_rom/esp32c2/esp_rom_caps.h | 1 + .../esp_rom/esp32c5/Kconfig.soc_caps.in | 78 ------------------- .../esp32c5/beta3/esp32c5/Kconfig.soc_caps.in | 4 + .../esp_rom/include/esp_rom_multi_heap.h | 9 ++- .../esp_rom/patches/esp_rom_multi_heap.c | 8 -- components/esp_rom/patches/esp_rom_tlsf.c | 68 +++++++++++++++- components/heap/Kconfig | 9 --- components/heap/include/esp_heap_caps.h | 4 +- components/heap/include/multi_heap.h | 2 +- .../test_apps/heap_tests/main/test_walker.c | 5 +- components/heap/tlsf | 2 +- 13 files changed, 88 insertions(+), 108 deletions(-) diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index 9b9872b1da..3b05e51d59 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -44,7 +44,7 @@ else() endif() endif() - if(CONFIG_HEAP_TLSF_USE_ROM_IMPL AND (CONFIG_ESP_ROM_TLSF_CHECK_PATCH OR CONFIG_HEAP_TLSF_CHECK_PATCH)) + if(CONFIG_HEAP_TLSF_USE_ROM_IMPL AND CONFIG_ESP_ROM_TLSF_CHECK_PATCH) # This file shall be included in the build if TLSF in ROM is activated list(APPEND sources "patches/esp_rom_tlsf.c") endif() diff --git a/components/esp_rom/esp32c2/Kconfig.soc_caps.in b/components/esp_rom/esp32c2/Kconfig.soc_caps.in index 19913c950b..c1fa90c7e8 100644 --- a/components/esp_rom/esp32c2/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32c2/Kconfig.soc_caps.in @@ -39,6 +39,10 @@ config ESP_ROM_HAS_HEAP_TLSF bool default y +config ESP_ROM_TLSF_CHECK_PATCH + bool + default y + config ESP_ROM_MULTI_HEAP_WALK_PATCH bool default y diff --git a/components/esp_rom/esp32c2/esp_rom_caps.h b/components/esp_rom/esp32c2/esp_rom_caps.h index 9c71f9b9e2..1362fd77f4 100644 --- a/components/esp_rom/esp32c2/esp_rom_caps.h +++ b/components/esp_rom/esp32c2/esp_rom_caps.h @@ -15,6 +15,7 @@ #define ESP_ROM_HAS_HAL_WDT (1) // ROM has the implementation of Watchdog HAL driver #define ESP_ROM_HAS_HAL_SYSTIMER (1) // ROM has the implementation of Systimer HAL driver #define ESP_ROM_HAS_HEAP_TLSF (1) // ROM has the implementation of the tlsf and multi-heap library +#define ESP_ROM_TLSF_CHECK_PATCH (1) // ROM does not contain the patch of tlsf_check_pool() #define ESP_ROM_MULTI_HEAP_WALK_PATCH (1) // ROM does not contain the patch of multi_heap_walk() #define ESP_ROM_HAS_LAYOUT_TABLE (1) // ROM has the layout table #define ESP_ROM_HAS_SPI_FLASH (1) // ROM has the implementation of SPI Flash driver diff --git a/components/esp_rom/esp32c5/Kconfig.soc_caps.in b/components/esp_rom/esp32c5/Kconfig.soc_caps.in index 4f1584f9b3..20c519bbcb 100644 --- a/components/esp_rom/esp32c5/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32c5/Kconfig.soc_caps.in @@ -7,84 +7,6 @@ if IDF_TARGET_ESP32C5_BETA3_VERSION source "$IDF_PATH/components/esp_rom/esp32c5/beta3/esp32c5/Kconfig.soc_caps.in" endif -<<<<<<< HEAD if IDF_TARGET_ESP32C5_MP_VERSION source "$IDF_PATH/components/esp_rom/esp32c5/mp/esp32c5/Kconfig.soc_caps.in" endif -======= -config ESP_ROM_HAS_CRC_BE - bool - default y - -config ESP_ROM_HAS_JPEG_DECODE - bool - default y - -config ESP_ROM_UART_CLK_IS_XTAL - bool - default y - -config ESP_ROM_USB_SERIAL_DEVICE_NUM - int - default 3 - -config ESP_ROM_HAS_RETARGETABLE_LOCKING - bool - default y - -config ESP_ROM_GET_CLK_FREQ - bool - default y - -config ESP_ROM_HAS_RVFPLIB - bool - default y - -config ESP_ROM_HAS_HAL_WDT - bool - default y - -config ESP_ROM_HAS_HAL_SYSTIMER - bool - default y - -config ESP_ROM_HAS_HEAP_TLSF - bool - default y - -config ESP_ROM_TLSF_CHECK_PATCH - bool - default y - -config ESP_ROM_MULTI_HEAP_WALK_PATCH - bool - default y - -config ESP_ROM_HAS_LAYOUT_TABLE - bool - default y - -config ESP_ROM_HAS_SPI_FLASH - bool - default y - -config ESP_ROM_WITHOUT_REGI2C - bool - default y - -config ESP_ROM_HAS_NEWLIB_NORMAL_FORMAT - bool - default y - -config ESP_ROM_WDT_INIT_PATCH - bool - default y - -config ESP_ROM_RAM_APP_NEEDS_MMU_INIT - bool - default y - -config ESP_ROM_USB_OTG_NUM - int - default -1 ->>>>>>> 9468f4df09 (feat(heap): Add walker to the heap component) diff --git a/components/esp_rom/esp32c5/beta3/esp32c5/Kconfig.soc_caps.in b/components/esp_rom/esp32c5/beta3/esp32c5/Kconfig.soc_caps.in index f2b89066e3..0f8129562c 100644 --- a/components/esp_rom/esp32c5/beta3/esp32c5/Kconfig.soc_caps.in +++ b/components/esp_rom/esp32c5/beta3/esp32c5/Kconfig.soc_caps.in @@ -51,6 +51,10 @@ config ESP_ROM_TLSF_CHECK_PATCH bool default y +config ESP_ROM_MULTI_HEAP_WALK_PATCH + bool + default y + config ESP_ROM_HAS_LAYOUT_TABLE bool default y diff --git a/components/esp_rom/include/esp_rom_multi_heap.h b/components/esp_rom/include/esp_rom_multi_heap.h index c7dfa493ae..b95ce4607d 100644 --- a/components/esp_rom/include/esp_rom_multi_heap.h +++ b/components/esp_rom/include/esp_rom_multi_heap.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,10 +20,13 @@ typedef struct multi_heap_info *multi_heap_handle_t; * * @param block_ptr Pointer to the block data * @param block_size The size of the block - * @param block_used Block status. True if free, false if used + * @param block_used Block status. 0: free, 1: allocated * @param user_data Opaque pointer to user defined data + * + * @return True if the walker is expected to continue the heap traversal + * False if the walker is expected to stop the traversal of the heap */ -typedef void (*multi_heap_walker_cb_t)(void *block_ptr, size_t block_size, int block_used, void *user_data); +typedef bool (*multi_heap_walker_cb_t)(void *block_ptr, size_t block_size, int block_used, void *user_data); /** * @brief Call the tlsf_walk_pool function of the heap given as parameter with diff --git a/components/esp_rom/patches/esp_rom_multi_heap.c b/components/esp_rom/patches/esp_rom_multi_heap.c index 4690bfe4e4..6a6682dbf3 100644 --- a/components/esp_rom/patches/esp_rom_multi_heap.c +++ b/components/esp_rom/patches/esp_rom_multi_heap.c @@ -7,8 +7,6 @@ /* * This file is a patch for the multi_heap.c file stored in ROM * - added function multi_heap_walk - * - added function multi_heap_walker - * - added structure walker_data_t */ #include @@ -37,12 +35,6 @@ typedef struct multi_heap_info { void* heap_data; } heap_t; -typedef struct walker_data { - void *opaque_ptr; - multi_heap_walker_cb_t walker; - multi_heap_handle_t heap; -} walker_data_t; - extern void tlsf_walk_pool(pool_t pool, tlsf_walker walker, void* user); extern pool_t tlsf_get_pool(tlsf_t tlsf); extern void multi_heap_internal_lock(multi_heap_handle_t heap); diff --git a/components/esp_rom/patches/esp_rom_tlsf.c b/components/esp_rom/patches/esp_rom_tlsf.c index 06da058328..ad3af65d42 100644 --- a/components/esp_rom/patches/esp_rom_tlsf.c +++ b/components/esp_rom/patches/esp_rom_tlsf.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,6 +15,7 @@ #include #include #include +#include #include "esp_rom_caps.h" #include "esp_rom_tlsf.h" @@ -24,13 +25,17 @@ */ typedef void* tlsf_t; typedef void* pool_t; -typedef void* tlsf_walker; +typedef ptrdiff_t tlsfptr_t; /* ---------------------------------------------------------------- * Bring certain inline functions, macro and structures from the * tlsf ROM implementation to be able to compile the patch. * ---------------------------------------------------------------- */ +#if !defined (tlsf_assert) +#define tlsf_assert assert +#endif + #define tlsf_cast(t, exp) ((t) (exp)) #define block_header_free_bit (1 << 0) @@ -72,6 +77,30 @@ static inline __attribute__((always_inline)) block_header_t* block_from_ptr(cons tlsf_cast(unsigned char*, ptr) - block_start_offset); } +static inline __attribute__((always_inline)) block_header_t* offset_to_block(const void* ptr, size_t size) +{ + return tlsf_cast(block_header_t*, tlsf_cast(tlsfptr_t, ptr) + size); +} + +static inline __attribute__((always_inline)) int block_is_last(const block_header_t* block) +{ + return block_size(block) == 0; +} + +static inline __attribute__((always_inline)) void* block_to_ptr(const block_header_t* block) +{ + return tlsf_cast(void*, + tlsf_cast(unsigned char*, block) + block_start_offset); +} + +static inline __attribute__((always_inline)) block_header_t* block_next(const block_header_t* block) +{ + block_header_t* next = offset_to_block(block_to_ptr(block), + block_size(block) - block_header_overhead); + tlsf_assert(!block_is_last(block)); + return next; +} + /* ---------------------------------------------------------------- * End of the environment necessary to compile and link the patch * defined below @@ -92,7 +121,9 @@ typedef struct integrity_t int status; } integrity_t; -static void integrity_walker(void* ptr, size_t size, int used, void* user) +typedef bool (*tlsf_walker)(void* ptr, size_t size, int used, void* user); + +static bool integrity_walker(void* ptr, size_t size, int used, void* user) { block_header_t* block = block_from_ptr(ptr); integrity_t* integ = tlsf_cast(integrity_t*, user); @@ -124,9 +155,38 @@ static void integrity_walker(void* ptr, size_t size, int used, void* user) integ->prev_status = this_status; integ->status += status; + + return true; +} + +static bool default_walker(void* ptr, size_t size, int used, void* user) +{ + (void)user; + printf("\t%p %s size: %x (%p)\n", ptr, used ? "used" : "free", (unsigned int)size, block_from_ptr(ptr)); + return true; +} + +void tlsf_walk_pool(pool_t pool, tlsf_walker walker, void* user) +{ + tlsf_walker pool_walker = walker ? walker : default_walker; + block_header_t* block = + offset_to_block(pool, -(int)block_header_overhead); + + bool ret_val = true; + while (block && !block_is_last(block) && ret_val == true) + { + ret_val = pool_walker( + block_to_ptr(block), + block_size(block), + !block_is_free(block), + user); + + if (ret_val == true) { + block = block_next(block); + } + } } -extern void tlsf_walk_pool(pool_t pool, tlsf_walker walker, void* user); int tlsf_check_pool(pool_t pool) { /* Check that the blocks are physically correct. */ diff --git a/components/heap/Kconfig b/components/heap/Kconfig index e593e4707a..723ff3d300 100644 --- a/components/heap/Kconfig +++ b/components/heap/Kconfig @@ -119,15 +119,6 @@ menu "Heap memory debugging" features will be added and bugs will be fixed in the IDF source but cannot be synced to ROM. - config HEAP_TLSF_CHECK_PATCH - bool "Patch the tlsf_check_pool() for ROM HEAP TLSF implementation" - depends on HEAP_TLSF_USE_ROM_IMPL && IDF_TARGET_ESP32C2 && ESP32C2_REV_MIN_FULL < 200 - default y - help - ROM does not contain the patch of tlsf_check_pool() allowing perform - the integrity checking on used blocks. The patch to allow such check - needs to be applied. - config HEAP_PLACE_FUNCTION_INTO_FLASH bool "Force the entire heap component to be placed in flash memory" depends on !HEAP_TLSF_USE_ROM_IMPL diff --git a/components/heap/include/esp_heap_caps.h b/components/heap/include/esp_heap_caps.h index 96e9b88977..4d590204e5 100644 --- a/components/heap/include/esp_heap_caps.h +++ b/components/heap/include/esp_heap_caps.h @@ -460,7 +460,7 @@ typedef struct walker_heap_info { typedef struct walker_block_info { void *ptr; ///< Pointer to the block data size_t size; ///< The size of the block - bool used; ///< Block status. True if free, false if used + bool used; ///< Block status. True: used, False: free } walker_block_info_t; /** @@ -472,7 +472,7 @@ typedef struct walker_block_info { * @param user_data Opaque pointer to user defined data * * @return True to proceed with the heap traversal - * False to stop th traversal of the current heap and continue + * False to stop the traversal of the current heap and continue * with the traversal of the next heap (if any) */ typedef bool (*heap_caps_walker_cb_t)(walker_heap_into_t heap_info, walker_block_info_t block_info, void *user_data); diff --git a/components/heap/include/multi_heap.h b/components/heap/include/multi_heap.h index f769fa4a7f..20e1ba977e 100644 --- a/components/heap/include/multi_heap.h +++ b/components/heap/include/multi_heap.h @@ -212,7 +212,7 @@ void multi_heap_restore_minimum_free_bytes(multi_heap_handle_t heap, const size_ * * @param block_ptr Pointer to the block data * @param block_size The size of the block - * @param block_used Block status. 0 if free, else, false + * @param block_used Block status. 0: free, 1: allocated * @param user_data Opaque pointer to user defined data * * @return True if the walker is expected to continue the heap traversal diff --git a/components/heap/test_apps/heap_tests/main/test_walker.c b/components/heap/test_apps/heap_tests/main/test_walker.c index 3a96df7df2..8db8dc449d 100644 --- a/components/heap/test_apps/heap_tests/main/test_walker.c +++ b/components/heap/test_apps/heap_tests/main/test_walker.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -85,6 +85,9 @@ TEST_CASE("heap walker corrupted heap detection", "[heap]") size_t metadata_size_tail = 0; calculate_block_metadata_size(&metadata_size_head, &metadata_size_tail); (void)metadata_size_tail; + + /* corrupting the size field of the block metadata with a size bigger + * than the heap itself */ *((uint32_t*)default_ptr - (metadata_size_head / 4) - 1) = 0xFF000000; /* Write the pass code in the first word of the allocated memory */ diff --git a/components/heap/tlsf b/components/heap/tlsf index e282f0be5a..8fc595fe22 160000 --- a/components/heap/tlsf +++ b/components/heap/tlsf @@ -1 +1 @@ -Subproject commit e282f0be5a8488f48bf04cdc74514553c03e3c64 +Subproject commit 8fc595fe223cd0b3b5d7b29eb86825e4bd38e6e8