Home | History | Annotate | Download | only in Common
      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