]> jfr.im git - irc/evilnet/x3.git/blame - src/alloc-x3.c
Merge branch 'master' of github.com:evilnet/x3
[irc/evilnet/x3.git] / src / alloc-x3.c
CommitLineData
1136f709 1/* alloc-srvx.c - Debug allocation wrapper
ec1a68c8 2 * Copyright 2005 srvx Development Team
3 *
2f61d1d7 4 * This file is part of srvx.
ec1a68c8 5 *
1136f709 6 * srvx is free software; you can redistribute it and/or modify
ec1a68c8 7 * it under the terms of the GNU General Public License as published by
be2c97a5 8 * the Free Software Foundation; either version 3 of the License, or
ec1a68c8 9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include "common.h"
0d16e639 18#include "log.h"
ec1a68c8 19
20#undef malloc
21#undef free
2f61d1d7 22
ec1a68c8 23#define ALLOC_MAGIC 0x1acf
24#define FREE_MAGIC 0xfc1d
25const char redzone[] = { '\x03', '\x47', '\x76', '\xc7' };
26
27struct alloc_header {
28 unsigned int file_id : 8;
29 unsigned int size : 24;
30 unsigned int line : 16;
31 unsigned int magic : 16;
32};
33
34static char file_id_map[256][32];
35static unsigned int file_ids_used;
36unsigned long alloc_count, alloc_size;
37
38static int
39file_id_cmp(const void *a_, const void *b_)
40{
41 return strcmp(a_, b_);
42}
43
44static unsigned int
45get_file_id(const char *fname)
46{
47 void *entry;
48
49 entry = bsearch(fname, file_id_map, file_ids_used, sizeof(file_id_map[0]), file_id_cmp);
50 if (entry)
51 return ((char*)entry - file_id_map[0]) / sizeof(file_id_map[0]);
52 strcpy(file_id_map[file_ids_used++], fname);
53 qsort(file_id_map, file_ids_used, sizeof(file_id_map[0]), file_id_cmp);
54 return file_ids_used - 1;
55}
56
57void *
83ff05c3 58x3_malloc(const char *file, unsigned int line, size_t size)
ec1a68c8 59{
60 struct alloc_header *block;
2f61d1d7 61
ec1a68c8 62 block = malloc(sizeof(*block) + size + sizeof(redzone));
63 assert(block != NULL);
0d16e639 64 if (block->magic == ALLOC_MAGIC && block->file_id < file_ids_used) {
65 /* Only report the error, due to possible false positives. */
2f61d1d7 66 log_module(MAIN_LOG, LOG_WARNING, "Detected possible reallocation: %p (called by %s:%u/%lu; allocated by %u:%u/%u).",
67 block, file, line, (unsigned long)size,
68 block->file_id, block->line, block->size);
0d16e639 69 }
ec1a68c8 70 memset(block, 0, sizeof(*block) + size);
71 memcpy((char*)(block + 1) + size, redzone, sizeof(redzone));
72 block->file_id = get_file_id(file);
73 block->line = line;
74 block->size = size;
75 block->magic = ALLOC_MAGIC;
76 alloc_count++;
77 alloc_size += size;
78 return block + 1;
79}
80
81void *
83ff05c3 82x3_realloc(const char *file, unsigned int line, void *ptr, size_t size)
2f61d1d7 83{
ec1a68c8 84 struct alloc_header *block, *newblock;
2f61d1d7 85
ec1a68c8 86 if (!ptr)
83ff05c3 87 return x3_malloc(file, line, size);
ec1a68c8 88
89 verify(ptr);
90 block = (struct alloc_header *)ptr - 1;
91
92 if (block->size >= size)
93 return block + 1;
2f61d1d7 94
ec1a68c8 95 newblock = malloc(sizeof(*newblock) + size + sizeof(redzone));
2f61d1d7 96 assert(newblock != NULL);
ec1a68c8 97 memset(newblock, 0, sizeof(*newblock));
98 memcpy(newblock + 1, block + 1, block->size);
99 memset((char*)(newblock + 1) + block->size, 0, size - block->size);
100 memcpy((char*)(newblock + 1) + size, redzone, sizeof(redzone));
101 newblock->file_id = get_file_id(file);
102 newblock->line = line;
103 newblock->size = size;
104 newblock->magic = ALLOC_MAGIC;
105 alloc_count++;
106 alloc_size += size;
2f61d1d7 107
83ff05c3 108 x3_free(file, line, block + 1);
ec1a68c8 109
110 return newblock + 1;
111}
112
113char *
83ff05c3 114x3_strdup(const char *file, unsigned int line, const char *src)
ec1a68c8 115{
116 char *target;
117 size_t len;
118
119 len = strlen(src) + 1;
83ff05c3 120 target = x3_malloc(file, line, len);
ec1a68c8 121 memcpy(target, src, len);
122 return target;
123}
124
2f61d1d7 125void
83ff05c3 126x3_free(UNUSED_ARG(const char *file), UNUSED_ARG(unsigned int line), void *ptr)
ec1a68c8 127{
128 struct alloc_header *block;
129 size_t size;
130
131 if (!ptr)
132 return;
0d16e639 133 verify(ptr);
2f61d1d7 134 block = (struct alloc_header *)ptr - 1;
ec1a68c8 135 size = block->size;
136 memset(block + 1, 0xde, size);
137 block->magic = FREE_MAGIC;
138 free(block);
2f61d1d7 139 alloc_count--;
140 alloc_size -= size;
ec1a68c8 141}
142
143void
144verify(const void *ptr)
145{
146 const struct alloc_header *header;
147 if (!ptr)
148 return;
149 header = (const struct alloc_header*)ptr - 1;
150 assert(header->magic == ALLOC_MAGIC);
151 assert(!memcmp((char*)(header + 1) + header->size, redzone, sizeof(redzone)));
152}