duma.h 13 KB

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