-
Notifications
You must be signed in to change notification settings - Fork 10
/
duma.h
423 lines (373 loc) · 17.2 KB
/
duma.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
/*
* DUMA - Red-Zone memory allocator.
* Copyright (C) 2020-2022 Jeffrey H. Johnson <trnsz@pobox.com>
* Copyright (C) 2006 Michael Eddington <meddington@gmail.com>
* Copyright (C) 2002-2021 Hayati Ayguen <h_ayguen@web.de>, Procitec GmbH
* Copyright (C) 1987-1999 Bruce Perens <bruce@perens.com>
* License: GNU GPL (GNU General Public License, see COPYING-GPL)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* FILE CONTENTS:
* header file for inclusion from YOUR application code
*/
/* explicitly no "#ifndef _DUMA_H_" to allow mutliple inclusions
* within single source file with inclusion of noduma.h in between
*/
#include <stdlib.h>
/*
* #include <stdlib.h>
*
* You must include <stdlib.h> before including <duma.h> !
*
*/
/* for enabling inclusion of duma.h after inclusion of efencint.h */
/* remove previous definitions */
#define SKIP_DUMA_NO_CXX
#include "noduma.h"
#undef SKIP_DUMA_NO_CXX
#include "duma_config.h"
#ifdef __cplusplus
#define DUMA_EXTERN_C extern "C"
#else
#define DUMA_EXTERN_C extern
#endif
#ifdef DUMA_NO_DUMA
/* enable these macros even in release code, but do nothing */
#define DUMA_newFrame() \
do { \
} while (0)
#define DUMA_delFrame() \
do { \
} while (0)
#define DUMA_SET_ALIGNMENT(V) \
do { \
} while (0)
#define DUMA_SET_PROTECT_BELOW(V) \
do { \
} while (0)
#define DUMA_SET_FILL(V) \
do { \
} while (0)
#define DUMA_ASSERT(EXPR) \
do { \
} while (0)
#define DUMA_CHECK(BASEADR) \
do { \
} while (0)
#define DUMA_CHECKALL() \
do { \
} while (0)
#define CA_DECLARE(NAME, SIZE) \
do { \
} while (0)
#define CA_DEFINE(TYPE, NAME, SIZE) TYPE NAME[SIZE]
#define CA_REF(NAME, INDEX) NAME[INDEX]
#else /* ifndef DUMA_NO_DUMA */
#ifndef DUMA_EXTERNS_DECLARED
#define DUMA_EXTERNS_DECLARED
/* global DUMA variables */
DUMA_EXTERN_C int DUMA_OUTPUT_DEBUG;
DUMA_EXTERN_C int DUMA_OUTPUT_STDOUT;
DUMA_EXTERN_C int DUMA_OUTPUT_STDERR;
DUMA_EXTERN_C char *DUMA_OUTPUT_FILE;
DUMA_EXTERN_C int DUMA_OUTPUT_STACKTRACE;
#endif /* DUMA_EXTERNS_DECLARED */
/* set Maximum Delete Depth (depth of recursive destructor calls) */
#ifndef DUMA_MAX_DEL_DEPTH
#define DUMA_MAX_DEL_DEPTH 256
#endif
#ifndef DUMA_TLSVARTYPE_DEFINED
#define DUMA_TLSVARTYPE_DEFINED
/* GitHub #82 - following variables should exist per thread ("thread-local") */
typedef struct {
/*
* ALIGNMENT is a global variable used to control the default alignment
* of buffers returned by malloc(), calloc(), and realloc(). It is all-caps
* so that its name matches the name of the environment variable that is used
* to set it. This gives the programmer one less name to remember.
*/
int ALIGNMENT;
/*
* PROTECT_BELOW is used to modify the behavior of the allocator. When
* its value is non-zero, the allocator will place an inaccessable page
* immediately _before_ the malloc buffer in the address space, instead
* of _after_ it. Use this to detect malloc buffer under-runs, rather than
* over-runs. It won't detect both at the same time, so you should test your
* software twice, once with this value clear, and once with it set.
*/
int PROTECT_BELOW;
/*
* FILL is set to 0-255 if DUMA should fill all new allocated
* memory with the specified value. Set to -1 when DUMA should not
* initialise allocated memory.
* default is set to initialise with 255, cause many programs rely on
* initialisation to 0!
*/
int FILL;
#if !defined(DUMA_NO_CPP_SUPPORT) && !defined(DUMA_NO_LEAKDETECTION)
int Magic;
int DelPtr;
const char *DelFile[DUMA_MAX_DEL_DEPTH];
int DelLine[DUMA_MAX_DEL_DEPTH];
#endif
} DUMA_TLSVARS_T;
#endif
#ifndef DUMA_GLOBALS_DEFINED
#define DUMA_GLOBALS_DEFINED
typedef struct {
/* Protection Space A */
char acSpaceA[2 * DUMA_PAGE_SIZE];
/* Variable: _duma_allocList
*
* _DUMA_allocList points to the array of slot structures used to manage the
* malloc arena.
*/
struct _DUMA_Slot *allocList;
/* Variable: _duma_null_addr
*
* _duma_null_addr is the address malloc() or C++ operator new returns, when
* size is 0 two pages get reserved and protected
*/
void *null_addr;
/* Variable */
DUMA_TLSVARS_T TLS;
/* Protection Space B */
char acSpaceB[2 * DUMA_PAGE_SIZE];
} DUMA_GLOBALVARS_T;
DUMA_EXTERN_C DUMA_GLOBALVARS_T _duma_g;
#endif /* DUMA_GLOBALS_DEFINED */
#define GET_DUMA_TLSVARS() (&_duma_g.TLS)
#ifndef DUMA_SET_ALIGNMENT
#define DUMA_SET_ALIGNMENT(V) GET_DUMA_TLSVARS()->ALIGNMENT = (V)
#endif
#ifndef DUMA_SET_PROTECT_BELOW
#define DUMA_SET_PROTECT_BELOW(V) GET_DUMA_TLSVARS()->PROTECT_BELOW = (V)
#endif
#ifndef DUMA_SET_FILL
#define DUMA_SET_FILL(V) GET_DUMA_TLSVARS()->FILL = (V)
#endif
#ifndef DUMA_ENUMS_DECLARED
#define DUMA_ENUMS_DECLARED
/* allocator defines the type of calling allocator/deallocator function */
enum _DUMA_Allocator {
EFA_INT_ALLOC,
EFA_INT_DEALLOC,
EFA_MALLOC,
EFA_CALLOC,
EFA_FREE,
EFA_MEMALIGN,
EFA_POSIX_MEMALIGN,
EFA_REALLOC,
EFA_VALLOC,
EFA_STRDUP,
EFA_NEW_ELEM,
EFA_DEL_ELEM,
EFA_NEW_ARRAY,
EFA_DEL_ARRAY
/* use following enums when calling _duma_allocate()/_duma_deallocate()
* from user defined member operators
*/
,
EFA_MEMBER_NEW_ELEM,
EFA_MEMBER_DEL_ELEM,
EFA_MEMBER_NEW_ARRAY,
EFA_MEMBER_DEL_ARRAY
};
enum _DUMA_FailReturn { DUMA_FAIL_NULL, DUMA_FAIL_ENV };
#endif /* DUMA_ENUMS_DECLARED */
#ifndef DUMA_FUNCTIONS_DECLARED
#define DUMA_FUNCTIONS_DECLARED
DUMA_EXTERN_C void _duma_init(void);
DUMA_EXTERN_C void _duma_assert(const char *exprstr, const char *filename,
int lineno);
DUMA_EXTERN_C void duma_check(void *address);
DUMA_EXTERN_C void duma_checkAll();
DUMA_EXTERN_C void *duma_alloc_return(void *address);
#ifdef DUMA_EXPLICIT_INIT
DUMA_EXTERN_C void duma_init(void);
#endif
#ifndef DUMA_NO_LEAKDETECTION
DUMA_EXTERN_C void *_duma_allocate(size_t alignment, size_t userSize,
int protectBelow, int fillByte,
int protectAllocList,
enum _DUMA_Allocator allocator,
enum _DUMA_FailReturn fail,
const char *filename, int lineno);
DUMA_EXTERN_C void _duma_deallocate(void *baseAdr, int protectAllocList,
enum _DUMA_Allocator allocator,
const char *filename, int lineno);
DUMA_EXTERN_C void *_duma_malloc(size_t size, const char *filename, int lineno);
DUMA_EXTERN_C void *_duma_calloc(size_t elemCount, size_t elemSize,
const char *filename, int lineno);
DUMA_EXTERN_C void _duma_free(void *baseAdr, const char *filename, int lineno);
DUMA_EXTERN_C void *_duma_memalign(size_t alignment, size_t userSize,
const char *filename, int lineno);
DUMA_EXTERN_C int _duma_posix_memalign(void **memptr, size_t alignment,
size_t userSize, const char *filename,
int lineno);
DUMA_EXTERN_C void *_duma_realloc(void *baseAdr, size_t newSize,
const char *filename, int lineno);
DUMA_EXTERN_C void *_duma_valloc(size_t size, const char *filename, int lineno);
DUMA_EXTERN_C size_t _duma_malloc_usable_size(void *ptr, const char *filename,
int lineno);
DUMA_EXTERN_C char *_duma_strdup(const char *str, const char *filename,
int lineno);
DUMA_EXTERN_C void *_duma_memcpy(void *dest, const void *src, size_t size,
const char *filename, int lineno);
DUMA_EXTERN_C void *_duma_memmove(void *dest, const void *src, size_t size);
DUMA_EXTERN_C char *_duma_strcpy(char *dest, const char *src,
const char *filename, int lineno);
DUMA_EXTERN_C char *_duma_strncpy(char *dest, const char *src, size_t size,
const char *filename, int lineno);
DUMA_EXTERN_C char *_duma_strcat(char *dest, const char *src,
const char *filename, int lineno);
DUMA_EXTERN_C char *_duma_strncat(char *dest, const char *src, size_t size,
const char *filename, int lineno);
DUMA_EXTERN_C void DUMA_newFrame(void);
DUMA_EXTERN_C void DUMA_delFrame(void);
#else /* DUMA_NO_LEAKDETECTION */
DUMA_EXTERN_C void *_duma_allocate(size_t alignment, size_t userSize,
int protectBelow, int fillByte,
int protectAllocList,
enum _DUMA_Allocator allocator,
enum _DUMA_FailReturn fail);
DUMA_EXTERN_C void _duma_deallocate(void *baseAdr, int protectAllocList,
enum _DUMA_Allocator allocator);
DUMA_EXTERN_C void *_duma_malloc(size_t size);
DUMA_EXTERN_C void *_duma_calloc(size_t elemCount, size_t elemSize);
DUMA_EXTERN_C void _duma_free(void *baseAdr);
DUMA_EXTERN_C void *_duma_memalign(size_t alignment, size_t userSize);
DUMA_EXTERN_C int _duma_posix_memalign(void **memptr, size_t alignment,
size_t userSize);
DUMA_EXTERN_C void *_duma_realloc(void *baseAdr, size_t newSize);
DUMA_EXTERN_C void *_duma_valloc(size_t size);
DUMA_EXTERN_C size_t _duma_malloc_usable_size(void *ptr);
DUMA_EXTERN_C char *_duma_strdup(const char *str);
DUMA_EXTERN_C void *_duma_memcpy(void *dest, const void *src, size_t size);
DUMA_EXTERN_C void *_duma_memmove(void *dest, const void *src, size_t size);
DUMA_EXTERN_C char *_duma_strcpy(char *dest, const char *src);
DUMA_EXTERN_C char *_duma_strncpy(char *dest, const char *src, size_t size);
DUMA_EXTERN_C char *_duma_strcat(char *dest, const char *src);
DUMA_EXTERN_C char *_duma_strncat(char *dest, const char *src, size_t size);
#endif /* DUMA_NO_LEAKDETECTION */
#endif /* DUMA_FUNCTIONS_DECLARED */
#ifndef DUMA_SKIP_SETUP
#ifndef DUMA_NO_LEAKDETECTION
#define malloc(SIZE) _duma_malloc(SIZE, __FILE__, __LINE__)
#define calloc(ELEMCOUNT, ELEMSIZE) \
_duma_calloc(ELEMCOUNT, ELEMSIZE, __FILE__, __LINE__)
#define free(BASEADR) _duma_free(BASEADR, __FILE__, __LINE__)
#define memalign(ALIGNMENT, SIZE) \
_duma_memalign(ALIGNMENT, SIZE, __FILE__, __LINE__)
#define posix_memalign(MEMPTR, ALIGNMENT, SIZE) \
_duma_posix_memalign(MEMPTR, ALIGNMENT, SIZE, __FILE__, __LINE__)
#define realloc(BASEADR, NEWSIZE) \
_duma_realloc(BASEADR, NEWSIZE, __FILE__, __LINE__)
#define valloc(SIZE) _duma_valloc(SIZE, __FILE__, __LINE__)
#define malloc_usable_size(PTR) \
_duma_malloc_usable_size(PTR, __FILE__, __LINE__)
#define strdup(STR) _duma_strdup(STR, __FILE__, __LINE__)
#define memcpy(DEST, SRC, SIZE) \
_duma_memcpy(DEST, SRC, SIZE, __FILE__, __LINE__)
#define memmove(DEST, SRC, SIZE) _duma_memmove(DEST, SRC, SIZE)
#define strcpy(DEST, SRC) _duma_strcpy(DEST, SRC, __FILE__, __LINE__)
#define strncpy(DEST, SRC, SIZE) \
_duma_strncpy(DEST, SRC, SIZE, __FILE__, __LINE__)
#define strcat(DEST, SRC) _duma_strcat(DEST, SRC, __FILE__, __LINE__)
#define strncat(DEST, SRC, SIZE) \
_duma_strncat(DEST, SRC, SIZE, __FILE__, __LINE__)
#else /* DUMA_NO_LEAKDETECTION */
#define DUMA_newFrame() \
do { \
} while (0)
#define DUMA_delFrame() \
do { \
} while (0)
#endif /* DUMA_NO_LEAKDETECTION */
#endif // DUMA_SKIP_SETUP
#ifndef DUMA_ASSERT
#define DUMA_ASSERT(EXPR) \
((EXPR) || (_duma_assert(#EXPR, __FILE__, __LINE__), 0))
#endif
#ifndef DUMA_CHECK
#define DUMA_CHECK(BASEADR) duma_check(BASEADR)
#endif
#ifndef DUMA_CHECKALL
#define DUMA_CHECKALL() duma_checkAll()
#endif
/*
* protection of functions return address
*/
#ifdef __GNUC__
#define DUMA_FN_PROT_START \
const void *DUMA_RET_ADDR = __builtin_return_address(0); \
{
#define DUMA_FN_PROT_END \
} \
DUMA_ASSERT(__builtin_return_address(0) == DUMA_RET_ADDR);
#define DUMA_FN_PROT_RET(EXPR) \
do { \
DUMA_ASSERT(__builtin_return_address(0) == DUMA_RET_ADDR); \
return (EXPR); \
} while (0)
#define DUMA_FN_PROT_RET_VOID() \
do { \
DUMA_ASSERT(__builtin_return_address(0) == DUMA_RET_ADDR); \
return; \
} while (0)
#else
#define DUMA_FN_PROT_START \
int aiDUMA_PROT[4] = {'E', 'F', 'P', 'R'}; \
{
#define DUMA_FN_PROT_END \
} \
DUMA_ASSERT('E' == aiDUMA_PROT[0] && 'F' == aiDUMA_PROT[1] && \
'P' == aiDUMA_PROT[2] && 'R' == aiDUMA_PROT[3]);
#define DUMA_FN_PROT_RET(EXPR) \
do { \
DUMA_ASSERT('E' == aiDUMA_PROT[0] && 'F' == aiDUMA_PROT[1] && \
'P' == aiDUMA_PROT[2] && 'R' == aiDUMA_PROT[3]); \
return (EXPR); \
} while (0)
#define DUMA_FN_PROT_RET_VOID() \
do { \
DUMA_ASSERT('E' == aiDUMA_PROT[0] && 'F' == aiDUMA_PROT[1] && \
'P' == aiDUMA_PROT[2] && 'R' == aiDUMA_PROT[3]); \
return; \
} while (0)
#endif
/* declaration of an already defined array to enable checking at every reference
* when using CA_REF()
*/
#define CA_DECLARE(NAME, SIZE) \
const unsigned long NAME##_checkedsize = (SIZE); \
unsigned long NAME##_checkedidx
/* definition of a checked array adds definitions for its size and an extra
* temporary. every array gets its own temporary to avoid problems with
* threading a global temporary would have.
*/
#define CA_DEFINE(TYPE, NAME, SIZE) \
TYPE NAME[SIZE]; \
CA_DECLARE(NAME, SIZE)
/* every access to a checked array is preceded an assert() on the index;
* the index parameter is stored to a temporary to avoid double execution of
* index, when index contains f.e. a "++".
*/
#define CA_REF(NAME, INDEX) \
NAME[DUMA_ASSERT((NAME##_checkedidx = (INDEX)) < NAME##_checkedsize), \
NAME##_checkedidx]
#endif /* end ifdef DUMA_NO_DUMA */