private.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. /*
  2. * private.h
  3. */
  4. #include "lub/heap.h"
  5. #include "lub/bintree.h"
  6. #include "lub/types.h"
  7. #include "lub/dblockpool.h"
  8. #include "lub/size_fmt.h"
  9. /**********************************************************
  10. * PRIVATE TYPES
  11. ********************************************************** */
  12. typedef struct _lub_heap_node lub_heap_node_t;
  13. typedef struct _lub_heap_context lub_heap_context_t;
  14. typedef struct _lub_heap_cache lub_heap_cache_t;
  15. typedef enum {
  16. LUB_HEAP_TAINT_INITIAL = 0xBB,
  17. LUB_HEAP_TAINT_FREE = 0xFF,
  18. LUB_HEAP_TAINT_ALLOC = 0xAA
  19. } lub_heap_taint_t;
  20. typedef struct _lub_heap_stackframe stackframe_t;
  21. /**********************************************************
  22. * PRIVATE TYPES
  23. ********************************************************** */
  24. /* type to indicate the number of long words in a block */
  25. typedef unsigned long words_t;
  26. typedef struct lub_heap_tag_s lub_heap_tag_t;
  27. typedef struct lub_heap_segment_s lub_heap_segment_t;
  28. typedef union lub_heap_block_u lub_heap_block_t;
  29. typedef struct lub_heap_alloc_block_s lub_heap_alloc_block_t;
  30. /*
  31. * a special type which hold both a size and block type
  32. */
  33. struct lub_heap_tag_s
  34. {
  35. unsigned free : 1; /* indicates whether free/alloc block */
  36. unsigned segment : 1; /* indicates boundary of segment */
  37. unsigned words : 30; /* number of 4 byte words in block */
  38. };
  39. typedef struct lub_heap_key_s lub_heap_key_t;
  40. struct lub_heap_key_s
  41. {
  42. words_t words;
  43. const lub_heap_free_block_t *block;
  44. };
  45. /*
  46. * A specialisation of a generic block to hold free block information
  47. */
  48. struct lub_heap_free_block_s
  49. {
  50. lub_heap_tag_t tag;
  51. /*
  52. * node to hold this block in the size based binary tree
  53. */
  54. lub_bintree_node_t bt_node;
  55. /* space holder for the trailing tag */
  56. lub_heap_tag_t _tail;
  57. };
  58. /*
  59. * A specialisation of a generic block to hold free block information
  60. */
  61. struct lub_heap_alloc_block_s
  62. {
  63. lub_heap_tag_t tag;
  64. /* space holder for trailing tag */
  65. lub_heap_tag_t memory[1];
  66. };
  67. /* a generic block instance */
  68. union lub_heap_block_u
  69. {
  70. lub_heap_alloc_block_t alloc;
  71. lub_heap_free_block_t free;
  72. };
  73. /*
  74. * This is the control block for a segment
  75. */
  76. struct lub_heap_segment_s
  77. {
  78. lub_heap_segment_t *next;
  79. words_t words;
  80. lub_bintree_node_t bt_node;
  81. };
  82. /*
  83. * This is the control block assigned to represent the heap instance
  84. */
  85. struct lub_heap_s
  86. {
  87. /*
  88. * A cache control block if one exists
  89. */
  90. lub_heap_cache_t *cache;
  91. /*
  92. * A binary tree of free blocks
  93. */
  94. lub_bintree_t free_tree;
  95. /*
  96. * This is used to supress leak tracking
  97. */
  98. unsigned long suppress;
  99. /*
  100. * statistics for this heap
  101. */
  102. lub_heap_stats_t stats;
  103. /*
  104. * reference to next heap in the system
  105. */
  106. struct lub_heap_s *next;
  107. /*
  108. * reference to next segment (this must be last in the structure)
  109. */
  110. lub_heap_segment_t first_segment;
  111. };
  112. /*---------------------------------------------------------
  113. * PRIVATE META DATA
  114. *--------------------------------------------------------- */
  115. /*
  116. * a pointer to the start of data segment
  117. */
  118. extern char *lub_heap_data_start;
  119. /*
  120. * a pointer to the end of data segment
  121. */
  122. extern char *lub_heap_data_end;
  123. /*---------------------------------------------------------
  124. * PRIVATE META FUNCTIONS
  125. *--------------------------------------------------------- */
  126. /*
  127. * This operation sends to STDOUT the textual representation
  128. * of the provided address in memory.
  129. */
  130. extern void
  131. lub_heap_symShow(
  132. /*
  133. * The address of the function name to resolve
  134. */
  135. unsigned address
  136. );
  137. /*
  138. * This operation indicates whether the function represented by the
  139. * specified address contains the specified string.
  140. */
  141. extern bool_t
  142. lub_heap_symMatch(
  143. /*
  144. * The address of the function name to resolve
  145. */
  146. unsigned address,
  147. /*
  148. * The substring to match against
  149. */
  150. const char *substring
  151. );
  152. /*
  153. * This operation fills out the current stackframe
  154. */
  155. extern void
  156. lub_heap__get_stackframe(stackframe_t *stack,unsigned max);
  157. /*
  158. * A platform implementation should scan the BSS section
  159. * for any memory references.
  160. */
  161. extern void
  162. lub_heap_scan_bss(void);
  163. /*
  164. * A platform implementation should scan the DATA section
  165. * for any memory references.
  166. */
  167. extern void
  168. lub_heap_scan_data(void);
  169. /*
  170. * If possible a platform implementation should scan the current
  171. * stack for any memory references.
  172. * NB. if a platform happens to have allocated it stack from the
  173. * BSS or DATA section then this doesn't need to do anything.
  174. */
  175. extern void
  176. lub_heap_scan_stack(void);
  177. /*
  178. * This function fills out the specified memory with tainted
  179. * bytes if tainting is enabled for the system.
  180. */
  181. extern void
  182. lub_heap_taint_memory(
  183. /*
  184. * a pointer to the start of the memory to taint
  185. */
  186. char *ptr,
  187. /*
  188. * the type of tainting to perform
  189. */
  190. lub_heap_taint_t type,
  191. /*
  192. * the number of bytes to taint
  193. */
  194. size_t size
  195. );
  196. /*
  197. * If possible a platform implementation should
  198. * take this oportunity to write the value 0xCC
  199. * to all the stacks between the high water mark
  200. * and the current stack pointer.
  201. * This prevents any pointer droppings from hiding
  202. * memory leaks.
  203. */
  204. extern void
  205. lub_heap_clean_stacks(void);
  206. /*---------------------------------------------------------
  207. * PRIVATE METHODS
  208. *--------------------------------------------------------- */
  209. /*
  210. * This operation is the raw interface for allocating/releasing memory
  211. * to/from the dynamic heap. Memory allocated by this call will not be
  212. * monitored by the leak detection code.
  213. *
  214. * It changes the size of the object referenced by a passed in
  215. * pointer to "size". The contents will be unchanged up to the minimum of the old
  216. * and new sizes. If the new size is larger, the new space is uninitialised.
  217. *
  218. * \pre
  219. * - The heap needs to have been created with an initial memory segment.
  220. * - If "*ptr" contains a non-NULL value then this MUST have
  221. * been allocated using this operation, from the same heap instance.
  222. *
  223. * \return
  224. * - the status of the operation.
  225. *
  226. * \post
  227. * - The client takes responsiblity for releasing any allocated memory when they
  228. * are finished with it.
  229. * - If *ptr contains a non-NULL value, then after a succesfull call, the
  230. * initial memory referenced by it may have been released for reuse,
  231. * and the pointer modified to reference some new memory.
  232. * - *ptr may contain NULL in which case no memory will be released back to the
  233. * heap for reuse, and the pointer is filled out with the allocated memory.
  234. * - (size == 0) No new memory will be allocated, *ptr will be set to NULL,
  235. * and any original memory referenced by it will have been released.
  236. */
  237. extern lub_heap_status_t
  238. lub_heap_raw_realloc(
  239. /*
  240. * The heap instance.
  241. */
  242. lub_heap_t *instance,
  243. /*
  244. * A reference to the client pointer which was previously handed out.
  245. */
  246. char **ptr,
  247. /*
  248. * The size of the requested memory
  249. */
  250. size_t size,
  251. /*
  252. * The alignment of the requested memory
  253. */
  254. lub_heap_align_t alignment);
  255. /*
  256. * This is called before an actual realloc operation runs.
  257. * It provides the opportunity for the leak detector to release
  258. * any previous details and to modify the size and pointer to account
  259. * for its internal overheads.
  260. *
  261. * \return
  262. * The number of bytes which should be allocated by the realloc call.
  263. *
  264. * \post
  265. * - the 'node' currently held in the database will be removed, potentially
  266. * deleting the 'context' in the process.
  267. * - the leak_detector will note the fact that it is wrapping a realloc
  268. * call and any further calls which are invoked during the process will
  269. * NOT be monitored.
  270. */
  271. extern void
  272. lub_heap_pre_realloc(
  273. /*
  274. * The heap instance.
  275. */
  276. lub_heap_t *instance,
  277. /*
  278. * A reference to the client pointer which was previously handed out.
  279. */
  280. char **ptr,
  281. /*
  282. * A reference to the size of the requested memory
  283. */
  284. size_t *size);
  285. /*
  286. * This is called after a realloc has been done, just before the results
  287. * are returned to the client.
  288. * It provides the opportunity for the leak detector to store details
  289. * on the allocation and track it.
  290. *
  291. * \return
  292. * The pointer which should be returned to the client. This will skip any
  293. * housekeeping details which will have been added to the start of the
  294. * block.
  295. *
  296. * \post
  297. * - the 'node' currently will be added into the database, creating a
  298. * context if appropriate.
  299. * - the leak_detector will note the fact that the wrapping of a realloc()
  300. * call has completed and will start to monitor further calls again.
  301. */
  302. extern void
  303. lub_heap_post_realloc(
  304. /*
  305. * The heap instance
  306. */
  307. lub_heap_t *instance,
  308. /*
  309. * A reference to the client pointer which has been allocated.
  310. */
  311. char **ptr
  312. );
  313. /*
  314. * This function clears all the current leak information from the heap
  315. *
  316. * It is also used to define the number of stack frames which are
  317. * used to specify a context.
  318. *
  319. */
  320. void
  321. lub_heap_clearAll(
  322. /*
  323. * The heap instance
  324. */
  325. lub_heap_t *instance,
  326. /*
  327. * The number of stack frames to account for when evaluating
  328. * a context. A value of zero means "don't change"
  329. */
  330. unsigned frames
  331. );
  332. /*
  333. * This allows the tracking of allocation failures.
  334. */
  335. void
  336. lub_heap_alloc_failed(lub_heap_context_t *instance);
  337. /*
  338. * This allows the tracking of free failures.
  339. */
  340. void
  341. lub_heap_free_failed(void);
  342. /*
  343. * This method slices the specified number of words off the
  344. * bottom of the specified free block.
  345. * The original block is then shrunk appropriately and the
  346. * address of the new free block updated accordingly.
  347. * The result returned is a pointer to the requested memory.
  348. * If the slice cannot be taken then NULL is returned and the
  349. * free block is unaltered.
  350. *
  351. * It is assumed that the free block has been removed from the
  352. * tree prior to calling this method.
  353. */
  354. extern void *
  355. lub_heap_slice_from_bottom(lub_heap_t *instance,
  356. lub_heap_free_block_t **ptr_block,
  357. words_t *words,
  358. bool_t seg_start);
  359. /*
  360. * This method slices the specified number of words off the
  361. * top of the current free block.
  362. * The block is then shrunk appropriately and the assigned memory
  363. * is returned. The client's free block pointer is updated accordingly
  364. * e.g. if the request absorbs all of the free_block the client's
  365. * pointer is set to NULL.
  366. * If there is insufficient space to slice this free block then
  367. * NULL is returned and the free block is unaltered.
  368. */
  369. extern void *
  370. lub_heap_slice_from_top(lub_heap_t *instance,
  371. lub_heap_free_block_t **ptr_block,
  372. words_t *words,
  373. bool_t seg_end);
  374. /*
  375. * This method initialises a free block from some specified memory.
  376. */
  377. extern void
  378. lub_heap_init_free_block(lub_heap_t *instance,
  379. void *ptr,
  380. size_t size,
  381. bool_t seg_start,
  382. bool_t seg_end);
  383. /*
  384. * This method takes an existing allocated block and extends it by
  385. * trying to take memory from a free block immediately
  386. * above it
  387. */
  388. extern bool_t
  389. lub_heap_extend_upwards(lub_heap_t *instance,
  390. lub_heap_block_t **block,
  391. words_t words);
  392. /*
  393. * This method takes an existing allocated block and extends it by
  394. * trying to take memory from a free block immediately
  395. * below it
  396. */
  397. extern bool_t
  398. lub_heap_extend_downwards(lub_heap_t *instance,
  399. lub_heap_block_t **block,
  400. words_t words);
  401. /*
  402. * This method takes an existing allocated block and extends it by
  403. * trying to take memory from free blocks immediately
  404. * above and below it.
  405. */
  406. extern bool_t
  407. lub_heap_extend_both_ways(lub_heap_t *instance,
  408. lub_heap_block_t **block,
  409. words_t words);
  410. /*
  411. * This method creates a new alloc block from the specified heap
  412. */
  413. extern void *
  414. lub_heap_new_alloc_block(lub_heap_t *instance,
  415. words_t words);
  416. extern void
  417. lub_heap_graft_to_top(lub_heap_t *instance,
  418. lub_heap_block_t *free_block,
  419. void *ptr,
  420. words_t words,
  421. bool_t seg_end,
  422. bool_t other_free_block);
  423. extern void
  424. lub_heap_graft_to_bottom(lub_heap_t *instance,
  425. lub_heap_block_t *free_block,
  426. void *ptr,
  427. words_t words,
  428. bool_t seg_start,
  429. bool_t other_free_block);
  430. extern lub_heap_status_t
  431. lub_heap_merge_with_next(lub_heap_t *instance,
  432. lub_heap_block_t *block);
  433. extern lub_heap_status_t
  434. lub_heap_merge_with_previous(lub_heap_t *instance,
  435. lub_heap_block_t *block);
  436. extern lub_heap_status_t
  437. lub_heap_new_free_block(lub_heap_t *instance,
  438. lub_heap_block_t *block);
  439. /*
  440. * Given a block reference find the trailing tag
  441. */
  442. extern lub_heap_tag_t *
  443. lub_heap_block__get_tail(lub_heap_block_t *block);
  444. /*
  445. * Find the first block reference in the specified segment
  446. */
  447. lub_heap_block_t *
  448. lub_heap_block_getfirst(const lub_heap_segment_t *seg);
  449. /*
  450. * Given a block reference find the next one
  451. */
  452. extern lub_heap_block_t *
  453. lub_heap_block_getnext(lub_heap_block_t *block);
  454. /*
  455. * Given a block reference find the previous one
  456. */
  457. extern lub_heap_block_t *
  458. lub_heap_block_getprevious(lub_heap_block_t *block);
  459. /*
  460. * This checks the integrity of the current block
  461. * If the header and trailer values are different then
  462. * some form of memory corruption must have occured.
  463. */
  464. extern bool_t
  465. lub_heap_block_check(lub_heap_block_t *block);
  466. extern void
  467. lub_heap_block_getkey(const void *clientnode,
  468. lub_bintree_key_t *key);
  469. extern void
  470. lub_heap_scan_all(void);
  471. extern bool_t
  472. lub_heap_check_memory(lub_heap_t *instance);
  473. extern lub_heap_block_t *
  474. lub_heap_block_from_ptr(char *ptr);
  475. extern const lub_heap_segment_t *
  476. lub_heap_segment_findnext(const void *address);
  477. extern void
  478. lub_heap_align_block(lub_heap_t *this,
  479. lub_heap_align_t alignment,
  480. char **ptr,
  481. size_t *size);
  482. lub_heap_status_t
  483. lub_heap_cache_realloc(lub_heap_t *this,
  484. char **ptr,
  485. size_t requested_size);
  486. void
  487. lub_heap_cache_show(lub_heap_cache_t *this);