3 Copyright (c) 2004 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 File for memory allocation tracking functions.
26 // Get back to original alloc/free calls.
33 // Start of allocation list.
35 STATIC MY_ALLOC_STRUCT
*MyAllocData
= NULL
;
40 STATIC UINT32 MyAllocHeadMagik
= MYALLOC_HEAD_MAGIK
;
41 STATIC UINT32 MyAllocTailMagik
= MYALLOC_TAIL_MAGIK
;
44 // ////////////////////////////////////////////////////////////////////////////
56 // Check for corruptions in the allocated memory chain. If a corruption
57 // is detection program operation stops w/ an exit(1) call.
61 // Final := When FALSE, MyCheck() returns if the allocated memory chain
62 // has not been corrupted. When TRUE, MyCheck() returns if there
63 // are no un-freed allocations. If there are un-freed allocations,
64 // they are displayed and exit(1) is called.
67 // File := Set to __FILE__ by macro expansion.
69 // Line := Set to __LINE__ by macro expansion.
83 if (File
== NULL
|| Line
== 0) {
85 "\nMyCheck(Final=%u, File=%s, Line=%u)"
86 "Invalid parameter(s).\n",
95 if (strlen ((CHAR8
*)File
) == 0) {
97 "\nMyCheck(Final=%u, File=%s, Line=%u)"
98 "Invalid parameter.\n",
107 // Check structure contents.
109 for (Tmp
= MyAllocData
; Tmp
!= NULL
; Tmp
= Tmp
->Next
) {
110 if (memcmp(Tmp
->Buffer
, &MyAllocHeadMagik
, sizeof MyAllocHeadMagik
) ||
111 memcmp(&Tmp
->Buffer
[Tmp
->Size
+ sizeof(UINT32
)], &MyAllocTailMagik
, sizeof MyAllocTailMagik
)) {
116 // If Tmp is not NULL, the structure is corrupt.
120 "\nMyCheck(Final=%u, File=%s, Line=%u)""\nStructure corrupted!"
121 "\nFile=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",
126 (unsigned) Tmp
->Line
,
127 (unsigned) Tmp
->Size
,
128 (unsigned) *(UINT32
*) (Tmp
->Buffer
),
129 (unsigned) *(UINT32
*) (&Tmp
->Buffer
[Tmp
->Size
+ sizeof (UINT32
)])
135 // If Final is TRUE, display the state of the structure chain.
138 if (MyAllocData
!= NULL
) {
140 "\nMyCheck(Final=%u, File=%s, Line=%u)"
141 "\nSome allocated items have not been freed.\n",
147 for (Tmp
= MyAllocData
; Tmp
!= NULL
; Tmp
= Tmp
->Next
) {
149 "File=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",
151 (unsigned) Tmp
->Line
,
152 (unsigned) Tmp
->Size
,
153 (unsigned) *(UINT32
*) (Tmp
->Buffer
),
154 (unsigned) *(UINT32
*) (&Tmp
->Buffer
[Tmp
->Size
+ sizeof (UINT32
)])
161 // ////////////////////////////////////////////////////////////////////////////
173 // Allocate a new link in the allocation chain along with enough storage
174 // for the File[] string, requested Size and alignment overhead. If
175 // memory cannot be allocated or the allocation chain has been corrupted,
176 // exit(1) will be called.
180 // Size := Number of bytes (UINT8) requested by the called.
181 // Size cannot be zero.
183 // File := Set to __FILE__ by macro expansion.
185 // Line := Set to __LINE__ by macro expansion.
189 // Pointer to the caller's buffer.
194 MY_ALLOC_STRUCT
*Tmp
;
198 // Check for invalid parameters.
200 if (Size
== 0 || File
== NULL
|| Line
== 0) {
202 "\nMyAlloc(Size=%u, File=%s, Line=%u)"
203 "\nInvalid parameter(s).\n",
212 Len
= strlen ((CHAR8
*)File
);
215 "\nMyAlloc(Size=%u, File=%s, Line=%u)"
216 "\nInvalid parameter.\n",
225 // Check the allocation list for corruption.
227 MyCheck (0, (UINT8
*)__FILE__
, __LINE__
);
230 // Allocate a new entry.
234 sizeof (MY_ALLOC_STRUCT
) + Len
+ 1 + sizeof (UINT64
) + Size
+ (sizeof MyAllocHeadMagik
) + (sizeof MyAllocTailMagik
)
239 "\nMyAlloc(Size=%u, File=%s, Line=%u)"
240 "\nOut of memory.\n",
249 // Fill in the new entry.
251 Tmp
->File
= ((UINT8
*) Tmp
) + sizeof (MY_ALLOC_STRUCT
);
252 strcpy ((CHAR8
*)Tmp
->File
, (CHAR8
*)File
);
255 Tmp
->Buffer
= (UINT8
*) (((UINTN
) Tmp
+ Len
+ 9) &~7);
257 memcpy (Tmp
->Buffer
, &MyAllocHeadMagik
, sizeof MyAllocHeadMagik
);
260 &Tmp
->Buffer
[Size
+ sizeof (UINT32
)],
262 sizeof MyAllocTailMagik
265 Tmp
->Next
= MyAllocData
;
266 Tmp
->Cksum
= (UINTN
) Tmp
+ (UINTN
) (Tmp
->Next
) + Tmp
->Line
+ Tmp
->Size
+ (UINTN
) (Tmp
->File
) + (UINTN
) (Tmp
->Buffer
);
270 return Tmp
->Buffer
+ sizeof (UINT32
);
273 // ////////////////////////////////////////////////////////////////////////////
286 // This does a MyAlloc(), memcpy() and MyFree(). There is no optimization
287 // for shrinking or expanding buffers. An invalid parameter will cause
288 // MyRealloc() to fail with a call to exit(1).
292 // Ptr := Pointer to the caller's buffer to be re-allocated.
294 // Size := Size of new buffer. Size cannot be zero.
296 // File := Set to __FILE__ by macro expansion.
298 // Line := Set to __LINE__ by macro expansion.
302 // Pointer to new caller's buffer.
307 MY_ALLOC_STRUCT
*Tmp
;
311 // Check for invalid parameter(s).
313 if (Size
== 0 || File
== NULL
|| Line
== 0) {
315 "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
316 "\nInvalid parameter(s).\n",
326 if (strlen ((CHAR8
*)File
) == 0) {
328 "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
329 "\nInvalid parameter.\n",
339 // Find existing buffer in allocation list.
343 } else if (&MyAllocData
->Buffer
[sizeof (UINT32
)] == Ptr
) {
346 for (Tmp
= MyAllocData
;; Tmp
= Tmp
->Next
) {
347 if (Tmp
->Next
== NULL
) {
349 "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
350 "\nCould not find buffer.\n",
364 // Allocate new buffer, copy old data, free old buffer.
366 Buffer
= MyAlloc (Size
, File
, Line
);
368 if (Buffer
!= NULL
&& Tmp
!= NULL
) {
371 &Tmp
->Buffer
[sizeof (UINT32
)],
372 ((Size
<= Tmp
->Size
) ? Size
: Tmp
->Size
)
375 MyFree (Ptr
, (UINT8
*)__FILE__
, __LINE__
);
381 // ////////////////////////////////////////////////////////////////////////////
393 // Release a previously allocated buffer. Invalid parameters will cause
394 // MyFree() to fail with an exit(1) call.
398 // Ptr := Pointer to the caller's buffer to be freed.
399 // A NULL pointer will be ignored.
401 // File := Set to __FILE__ by macro expansion.
403 // Line := Set to __LINE__ by macro expansion.
412 MY_ALLOC_STRUCT
*Tmp
;
413 MY_ALLOC_STRUCT
*Tmp2
;
416 // Check for invalid parameter(s).
418 if (File
== NULL
|| Line
== 0) {
420 "\nMyFree(Ptr=%p, File=%s, Line=%u)"
421 "\nInvalid parameter(s).\n",
430 if (strlen ((CHAR8
*)File
) == 0) {
432 "\nMyFree(Ptr=%p, File=%s, Line=%u)"
433 "\nInvalid parameter.\n",
442 // Freeing NULL is always valid.
448 // Fail if nothing is allocated.
450 if (MyAllocData
== NULL
) {
452 "\nMyFree(Ptr=%p, File=%s, Line=%u)"
453 "\nCalled before memory allocated.\n",
462 // Check for corrupted allocation list.
464 MyCheck (0, (UINT8
*)__FILE__
, __LINE__
);
467 // Need special check for first item in list.
469 if (&MyAllocData
->Buffer
[sizeof (UINT32
)] == Ptr
) {
471 // Unlink first item in list.
474 MyAllocData
= MyAllocData
->Next
;
477 // Walk list looking for matching item.
479 for (Tmp
= MyAllocData
;; Tmp
= Tmp
->Next
) {
481 // Fail if end of list is reached.
483 if (Tmp
->Next
== NULL
) {
485 "\nMyFree(Ptr=%p, File=%s, Line=%u)\n"
495 // Leave loop when match is found.
497 if (&Tmp
->Next
->Buffer
[sizeof (UINT32
)] == Ptr
) {
502 // Unlink item from list.
505 Tmp
->Next
= Tmp
->Next
->Next
;
514 #endif /* USE_MYALLOC */
516 /* eof - MyAlloc.c */