]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/Common/MyAlloc.c
Check In tool source code based on Build tool project revision r1655.
[mirror_edk2.git] / BaseTools / Source / C / Common / MyAlloc.c
1 /** @file
2
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
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
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=%s, Line=%u)"
86 "Invalid parameter(s).\n",
87 Final,
88 File,
89 (UINT32)Line
90 );
91
92 exit (1);
93 }
94
95 if (strlen ((CHAR8 *)File) == 0) {
96 printf (
97 "\nMyCheck(Final=%u, File=%s, Line=%u)"
98 "Invalid parameter.\n",
99 Final,
100 File,
101 (UINT32)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 (UINT32)Line,
125 Tmp->File,
126 (UINT32)Tmp->Line,
127 (UINT32)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 (UINT32)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 (UINT32)Tmp->Line,
152 (UINT32)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 *
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=%s, Line=%u)"
203 "\nInvalid parameter(s).\n",
204 (UINT32)Size,
205 File,
206 (UINT32)Line
207 );
208
209 exit (1);
210 }
211
212 Len = strlen ((CHAR8 *)File);
213 if (Len == 0) {
214 printf (
215 "\nMyAlloc(Size=%u, File=%s, Line=%u)"
216 "\nInvalid parameter.\n",
217 (UINT32)Size,
218 File,
219 (UINT32)Line
220 );
221
222 exit (1);
223 }
224 //
225 // Check the allocation list for corruption.
226 //
227 MyCheck (0, (UINT8 *)__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 (UINT32)Size,
242 File,
243 (UINT32)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 ((CHAR8 *)Tmp->File, (CHAR8 *)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 *
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=%p, Size=%u, File=%s, Line=%u)"
316 "\nInvalid parameter(s).\n",
317 Ptr,
318 (UINT32)Size,
319 File,
320 (UINT32)Line
321 );
322
323 exit (1);
324 }
325
326 if (strlen ((CHAR8 *)File) == 0) {
327 printf (
328 "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
329 "\nInvalid parameter.\n",
330 Ptr,
331 (UINT32)Size,
332 File,
333 (UINT32)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=%p, Size=%u, File=%s, Line=%u)"
350 "\nCould not find buffer.\n",
351 Ptr,
352 (UINT32)Size,
353 File,
354 (UINT32)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, (UINT8 *)__FILE__, __LINE__);
376 }
377
378 return Buffer;
379 }
380 //
381 // ////////////////////////////////////////////////////////////////////////////
382 //
383 //
384 VOID
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=%p, File=%s, Line=%u)"
421 "\nInvalid parameter(s).\n",
422 Ptr,
423 File,
424 (UINT32)Line
425 );
426
427 exit (1);
428 }
429
430 if (strlen ((CHAR8 *)File) == 0) {
431 printf (
432 "\nMyFree(Ptr=%p, File=%s, Line=%u)"
433 "\nInvalid parameter.\n",
434 Ptr,
435 File,
436 (UINT32)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=%p, File=%s, Line=%u)"
453 "\nCalled before memory allocated.\n",
454 Ptr,
455 File,
456 (UINT32)Line
457 );
458
459 exit (1);
460 }
461 //
462 // Check for corrupted allocation list.
463 //
464 MyCheck (0, (UINT8 *)__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=%p, File=%s, Line=%u)\n"
486 "\nNot found.\n",
487 Ptr,
488 File,
489 (UINT32)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 */