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 */ 555