2 File for memory allocation tracking functions.
4 Copyright (c) 2004 - 2014, 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.
76 if (File
== NULL
|| Line
== 0) {
78 "\nMyCheck(Final=%u, File=%s, Line=%u)"
79 "Invalid parameter(s).\n",
88 if (strlen ((CHAR8
*)File
) == 0) {
90 "\nMyCheck(Final=%u, File=%s, Line=%u)"
91 "Invalid parameter.\n",
100 // Check structure contents.
102 for (Tmp
= MyAllocData
; Tmp
!= NULL
; Tmp
= Tmp
->Next
) {
103 if (memcmp(Tmp
->Buffer
, &MyAllocHeadMagik
, sizeof MyAllocHeadMagik
) ||
104 memcmp(&Tmp
->Buffer
[Tmp
->Size
+ sizeof(UINT32
)], &MyAllocTailMagik
, sizeof MyAllocTailMagik
)) {
109 // If Tmp is not NULL, the structure is corrupt.
113 "\nMyCheck(Final=%u, File=%s, Line=%u)""\nStructure corrupted!"
114 "\nFile=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",
119 (unsigned) Tmp
->Line
,
120 (unsigned) Tmp
->Size
,
121 (unsigned) *(UINT32
*) (Tmp
->Buffer
),
122 (unsigned) *(UINT32
*) (&Tmp
->Buffer
[Tmp
->Size
+ sizeof (UINT32
)])
128 // If Final is TRUE, display the state of the structure chain.
131 if (MyAllocData
!= NULL
) {
133 "\nMyCheck(Final=%u, File=%s, Line=%u)"
134 "\nSome allocated items have not been freed.\n",
140 for (Tmp
= MyAllocData
; Tmp
!= NULL
; Tmp
= Tmp
->Next
) {
142 "File=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",
144 (unsigned) Tmp
->Line
,
145 (unsigned) Tmp
->Size
,
146 (unsigned) *(UINT32
*) (Tmp
->Buffer
),
147 (unsigned) *(UINT32
*) (&Tmp
->Buffer
[Tmp
->Size
+ sizeof (UINT32
)])
154 // ////////////////////////////////////////////////////////////////////////////
166 // Allocate a new link in the allocation chain along with enough storage
167 // for the File[] string, requested Size and alignment overhead. If
168 // memory cannot be allocated or the allocation chain has been corrupted,
169 // exit(1) will be called.
173 // Size := Number of bytes (UINT8) requested by the called.
174 // Size cannot be zero.
176 // File := Set to __FILE__ by macro expansion.
178 // Line := Set to __LINE__ by macro expansion.
182 // Pointer to the caller's buffer.
187 MY_ALLOC_STRUCT
*Tmp
;
191 // Check for invalid parameters.
193 if (Size
== 0 || File
== NULL
|| Line
== 0) {
195 "\nMyAlloc(Size=%u, File=%s, Line=%u)"
196 "\nInvalid parameter(s).\n",
205 Len
= strlen ((CHAR8
*)File
);
208 "\nMyAlloc(Size=%u, File=%s, Line=%u)"
209 "\nInvalid parameter.\n",
218 // Check the allocation list for corruption.
220 MyCheck (0, (UINT8
*)__FILE__
, __LINE__
);
223 // Allocate a new entry.
227 sizeof (MY_ALLOC_STRUCT
) + Len
+ 1 + sizeof (UINT64
) + Size
+ (sizeof MyAllocHeadMagik
) + (sizeof MyAllocTailMagik
)
232 "\nMyAlloc(Size=%u, File=%s, Line=%u)"
233 "\nOut of memory.\n",
242 // Fill in the new entry.
244 Tmp
->File
= ((UINT8
*) Tmp
) + sizeof (MY_ALLOC_STRUCT
);
245 strcpy ((CHAR8
*)Tmp
->File
, (CHAR8
*)File
);
248 Tmp
->Buffer
= (UINT8
*) (((UINTN
) Tmp
+ Len
+ 9) &~7);
250 memcpy (Tmp
->Buffer
, &MyAllocHeadMagik
, sizeof MyAllocHeadMagik
);
253 &Tmp
->Buffer
[Size
+ sizeof (UINT32
)],
255 sizeof MyAllocTailMagik
258 Tmp
->Next
= MyAllocData
;
259 Tmp
->Cksum
= (UINTN
) Tmp
+ (UINTN
) (Tmp
->Next
) + Tmp
->Line
+ Tmp
->Size
+ (UINTN
) (Tmp
->File
) + (UINTN
) (Tmp
->Buffer
);
263 return Tmp
->Buffer
+ sizeof (UINT32
);
266 // ////////////////////////////////////////////////////////////////////////////
279 // This does a MyAlloc(), memcpy() and MyFree(). There is no optimization
280 // for shrinking or expanding buffers. An invalid parameter will cause
281 // MyRealloc() to fail with a call to exit(1).
285 // Ptr := Pointer to the caller's buffer to be re-allocated.
287 // Size := Size of new buffer. Size cannot be zero.
289 // File := Set to __FILE__ by macro expansion.
291 // Line := Set to __LINE__ by macro expansion.
295 // Pointer to new caller's buffer.
300 MY_ALLOC_STRUCT
*Tmp
;
304 // Check for invalid parameter(s).
306 if (Size
== 0 || File
== NULL
|| Line
== 0) {
308 "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
309 "\nInvalid parameter(s).\n",
319 if (strlen ((CHAR8
*)File
) == 0) {
321 "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
322 "\nInvalid parameter.\n",
332 // Find existing buffer in allocation list.
336 } else if (&MyAllocData
->Buffer
[sizeof (UINT32
)] == Ptr
) {
339 for (Tmp
= MyAllocData
;; Tmp
= Tmp
->Next
) {
340 if (Tmp
->Next
== NULL
) {
342 "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
343 "\nCould not find buffer.\n",
357 // Allocate new buffer, copy old data, free old buffer.
359 Buffer
= MyAlloc (Size
, File
, Line
);
361 if (Buffer
!= NULL
&& Tmp
!= NULL
) {
364 &Tmp
->Buffer
[sizeof (UINT32
)],
365 ((Size
<= Tmp
->Size
) ? Size
: Tmp
->Size
)
368 MyFree (Ptr
, (UINT8
*)__FILE__
, __LINE__
);
374 // ////////////////////////////////////////////////////////////////////////////
386 // Release a previously allocated buffer. Invalid parameters will cause
387 // MyFree() to fail with an exit(1) call.
391 // Ptr := Pointer to the caller's buffer to be freed.
392 // A NULL pointer will be ignored.
394 // File := Set to __FILE__ by macro expansion.
396 // Line := Set to __LINE__ by macro expansion.
405 MY_ALLOC_STRUCT
*Tmp
;
406 MY_ALLOC_STRUCT
*Tmp2
;
409 // Check for invalid parameter(s).
411 if (File
== NULL
|| Line
== 0) {
413 "\nMyFree(Ptr=%p, File=%s, Line=%u)"
414 "\nInvalid parameter(s).\n",
423 if (strlen ((CHAR8
*)File
) == 0) {
425 "\nMyFree(Ptr=%p, File=%s, Line=%u)"
426 "\nInvalid parameter.\n",
435 // Freeing NULL is always valid.
441 // Fail if nothing is allocated.
443 if (MyAllocData
== NULL
) {
445 "\nMyFree(Ptr=%p, File=%s, Line=%u)"
446 "\nCalled before memory allocated.\n",
455 // Check for corrupted allocation list.
457 MyCheck (0, (UINT8
*)__FILE__
, __LINE__
);
460 // Need special check for first item in list.
462 if (&MyAllocData
->Buffer
[sizeof (UINT32
)] == Ptr
) {
464 // Unlink first item in list.
467 MyAllocData
= MyAllocData
->Next
;
470 // Walk list looking for matching item.
472 for (Tmp
= MyAllocData
;; Tmp
= Tmp
->Next
) {
474 // Fail if end of list is reached.
476 if (Tmp
->Next
== NULL
) {
478 "\nMyFree(Ptr=%p, File=%s, Line=%u)\n"
488 // Leave loop when match is found.
490 if (&Tmp
->Next
->Buffer
[sizeof (UINT32
)] == Ptr
) {
495 // Unlink item from list.
498 Tmp
->Next
= Tmp
->Next
->Next
;
507 #endif /* USE_MYALLOC */
509 /* eof - MyAlloc.c */