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