Home | History | Annotate | Download | only in Common
      1 /*++
      2 
      3 Copyright (c) 2004, Intel Corporation. All rights reserved.<BR>
      4 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=%xh, Line=%u)"
     86       "Invalid parameter(s).\n",
     87       Final,
     88       File,
     89       Line
     90       );
     91 
     92     exit (1);
     93   }
     94 
     95   if (strlen (File) == 0) {
     96     printf (
     97       "\nMyCheck(Final=%u, File=%s, Line=%u)"
     98       "Invalid parameter.\n",
     99       Final,
    100       File,
    101       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       Line,
    125       Tmp->File,
    126       Tmp->Line,
    127       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         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           Tmp->Line,
    152           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=%xh, Line=%u)"
    203       "\nInvalid parameter(s).\n",
    204       Size,
    205       File,
    206       Line
    207       );
    208 
    209     exit (1);
    210   }
    211 
    212   Len = strlen (File);
    213   if (Len == 0) {
    214     printf (
    215       "\nMyAlloc(Size=%u, File=%s, Line=%u)"
    216       "\nInvalid parameter.\n",
    217       Size,
    218       File,
    219       Line
    220       );
    221 
    222     exit (1);
    223   }
    224   //
    225   // Check the allocation list for corruption.
    226   //
    227   MyCheck (0, __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       Size,
    242       File,
    243       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 (Tmp->File, 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=%xh, Size=%u, File=%xh, Line=%u)"
    316       "\nInvalid parameter(s).\n",
    317       Ptr,
    318       Size,
    319       File,
    320       Line
    321       );
    322 
    323     exit (1);
    324   }
    325 
    326   if (strlen (File) == 0) {
    327     printf (
    328       "\nMyRealloc(Ptr=%xh, Size=%u, File=%s, Line=%u)"
    329       "\nInvalid parameter.\n",
    330       Ptr,
    331       Size,
    332       File,
    333       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=%xh, Size=%u, File=%s, Line=%u)"
    350           "\nCould not find buffer.\n",
    351           Ptr,
    352           Size,
    353           File,
    354           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, __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=%xh, File=%xh, Line=%u)"
    421       "\nInvalid parameter(s).\n",
    422       Ptr,
    423       File,
    424       Line
    425       );
    426 
    427     exit (1);
    428   }
    429 
    430   if (strlen (File) == 0) {
    431     printf (
    432       "\nMyFree(Ptr=%xh, File=%s, Line=%u)"
    433       "\nInvalid parameter.\n",
    434       Ptr,
    435       File,
    436       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=%xh, File=%s, Line=%u)"
    453       "\nCalled before memory allocated.\n",
    454       Ptr,
    455       File,
    456       Line
    457       );
    458 
    459     exit (1);
    460   }
    461   //
    462   // Check for corrupted allocation list.
    463   //
    464   MyCheck (0, __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=%xh, File=%s, Line=%u)\n"
    486           "\nNot found.\n",
    487           Ptr,
    488           File,
    489           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 */
    517