From 83ec6f3d585880e5b096ccb53a25742c7ad07a88 Mon Sep 17 00:00:00 2001 From: Dong Heng Date: Wed, 4 Jul 2018 14:30:53 +0800 Subject: [PATCH] feat(newlib): Use new private malloc function Add return address to debug memory leak. --- .../esp8266/source/esp_wifi_os_adapter.c | 59 +++++++++++++-- components/freertos/port/esp8266/heap_5.c | 73 +++++++++---------- components/newlib/newlib/port/esp_malloc.c | 68 +++++++++++++++++ components/newlib/newlib/port/syscall.c | 23 +++--- 4 files changed, 171 insertions(+), 52 deletions(-) create mode 100644 components/newlib/newlib/port/esp_malloc.c diff --git a/components/esp8266/source/esp_wifi_os_adapter.c b/components/esp8266/source/esp_wifi_os_adapter.c index c090f149..7b6942a0 100644 --- a/components/esp8266/source/esp_wifi_os_adapter.c +++ b/components/esp8266/source/esp_wifi_os_adapter.c @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include + #include "esp_libc.h" #include "esp_system.h" #include "esp_wifi_os_adapter.h" @@ -275,30 +277,75 @@ static bool timer_delete_wrapper(void *timer, uint32_t ticks) static void *malloc_wrapper(uint32_t s, uint32_t cap) { + bool iram; + void *return_addr = (void *)__builtin_return_address(0); + if (cap & (OSI_MALLOC_CAP_8BIT | OSI_MALLOC_CAP_DMA)) - return os_malloc(s); + iram = false; else - return os_malloc_iram(s); + iram = true; + + return pvPortMalloc_trace(s, return_addr, (unsigned)-1, iram); } static void *zalloc_wrapper(uint32_t s, uint32_t cap) { - return os_zalloc(s); + bool iram; + void *return_addr = (void *)__builtin_return_address(0); + + if (cap & (OSI_MALLOC_CAP_8BIT | OSI_MALLOC_CAP_DMA)) + iram = false; + else + iram = true; + + char *p = pvPortMalloc_trace(s, return_addr, (unsigned)-1, iram); + if (p) + memset(p, 0, s); + + return p; } static void *realloc_wrapper(void *ptr, uint32_t s, uint32_t cap) { - return os_realloc(ptr, s); + bool iram; + void *return_addr = (void *)__builtin_return_address(0); + + if (cap & (OSI_MALLOC_CAP_8BIT | OSI_MALLOC_CAP_DMA)) + iram = false; + else + iram = true; + + void *p = pvPortMalloc_trace(s, return_addr, (unsigned)-1, iram); + if (p && ptr) { + memcpy(p, ptr, s); + vPortFree_trace(ptr, return_addr, (unsigned)-1); + } + + return p; } static void *calloc_wrapper(uint32_t cnt, uint32_t s, uint32_t cap) { - return os_calloc(cnt, s); + bool iram; + void *return_addr = (void *)__builtin_return_address(0); + + if (cap & (OSI_MALLOC_CAP_8BIT | OSI_MALLOC_CAP_DMA)) + iram = false; + else + iram = true; + + char *p = pvPortMalloc_trace(cnt * s, return_addr, (unsigned)-1, iram); + if (p) + memset(p, 0, cnt * s); + + return p; } static void free_wrapper(void *ptr) { - os_free(ptr); + void *return_addr = (void *)__builtin_return_address(0); + + vPortFree_trace(ptr, return_addr, (unsigned)-1); } static void srand_wrapper(uint32_t seed) diff --git a/components/freertos/port/esp8266/heap_5.c b/components/freertos/port/esp8266/heap_5.c index 0b98b2bf..7f43e8d5 100644 --- a/components/freertos/port/esp8266/heap_5.c +++ b/components/freertos/port/esp8266/heap_5.c @@ -268,7 +268,10 @@ void pvShowMalloc() } else { basename = ""; } - printf("F:%-30sL:%4u malloc %10d @ %p\n", basename, blk->line, blk->xBlockSize - 0x80000000, ( void * ) ( ( ( unsigned char * ) blk ) + uxHeapStructSize)); + if (((unsigned)-1) == blk->line) + printf("F(1):%-30p malloc %10d @ %p\n", blk->file, blk->xBlockSize - 0x80000000, ( void * ) ( ( ( unsigned char * ) blk ) + uxHeapStructSize)); + else + printf("F(2):%-30sL:%4u malloc %10d @ %p\n", basename, blk->line, blk->xBlockSize - 0x80000000, ( void * ) ( ( ( unsigned char * ) blk ) + uxHeapStructSize)); //ets_printf("sh3,"); // ets_delay_us(2000); system_soft_wdt_feed(); @@ -332,7 +335,9 @@ size_t xPortWantedSizeAlign(size_t xWantedSize) void *pvPortMalloc( size_t xWantedSize ) #ifdef MEMLEAK_DEBUG { - return pvPortMalloc_trace( xWantedSize, __FILE__, __LINE__, false ); + void *return_addr = (void *)__builtin_return_address(0); + + return pvPortMalloc_trace( xWantedSize, return_addr, (unsigned)-1, false ); } void *pvPortMalloc_trace( size_t xWantedSize, const char * file, unsigned line, bool use_iram ) @@ -511,14 +516,15 @@ static bool is_inited = false; return pvReturn; } -void *malloc(size_t nbytes) __attribute__((alias("pvPortMalloc"))); /*-----------------------------------------------------------*/ void vPortFree( void *pv ) #ifdef MEMLEAK_DEBUG { - return vPortFree_trace( pv, __FILE__, __LINE__ ); + void *return_addr = (void *)__builtin_return_address(0); + + vPortFree_trace(pv, return_addr, (unsigned)-1); } void vPortFree_trace( void *pv, const char * file, unsigned line ) @@ -580,76 +586,69 @@ BlockLink_t *pxLink; } } } -void free(void *ptr) __attribute__((alias("vPortFree"))); /*-----------------------------------------------------------*/ void *pvPortCalloc(size_t count, size_t size) #ifdef MEMLEAK_DEBUG { - return pvPortCalloc_trace(count, size, __FILE__, __LINE__); + void *return_addr = (void *)__builtin_return_address(0); + + return pvPortCalloc_trace(count, size, return_addr, (unsigned)-1); } void *pvPortCalloc_trace(size_t count, size_t size, const char * file, unsigned line) #endif { - void *p; -//ets_printf("1,"); - /* allocate 'count' objects of size 'size' */ - p = pvPortMalloc_t(count * size); -//ets_printf("2,"); - if (p) { - /* zero the memory */ - memset(p, 0, count * size); - } -//ets_printf("3,"); - return p; -} + char *p = pvPortMalloc_trace(count * size, file, line, true); + if (p) + memset(p, 0, count * size); -void *calloc(size_t count, size_t nbytes) __attribute__((alias("pvPortCalloc"))); + return p; +} /*-----------------------------------------------------------*/ void *pvPortRealloc(void *mem, size_t newsize) #ifdef MEMLEAK_DEBUG { - return pvPortRealloc_trace(mem, newsize, __FILE__, __LINE__); + void *return_addr = (void *)__builtin_return_address(0); + + return pvPortRealloc_trace(mem, newsize, return_addr, (unsigned)-1); } + void *pvPortRealloc_trace(void *mem, size_t newsize, const char *file, unsigned line) #endif { - if (newsize == 0) { - vPortFree_t(mem); - return NULL; + void *return_addr = (void *)__builtin_return_address(0); + + void *p = pvPortMalloc_trace(newsize, file, line, true); + if (p && mem) { + memcpy(p, mem, newsize); + vPortFree_trace(mem, return_addr, 0); } - void *p; - p = pvPortMalloc_t(newsize); - if (p) { - /* zero the memory */ - if (mem != NULL) { - memcpy(p, mem, newsize); - vPortFree_t(mem); - } - } return p; } -void *realloc(void *ptr, size_t nbytes) __attribute__((alias("pvPortRealloc"))); - /*-----------------------------------------------------------*/ void *pvPortZalloc(size_t size) #ifdef MEMLEAK_DEBUG { - return pvPortZalloc_trace( size, __FILE__, __LINE__ ); + void *return_addr = (void *)__builtin_return_address(0); + + return pvPortZalloc_trace(size, return_addr, (unsigned)-1); } void *pvPortZalloc_trace(size_t size, const char * file, unsigned line) #endif { - return pvPortCalloc_t(1, size); + char *p = pvPortMalloc_trace(size, file, line, true); + if (p) + memset(p, 0, size); + + return p; } -void *zalloc(size_t nbytes) __attribute__((alias("pvPortZalloc"))); size_t xPortGetFreeHeapSize( void ) { diff --git a/components/newlib/newlib/port/esp_malloc.c b/components/newlib/newlib/port/esp_malloc.c new file mode 100644 index 00000000..4212f920 --- /dev/null +++ b/components/newlib/newlib/port/esp_malloc.c @@ -0,0 +1,68 @@ +// Copyright 2018-2019 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. + +#include +#include +#include +#include "FreeRTOS.h" + +void *malloc(size_t n) +{ + void *return_addr = (void *)__builtin_return_address(0); + + return pvPortMalloc_trace(n, return_addr, (unsigned)-1, true); +} + +void *realloc(void *old_ptr, size_t n) +{ + void *return_addr = (void *)__builtin_return_address(0); + + void *p = pvPortMalloc_trace(n, return_addr, (unsigned)-1, true); + if (p && old_ptr) { + memcpy(p, old_ptr, n); + vPortFree_trace(old_ptr, return_addr, 0); + } + + return p; +} + +void *zalloc(size_t n) +{ + void *return_addr = (void *)__builtin_return_address(0); + + char *p = pvPortMalloc_trace(n, return_addr, (unsigned)-1, true); + if (p) + memset(p, 0, n); + + return p; +} + +void *calloc(size_t c, size_t s) +{ + void *return_addr = (void *)__builtin_return_address(0); + + char *p = pvPortMalloc_trace(c * s, return_addr, (unsigned)-1, true); + if (p) + memset(p, 0, c * s); + + return p; +} + +void free(void *ptr) +{ + void *return_addr = (void *)__builtin_return_address(0); + + vPortFree_trace(ptr, return_addr, (unsigned)-1); +} + diff --git a/components/newlib/newlib/port/syscall.c b/components/newlib/newlib/port/syscall.c index 343ae6e7..e3bf24ba 100644 --- a/components/newlib/newlib/port/syscall.c +++ b/components/newlib/newlib/port/syscall.c @@ -91,19 +91,20 @@ void *_sbrk_r(struct _reent *r, ptrdiff_t incr) void *_malloc_r(struct _reent *r, size_t n) { -#ifndef MEMLEAK_DEBUG - return pvPortMalloc(n); -#else - return pvPortMalloc_trace(n, NULL, 0, false); -#endif + void *return_addr = (void *)__builtin_return_address(0); + + return pvPortMalloc_trace(n, return_addr, (unsigned)-1, true); + } void *_realloc_r(struct _reent *r, void *old_ptr, size_t n) { - void *p = pvPortMalloc(n); + void *return_addr = (void *)__builtin_return_address(0); + + void *p = pvPortMalloc_trace(n, return_addr, (unsigned)-1, true); if (p && old_ptr) { memcpy(p, old_ptr, n); - vPortFree(old_ptr); + vPortFree_trace(old_ptr, return_addr, 0); } return p; @@ -111,7 +112,9 @@ void *_realloc_r(struct _reent *r, void *old_ptr, size_t n) void *_calloc_r(struct _reent *r, size_t c, size_t s) { - char *p = pvPortMalloc(c * s); + void *return_addr = (void *)__builtin_return_address(0); + + char *p = pvPortMalloc_trace(c * s, return_addr, (unsigned)-1, true); if (p) memset(p, 0, c * s); @@ -120,7 +123,9 @@ void *_calloc_r(struct _reent *r, size_t c, size_t s) void _free_r(struct _reent *r, void *ptr) { - vPortFree(ptr); + void *return_addr = (void *)__builtin_return_address(0); + + vPortFree_trace(ptr, return_addr, (unsigned)-1); } void _exit(int status)