]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/Common/MyAlloc.c
License header updated to match correct format.
[mirror_edk2.git] / BaseTools / Source / C / Common / MyAlloc.c
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
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 *
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 *
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
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 */