duma_hlp.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /*
  2. * DUMA - Red-Zone memory allocator.
  3. * Copyright (C) 2002-2009 Hayati Ayguen <h_ayguen@web.de>, Procitec GmbH
  4. * License: GNU LGPL (GNU Lesser General Public License, see COPYING-GPL)
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library 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 GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. *
  20. * FILE CONTENTS:
  21. * internal implementation file
  22. * contains helper functions for DUMA
  23. */
  24. /* Function: reduceProtectedMemory
  25. *
  26. * delete reductionSizekB amount of memory, which has already
  27. * been freed but got protected
  28. * return != 0 when more memory reducable
  29. */
  30. static int reduceProtectedMemory(size_t reductionSizekB) {
  31. struct _DUMA_Slot *slot = _duma_g.allocList;
  32. size_t count = _duma_s.slotCount;
  33. size_t alreadyReducekB = 0;
  34. #ifndef WIN32
  35. /* Windows VirtualFree(,,MEM_RELEASE) can only free whole allocations. not
  36. * parts */
  37. size_t delSize, newSize;
  38. /* 1- try reducing memory to just keep page(s) with userAddress */
  39. for (; count > 0 && alreadyReducekB < reductionSizekB; --count, ++slot)
  40. if (DUMAST_ALL_PROTECTED == slot->state) {
  41. /* free memory above userAddr; keep userAddr protected */
  42. newSize = (char *)slot->userAddress - (char *)slot->internalAddress;
  43. newSize = (newSize + DUMA_PAGE_SIZE) & ~(DUMA_PAGE_SIZE - 1);
  44. delSize = slot->internalSize - newSize;
  45. Page_Delete((char *)slot->internalAddress + newSize, delSize);
  46. alreadyReducekB += (delSize + 1023) >> 10;
  47. slot->state = DUMAST_BEGIN_PROTECTED;
  48. /* but keep the slot and userAddr */
  49. slot->internalSize = newSize;
  50. if (alreadyReducekB >= reductionSizekB) {
  51. _duma_s.sumProtectedMem -= alreadyReducekB;
  52. _duma_s.sumAllocatedMem -= alreadyReducekB;
  53. return 1;
  54. }
  55. }
  56. #endif
  57. /* 2- deallocate all page(s) with userAddress, empty whole slot */
  58. slot = _duma_g.allocList;
  59. count = _duma_s.slotCount;
  60. for (; count > 0 && alreadyReducekB < reductionSizekB; --count, ++slot)
  61. if (DUMAST_BEGIN_PROTECTED == slot->state
  62. #if defined(WIN32)
  63. || DUMAST_ALL_PROTECTED == slot->state
  64. #endif
  65. ) {
  66. /* free all the memory */
  67. Page_Delete(slot->internalAddress, slot->internalSize);
  68. alreadyReducekB += (slot->internalSize + 1023) >> 10;
  69. /* free slot and userAddr */
  70. slot->internalAddress = slot->userAddress = 0;
  71. slot->internalSize = slot->userSize = 0;
  72. slot->state = DUMAST_EMPTY;
  73. slot->allocator = EFA_INT_ALLOC;
  74. #ifndef DUMA_NO_LEAKDETECTION
  75. slot->fileSource = DUMAFS_EMPTY;
  76. slot->filename = 0;
  77. slot->lineno = 0;
  78. #endif
  79. if (alreadyReducekB >= reductionSizekB) {
  80. _duma_s.sumProtectedMem -= alreadyReducekB;
  81. _duma_s.sumAllocatedMem -= alreadyReducekB;
  82. return 1;
  83. }
  84. }
  85. return 0;
  86. }
  87. /* Function: slotForUserAddress
  88. *
  89. * Find the slot structure for a user address.
  90. */
  91. static struct _DUMA_Slot *slotForUserAddress(void *address) {
  92. struct _DUMA_Slot *slot = _duma_g.allocList;
  93. size_t count = _duma_s.slotCount;
  94. for (; count > 0; --count, ++slot)
  95. if (slot->userAddress == address)
  96. return slot;
  97. return 0;
  98. }
  99. /* Function: nearestSlotForUserAddress
  100. *
  101. * Find the nearest slot structure for a user address.
  102. */
  103. static struct _DUMA_Slot *nearestSlotForUserAddress(void *userAddress) {
  104. struct _DUMA_Slot *slot = _duma_g.allocList;
  105. size_t count = _duma_s.slotCount;
  106. for (; count > 0; --count, ++slot)
  107. if ((char *)slot->internalAddress <= (char *)userAddress &&
  108. (char *)userAddress <=
  109. (char *)slot->internalAddress + slot->internalSize)
  110. return slot;
  111. return 0;
  112. }
  113. /* Function: _duma_init_slack
  114. *
  115. * Initialise the no mans land, for a given slot
  116. */
  117. static void _duma_init_slack(struct _DUMA_Slot *slot) {
  118. char *accBegAddr, *accEndAddr;
  119. char *tmpBegAddr, *tmpEndAddr;
  120. #ifdef DUMA_EXPLICIT_INIT
  121. slot->slackfill = _duma_s.SLACKFILL;
  122. #endif
  123. /* nothing to do for zero userSize */
  124. if (!slot->userSize)
  125. return;
  126. /* calculate accessible non-protectable address area */
  127. if ((char *)slot->protAddress < (char *)slot->userAddress) {
  128. /* DUMA_PROTECT_BELOW was 1 when allocating this piece of memory */
  129. accBegAddr = (char *)slot->userAddress;
  130. accEndAddr = (char *)slot->internalAddress + slot->internalSize;
  131. } else {
  132. /* DUMA_PROTECT_BELOW was 0 when allocating this piece of memory */
  133. accBegAddr = (char *)slot->internalAddress;
  134. accEndAddr = (char *)slot->protAddress;
  135. }
  136. tmpBegAddr = accBegAddr;
  137. tmpEndAddr = (char *)slot->userAddress;
  138. while (tmpBegAddr < tmpEndAddr)
  139. *tmpBegAddr++ = (char)_duma_s.SLACKFILL;
  140. tmpBegAddr = (char *)slot->userAddress + slot->userSize;
  141. tmpEndAddr = accEndAddr;
  142. while (tmpBegAddr < tmpEndAddr)
  143. *tmpBegAddr++ = (char)_duma_s.SLACKFILL;
  144. }
  145. /* Function: _duma_check_slack
  146. *
  147. * Checks the integrity of no mans land, for a given slot
  148. */
  149. static void _duma_check_slack(struct _DUMA_Slot *slot) {
  150. char *accBegAddr, *accEndAddr;
  151. char *tmpBegAddr, *tmpEndAddr;
  152. char slackfill;
  153. #ifdef DUMA_EXPLICIT_INIT
  154. slackfill = (char)slot->slackfill;
  155. #else
  156. slackfill = (char)_duma_s.SLACKFILL;
  157. #endif
  158. /* nothing to do for zero userSize */
  159. if (!slot->userSize)
  160. return;
  161. if (!slot->internalAddress)
  162. return;
  163. /* calculate accessible non-protectable address area */
  164. if ((char *)slot->protAddress < (char *)slot->userAddress) {
  165. /* DUMA_PROTECT_BELOW was 1 when allocating this piece of memory */
  166. accBegAddr = (char *)slot->userAddress;
  167. accEndAddr = (char *)slot->internalAddress + slot->internalSize;
  168. } else {
  169. /* DUMA_PROTECT_BELOW was 0 when allocating this piece of memory */
  170. accBegAddr = (char *)slot->internalAddress;
  171. accEndAddr = (char *)slot->protAddress;
  172. }
  173. tmpBegAddr = accBegAddr;
  174. tmpEndAddr = (char *)slot->userAddress;
  175. while (tmpBegAddr < tmpEndAddr) {
  176. if ((char)slackfill != *tmpBegAddr++) {
  177. #ifndef DUMA_NO_LEAKDETECTION
  178. DUMA_Abort("ptr=%a: detected overwrite of ptrs no mans land below "
  179. "userSpace, size=%d alloced from %s(%i)",
  180. (DUMA_ADDR)slot->userAddress, (DUMA_SIZE)slot->userSize,
  181. slot->filename, slot->lineno);
  182. #else
  183. DUMA_Abort(
  184. "ptr=%a: detected overwrite of ptrs no mans land below userSpace",
  185. (DUMA_ADDR)slot->userAddress);
  186. #endif
  187. }
  188. }
  189. tmpBegAddr = (char *)slot->userAddress + slot->userSize;
  190. tmpEndAddr = accEndAddr;
  191. while (tmpBegAddr < tmpEndAddr) {
  192. if ((char)slackfill != *tmpBegAddr++) {
  193. #ifndef DUMA_NO_LEAKDETECTION
  194. DUMA_Abort("detected overwrite of no mans land above userSpace: ptr=%a, "
  195. "size=%d\nalloced from %s(%i)",
  196. (DUMA_ADDR)slot->userAddress, (DUMA_SIZE)slot->userSize,
  197. slot->filename, slot->lineno);
  198. #else
  199. DUMA_Abort("detected overwrite of no mans land above userSpace: ptr=%a",
  200. (DUMA_ADDR)slot->userAddress);
  201. #endif
  202. }
  203. }
  204. }
  205. /* Function: _duma_check_all_slacks
  206. *
  207. * Checks the integrity of all no mans land
  208. */
  209. static void _duma_check_all_slacks(void) {
  210. struct _DUMA_Slot *slot = _duma_g.allocList;
  211. size_t count = _duma_s.slotCount;
  212. for (; count > 0; --count, ++slot) {
  213. /* CHECK INTEGRITY OF NO MANS LAND */
  214. if (DUMAST_IN_USE == slot->state && slot->userSize)
  215. _duma_check_slack(slot);
  216. }
  217. }