feat(newlib): Use new private malloc function

Add return address to debug memory leak.
This commit is contained in:
Dong Heng
2018-07-04 14:30:53 +08:00
parent f25de8ffe3
commit 83ec6f3d58
4 changed files with 171 additions and 52 deletions

View File

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <string.h>
#include "esp_libc.h" #include "esp_libc.h"
#include "esp_system.h" #include "esp_system.h"
#include "esp_wifi_os_adapter.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) 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)) if (cap & (OSI_MALLOC_CAP_8BIT | OSI_MALLOC_CAP_DMA))
return os_malloc(s); iram = false;
else 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) 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) 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) 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) 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) static void srand_wrapper(uint32_t seed)

View File

@ -268,7 +268,10 @@ void pvShowMalloc()
} else { } else {
basename = ""; 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_printf("sh3,");
// ets_delay_us(2000); // ets_delay_us(2000);
system_soft_wdt_feed(); system_soft_wdt_feed();
@ -332,7 +335,9 @@ size_t xPortWantedSizeAlign(size_t xWantedSize)
void *pvPortMalloc( size_t xWantedSize ) void *pvPortMalloc( size_t xWantedSize )
#ifdef MEMLEAK_DEBUG #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 ) 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; return pvReturn;
} }
void *malloc(size_t nbytes) __attribute__((alias("pvPortMalloc")));
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortFree( void *pv ) void vPortFree( void *pv )
#ifdef MEMLEAK_DEBUG #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 ) 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) void *pvPortCalloc(size_t count, size_t size)
#ifdef MEMLEAK_DEBUG #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) void *pvPortCalloc_trace(size_t count, size_t size, const char * file, unsigned line)
#endif #endif
{ {
void *p; char *p = pvPortMalloc_trace(count * size, file, line, true);
//ets_printf("1,"); if (p)
/* allocate 'count' objects of size 'size' */ memset(p, 0, count * size);
p = pvPortMalloc_t(count * size);
//ets_printf("2,");
if (p) {
/* zero the memory */
memset(p, 0, count * size);
}
//ets_printf("3,");
return p;
}
void *calloc(size_t count, size_t nbytes) __attribute__((alias("pvPortCalloc"))); return p;
}
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void *pvPortRealloc(void *mem, size_t newsize) void *pvPortRealloc(void *mem, size_t newsize)
#ifdef MEMLEAK_DEBUG #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) void *pvPortRealloc_trace(void *mem, size_t newsize, const char *file, unsigned line)
#endif #endif
{ {
if (newsize == 0) { void *return_addr = (void *)__builtin_return_address(0);
vPortFree_t(mem);
return NULL; 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; return p;
} }
void *realloc(void *ptr, size_t nbytes) __attribute__((alias("pvPortRealloc")));
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void *pvPortZalloc(size_t size) void *pvPortZalloc(size_t size)
#ifdef MEMLEAK_DEBUG #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) void *pvPortZalloc_trace(size_t size, const char * file, unsigned line)
#endif #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 ) size_t xPortGetFreeHeapSize( void )
{ {

View File

@ -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 <stddef.h>
#include <string.h>
#include <stdlib.h>
#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);
}

View File

@ -91,19 +91,20 @@ void *_sbrk_r(struct _reent *r, ptrdiff_t incr)
void *_malloc_r(struct _reent *r, size_t n) void *_malloc_r(struct _reent *r, size_t n)
{ {
#ifndef MEMLEAK_DEBUG void *return_addr = (void *)__builtin_return_address(0);
return pvPortMalloc(n);
#else return pvPortMalloc_trace(n, return_addr, (unsigned)-1, true);
return pvPortMalloc_trace(n, NULL, 0, false);
#endif
} }
void *_realloc_r(struct _reent *r, void *old_ptr, size_t n) 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) { if (p && old_ptr) {
memcpy(p, old_ptr, n); memcpy(p, old_ptr, n);
vPortFree(old_ptr); vPortFree_trace(old_ptr, return_addr, 0);
} }
return p; 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) 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) if (p)
memset(p, 0, c * s); 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) 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) void _exit(int status)