MyAlloc.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. /** @file
  2. File for memory allocation tracking functions.
  3. Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "MyAlloc.h"
  7. #if USE_MYALLOC
  8. //
  9. // Get back to original alloc/free calls.
  10. //
  11. #undef malloc
  12. #undef calloc
  13. #undef realloc
  14. #undef free
  15. //
  16. // Start of allocation list.
  17. //
  18. STATIC MY_ALLOC_STRUCT *MyAllocData = NULL;
  19. //
  20. //
  21. //
  22. STATIC UINT32 MyAllocHeadMagik = MYALLOC_HEAD_MAGIK;
  23. STATIC UINT32 MyAllocTailMagik = MYALLOC_TAIL_MAGIK;
  24. //
  25. // ////////////////////////////////////////////////////////////////////////////
  26. //
  27. //
  28. VOID
  29. MyCheck (
  30. BOOLEAN Final,
  31. UINT8 File[],
  32. UINTN Line
  33. )
  34. // *++
  35. // Description:
  36. //
  37. // Check for corruptions in the allocated memory chain. If a corruption
  38. // is detection program operation stops w/ an exit(1) call.
  39. //
  40. // Parameters:
  41. //
  42. // Final := When FALSE, MyCheck() returns if the allocated memory chain
  43. // has not been corrupted. When TRUE, MyCheck() returns if there
  44. // are no un-freed allocations. If there are un-freed allocations,
  45. // they are displayed and exit(1) is called.
  46. //
  47. //
  48. // File := Set to __FILE__ by macro expansion.
  49. //
  50. // Line := Set to __LINE__ by macro expansion.
  51. //
  52. // Returns:
  53. //
  54. // n/a
  55. //
  56. // --*/
  57. //
  58. {
  59. MY_ALLOC_STRUCT *Tmp;
  60. //
  61. // Check parameters.
  62. //
  63. if (File == NULL) {
  64. printf (
  65. "\nMyCheck(Final=%u, File=NULL, Line=%u)"
  66. "Invalid parameter(s).\n",
  67. Final,
  68. (unsigned)Line
  69. );
  70. exit (1);
  71. }
  72. if (Line == 0) {
  73. printf (
  74. "\nMyCheck(Final=%u, File=%s, Line=%u)"
  75. "Invalid parameter(s).\n",
  76. Final,
  77. File,
  78. (unsigned)Line
  79. );
  80. exit (1);
  81. }
  82. if (strlen ((CHAR8 *)File) == 0) {
  83. printf (
  84. "\nMyCheck(Final=%u, File=%s, Line=%u)"
  85. "Invalid parameter.\n",
  86. Final,
  87. File,
  88. (unsigned)Line
  89. );
  90. exit (1);
  91. }
  92. //
  93. // Check structure contents.
  94. //
  95. for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) {
  96. if (memcmp(Tmp->Buffer, &MyAllocHeadMagik, sizeof MyAllocHeadMagik) ||
  97. memcmp(&Tmp->Buffer[Tmp->Size + sizeof(UINT32)], &MyAllocTailMagik, sizeof MyAllocTailMagik)) {
  98. break;
  99. }
  100. }
  101. //
  102. // If Tmp is not NULL, the structure is corrupt.
  103. //
  104. if (Tmp != NULL) {
  105. printf (
  106. "\nMyCheck(Final=%u, File=%s, Line=%u)""\nStructure corrupted!"
  107. "\nFile=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",
  108. Final,
  109. File,
  110. (unsigned)Line,
  111. Tmp->File,
  112. (unsigned) Tmp->Line,
  113. (unsigned) Tmp->Size,
  114. (unsigned) *(UINT32 *) (Tmp->Buffer),
  115. (unsigned) *(UINT32 *) (&Tmp->Buffer[Tmp->Size + sizeof (UINT32)])
  116. );
  117. exit (1);
  118. }
  119. //
  120. // If Final is TRUE, display the state of the structure chain.
  121. //
  122. if (Final) {
  123. if (MyAllocData != NULL) {
  124. printf (
  125. "\nMyCheck(Final=%u, File=%s, Line=%u)"
  126. "\nSome allocated items have not been freed.\n",
  127. Final,
  128. File,
  129. (unsigned)Line
  130. );
  131. for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) {
  132. printf (
  133. "File=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",
  134. Tmp->File,
  135. (unsigned) Tmp->Line,
  136. (unsigned) Tmp->Size,
  137. (unsigned) *(UINT32 *) (Tmp->Buffer),
  138. (unsigned) *(UINT32 *) (&Tmp->Buffer[Tmp->Size + sizeof (UINT32)])
  139. );
  140. }
  141. }
  142. }
  143. }
  144. //
  145. // ////////////////////////////////////////////////////////////////////////////
  146. //
  147. //
  148. VOID *
  149. MyAlloc (
  150. UINTN Size,
  151. UINT8 File[],
  152. UINTN Line
  153. )
  154. // *++
  155. // Description:
  156. //
  157. // Allocate a new link in the allocation chain along with enough storage
  158. // for the File[] string, requested Size and alignment overhead. If
  159. // memory cannot be allocated or the allocation chain has been corrupted,
  160. // exit(1) will be called.
  161. //
  162. // Parameters:
  163. //
  164. // Size := Number of bytes (UINT8) requested by the called.
  165. // Size cannot be zero.
  166. //
  167. // File := Set to __FILE__ by macro expansion.
  168. //
  169. // Line := Set to __LINE__ by macro expansion.
  170. //
  171. // Returns:
  172. //
  173. // Pointer to the caller's buffer.
  174. //
  175. // --*/
  176. //
  177. {
  178. MY_ALLOC_STRUCT *Tmp;
  179. UINTN Len;
  180. //
  181. // Check for invalid parameters.
  182. //
  183. if (File == NULL) {
  184. printf (
  185. "\nMyAlloc(Size=%u, File=NULL, Line=%u)"
  186. "\nInvalid parameter(s).\n",
  187. (unsigned)Size,
  188. (unsigned)Line
  189. );
  190. exit (1);
  191. }
  192. if (Size == 0 || Line == 0) {
  193. printf (
  194. "\nMyAlloc(Size=%u, File=%s, Line=%u)"
  195. "\nInvalid parameter(s).\n",
  196. (unsigned)Size,
  197. File,
  198. (unsigned)Line
  199. );
  200. exit (1);
  201. }
  202. Len = strlen ((CHAR8 *)File);
  203. if (Len == 0) {
  204. printf (
  205. "\nMyAlloc(Size=%u, File=%s, Line=%u)"
  206. "\nInvalid parameter.\n",
  207. (unsigned)Size,
  208. File,
  209. (unsigned)Line
  210. );
  211. exit (1);
  212. }
  213. //
  214. // Check the allocation list for corruption.
  215. //
  216. MyCheck (0, (UINT8 *)__FILE__, __LINE__);
  217. //
  218. // Allocate a new entry.
  219. //
  220. Tmp = calloc (
  221. 1,
  222. sizeof (MY_ALLOC_STRUCT) + Len + 1 + sizeof (UINT64) + Size + (sizeof MyAllocHeadMagik) + (sizeof MyAllocTailMagik)
  223. );
  224. if (Tmp == NULL) {
  225. printf (
  226. "\nMyAlloc(Size=%u, File=%s, Line=%u)"
  227. "\nOut of memory.\n",
  228. (unsigned)Size,
  229. File,
  230. (unsigned)Line
  231. );
  232. exit (1);
  233. }
  234. //
  235. // Fill in the new entry.
  236. //
  237. Tmp->File = ((UINT8 *) Tmp) + sizeof (MY_ALLOC_STRUCT);
  238. strcpy ((CHAR8 *)Tmp->File, (CHAR8 *)File);
  239. Tmp->Line = Line;
  240. Tmp->Size = Size;
  241. Tmp->Buffer = (UINT8 *) (((UINTN) Tmp + Len + 9) &~7);
  242. memcpy (Tmp->Buffer, &MyAllocHeadMagik, sizeof MyAllocHeadMagik);
  243. memcpy (
  244. &Tmp->Buffer[Size + sizeof (UINT32)],
  245. &MyAllocTailMagik,
  246. sizeof MyAllocTailMagik
  247. );
  248. Tmp->Next = MyAllocData;
  249. Tmp->Cksum = (UINTN) Tmp + (UINTN) (Tmp->Next) + Tmp->Line + Tmp->Size + (UINTN) (Tmp->File) + (UINTN) (Tmp->Buffer);
  250. MyAllocData = Tmp;
  251. return Tmp->Buffer + sizeof (UINT32);
  252. }
  253. //
  254. // ////////////////////////////////////////////////////////////////////////////
  255. //
  256. //
  257. VOID *
  258. MyRealloc (
  259. VOID *Ptr,
  260. UINTN Size,
  261. UINT8 File[],
  262. UINTN Line
  263. )
  264. // *++
  265. // Description:
  266. //
  267. // This does a MyAlloc(), memcpy() and MyFree(). There is no optimization
  268. // for shrinking or expanding buffers. An invalid parameter will cause
  269. // MyRealloc() to fail with a call to exit(1).
  270. //
  271. // Parameters:
  272. //
  273. // Ptr := Pointer to the caller's buffer to be re-allocated.
  274. //
  275. // Size := Size of new buffer. Size cannot be zero.
  276. //
  277. // File := Set to __FILE__ by macro expansion.
  278. //
  279. // Line := Set to __LINE__ by macro expansion.
  280. //
  281. // Returns:
  282. //
  283. // Pointer to new caller's buffer.
  284. //
  285. // --*/
  286. //
  287. {
  288. MY_ALLOC_STRUCT *Tmp;
  289. VOID *Buffer;
  290. //
  291. // Check for invalid parameter(s).
  292. //
  293. if (File == NULL) {
  294. printf (
  295. "\nMyRealloc(Ptr=%p, Size=%u, File=NULL, Line=%u)"
  296. "\nInvalid parameter(s).\n",
  297. Ptr,
  298. (unsigned)Size,
  299. (unsigned)Line
  300. );
  301. exit (1);
  302. }
  303. if (Size == 0 || Line == 0) {
  304. printf (
  305. "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
  306. "\nInvalid parameter(s).\n",
  307. Ptr,
  308. (unsigned)Size,
  309. File,
  310. (unsigned)Line
  311. );
  312. exit (1);
  313. }
  314. if (strlen ((CHAR8 *)File) == 0) {
  315. printf (
  316. "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
  317. "\nInvalid parameter.\n",
  318. Ptr,
  319. (unsigned)Size,
  320. File,
  321. (unsigned)Line
  322. );
  323. exit (1);
  324. }
  325. //
  326. // Find existing buffer in allocation list.
  327. //
  328. if (Ptr == NULL) {
  329. Tmp = NULL;
  330. } else if (&MyAllocData->Buffer[sizeof (UINT32)] == Ptr) {
  331. Tmp = MyAllocData;
  332. } else {
  333. for (Tmp = MyAllocData;; Tmp = Tmp->Next) {
  334. if (Tmp->Next == NULL) {
  335. printf (
  336. "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
  337. "\nCould not find buffer.\n",
  338. Ptr,
  339. (unsigned)Size,
  340. File,
  341. (unsigned)Line
  342. );
  343. exit (1);
  344. }
  345. Tmp = Tmp->Next;
  346. }
  347. }
  348. //
  349. // Allocate new buffer, copy old data, free old buffer.
  350. //
  351. Buffer = MyAlloc (Size, File, Line);
  352. if (Buffer != NULL && Tmp != NULL) {
  353. memcpy (
  354. Buffer,
  355. &Tmp->Buffer[sizeof (UINT32)],
  356. ((Size <= Tmp->Size) ? Size : Tmp->Size)
  357. );
  358. MyFree (Ptr, (UINT8 *)__FILE__, __LINE__);
  359. }
  360. return Buffer;
  361. }
  362. //
  363. // ////////////////////////////////////////////////////////////////////////////
  364. //
  365. //
  366. VOID
  367. MyFree (
  368. VOID *Ptr,
  369. UINT8 File[],
  370. UINTN Line
  371. )
  372. // *++
  373. // Description:
  374. //
  375. // Release a previously allocated buffer. Invalid parameters will cause
  376. // MyFree() to fail with an exit(1) call.
  377. //
  378. // Parameters:
  379. //
  380. // Ptr := Pointer to the caller's buffer to be freed.
  381. // A NULL pointer will be ignored.
  382. //
  383. // File := Set to __FILE__ by macro expansion.
  384. //
  385. // Line := Set to __LINE__ by macro expansion.
  386. //
  387. // Returns:
  388. //
  389. // n/a
  390. //
  391. // --*/
  392. //
  393. {
  394. MY_ALLOC_STRUCT *Tmp;
  395. MY_ALLOC_STRUCT *Tmp2;
  396. //
  397. // Check for invalid parameter(s).
  398. //
  399. if (File == NULL) {
  400. printf (
  401. "\nMyFree(Ptr=%p, File=NULL, Line=%u)"
  402. "\nInvalid parameter(s).\n",
  403. Ptr,
  404. (unsigned)Line
  405. );
  406. exit (1);
  407. }
  408. if (Line == 0) {
  409. printf (
  410. "\nMyFree(Ptr=%p, File=%s, Line=%u)"
  411. "\nInvalid parameter(s).\n",
  412. Ptr,
  413. File,
  414. (unsigned)Line
  415. );
  416. exit (1);
  417. }
  418. if (strlen ((CHAR8 *)File) == 0) {
  419. printf (
  420. "\nMyFree(Ptr=%p, File=%s, Line=%u)"
  421. "\nInvalid parameter.\n",
  422. Ptr,
  423. File,
  424. (unsigned)Line
  425. );
  426. exit (1);
  427. }
  428. //
  429. // Freeing NULL is always valid.
  430. //
  431. if (Ptr == NULL) {
  432. return ;
  433. }
  434. //
  435. // Fail if nothing is allocated.
  436. //
  437. if (MyAllocData == NULL) {
  438. printf (
  439. "\nMyFree(Ptr=%p, File=%s, Line=%u)"
  440. "\nCalled before memory allocated.\n",
  441. Ptr,
  442. File,
  443. (unsigned)Line
  444. );
  445. exit (1);
  446. }
  447. //
  448. // Check for corrupted allocation list.
  449. //
  450. MyCheck (0, (UINT8 *)__FILE__, __LINE__);
  451. //
  452. // Need special check for first item in list.
  453. //
  454. if (&MyAllocData->Buffer[sizeof (UINT32)] == Ptr) {
  455. //
  456. // Unlink first item in list.
  457. //
  458. Tmp = MyAllocData;
  459. MyAllocData = MyAllocData->Next;
  460. } else {
  461. //
  462. // Walk list looking for matching item.
  463. //
  464. for (Tmp = MyAllocData;; Tmp = Tmp->Next) {
  465. //
  466. // Fail if end of list is reached.
  467. //
  468. if (Tmp->Next == NULL) {
  469. printf (
  470. "\nMyFree(Ptr=%p, File=%s, Line=%u)\n"
  471. "\nNot found.\n",
  472. Ptr,
  473. File,
  474. (unsigned)Line
  475. );
  476. exit (1);
  477. }
  478. //
  479. // Leave loop when match is found.
  480. //
  481. if (&Tmp->Next->Buffer[sizeof (UINT32)] == Ptr) {
  482. break;
  483. }
  484. }
  485. //
  486. // Unlink item from list.
  487. //
  488. Tmp2 = Tmp->Next;
  489. Tmp->Next = Tmp->Next->Next;
  490. Tmp = Tmp2;
  491. }
  492. //
  493. // Release item.
  494. //
  495. free (Tmp);
  496. }
  497. #endif /* USE_MYALLOC */
  498. /* eof - MyAlloc.c */