2 File for memory allocation tracking functions.
4 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 // Get back to original alloc/free calls.
26 // Start of allocation list.
28 STATIC MY_ALLOC_STRUCT
*MyAllocData
= NULL
;
33 STATIC UINT32 MyAllocHeadMagik
= MYALLOC_HEAD_MAGIK
;
34 STATIC UINT32 MyAllocTailMagik
= MYALLOC_TAIL_MAGIK
;
37 // ////////////////////////////////////////////////////////////////////////////
49 // Check for corruptions in the allocated memory chain. If a corruption
50 // is detection program operation stops w/ an exit(1) call.
54 // Final := When FALSE, MyCheck() returns if the allocated memory chain
55 // has not been corrupted. When TRUE, MyCheck() returns if there
56 // are no un-freed allocations. If there are un-freed allocations,
57 // they are displayed and exit(1) is called.
60 // File := Set to __FILE__ by macro expansion.
62 // Line := Set to __LINE__ by macro expansion.
78 "\nMyCheck(Final=%u, File=NULL, Line=%u)"
79 "Invalid parameter(s).\n",
89 "\nMyCheck(Final=%u, File=%s, Line=%u)"
90 "Invalid parameter(s).\n",
99 if (strlen ((CHAR8
*)File
) == 0) {
101 "\nMyCheck(Final=%u, File=%s, Line=%u)"
102 "Invalid parameter.\n",
111 // Check structure contents.
113 for (Tmp
= MyAllocData
; Tmp
!= NULL
; Tmp
= Tmp
->Next
) {
114 if (memcmp(Tmp
->Buffer
, &MyAllocHeadMagik
, sizeof MyAllocHeadMagik
) ||
115 memcmp(&Tmp
->Buffer
[Tmp
->Size
+ sizeof(UINT32
)], &MyAllocTailMagik
, sizeof MyAllocTailMagik
)) {
120 // If Tmp is not NULL, the structure is corrupt.
124 "\nMyCheck(Final=%u, File=%s, Line=%u)""\nStructure corrupted!"
125 "\nFile=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",
130 (unsigned) Tmp
->Line
,
131 (unsigned) Tmp
->Size
,
132 (unsigned) *(UINT32
*) (Tmp
->Buffer
),
133 (unsigned) *(UINT32
*) (&Tmp
->Buffer
[Tmp
->Size
+ sizeof (UINT32
)])
139 // If Final is TRUE, display the state of the structure chain.
142 if (MyAllocData
!= NULL
) {
144 "\nMyCheck(Final=%u, File=%s, Line=%u)"
145 "\nSome allocated items have not been freed.\n",
151 for (Tmp
= MyAllocData
; Tmp
!= NULL
; Tmp
= Tmp
->Next
) {
153 "File=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",
155 (unsigned) Tmp
->Line
,
156 (unsigned) Tmp
->Size
,
157 (unsigned) *(UINT32
*) (Tmp
->Buffer
),
158 (unsigned) *(UINT32
*) (&Tmp
->Buffer
[Tmp
->Size
+ sizeof (UINT32
)])
165 // ////////////////////////////////////////////////////////////////////////////
177 // Allocate a new link in the allocation chain along with enough storage
178 // for the File[] string, requested Size and alignment overhead. If
179 // memory cannot be allocated or the allocation chain has been corrupted,
180 // exit(1) will be called.
184 // Size := Number of bytes (UINT8) requested by the called.
185 // Size cannot be zero.
187 // File := Set to __FILE__ by macro expansion.
189 // Line := Set to __LINE__ by macro expansion.
193 // Pointer to the caller's buffer.
198 MY_ALLOC_STRUCT
*Tmp
;
202 // Check for invalid parameters.
206 "\nMyAlloc(Size=%u, File=NULL, Line=%u)"
207 "\nInvalid parameter(s).\n",
215 if (Size
== 0 || Line
== 0) {
217 "\nMyAlloc(Size=%u, File=%s, Line=%u)"
218 "\nInvalid parameter(s).\n",
227 Len
= strlen ((CHAR8
*)File
);
230 "\nMyAlloc(Size=%u, File=%s, Line=%u)"
231 "\nInvalid parameter.\n",
240 // Check the allocation list for corruption.
242 MyCheck (0, (UINT8
*)__FILE__
, __LINE__
);
245 // Allocate a new entry.
249 sizeof (MY_ALLOC_STRUCT
) + Len
+ 1 + sizeof (UINT64
) + Size
+ (sizeof MyAllocHeadMagik
) + (sizeof MyAllocTailMagik
)
254 "\nMyAlloc(Size=%u, File=%s, Line=%u)"
255 "\nOut of memory.\n",
264 // Fill in the new entry.
266 Tmp
->File
= ((UINT8
*) Tmp
) + sizeof (MY_ALLOC_STRUCT
);
267 strcpy ((CHAR8
*)Tmp
->File
, (CHAR8
*)File
);
270 Tmp
->Buffer
= (UINT8
*) (((UINTN
) Tmp
+ Len
+ 9) &~7);
272 memcpy (Tmp
->Buffer
, &MyAllocHeadMagik
, sizeof MyAllocHeadMagik
);
275 &Tmp
->Buffer
[Size
+ sizeof (UINT32
)],
277 sizeof MyAllocTailMagik
280 Tmp
->Next
= MyAllocData
;
281 Tmp
->Cksum
= (UINTN
) Tmp
+ (UINTN
) (Tmp
->Next
) + Tmp
->Line
+ Tmp
->Size
+ (UINTN
) (Tmp
->File
) + (UINTN
) (Tmp
->Buffer
);
285 return Tmp
->Buffer
+ sizeof (UINT32
);
288 // ////////////////////////////////////////////////////////////////////////////
301 // This does a MyAlloc(), memcpy() and MyFree(). There is no optimization
302 // for shrinking or expanding buffers. An invalid parameter will cause
303 // MyRealloc() to fail with a call to exit(1).
307 // Ptr := Pointer to the caller's buffer to be re-allocated.
309 // Size := Size of new buffer. Size cannot be zero.
311 // File := Set to __FILE__ by macro expansion.
313 // Line := Set to __LINE__ by macro expansion.
317 // Pointer to new caller's buffer.
322 MY_ALLOC_STRUCT
*Tmp
;
326 // Check for invalid parameter(s).
330 "\nMyRealloc(Ptr=%p, Size=%u, File=NULL, Line=%u)"
331 "\nInvalid parameter(s).\n",
340 if (Size
== 0 || Line
== 0) {
342 "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
343 "\nInvalid parameter(s).\n",
353 if (strlen ((CHAR8
*)File
) == 0) {
355 "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
356 "\nInvalid parameter.\n",
366 // Find existing buffer in allocation list.
370 } else if (&MyAllocData
->Buffer
[sizeof (UINT32
)] == Ptr
) {
373 for (Tmp
= MyAllocData
;; Tmp
= Tmp
->Next
) {
374 if (Tmp
->Next
== NULL
) {
376 "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
377 "\nCould not find buffer.\n",
391 // Allocate new buffer, copy old data, free old buffer.
393 Buffer
= MyAlloc (Size
, File
, Line
);
395 if (Buffer
!= NULL
&& Tmp
!= NULL
) {
398 &Tmp
->Buffer
[sizeof (UINT32
)],
399 ((Size
<= Tmp
->Size
) ? Size
: Tmp
->Size
)
402 MyFree (Ptr
, (UINT8
*)__FILE__
, __LINE__
);
408 // ////////////////////////////////////////////////////////////////////////////
420 // Release a previously allocated buffer. Invalid parameters will cause
421 // MyFree() to fail with an exit(1) call.
425 // Ptr := Pointer to the caller's buffer to be freed.
426 // A NULL pointer will be ignored.
428 // File := Set to __FILE__ by macro expansion.
430 // Line := Set to __LINE__ by macro expansion.
439 MY_ALLOC_STRUCT
*Tmp
;
440 MY_ALLOC_STRUCT
*Tmp2
;
443 // Check for invalid parameter(s).
447 "\nMyFree(Ptr=%p, File=NULL, Line=%u)"
448 "\nInvalid parameter(s).\n",
458 "\nMyFree(Ptr=%p, File=%s, Line=%u)"
459 "\nInvalid parameter(s).\n",
468 if (strlen ((CHAR8
*)File
) == 0) {
470 "\nMyFree(Ptr=%p, File=%s, Line=%u)"
471 "\nInvalid parameter.\n",
480 // Freeing NULL is always valid.
486 // Fail if nothing is allocated.
488 if (MyAllocData
== NULL
) {
490 "\nMyFree(Ptr=%p, File=%s, Line=%u)"
491 "\nCalled before memory allocated.\n",
500 // Check for corrupted allocation list.
502 MyCheck (0, (UINT8
*)__FILE__
, __LINE__
);
505 // Need special check for first item in list.
507 if (&MyAllocData
->Buffer
[sizeof (UINT32
)] == Ptr
) {
509 // Unlink first item in list.
512 MyAllocData
= MyAllocData
->Next
;
515 // Walk list looking for matching item.
517 for (Tmp
= MyAllocData
;; Tmp
= Tmp
->Next
) {
519 // Fail if end of list is reached.
521 if (Tmp
->Next
== NULL
) {
523 "\nMyFree(Ptr=%p, File=%s, Line=%u)\n"
533 // Leave loop when match is found.
535 if (&Tmp
->Next
->Buffer
[sizeof (UINT32
)] == Ptr
) {
540 // Unlink item from list.
543 Tmp
->Next
= Tmp
->Next
->Next
;
552 #endif /* USE_MYALLOC */
554 /* eof - MyAlloc.c */