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
|
/*
* DUMA - Red-Zone memory allocator.
* Copyright (C) 2006 Michael Eddington <meddington@gmail.com>
* Copyright (C) 2002-2005 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
/* TODO 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 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 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 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 */
|