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