Files
Gen4_R-Car_Trace32/2_Trunk/demo/arm/etc/malloc/t32mem.c
2025-10-14 09:52:32 +09:00

261 lines
5.4 KiB
C

#include "stdlib.h"
/*
* Size of guard space inserted before and after the block.
* Larger sizes will more likely catch out-of-bound writes
* but consume more memory. The default is 16.
* When changed the size must also be supplied to the
* Data.MallocList command with the /Guard option.
*/
#define T32_GUARD_SIZE 16
/*
* Define this if you want to trace the memory allocations
* (by a hardware or software trace).
*/
#define T32_MEMTRACE
/*
* Define this if you want to use the LOGGER command to make the trace.
*/
#define T32_MEMLOGGER
/*
* Structure inserted before each block.
* The structures form a double linked list.
* The layout of the structure should not be changed
* as it is (hardcoded) used in the debugger commands.
*/
typedef struct T32_allocHeader
{
struct T32_allocHeader * prev;
struct T32_allocHeader * next;
void * caller;
size_t size;
#if T32_GUARD_SIZE
unsigned char guard[T32_GUARD_SIZE];
#endif
}
T32_allocHeader;
/*
* First and last element of the double linked list.
* All allocated control blocks are inserted between them.
*/
extern T32_allocHeader T32_LastNode;
T32_allocHeader T32_FirstNode = { 0, &T32_LastNode };
T32_allocHeader T32_LastNode = { &T32_FirstNode, 0 };
#define T32_INSERTNODE(p) { (p)->prev = T32_LastNode.prev; (p)->next = &T32_LastNode; T32_LastNode.prev->next = (p); T32_LastNode.prev = (p); }
#define T32_REMOVENODE(p) { (p)->prev->next = (p)->next; (p)->next->prev = (p)->prev; }
/*
* Structure for tracing malloc/free calls.
* The values are only written and only used by the trace tool.
*/
struct
{
void * caller;
size_t size;
void * ptr;
size_t totalsize;
size_t maxsize;
}
T32_MemTrace;
static size_t TotalSize, MaxSize;
#ifdef T32_MEMTRACE
#define T32_TRACENODE(p,s,c) { \
TotalSize += (s); \
if (TotalSize >= MaxSize) \
MaxSize = TotalSize; \
T32_MemTrace.caller = (c); \
T32_MemTrace.size = (s); \
T32_MemTrace.ptr = (void *) ((p) + 1); \
T32_MemTrace.totalsize = TotalSize; \
T32_MemTrace.maxsize = MaxSize; \
}
#else
#define T32_TRACENODE(p,size,caller)
#endif
#ifdef T32_MEMLOGGER
#define T32_TRACELOGGER() { \
T32_LoggerData(0x34, &T32_MemTrace.caller, T32_MemTrace.caller); \
T32_LoggerData(0x34, &T32_MemTrace.size, T32_MemTrace.size); \
T32_LoggerData(0x34, &T32_MemTrace.ptr, T32_MemTrace.ptr); \
T32_LoggerData(0x34, &T32_MemTrace.totalsize, T32_MemTrace.totalsize); \
T32_LoggerData(0x34, &T32_MemTrace.maxsize, T32_MemTrace.maxsize); \
}
#else
#define T32_TRACELOGGER()
#endif
/*
* Code to set and check the guard area.
* The guard area allows the debugger to check for
* out-of-bounds writes to the heap.
* The contents of the guard area should not be changed.
*/
static void SetGuard(unsigned char * guard)
{
int i;
for (i = 0; i < T32_GUARD_SIZE; i++)
guard[i] = (unsigned char) (i + 1);
}
static int CheckGuard(unsigned char * guard)
{
int i;
for (i = 0; i < T32_GUARD_SIZE; i++)
if (guard[i] != (unsigned char) (i + 1))
return 1;
return 0;
}
/*
* Breakpoint location. This function is called when an error
* is detected by the allocation check functions.
*/
void T32_breakpoint()
{
}
/*
* Hooks for the alloc functions.
* The code for these functions may needs to be copied
* if you have different allocation routines (e.g. calloc).
*/
void * T32_malloc(size_t size)
{
void * caller;
T32_allocHeader *tptr;
caller = (void *) __return_address();
tptr = malloc(size + sizeof(T32_allocHeader) + T32_GUARD_SIZE);
if (tptr == (T32_allocHeader *) 0)
return (void *) 0;
tptr->caller = caller;
tptr->size = size;
#if T32_GUARD_SIZE
SetGuard(tptr->guard);
SetGuard(((unsigned char *) (tptr + 1)) + size);
#endif
T32_INSERTNODE(tptr);
T32_TRACENODE(tptr,size,caller);
T32_TRACELOGGER();
return (void *) (tptr + 1);
}
void * T32_realloc(void * ptr, size_t size)
{
void *caller;
T32_allocHeader *tptr;
caller = (void *) __return_address();
if (ptr == (void *) 0) {
tptr = (T32_allocHeader *) 0;
} else {
tptr = ((T32_allocHeader *) (ptr)) - 1;
#if T32_GUARD_SIZE
if (CheckGuard(tptr->guard))
T32_breakpoint();
if (CheckGuard(((unsigned char *) (tptr + 1)) + tptr->size))
T32_breakpoint();
#endif
T32_REMOVENODE(tptr);
T32_TRACENODE(tptr, ~tptr->size, caller);
T32_TRACELOGGER();
}
if (size == 0) {
tptr = realloc(tptr, size);
return (void *) tptr;
} else {
tptr = realloc(tptr, size + sizeof(T32_allocHeader) + T32_GUARD_SIZE);
if (tptr == (T32_allocHeader *) 0)
return (void *) 0;
tptr->caller = caller;
tptr->size = size;
#if T32_GUARD_SIZE
SetGuard(((unsigned char *) (tptr + 1)) + size);
SetGuard(((unsigned char *) (tptr + 1)) + size);
#endif
T32_INSERTNODE(tptr);
T32_TRACENODE(tptr, size, caller);
T32_TRACELOGGER();
return (void *) (tptr + 1);
}
}
void T32_free(void * ptr)
{
void *caller;
T32_allocHeader *tptr;
caller = (void *) __return_address();
if (ptr == (void *) 0) {
tptr = (T32_allocHeader *) 0;
} else {
tptr = ((T32_allocHeader *) (ptr)) - 1;
#if T32_GUARD_SIZE
if (CheckGuard(tptr->guard))
T32_breakpoint();
if (CheckGuard(((unsigned char *) (tptr + 1)) + tptr->size))
T32_breakpoint();
#endif
T32_REMOVENODE(tptr);
T32_TRACENODE(tptr, ~tptr->size, caller);
T32_TRACELOGGER();
}
free(tptr);
}