blob: 3739b62695371f114d05df554c11670783bbd41a [file] [log] [blame]
#include <malloc.h>
#include <common.h>
#include <config.h>
#define MARK (0xCD)
#define INICONTENT (0x0)
#define MARK_SIZE (4)
#define ALIGN_SIZE (sizeof(Align))
#define REVALUEUPALIGN(val) ((val) ? (((val) - 1) / ALIGN_SIZE + 1) : 0)
#define HEADER_ALIGN_SIZE (REVALUEUPALIGN(sizeof(HeaderStruct)))
typedef union Header_tag Header;
static Header *g_Header = NULL;
typedef union
{
long l_dummy;
double d_dummy;
void *p_dummy;
} Align;
typedef struct
{
int size;
char *filename;
int line;
Header *prev;
Header *next;
unsigned char mark[MARK_SIZE];
} HeaderStruct;
union Header_tag
{
HeaderStruct s;
Align u[HEADER_ALIGN_SIZE];
};
static void chain_block(Header *header)
{
if (g_Header)
{
g_Header->s.prev = header;
}
header->s.prev = NULL;
header->s.next = g_Header;
g_Header = header;
}
static void unchain_block(Header *header)
{
if (header->s.prev)
{
header->s.prev->s.next = header->s.next;
}
else
{
g_Header = header->s.next;
}
if (header->s.next)
{
header->s.next->s.prev = header->s.prev;
}
}
static void set_header(Header *header, int size, char *filename, int line)
{
header->s.size = size;
header->s.filename = filename;
header->s.line = line;
header->s.prev = NULL;
header->s.next = NULL;
memset(header->s.mark, MARK, (char*)&header[1] - (char*)header->s.mark);
}
static void set_tail(void *ptr, int alloc_size)
{
char *tail;
tail = ((char*)ptr) + alloc_size - MARK_SIZE;
memset(tail, MARK, MARK_SIZE);
}
static int check_mark_sub(unsigned char *mark, int size)
{
int i;
for (i = 0; i < size; i++)
{
if (mark[i] != MARK) {
return -1;
}
}
return 0;
}
static int check_mark(Header *header)
{
unsigned char *tail;
if (check_mark_sub(header->s.mark, (char*)&header[1] - (char*)header->s.mark))
{
printf("bad mark at header allocated in %s:%d\n", header->s.filename, header->s.line);
return -1;
}
tail = ((unsigned char*)header) + header->s.size + sizeof(Header);
if (check_mark_sub(tail, MARK_SIZE))
{
printf("bad mark at tail allocated in %s:%d\n", header->s.filename, header->s.line);
return -2;
}
return 0;
}
void* MEM_malloc(char *filename, int line, size_t size)
{
void *ptr;
size_t alloc_size;
#if DEBUG
alloc_size = size + sizeof(Header) + MARK_SIZE;
#else
alloc_size = size;
#endif /* DEBUG */
ptr = malloc(alloc_size);
if (ptr == NULL)
{
return NULL;
}
#if DEBUG
memset(ptr, INICONTENT, alloc_size);
set_header(ptr, size, filename, line);
set_tail(ptr, alloc_size);
chain_block((Header*)ptr);
ptr = (char*)ptr + sizeof(Header);
#endif /* DEBUG */
return ptr;
}
void MEM_free(void *ptr)
{
void *real_ptr;
if (ptr == NULL)
return;
#if DEBUG
real_ptr = (char*)ptr - sizeof(Header);
check_mark((Header*)real_ptr);
unchain_block(real_ptr);
#else
real_ptr = ptr;
#endif /* DEBUG */
free(real_ptr);
}