From 4a392932f1909364e606fa893cea3ce14e0c8122 Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Tue, 12 Nov 2019 14:01:27 +0800 Subject: [PATCH] heap/heap_caps: added special case for esp32s2 when handling memory allocated (and aliased) from IRAM --- components/heap/heap_caps.c | 14 +++++++++++++- components/heap/multi_heap_poisoning.c | 14 ++++++++++++++ components/heap/test/test_realloc.c | 3 +-- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/components/heap/heap_caps.c b/components/heap/heap_caps.c index 9e2ddd3a41..28cb7bf4d1 100644 --- a/components/heap/heap_caps.c +++ b/components/heap/heap_caps.c @@ -107,6 +107,7 @@ IRAM_ATTR void *heap_caps_malloc( size_t size, uint32_t caps ) //we need to 'invert' it (lowest address in DRAM == highest address in IRAM and vice-versa) and //add a pointer to the DRAM equivalent before the address we're going to return. ret = multi_heap_malloc(heap->heap, size + 4); // int overflow checked above + if (ret != NULL) { return dram_alloc_to_iram_addr(ret, size + 4); // int overflow checked above } @@ -287,8 +288,18 @@ IRAM_ATTR void *heap_caps_realloc( void *ptr, size_t size, int caps) return NULL; } - heap_t *heap = find_containing_heap(ptr); +#if CONFIG_IDF_TARGET_ESP32S2BETA + //On esp32s2 the pointer to heap may be aliased, we need to + //recover it before to manage a new allocation: + if(esp_ptr_in_diram_iram((void *)ptr)) { + //pointer must be already aliased, otherwise just ignore this part: + uint32_t *dram_addr = (uint32_t *)ptr; + ptr = (void *)dram_addr[-1]; + //printf("[HEAP_CAPS_MALLOC]: obtained pointer that was aliased: %p \n", (void *)ptr); + } +#endif + heap_t *heap = find_containing_heap(ptr); assert(heap != NULL && "realloc() pointer is outside heap areas"); // are the existing heap's capabilities compatible with the @@ -308,6 +319,7 @@ IRAM_ATTR void *heap_caps_realloc( void *ptr, size_t size, int caps) // in a different heap with requested capabilities. void *new_p = heap_caps_malloc(size, caps); if (new_p != NULL) { + size_t old_size = multi_heap_get_allocated_size(heap->heap, ptr); assert(old_size > 0); memcpy(new_p, ptr, MIN(size, old_size)); diff --git a/components/heap/multi_heap_poisoning.c b/components/heap/multi_heap_poisoning.c index a896043abb..559ad18d2e 100644 --- a/components/heap/multi_heap_poisoning.c +++ b/components/heap/multi_heap_poisoning.c @@ -21,6 +21,7 @@ #include #include #include "multi_heap_internal.h" +#include "heap_private.h" /* Note: Keep platform-specific parts in this header, this source file should depend on libc only */ @@ -268,7 +269,20 @@ void *multi_heap_realloc(multi_heap_handle_t heap, void *p, size_t size) new_head = multi_heap_malloc_impl(heap, size + POISON_OVERHEAD); if (new_head != NULL) { result = poison_allocated_region(new_head, size); + +#if CONFIG_IDF_TARGET_ESP32S2BETA + //We may need to deal with aliased heap pointers. here too, + //mainly because the heap canary is located before the + //the slot reserved to preserve original DRAM address + //so the original user data is actually p + 4 ahead : + if(esp_ptr_in_diram_dram((void *)p)) { + memcpy(result, p + sizeof(intptr_t), MIN(size, orig_alloc_size)); + } else { + memcpy(result, p , MIN(size, orig_alloc_size)); + } +#else memcpy(result, p, MIN(size, orig_alloc_size)); +#endif multi_heap_free(heap, p); } #endif diff --git a/components/heap/test/test_realloc.c b/components/heap/test/test_realloc.c index 290ee3da6e..763cddab62 100644 --- a/components/heap/test/test_realloc.c +++ b/components/heap/test/test_realloc.c @@ -31,7 +31,6 @@ TEST_CASE("realloc move data to a new heap type", "[heap]") char *a = malloc(64); memcpy(a, buf, 64); - // move data from 'a' to IRAM char *b = heap_caps_realloc(a, 64, MALLOC_CAP_EXEC); TEST_ASSERT_NOT_NULL(b); @@ -40,7 +39,7 @@ TEST_CASE("realloc move data to a new heap type", "[heap]") TEST_ASSERT_EQUAL_HEX32_ARRAY(buf, b, 64/sizeof(uint32_t)); // Move data back to DRAM - char *c = heap_caps_realloc(b, 48, MALLOC_CAP_8BIT); + char *c = heap_caps_realloc(b, 48, MALLOC_CAP_8BIT); TEST_ASSERT_NOT_NULL(c); TEST_ASSERT_NOT_EQUAL(b, c); TEST_ASSERT(heap_caps_check_integrity(MALLOC_CAP_INVALID, true));