]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/Common/MyAlloc.c
BaseTools: Fix compile error on VS2010
[mirror_edk2.git] / BaseTools / Source / C / Common / MyAlloc.c
1 /** @file
2 File for memory allocation tracking functions.
3
4 Copyright (c) 2004 - 2016, 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
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) {
77 printf (
78 "\nMyCheck(Final=%u, File=NULL, Line=%u)"
79 "Invalid parameter(s).\n",
80 Final,
81 (unsigned)Line
82 );
83
84 exit (1);
85 }
86
87 if (Line == 0) {
88 printf (
89 "\nMyCheck(Final=%u, File=%s, Line=%u)"
90 "Invalid parameter(s).\n",
91 Final,
92 File,
93 (unsigned)Line
94 );
95
96 exit (1);
97 }
98
99 if (strlen ((CHAR8 *)File) == 0) {
100 printf (
101 "\nMyCheck(Final=%u, File=%s, Line=%u)"
102 "Invalid parameter.\n",
103 Final,
104 File,
105 (unsigned)Line
106 );
107
108 exit (1);
109 }
110 //
111 // Check structure contents.
112 //
113 for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) {
114 if (memcmp(Tmp->Buffer, &MyAllocHeadMagik, sizeof MyAllocHeadMagik) ||
115 memcmp(&Tmp->Buffer[Tmp->Size + sizeof(UINT32)], &MyAllocTailMagik, sizeof MyAllocTailMagik)) {
116 break;
117 }
118 }
119 //
120 // If Tmp is not NULL, the structure is corrupt.
121 //
122 if (Tmp != NULL) {
123 printf (
124 "\nMyCheck(Final=%u, File=%s, Line=%u)""\nStructure corrupted!"
125 "\nFile=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",
126 Final,
127 File,
128 (unsigned)Line,
129 Tmp->File,
130 (unsigned) Tmp->Line,
131 (unsigned) Tmp->Size,
132 (unsigned) *(UINT32 *) (Tmp->Buffer),
133 (unsigned) *(UINT32 *) (&Tmp->Buffer[Tmp->Size + sizeof (UINT32)])
134 );
135
136 exit (1);
137 }
138 //
139 // If Final is TRUE, display the state of the structure chain.
140 //
141 if (Final) {
142 if (MyAllocData != NULL) {
143 printf (
144 "\nMyCheck(Final=%u, File=%s, Line=%u)"
145 "\nSome allocated items have not been freed.\n",
146 Final,
147 File,
148 (unsigned)Line
149 );
150
151 for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) {
152 printf (
153 "File=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n",
154 Tmp->File,
155 (unsigned) Tmp->Line,
156 (unsigned) Tmp->Size,
157 (unsigned) *(UINT32 *) (Tmp->Buffer),
158 (unsigned) *(UINT32 *) (&Tmp->Buffer[Tmp->Size + sizeof (UINT32)])
159 );
160 }
161 }
162 }
163 }
164 //
165 // ////////////////////////////////////////////////////////////////////////////
166 //
167 //
168 VOID *
169 MyAlloc (
170 UINTN Size,
171 UINT8 File[],
172 UINTN Line
173 )
174 // *++
175 // Description:
176 //
177 // Allocate a new link in the allocation chain along with enough storage
178 // for the File[] string, requested Size and alignment overhead. If
179 // memory cannot be allocated or the allocation chain has been corrupted,
180 // exit(1) will be called.
181 //
182 // Parameters:
183 //
184 // Size := Number of bytes (UINT8) requested by the called.
185 // Size cannot be zero.
186 //
187 // File := Set to __FILE__ by macro expansion.
188 //
189 // Line := Set to __LINE__ by macro expansion.
190 //
191 // Returns:
192 //
193 // Pointer to the caller's buffer.
194 //
195 // --*/
196 //
197 {
198 MY_ALLOC_STRUCT *Tmp;
199 UINTN Len;
200
201 //
202 // Check for invalid parameters.
203 //
204 if (File == NULL) {
205 printf (
206 "\nMyAlloc(Size=%u, File=NULL, Line=%u)"
207 "\nInvalid parameter(s).\n",
208 (unsigned)Size,
209 (unsigned)Line
210 );
211
212 exit (1);
213 }
214
215 if (Size == 0 || Line == 0) {
216 printf (
217 "\nMyAlloc(Size=%u, File=%s, Line=%u)"
218 "\nInvalid parameter(s).\n",
219 (unsigned)Size,
220 File,
221 (unsigned)Line
222 );
223
224 exit (1);
225 }
226
227 Len = strlen ((CHAR8 *)File);
228 if (Len == 0) {
229 printf (
230 "\nMyAlloc(Size=%u, File=%s, Line=%u)"
231 "\nInvalid parameter.\n",
232 (unsigned)Size,
233 File,
234 (unsigned)Line
235 );
236
237 exit (1);
238 }
239 //
240 // Check the allocation list for corruption.
241 //
242 MyCheck (0, (UINT8 *)__FILE__, __LINE__);
243
244 //
245 // Allocate a new entry.
246 //
247 Tmp = calloc (
248 1,
249 sizeof (MY_ALLOC_STRUCT) + Len + 1 + sizeof (UINT64) + Size + (sizeof MyAllocHeadMagik) + (sizeof MyAllocTailMagik)
250 );
251
252 if (Tmp == NULL) {
253 printf (
254 "\nMyAlloc(Size=%u, File=%s, Line=%u)"
255 "\nOut of memory.\n",
256 (unsigned)Size,
257 File,
258 (unsigned)Line
259 );
260
261 exit (1);
262 }
263 //
264 // Fill in the new entry.
265 //
266 Tmp->File = ((UINT8 *) Tmp) + sizeof (MY_ALLOC_STRUCT);
267 strcpy ((CHAR8 *)Tmp->File, (CHAR8 *)File);
268 Tmp->Line = Line;
269 Tmp->Size = Size;
270 Tmp->Buffer = (UINT8 *) (((UINTN) Tmp + Len + 9) &~7);
271
272 memcpy (Tmp->Buffer, &MyAllocHeadMagik, sizeof MyAllocHeadMagik);
273
274 memcpy (
275 &Tmp->Buffer[Size + sizeof (UINT32)],
276 &MyAllocTailMagik,
277 sizeof MyAllocTailMagik
278 );
279
280 Tmp->Next = MyAllocData;
281 Tmp->Cksum = (UINTN) Tmp + (UINTN) (Tmp->Next) + Tmp->Line + Tmp->Size + (UINTN) (Tmp->File) + (UINTN) (Tmp->Buffer);
282
283 MyAllocData = Tmp;
284
285 return Tmp->Buffer + sizeof (UINT32);
286 }
287 //
288 // ////////////////////////////////////////////////////////////////////////////
289 //
290 //
291 VOID *
292 MyRealloc (
293 VOID *Ptr,
294 UINTN Size,
295 UINT8 File[],
296 UINTN Line
297 )
298 // *++
299 // Description:
300 //
301 // This does a MyAlloc(), memcpy() and MyFree(). There is no optimization
302 // for shrinking or expanding buffers. An invalid parameter will cause
303 // MyRealloc() to fail with a call to exit(1).
304 //
305 // Parameters:
306 //
307 // Ptr := Pointer to the caller's buffer to be re-allocated.
308 //
309 // Size := Size of new buffer. Size cannot be zero.
310 //
311 // File := Set to __FILE__ by macro expansion.
312 //
313 // Line := Set to __LINE__ by macro expansion.
314 //
315 // Returns:
316 //
317 // Pointer to new caller's buffer.
318 //
319 // --*/
320 //
321 {
322 MY_ALLOC_STRUCT *Tmp;
323 VOID *Buffer;
324
325 //
326 // Check for invalid parameter(s).
327 //
328 if (File == NULL) {
329 printf (
330 "\nMyRealloc(Ptr=%p, Size=%u, File=NULL, Line=%u)"
331 "\nInvalid parameter(s).\n",
332 Ptr,
333 (unsigned)Size,
334 (unsigned)Line
335 );
336
337 exit (1);
338 }
339
340 if (Size == 0 || Line == 0) {
341 printf (
342 "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
343 "\nInvalid parameter(s).\n",
344 Ptr,
345 (unsigned)Size,
346 File,
347 (unsigned)Line
348 );
349
350 exit (1);
351 }
352
353 if (strlen ((CHAR8 *)File) == 0) {
354 printf (
355 "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
356 "\nInvalid parameter.\n",
357 Ptr,
358 (unsigned)Size,
359 File,
360 (unsigned)Line
361 );
362
363 exit (1);
364 }
365 //
366 // Find existing buffer in allocation list.
367 //
368 if (Ptr == NULL) {
369 Tmp = NULL;
370 } else if (&MyAllocData->Buffer[sizeof (UINT32)] == Ptr) {
371 Tmp = MyAllocData;
372 } else {
373 for (Tmp = MyAllocData;; Tmp = Tmp->Next) {
374 if (Tmp->Next == NULL) {
375 printf (
376 "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)"
377 "\nCould not find buffer.\n",
378 Ptr,
379 (unsigned)Size,
380 File,
381 (unsigned)Line
382 );
383
384 exit (1);
385 }
386
387 Tmp = Tmp->Next;
388 }
389 }
390 //
391 // Allocate new buffer, copy old data, free old buffer.
392 //
393 Buffer = MyAlloc (Size, File, Line);
394
395 if (Buffer != NULL && Tmp != NULL) {
396 memcpy (
397 Buffer,
398 &Tmp->Buffer[sizeof (UINT32)],
399 ((Size <= Tmp->Size) ? Size : Tmp->Size)
400 );
401
402 MyFree (Ptr, (UINT8 *)__FILE__, __LINE__);
403 }
404
405 return Buffer;
406 }
407 //
408 // ////////////////////////////////////////////////////////////////////////////
409 //
410 //
411 VOID
412 MyFree (
413 VOID *Ptr,
414 UINT8 File[],
415 UINTN Line
416 )
417 // *++
418 // Description:
419 //
420 // Release a previously allocated buffer. Invalid parameters will cause
421 // MyFree() to fail with an exit(1) call.
422 //
423 // Parameters:
424 //
425 // Ptr := Pointer to the caller's buffer to be freed.
426 // A NULL pointer will be ignored.
427 //
428 // File := Set to __FILE__ by macro expansion.
429 //
430 // Line := Set to __LINE__ by macro expansion.
431 //
432 // Returns:
433 //
434 // n/a
435 //
436 // --*/
437 //
438 {
439 MY_ALLOC_STRUCT *Tmp;
440 MY_ALLOC_STRUCT *Tmp2;
441
442 //
443 // Check for invalid parameter(s).
444 //
445 if (File == NULL) {
446 printf (
447 "\nMyFree(Ptr=%p, File=NULL, Line=%u)"
448 "\nInvalid parameter(s).\n",
449 Ptr,
450 (unsigned)Line
451 );
452
453 exit (1);
454 }
455
456 if (Line == 0) {
457 printf (
458 "\nMyFree(Ptr=%p, File=%s, Line=%u)"
459 "\nInvalid parameter(s).\n",
460 Ptr,
461 File,
462 (unsigned)Line
463 );
464
465 exit (1);
466 }
467
468 if (strlen ((CHAR8 *)File) == 0) {
469 printf (
470 "\nMyFree(Ptr=%p, File=%s, Line=%u)"
471 "\nInvalid parameter.\n",
472 Ptr,
473 File,
474 (unsigned)Line
475 );
476
477 exit (1);
478 }
479 //
480 // Freeing NULL is always valid.
481 //
482 if (Ptr == NULL) {
483 return ;
484 }
485 //
486 // Fail if nothing is allocated.
487 //
488 if (MyAllocData == NULL) {
489 printf (
490 "\nMyFree(Ptr=%p, File=%s, Line=%u)"
491 "\nCalled before memory allocated.\n",
492 Ptr,
493 File,
494 (unsigned)Line
495 );
496
497 exit (1);
498 }
499 //
500 // Check for corrupted allocation list.
501 //
502 MyCheck (0, (UINT8 *)__FILE__, __LINE__);
503
504 //
505 // Need special check for first item in list.
506 //
507 if (&MyAllocData->Buffer[sizeof (UINT32)] == Ptr) {
508 //
509 // Unlink first item in list.
510 //
511 Tmp = MyAllocData;
512 MyAllocData = MyAllocData->Next;
513 } else {
514 //
515 // Walk list looking for matching item.
516 //
517 for (Tmp = MyAllocData;; Tmp = Tmp->Next) {
518 //
519 // Fail if end of list is reached.
520 //
521 if (Tmp->Next == NULL) {
522 printf (
523 "\nMyFree(Ptr=%p, File=%s, Line=%u)\n"
524 "\nNot found.\n",
525 Ptr,
526 File,
527 (unsigned)Line
528 );
529
530 exit (1);
531 }
532 //
533 // Leave loop when match is found.
534 //
535 if (&Tmp->Next->Buffer[sizeof (UINT32)] == Ptr) {
536 break;
537 }
538 }
539 //
540 // Unlink item from list.
541 //
542 Tmp2 = Tmp->Next;
543 Tmp->Next = Tmp->Next->Next;
544 Tmp = Tmp2;
545 }
546 //
547 // Release item.
548 //
549 free (Tmp);
550 }
551
552 #endif /* USE_MYALLOC */
553
554 /* eof - MyAlloc.c */