Home | History | Annotate | Download | only in EbcDebugger
      1 /** @file
      2 
      3 Copyright (c) 2007 - 2016, 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 
     13 **/
     14 
     15 #include "Edb.h"
     16 
     17 /**
     18 
     19   Load single symbol entry.
     20 
     21   @param  Object          - Symbol file object
     22   @param  Name            - Symbol name
     23   @param  ObjName         - Object name
     24   @param  Address         - Symbol address
     25   @param  Type            - Symbol type
     26 
     27   @retval EFI_SUCCESS - add single symbol entry successfully
     28 
     29 **/
     30 EFI_STATUS
     31 EdbLoadSymbolSingleEntry (
     32   IN EFI_DEBUGGER_SYMBOL_OBJECT  *Object,
     33   IN CHAR8                       *Name,
     34   IN CHAR8                       *ObjName,
     35   IN UINTN                       Address,
     36   IN EFI_DEBUGGER_SYMBOL_TYPE    Type
     37   )
     38 {
     39   EFI_DEBUGGER_SYMBOL_ENTRY  *Entry;
     40 
     41   //
     42   // Check Count VS MaxCount
     43   //
     44   if (Object->EntryCount >= Object->MaxEntryCount) {
     45     //
     46     // reallocate (for codebuffer too)
     47     // TBD
     48     //
     49     return EFI_OUT_OF_RESOURCES;
     50   }
     51 
     52   Entry = &Object->Entry[Object->EntryCount];
     53 
     54   //
     55   // Print Debug info
     56   //
     57   if (sizeof (UINTN) == sizeof(UINT64)) {
     58     DEBUG ((DEBUG_ERROR, "  Symbol: %a, Address: 0x%016lx (%d)\n", Name, (UINT64)Address, (UINTN)Type));
     59   } else {
     60     DEBUG ((DEBUG_ERROR, "  Symbol: %a, Address: 0x%08x (%d)\n", Name, Address, (UINTN)Type));
     61   }
     62 
     63   //
     64   // Fill the entry - name, RVA, type
     65   //
     66   AsciiStrnCpyS (Entry->Name, sizeof(Entry->Name), Name, sizeof(Entry->Name) - 1);
     67   if (ObjName != NULL) {
     68     AsciiStrnCpyS (Entry->ObjName, sizeof(Entry->ObjName), ObjName, sizeof(Entry->ObjName) - 1);
     69   }
     70   Entry->Rva = Address % EFI_DEBUGGER_DEFAULT_LINK_IMAGEBASE;
     71   Entry->Type = Type;
     72 
     73   //
     74   // Increase Count
     75   //
     76   Object->EntryCount++;
     77 
     78   //
     79   // Done
     80   //
     81   return EFI_SUCCESS;
     82 }
     83 
     84 typedef enum {
     85   EdbEbcMapParseStateUninitialized,
     86   EdbEbcMapParseStateSymbolStart,
     87   EdbEbcMapParseStateSeHandlerSymbol,
     88   EdbEbcMapParseStateFunctionSymbol,
     89   EdbEbcMapParseStateVarbssInitSymbol,
     90   EdbEbcMapParseStateCrtSymbol,
     91   EdbEbcMapParseStateVariableSymbol,
     92   EdbEbcMapParseStateStaticFunctionSymbol,
     93   EdbEbcMapParseStateMax,
     94 } EDB_EBC_MAP_PARSE_STATE;
     95 
     96 typedef enum {
     97   EdbEbcSymbolParseStateUninitialized,
     98   EdbEbcSymbolParseStateReadyForName,
     99   EdbEbcSymbolParseStateReadyForRVA,
    100   EdbEbcSymbolParseStateReadyForType,
    101   EdbEbcSymbolParseStateReadyForObject,
    102   EdbEbcSymbolParseStateMax,
    103 } EDB_EBC_SYMBOL_PARSE_STATE;
    104 
    105 /**
    106 
    107   The following code depends on the MAP file generated by IEC compiler (actually Microsoft linker).
    108 
    109   Sample as follows: EbcTest.map
    110 ===============================================================================
    111   EbcTest
    112 
    113  Timestamp is 45b02718 (Fri Jan 19 10:04:08 2007)
    114 
    115  Preferred load address is 10000000
    116 
    117  Start         Length     Name                   Class
    118  0001:00000000 00000370H .text                   CODE
    119  0002:00000000 00000030H _VARBSS_INIT            CODE
    120  0003:00000000 00000004H .CRT$TSA                DATA
    121  0003:00000004 00000004H .CRT$TSC                DATA
    122  0003:00000008 00000004H .CRT$X                  DATA
    123  0003:0000000c 00000008H .CRT$XCU                DATA
    124  0003:00000014 00000004H .CRT$Z                  DATA
    125  0003:00000020 0000001cH .rdata                  DATA
    126  0003:0000003c 00000000H .edata                  DATA
    127  0003:0000003c 00000056H .rdata$debug            DATA
    128  0004:00000000 00000070H .data                   DATA
    129  0004:00000070 00000020H .bss                    DATA
    130 
    131   Address         Publics by Value              Rva+Base     Lib:Object
    132 
    133  0000:00000000       ___safe_se_handler_table   00000000     <absolute>
    134  0000:00000000       ___safe_se_handler_count   00000000     <absolute>
    135  0001:00000042       TestSubRoutine             10000442 f   EbcTest.obj
    136  0001:0000011a       EfiMain                    1000051a f   EbcTest.obj
    137  0001:00000200       TestSubRoutineSub          10000600 f   EbcTestSub.obj
    138  0001:00000220       EfiStart                   10000620 f   EbcLib:EbcLib.obj
    139  0002:00000000       varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b02717 10000800 f   EbcTest.obj
    140  0002:00000020       varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTestSub$c45af77f3 10000820 f   EbcTestSub.obj
    141  0003:00000000       CrtThunkBegin              10000a00     EbcLib:EbcLib.obj
    142  0003:00000004       CrtThunkEnd                10000a04     EbcLib:EbcLib.obj
    143  0003:00000008       CrtBegin                   10000a08     EbcLib:EbcLib.obj
    144  0003:00000014       CrtEnd                     10000a14     EbcLib:EbcLib.obj
    145  0004:00000070       TestStr                    10000c70     EbcTest.obj
    146  0004:00000078       TestVariable1              10000c78     EbcTest.obj
    147  0004:00000080       TestSubVariableSub         10000c80     EbcTestSub.obj
    148 
    149  entry point at        0001:00000220
    150 
    151  Static symbols
    152 
    153  0001:00000000       TestSubRoutine2            10000400 f   EbcTest.obj
    154 ===============================================================================
    155 
    156 **/
    157 
    158 /**
    159 
    160   Load symbol entry by Iec.
    161 
    162   @param  Object          - Symbol file object
    163   @param  BufferSize      - Symbol file buffer size
    164   @param  Buffer          - Symbol file buffer
    165 
    166   @retval EFI_SUCCESS - add symbol entry successfully
    167 
    168 **/
    169 EFI_STATUS
    170 EdbLoadSymbolEntryByIec (
    171   IN EFI_DEBUGGER_SYMBOL_OBJECT  *Object,
    172   IN UINTN                       BufferSize,
    173   IN VOID                        *Buffer
    174   )
    175 {
    176   CHAR8                      *LineBuffer;
    177   CHAR8                      *FieldBuffer;
    178   EDB_EBC_MAP_PARSE_STATE    MapParseState;
    179   EDB_EBC_SYMBOL_PARSE_STATE SymbolParseState;
    180   CHAR8                      *Name;
    181   CHAR8                      *ObjName;
    182   UINTN                      Address;
    183   EFI_DEBUGGER_SYMBOL_TYPE   Type;
    184 
    185 
    186   //
    187   // Begin to parse the Buffer
    188   //
    189   LineBuffer = AsciiStrGetNewTokenLine (Buffer, "\n\r");
    190   MapParseState = EdbEbcMapParseStateUninitialized;
    191   //
    192   // Check each line
    193   //
    194   while (LineBuffer != NULL) {
    195     FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, " ");
    196     SymbolParseState = EdbEbcSymbolParseStateUninitialized;
    197     //
    198     // Init entry value
    199     //
    200     Name = NULL;
    201     ObjName = NULL;
    202     Address = 0;
    203     Type = EfiDebuggerSymbolTypeMax;
    204     //
    205     // Check each field
    206     //
    207     while (FieldBuffer != NULL) {
    208       if (AsciiStrCmp (FieldBuffer, "") == 0) {
    209         FieldBuffer = AsciiStrGetNextTokenField (" ");
    210         continue;
    211       }
    212       //
    213       // check "Address"
    214       //
    215       if (AsciiStrCmp (FieldBuffer, "Address") == 0) {
    216         MapParseState = EdbEbcMapParseStateSymbolStart;
    217         break;
    218       }
    219       //
    220       // check "Static"
    221       //
    222       if (AsciiStrCmp (FieldBuffer, "Static") == 0) {
    223         MapParseState = EdbEbcMapParseStateStaticFunctionSymbol;
    224         break;
    225       }
    226 
    227       if (MapParseState == EdbEbcMapParseStateUninitialized) {
    228         //
    229         // Do not parse anything until get "Address" or "Static"
    230         //
    231         break;
    232       }
    233       if (AsciiStrCmp (FieldBuffer, "entry") == 0) {
    234         //
    235         // Skip entry point
    236         //
    237         break;
    238       }
    239 
    240       //
    241       // Now we start to parse this line for Name, Address, and Object
    242       //
    243       switch (SymbolParseState) {
    244       case  EdbEbcSymbolParseStateUninitialized:
    245         //
    246         // Get the Address
    247         //
    248         SymbolParseState = EdbEbcSymbolParseStateReadyForName;
    249         break;
    250       case  EdbEbcSymbolParseStateReadyForName:
    251         //
    252         // Get the Name
    253         //
    254         if (AsciiStrnCmp (FieldBuffer, "___safe_se_handler", AsciiStrLen ("___safe_se_handler")) == 0) {
    255           //
    256           // skip SeHandler
    257           //
    258           MapParseState = EdbEbcMapParseStateSeHandlerSymbol;
    259           goto ExitFieldParse;
    260         } else if (AsciiStrnCmp (FieldBuffer, "varbss_init", AsciiStrLen ("varbss_init")) == 0) {
    261           //
    262           // check VarbssInit
    263           //
    264           MapParseState = EdbEbcMapParseStateVarbssInitSymbol;
    265 //          goto ExitFieldParse;
    266           Name = FieldBuffer;
    267           SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
    268         } else if (AsciiStrnCmp (FieldBuffer, "Crt", AsciiStrLen ("Crt")) == 0) {
    269           //
    270           // check Crt
    271           //
    272           MapParseState = EdbEbcMapParseStateCrtSymbol;
    273 //          goto ExitFieldParse;
    274           Name = FieldBuffer;
    275           SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
    276         } else {
    277           //
    278           // Now, it is normal function
    279           //
    280           switch (MapParseState) {
    281           case EdbEbcMapParseStateSeHandlerSymbol:
    282             MapParseState = EdbEbcMapParseStateFunctionSymbol;
    283             break;
    284           case EdbEbcMapParseStateCrtSymbol:
    285             MapParseState = EdbEbcMapParseStateVariableSymbol;
    286             break;
    287           case EdbEbcMapParseStateFunctionSymbol:
    288           case EdbEbcMapParseStateVariableSymbol:
    289           case EdbEbcMapParseStateStaticFunctionSymbol:
    290             break;
    291           default:
    292             ASSERT (FALSE);
    293             break;
    294           }
    295           Name = FieldBuffer;
    296           SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
    297         }
    298         break;
    299       case  EdbEbcSymbolParseStateReadyForRVA:
    300         //
    301         // Get the RVA
    302         //
    303         Address = AsciiXtoi (FieldBuffer);
    304         SymbolParseState = EdbEbcSymbolParseStateReadyForType;
    305         break;
    306       case  EdbEbcSymbolParseStateReadyForType:
    307         //
    308         // Get the Type. This is optional, only for "f".
    309         //
    310         if (AsciiStrCmp (FieldBuffer, "f") == 0) {
    311           SymbolParseState = EdbEbcSymbolParseStateReadyForObject;
    312           switch (MapParseState) {
    313           case EdbEbcMapParseStateFunctionSymbol:
    314           case EdbEbcMapParseStateVarbssInitSymbol:
    315             Type = EfiDebuggerSymbolFunction;
    316             break;
    317           case EdbEbcMapParseStateStaticFunctionSymbol:
    318             Type = EfiDebuggerSymbolStaticFunction;
    319             break;
    320           default:
    321             ASSERT (FALSE);
    322             break;
    323           }
    324           break;
    325         }
    326         //
    327         // Else it should be Object.
    328         // let it bypass here
    329         //
    330       case  EdbEbcSymbolParseStateReadyForObject:
    331         switch (Type) {
    332         case EfiDebuggerSymbolTypeMax:
    333           switch (MapParseState) {
    334           case EdbEbcMapParseStateVariableSymbol:
    335           case EdbEbcMapParseStateCrtSymbol:
    336             Type = EfiDebuggerSymbolGlobalVariable;
    337             break;
    338           case EdbEbcMapParseStateSeHandlerSymbol:
    339             //
    340             // do nothing here
    341             //
    342             break;
    343           default:
    344             ASSERT (FALSE);
    345             break;
    346           }
    347           break;
    348         case EfiDebuggerSymbolFunction:
    349         case EfiDebuggerSymbolStaticFunction:
    350           break;
    351         default:
    352           ASSERT (FALSE);
    353           break;
    354         }
    355         //
    356         // Get the Object
    357         //
    358         ObjName = FieldBuffer;
    359         SymbolParseState = EdbEbcSymbolParseStateUninitialized;
    360         break;
    361       default:
    362         ASSERT (FALSE);
    363         break;
    364       }
    365 
    366       //
    367       // Get the next field
    368       //
    369       FieldBuffer = AsciiStrGetNextTokenField (" ");
    370     }
    371 
    372     //
    373     // Add the entry if we get everything.
    374     //
    375     if ((Name != NULL) && (Type != EfiDebuggerSymbolTypeMax)) {
    376       EdbLoadSymbolSingleEntry (Object, Name, ObjName, Address, Type);
    377     }
    378 
    379 ExitFieldParse:
    380     //
    381     // Get the next line
    382     //
    383     LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
    384   }
    385 
    386   //
    387   // Done
    388   //
    389   return EFI_SUCCESS;
    390 }
    391 
    392 /**
    393 
    394   Load symbol entry.
    395 
    396   @param  Object          - Symbol file object
    397   @param  BufferSize      - Symbol file buffer size
    398   @param  Buffer          - Symbol file buffer
    399 
    400   @retval EFI_SUCCESS - add symbol entry successfully
    401 
    402 **/
    403 EFI_STATUS
    404 EdbLoadSymbolEntry (
    405   IN EFI_DEBUGGER_SYMBOL_OBJECT  *Object,
    406   IN UINTN                       BufferSize,
    407   IN VOID                        *Buffer
    408   )
    409 {
    410   //
    411   // MAP file format depends on the compiler (actually linker).
    412   //
    413   // It is possible to check the different MAP file format in this routine.
    414   // Now only IEC is supported.
    415   //
    416   return EdbLoadSymbolEntryByIec (Object, BufferSize, Buffer);
    417 }
    418 
    419 /**
    420 
    421   Find symbol file by name.
    422 
    423   @param  DebuggerPrivate - EBC Debugger private data structure
    424   @param  FileName        - Symbol file name
    425   @param  Index           - Symbol file index
    426 
    427   @return Object
    428 
    429 **/
    430 EFI_DEBUGGER_SYMBOL_OBJECT *
    431 EdbFindSymbolFile (
    432   IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
    433   IN CHAR16                      *FileName,
    434   IN OUT UINTN                   *Index OPTIONAL
    435   )
    436 {
    437   UINTN ObjectIndex;
    438 
    439   //
    440   // Check each Object
    441   //
    442   for (ObjectIndex = 0; ObjectIndex < DebuggerPrivate->DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
    443     if (StrCmp (FileName, DebuggerPrivate->DebuggerSymbolContext.Object[ObjectIndex].Name) == 0) {
    444       //
    445       // Name match, found it
    446       //
    447       if (Index != NULL) {
    448         *Index = ObjectIndex;
    449       }
    450       return &DebuggerPrivate->DebuggerSymbolContext.Object[ObjectIndex];
    451     }
    452   }
    453 
    454   //
    455   // Not found
    456   //
    457   return NULL;
    458 }
    459 
    460 /**
    461 
    462   Find symbol by address.
    463 
    464   @param  Address         - Symbol address
    465   @param  Type            - Search type
    466   @param  RetObject       - Symbol object
    467   @param  RetEntry        - Symbol entry
    468 
    469   @return Nearest symbol address
    470 
    471 **/
    472 UINTN
    473 EbdFindSymbolAddress (
    474   IN UINTN                       Address,
    475   IN EDB_MATCH_SYMBOL_TYPE       Type,
    476   OUT EFI_DEBUGGER_SYMBOL_OBJECT **RetObject,
    477   OUT EFI_DEBUGGER_SYMBOL_ENTRY  **RetEntry
    478   )
    479 {
    480   UINTN                      Index;
    481   UINTN                      SubIndex;
    482   UINTN                      CandidateLowerAddress;
    483   UINTN                      CandidateUpperAddress;
    484   EFI_DEBUGGER_SYMBOL_OBJECT *Object;
    485   EFI_DEBUGGER_SYMBOL_ENTRY  *Entry;
    486   EFI_DEBUGGER_SYMBOL_ENTRY  *LowEntry;
    487   EFI_DEBUGGER_SYMBOL_ENTRY  *UpperEntry;
    488   EFI_DEBUGGER_SYMBOL_OBJECT *LowObject;
    489   EFI_DEBUGGER_SYMBOL_OBJECT *UpperObject;
    490 
    491   if ((Type < 0) || (Type >= EdbMatchSymbolTypeMax)) {
    492     return 0;
    493   }
    494 
    495   //
    496   // Init
    497   //
    498   CandidateLowerAddress = 0;
    499   CandidateUpperAddress = (UINTN)-1;
    500   LowEntry = NULL;
    501   UpperEntry = NULL;
    502   LowObject = NULL;
    503   UpperObject = NULL;
    504 
    505   //
    506   // Go through each object
    507   //
    508   Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
    509   for (Index = 0; Index < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; Index++, Object++) {
    510     if (Object->EntryCount == 0) {
    511       continue;
    512     }
    513     //
    514     // Go through each entry
    515     //
    516     Entry = Object->Entry;
    517     for (SubIndex = 0; SubIndex < Object->EntryCount; SubIndex++, Entry++) {
    518       if (Address != Entry->Rva + Object->BaseAddress) {
    519         //
    520         // Check for nearest address
    521         //
    522         if (Address > Entry->Rva + Object->BaseAddress) {
    523           //
    524           // Record it if Current RVA < Address
    525           //
    526           if (CandidateLowerAddress < Entry->Rva + Object->BaseAddress) {
    527             CandidateLowerAddress = Entry->Rva + Object->BaseAddress;
    528             LowEntry = Entry;
    529             LowObject = Object;
    530           }
    531         } else {
    532           //
    533           // Record it if Current RVA > Address
    534           //
    535           if (CandidateUpperAddress > Entry->Rva + Object->BaseAddress) {
    536             CandidateUpperAddress = Entry->Rva + Object->BaseAddress;
    537             UpperEntry = Entry;
    538             UpperObject = Object;
    539           }
    540         }
    541         continue;
    542       }
    543       //
    544       // address match, return directly
    545       //
    546       *RetEntry = Entry;
    547       *RetObject = Object;
    548       return Address;
    549     }
    550   }
    551 
    552   //
    553   // No Match, provide latest symbol
    554   //
    555 
    556   if ((Address - CandidateLowerAddress) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE) {
    557     //
    558     // Check for lower address
    559     //
    560     if (((Type == EdbMatchSymbolTypeNearestAddress) &&
    561          ((CandidateUpperAddress - Address) > (Address - CandidateLowerAddress))) ||
    562         (Type == EdbMatchSymbolTypeLowerAddress)) {
    563       //
    564       // return nearest lower address
    565       //
    566       *RetEntry = LowEntry;
    567       *RetObject = LowObject;
    568       return CandidateLowerAddress;
    569     }
    570   }
    571 
    572   if ((CandidateUpperAddress - Address) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE) {
    573     //
    574     // Check for upper address
    575     //
    576     if (((Type == EdbMatchSymbolTypeNearestAddress) &&
    577          ((CandidateUpperAddress - Address) < (Address - CandidateLowerAddress))) ||
    578         (Type == EdbMatchSymbolTypeUpperAddress)) {
    579       //
    580       // return nearest upper address
    581       //
    582       *RetEntry = UpperEntry;
    583       *RetObject = UpperObject;
    584       return CandidateUpperAddress;
    585     }
    586   }
    587 
    588   //
    589   // No match and nearest one, return NULL
    590   //
    591   return 0;
    592 }
    593 
    594 /**
    595 
    596   Unload symbol file by name.
    597 
    598   @param  DebuggerPrivate - EBC Debugger private data structure
    599   @param  FileName        - Symbol file name
    600 
    601   @retval EFI_SUCCESS - unload symbol successfully
    602 
    603 **/
    604 EFI_STATUS
    605 EdbUnloadSymbol (
    606   IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
    607   IN CHAR16                      *FileName
    608   )
    609 {
    610   EFI_DEBUGGER_SYMBOL_OBJECT *Object;
    611   UINTN                      ObjectIndex;
    612   UINTN                      Index;
    613   EFI_DEBUGGER_SYMBOL_ENTRY  *OldEntry;
    614   UINTN                      OldEntryCount;
    615   UINTN                      MaxEntryCount;
    616   VOID                       **OldSourceBuffer;
    617 
    618   //
    619   // Find Symbol
    620   //
    621   Object = EdbFindSymbolFile (DebuggerPrivate, FileName, &ObjectIndex);
    622   if (Object == NULL) {
    623     EDBPrint (L"SymbolFile is not loaded!\n");
    624     return EFI_DEBUG_CONTINUE;
    625   }
    626 
    627   //
    628   // Record old data
    629   //
    630   Object = DebuggerPrivate->DebuggerSymbolContext.Object;
    631   OldEntry = Object->Entry;
    632   OldSourceBuffer = Object->SourceBuffer;
    633   MaxEntryCount = Object->MaxEntryCount;
    634   OldEntryCount = Object->EntryCount;
    635 
    636   //
    637   // Remove the matched Object
    638   //
    639   for (Index = ObjectIndex; Index < DebuggerPrivate->DebuggerSymbolContext.ObjectCount - 1; Index++) {
    640     CopyMem (&Object[Index], &Object[Index + 1], sizeof(EFI_DEBUGGER_SYMBOL_OBJECT));
    641   }
    642   ZeroMem (&Object[Index], sizeof(Object[Index]));
    643 
    644   //
    645   // Move old data to new place
    646   //
    647   Object[Index].Entry = OldEntry;
    648   Object[Index].SourceBuffer = OldSourceBuffer;
    649   Object[Index].MaxEntryCount = MaxEntryCount;
    650   DebuggerPrivate->DebuggerSymbolContext.ObjectCount --;
    651 
    652   //
    653   // Clean old entry data
    654   //
    655   for (Index = 0; Index < OldEntryCount; Index++) {
    656     ZeroMem (&OldEntry[Index], sizeof(OldEntry[Index]));
    657   }
    658 
    659   //
    660   // Free OldSourceBuffer
    661   //
    662   for (Index = 0; OldSourceBuffer[Index] != NULL; Index++) {
    663     gBS->FreePool (OldSourceBuffer[Index]);
    664     OldSourceBuffer[Index] = NULL;
    665   }
    666 
    667   return EFI_SUCCESS;
    668 }
    669 
    670 /**
    671 
    672   Load symbol file by name.
    673 
    674   @param  DebuggerPrivate - EBC Debugger private data structure
    675   @param  FileName        - Symbol file name
    676   @param  BufferSize      - Symbol file buffer size
    677   @param  Buffer          - Symbol file buffer
    678 
    679   @retval EFI_SUCCESS - load symbol successfully
    680 
    681 **/
    682 EFI_STATUS
    683 EdbLoadSymbol (
    684   IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
    685   IN CHAR16                      *FileName,
    686   IN UINTN                       BufferSize,
    687   IN VOID                        *Buffer
    688   )
    689 {
    690   EFI_DEBUGGER_SYMBOL_OBJECT *Object;
    691   EFI_STATUS                 Status;
    692 
    693   //
    694   // Check duplicated File
    695   //
    696   Object = EdbFindSymbolFile (DebuggerPrivate, FileName, NULL);
    697   if (Object != NULL) {
    698     Status = EdbUnloadSymbol (DebuggerPrivate, FileName);
    699     if (EFI_ERROR(Status)) {
    700       DEBUG ((DEBUG_ERROR, "Unload Duplicated Symbol File Error!\n"));
    701       return Status;
    702     }
    703   }
    704 
    705   //
    706   // Check Count VS MaxCount
    707   //
    708   if (DebuggerPrivate->DebuggerSymbolContext.ObjectCount >= DebuggerPrivate->DebuggerSymbolContext.MaxObjectCount) {
    709     //
    710     // reallocate
    711     // TBD
    712     //
    713     return EFI_OUT_OF_RESOURCES;
    714   }
    715 
    716   Object = &DebuggerPrivate->DebuggerSymbolContext.Object[DebuggerPrivate->DebuggerSymbolContext.ObjectCount];
    717 
    718   //
    719   // Init Object
    720   //
    721   Object->EntryCount = 0;
    722   Object->MaxEntryCount = EFI_DEBUGGER_SYMBOL_ENTRY_MAX;
    723 
    724   //
    725   // Load SymbolEntry
    726   //
    727   DEBUG ((DEBUG_ERROR, "Symbol File: %s\n", FileName));
    728   Status = EdbLoadSymbolEntry (Object, BufferSize, Buffer);
    729   if (EFI_ERROR (Status)) {
    730     return Status;
    731   }
    732 
    733   //
    734   // Fill Object value
    735   //
    736   StrnCpyS (Object->Name, sizeof(Object->Name) / sizeof(CHAR16),
    737             FileName, (sizeof(Object->Name) / sizeof(CHAR16)) - 1);
    738   Object->BaseAddress = 0;
    739 
    740   //
    741   // Increase the object count
    742   //
    743   DebuggerPrivate->DebuggerSymbolContext.ObjectCount ++;
    744 
    745   return EFI_SUCCESS;
    746 }
    747 
    748 /**
    749 
    750   Located PDB path name in PE image.
    751 
    752   @param  ImageBase - base of PE to search
    753 
    754   @return Pointer into image at offset of PDB file name if PDB file name is found,
    755   Otherwise a pointer to an empty string.
    756 
    757 **/
    758 CHAR8 *
    759 GetPdbPath (
    760   VOID *ImageBase
    761   )
    762 {
    763   CHAR8                           *PdbPath;
    764   UINT32                          DirCount;
    765   EFI_IMAGE_DOS_HEADER            *DosHdr;
    766   EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
    767   EFI_IMAGE_OPTIONAL_HEADER32     *OptionalHdr32;
    768   EFI_IMAGE_OPTIONAL_HEADER64     *OptionalHdr64;
    769   EFI_IMAGE_DATA_DIRECTORY        *DirectoryEntry;
    770   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
    771   VOID                            *CodeViewEntryPointer;
    772 
    773   //
    774   // Init value
    775   //
    776   CodeViewEntryPointer  = NULL;
    777   PdbPath               = NULL;
    778   DosHdr                = ImageBase;
    779 
    780   //
    781   // Check magic
    782   //
    783   if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
    784     return NULL;
    785   }
    786   NtHdr           = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) DosHdr + DosHdr->e_lfanew);
    787   //
    788   // Check Machine, filter for EBC
    789   //
    790   if (NtHdr->Pe32.FileHeader.Machine != EFI_IMAGE_MACHINE_EBC) {
    791     //
    792     // If not EBC, return NULL
    793     //
    794     return NULL;
    795   }
    796 
    797   //
    798   // Get DirectoryEntry
    799   // EBC spec says PE32+, but implementation uses PE32. So check dynamically here.
    800   //
    801   if (NtHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
    802     OptionalHdr32   = (VOID *) &NtHdr->Pe32.OptionalHeader;
    803     DirectoryEntry  = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHdr32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
    804   } else if (NtHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
    805     OptionalHdr64   = (VOID *) &NtHdr->Pe32Plus.OptionalHeader;
    806     DirectoryEntry  = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHdr64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
    807   } else {
    808     return NULL;
    809   }
    810   if (DirectoryEntry->VirtualAddress == 0) {
    811     return NULL;
    812   }
    813   //
    814   // Go through DirectoryEntry
    815   //
    816   for (DirCount = 0;
    817        (DirCount < DirectoryEntry->Size / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) && CodeViewEntryPointer == NULL;
    818        DirCount++
    819       ) {
    820     DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (DirectoryEntry->VirtualAddress + (UINTN) ImageBase + DirCount * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
    821     if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
    822       //
    823       // Match DebugEntry, only CODEVIEW_SIGNATURE_NB10 and CODEVIEW_SIGNATURE_RSDS are supported.
    824       //
    825       CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageBase);
    826       switch (*(UINT32 *) CodeViewEntryPointer) {
    827       case CODEVIEW_SIGNATURE_NB10:
    828         PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
    829         break;
    830       case CODEVIEW_SIGNATURE_RSDS:
    831         PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
    832         break;
    833       default:
    834         break;
    835       }
    836     }
    837   }
    838 
    839   //
    840   // Done successfully
    841   //
    842   return PdbPath;
    843 }
    844 
    845 /**
    846 
    847   Check whether PDB file and MAP file have same name.
    848 
    849   @param  PdbFileName - PDB file name
    850   @param  MapFileName - MAP file name
    851 
    852   @retval TRUE  - PDB and MAP file name match
    853   @retval FALSE - PDB and MAP file name not match
    854 
    855 **/
    856 BOOLEAN
    857 MatchPdbAndMap (
    858   IN CHAR8   *PdbFileName,
    859   IN CHAR16  *MapFileName
    860   )
    861 {
    862   UINTN   PdbNameSize;
    863   UINTN   MapNameSize;
    864   CHAR8   *PurePdbFileName;
    865   UINTN   Index;
    866 
    867   //
    868   // remove dir name
    869   //
    870   PurePdbFileName = PdbFileName;
    871   for (Index = 0; PdbFileName[Index] != 0; Index++) {
    872     if (PdbFileName[Index] == '\\') {
    873       PurePdbFileName = &PdbFileName[Index + 1];
    874     }
    875   }
    876   PdbFileName = PurePdbFileName;
    877 
    878   //
    879   // get size
    880   //
    881   PdbNameSize = AsciiStrLen (PdbFileName);
    882   MapNameSize = StrLen (MapFileName);
    883 
    884   if (PdbNameSize != MapNameSize) {
    885     return FALSE;
    886   }
    887 
    888   //
    889   // check the name
    890   //
    891   for (Index = 0; Index < MapNameSize - 4; Index++) {
    892     if ((PdbFileName[Index] | 0x20) != (MapFileName[Index] | 0x20)) {
    893       return FALSE;
    894     }
    895   }
    896 
    897   return TRUE;
    898 }
    899 
    900 //
    901 // BUGBUG: work-around start
    902 //
    903 typedef struct {
    904   EFI_DEBUG_IMAGE_INFO  *EfiDebugImageInfoTable;
    905   volatile UINT32       UpdateStatus;
    906   UINT32                TableSize;
    907 } EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD;
    908 
    909 EFI_DEBUG_IMAGE_INFO_TABLE_HEADER  mDebugImageInfoTableHeader;
    910 
    911 /**
    912 For compatibility consideration, we handle 2 cases:
    913 
    914 1) IA32:
    915   Old:                          New:
    916   +------------------------+    +------------------------+
    917   | EfiDebugImageInfoTable |    | UpdateStatus           |
    918   +------------------------+    +------------------------+
    919   | UpdateStatus           |    | TableSize              |
    920   +------------------------+    +------------------------+
    921   | TableSize              |    | EfiDebugImageInfoTable |
    922   +------------------------+    +------------------------+
    923 
    924 2) X64 and IPF:
    925   Old:                          New:
    926   +------------------------+    +------------------------+
    927   | EfiDebugImageInfoTable |    | UpdateStatus           |
    928   |                        |    +------------------------+
    929   |                        |    | TableSize              |
    930   +------------------------+    +------------------------+
    931   | UpdateStatus           |    | EfiDebugImageInfoTable |
    932   +------------------------+    |                        |
    933   | TableSize              |    |                        |
    934   +------------------------+    +------------------------+
    935 
    936   @param DebugImageInfoTableHeader  Point to the EFI_DEBUG_IMAGE_INFO_TABLE_HEADER structure.
    937 
    938 **/
    939 VOID
    940 EdbFixDebugImageInfoTable (
    941   IN OUT EFI_DEBUG_IMAGE_INFO_TABLE_HEADER **DebugImageInfoTableHeader
    942   )
    943 {
    944   mDebugImageInfoTableHeader.EfiDebugImageInfoTable = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->EfiDebugImageInfoTable;
    945   mDebugImageInfoTableHeader.UpdateStatus           = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->UpdateStatus;
    946   mDebugImageInfoTableHeader.TableSize              = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->TableSize;
    947 
    948   if ((*DebugImageInfoTableHeader)->UpdateStatus > 3) {
    949     *DebugImageInfoTableHeader = &mDebugImageInfoTableHeader;
    950     return ;
    951   }
    952 
    953   if ((*DebugImageInfoTableHeader)->TableSize % (EFI_PAGE_SIZE / (sizeof (VOID *))) != 0) {
    954     *DebugImageInfoTableHeader = &mDebugImageInfoTableHeader;
    955     return ;
    956   }
    957 
    958   return ;
    959 }
    960 //
    961 // BUGBUG: work-around end
    962 //
    963 
    964 /**
    965 
    966   Patch symbol RVA.
    967 
    968   @param  DebuggerPrivate - EBC Debugger private data structure
    969   @param  FileName        - Symbol file name
    970   @param  SearchType      - Search type for Object
    971 
    972   @retval EFI_SUCCESS   - Patch symbol RVA successfully
    973   @retval EFI_NOT_FOUND - Symbol RVA base not found
    974 
    975 **/
    976 EFI_STATUS
    977 EdbPatchSymbolRVA (
    978   IN EFI_DEBUGGER_PRIVATE_DATA     *DebuggerPrivate,
    979   IN CHAR16                        *FileName,
    980   IN EDB_EBC_IMAGE_RVA_SEARCH_TYPE SearchType
    981   )
    982 {
    983   EFI_STATUS            Status;
    984   UINTN                 ImageNumber;
    985   EFI_DEBUG_IMAGE_INFO  *ImageTable;
    986   CHAR8                 *PdbPath;
    987   VOID                  *ImageBase;
    988   VOID                  *CandidateImageBase;
    989   EFI_DEBUGGER_SYMBOL_OBJECT *Object;
    990 
    991   if (SearchType < 0 || SearchType >= EdbEbcImageRvaSearchTypeMax) {
    992     return EFI_INVALID_PARAMETER;
    993   }
    994 
    995   //
    996   // Get the related object
    997   //
    998   Object = EdbFindSymbolFile (DebuggerPrivate, FileName, NULL);
    999   if (Object == NULL) {
   1000     return EFI_NOT_FOUND;
   1001   }
   1002 
   1003   //
   1004   // Try again to get DebugImageInfoTable
   1005   //
   1006   if (mDebuggerPrivate.DebugImageInfoTableHeader == NULL) {
   1007     Status = EfiGetSystemConfigurationTable (
   1008                &gEfiDebugImageInfoTableGuid,
   1009                (VOID **) &mDebuggerPrivate.DebugImageInfoTableHeader
   1010                );
   1011     if (EFI_ERROR (Status)) {
   1012       EDBPrint (L"DebugImageInfoTable not found!\n");
   1013       return Status;
   1014     }
   1015   }
   1016   DEBUG ((DEBUG_ERROR, "DebugImageInfoTableHeader: %x\n", mDebuggerPrivate.DebugImageInfoTableHeader));
   1017 
   1018   //
   1019   // BUGBUG: work-around start
   1020   //
   1021   EdbFixDebugImageInfoTable (&mDebuggerPrivate.DebugImageInfoTableHeader);
   1022   //
   1023   // BUGBUG: work-around end
   1024   //
   1025 
   1026   //
   1027   // Go through DebugImageInfoTable for each Image
   1028   //
   1029   CandidateImageBase = NULL;
   1030   ImageTable  = mDebuggerPrivate.DebugImageInfoTableHeader->EfiDebugImageInfoTable;
   1031   for (ImageNumber = 0; ImageNumber < mDebuggerPrivate.DebugImageInfoTableHeader->TableSize; ImageNumber++) {
   1032     if (ImageTable[ImageNumber].NormalImage == NULL) {
   1033       continue;
   1034     }
   1035     ImageBase = ImageTable[ImageNumber].NormalImage->LoadedImageProtocolInstance->ImageBase;
   1036     //
   1037     // Get PDB path
   1038     //
   1039     PdbPath   = GetPdbPath (ImageBase);
   1040     if (PdbPath == NULL) {
   1041       continue;
   1042     }
   1043     //
   1044     // Check PDB name
   1045     //
   1046     if (!MatchPdbAndMap (PdbPath, FileName)) {
   1047       continue;
   1048     }
   1049     DEBUG ((DEBUG_ERROR, "ImageBase: %x\n", ImageBase));
   1050 
   1051     //
   1052     // Check SearchType
   1053     //
   1054     if (SearchType == EdbEbcImageRvaSearchTypeAny || SearchType == EdbEbcImageRvaSearchTypeFirst) {
   1055       //
   1056       // Assign base address and return
   1057       //
   1058       Object->BaseAddress = (UINTN)ImageBase;
   1059       return EFI_SUCCESS;
   1060     }
   1061 
   1062     //
   1063     // Get CandidateImageBase for EdbEbcImageRvaSearchTypeLast
   1064     //
   1065     CandidateImageBase = ImageBase;
   1066   }
   1067 
   1068   //
   1069   // Check EdbEbcImageRvaSearchTypeLast
   1070   //
   1071   if (SearchType == EdbEbcImageRvaSearchTypeLast) {
   1072     if (CandidateImageBase == NULL) {
   1073       return EFI_NOT_FOUND;
   1074     }
   1075     //
   1076     // Assign base address and return
   1077     //
   1078     Object->BaseAddress = (UINTN)CandidateImageBase;
   1079     return EFI_SUCCESS;
   1080   }
   1081 
   1082   //
   1083   // No match
   1084   //
   1085   return EFI_NOT_FOUND;
   1086 }
   1087 
   1088 /**
   1089 
   1090   Check whether OBJ file and COD file have same name.
   1091 
   1092   @param  ObjFileName - OBJ file name
   1093   @param  CodFileName - COD file name
   1094 
   1095   @retval TRUE  - OBJ and COD file name match
   1096   @retval FALSE - OBJ and COD file name not match
   1097 
   1098 **/
   1099 BOOLEAN
   1100 MatchObjAndCod (
   1101   IN CHAR8   *ObjFileName,
   1102   IN CHAR16  *CodFileName
   1103   )
   1104 {
   1105   UINTN   ObjNameSize;
   1106   UINTN   CodNameSize;
   1107   CHAR8   *PureObjFileName;
   1108   UINTN   Index;
   1109 
   1110   //
   1111   // remove library name
   1112   //
   1113   PureObjFileName = ObjFileName;
   1114   for (Index = 0; ObjFileName[Index] != 0; Index++) {
   1115     if (ObjFileName[Index] == ':') {
   1116       PureObjFileName = &ObjFileName[Index + 1];
   1117       break;
   1118     }
   1119   }
   1120   ObjFileName = PureObjFileName;
   1121 
   1122   //
   1123   // get size
   1124   //
   1125   ObjNameSize = AsciiStrLen (ObjFileName);
   1126   CodNameSize = StrLen (CodFileName);
   1127 
   1128   if (ObjNameSize != CodNameSize) {
   1129     return FALSE;
   1130   }
   1131 
   1132   //
   1133   // check the name
   1134   //
   1135   for (Index = 0; Index < CodNameSize - 4; Index++) {
   1136     if ((ObjFileName[Index] | 0x20) != (CodFileName[Index] | 0x20)) {
   1137       return FALSE;
   1138     }
   1139   }
   1140 
   1141   return TRUE;
   1142 }
   1143 
   1144 typedef enum {
   1145   EdbEbcCodParseStateUninitialized,
   1146   EdbEbcCodParseStateSymbolInitialized,
   1147   EdbEbcCodParseStateSymbolStart,
   1148   EdbEbcCodParseStateSymbolEnd,
   1149   EdbEbcCodParseStateMax,
   1150 } EDB_EBC_COD_PARSE_STATE;
   1151 
   1152 /**
   1153 
   1154   The following code depends on the COD file generated by IEC compiler.
   1155 
   1156 **/
   1157 
   1158 /**
   1159 
   1160   Load code by symbol by Iec.
   1161 
   1162   @param  Name            - Symbol file name
   1163   @param  Buffer          - Symbol file buffer
   1164   @param  BufferSize      - Symbol file buffer size
   1165   @param  CodeBufferSize  - Code buffer size
   1166   @param  FuncOffset      - Code funcion offset
   1167 
   1168   @return CodeBuffer
   1169 
   1170 **/
   1171 CHAR8 *
   1172 EdbLoadCodBySymbolByIec (
   1173   IN CHAR8                       *Name,
   1174   IN VOID                        *Buffer,
   1175   IN UINTN                       BufferSize,
   1176   OUT UINTN                      *CodeBufferSize,
   1177   OUT UINTN                      *FuncOffset
   1178   )
   1179 {
   1180   CHAR8                      *LineBuffer;
   1181   CHAR8                      *FieldBuffer;
   1182   VOID                       *BufferStart;
   1183   VOID                       *BufferEnd;
   1184   UINTN                      Offset;
   1185   EDB_EBC_COD_PARSE_STATE    CodParseState;
   1186   CHAR8                      Char[2];
   1187 
   1188   //
   1189   // Init
   1190   //
   1191   Char[0] = 9;
   1192   Char[1] = 0;
   1193   LineBuffer = AsciiStrGetNewTokenLine (Buffer, "\n\r");
   1194   Offset = (UINTN)-1;
   1195   BufferStart = NULL;
   1196   BufferEnd = NULL;
   1197   CodParseState = EdbEbcCodParseStateUninitialized;
   1198 
   1199   //
   1200   // Check each line
   1201   //
   1202   while (LineBuffer != NULL) {
   1203     switch (CodParseState) {
   1204     case EdbEbcCodParseStateUninitialized:
   1205       //
   1206       // check mark_begin, begin to check line after this match
   1207       //
   1208       if (AsciiStrCmp (LineBuffer, "; mark_begin;") == 0) {
   1209         CodParseState = EdbEbcCodParseStateSymbolInitialized;
   1210       }
   1211       LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
   1212       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
   1213       break;
   1214 
   1215     case EdbEbcCodParseStateSymbolInitialized:
   1216       //
   1217       // check mark_end, not check line after this match
   1218       //
   1219       if (AsciiStrCmp (LineBuffer, "; mark_end;") == 0) {
   1220         CodParseState = EdbEbcCodParseStateUninitialized;
   1221         LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
   1222         PatchForAsciiStrTokenBefore (LineBuffer, '\n');
   1223         break;
   1224       }
   1225 
   1226       //
   1227       // not check this line if the first char is as follows
   1228       //
   1229       if ((*LineBuffer == 0)   ||
   1230           (*LineBuffer == '$') ||
   1231           (*LineBuffer == ';') ||
   1232           (*LineBuffer == '_') ||
   1233           (*LineBuffer == ' ')) {
   1234         LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
   1235         PatchForAsciiStrTokenBefore (LineBuffer, '\n');
   1236         break;
   1237       }
   1238 
   1239       //
   1240       // get function name, function name is followed by char 0x09.
   1241       //
   1242       FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, Char);
   1243       ASSERT (FieldBuffer != NULL);
   1244       if (AsciiStriCmp (FieldBuffer, Name) == 0) {
   1245         BufferStart = FieldBuffer;
   1246         CodParseState = EdbEbcCodParseStateSymbolStart;
   1247       }
   1248       PatchForAsciiStrTokenAfter (FieldBuffer, 0x9);
   1249 
   1250       //
   1251       // Get next line
   1252       //
   1253       LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
   1254       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
   1255       break;
   1256 
   1257     case EdbEbcCodParseStateSymbolStart:
   1258       //
   1259       // check mark_end, if this match, means the function is found successfully.
   1260       //
   1261       if (AsciiStrCmp (LineBuffer, "; mark_end;") == 0) {
   1262         CodParseState = EdbEbcCodParseStateSymbolEnd;
   1263         //
   1264         // prepare CodeBufferSize, FuncOffset, and FuncStart to return
   1265         //
   1266         BufferEnd = LineBuffer + sizeof("; mark_end;") - 1;
   1267         *CodeBufferSize = (UINTN)BufferEnd - (UINTN)BufferStart;
   1268         *FuncOffset = Offset;
   1269         PatchForAsciiStrTokenAfter (LineBuffer, '\n');
   1270         return BufferStart;
   1271       }
   1272 
   1273       //
   1274       // Get function offset
   1275       //
   1276       if ((Offset == (UINTN)-1) &&
   1277           (*LineBuffer == ' ')) {
   1278         FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 2, " ");
   1279         Offset = AsciiXtoi (FieldBuffer);
   1280         PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
   1281       }
   1282 
   1283       //
   1284       // Get next line
   1285       //
   1286       LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
   1287       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
   1288       break;
   1289 
   1290     case EdbEbcCodParseStateSymbolEnd:
   1291       break;
   1292 
   1293     default:
   1294       break;
   1295     }
   1296   }
   1297 
   1298   //
   1299   // no function found
   1300   //
   1301   return NULL;
   1302 }
   1303 
   1304 /**
   1305 
   1306   Load code by symbol.
   1307 
   1308   @param  Name            - Symbol file name
   1309   @param  Buffer          - Symbol file buffer
   1310   @param  BufferSize      - Symbol file buffer size
   1311   @param  CodeBufferSize  - Code buffer size
   1312   @param  FuncOffset      - Code funcion offset
   1313 
   1314   @return CodeBuffer
   1315 
   1316 **/
   1317 CHAR8 *
   1318 EdbLoadCodBySymbol (
   1319   IN CHAR8                       *Name,
   1320   IN VOID                        *Buffer,
   1321   IN UINTN                       BufferSize,
   1322   OUT UINTN                      *CodeBufferSize,
   1323   OUT UINTN                      *FuncOffset
   1324   )
   1325 {
   1326   //
   1327   // COD file format depends on the compiler.
   1328   //
   1329   // It is possible to check the different COD file format in this routine.
   1330   // Now only IEC is supported.
   1331   //
   1332   return EdbLoadCodBySymbolByIec (Name, Buffer, BufferSize, CodeBufferSize, FuncOffset);
   1333 }
   1334 
   1335 /**
   1336 
   1337   Find code from object.
   1338 
   1339   @param  DebuggerPrivate    EBC Debugger private data structure
   1340   @param  Object          - Symbol object
   1341   @param  FileName        - File name
   1342 
   1343 **/
   1344 VOID *
   1345 EdbFindCodeFromObject (
   1346   IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
   1347   IN EFI_DEBUGGER_SYMBOL_OBJECT  *Object,
   1348   IN CHAR16                      *FileName
   1349   )
   1350 {
   1351   UINTN                      EntryIndex;
   1352 
   1353   //
   1354   // Go througn each Entry in this Object
   1355   //
   1356   for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
   1357     //
   1358     // This check is for Function only
   1359     //
   1360     if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
   1361         (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
   1362       continue;
   1363     }
   1364     //
   1365     // Skip match varbss_init function, because they has no source code
   1366     //
   1367     if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
   1368       continue;
   1369     }
   1370     //
   1371     // check the name
   1372     //
   1373     if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
   1374       continue;
   1375     }
   1376     //
   1377     // found it, return source buffer
   1378     //
   1379     if (Object->Entry[EntryIndex].CodBuffer != NULL) {
   1380       return Object->Entry[EntryIndex].SourceBuffer;
   1381     }
   1382   }
   1383 
   1384   //
   1385   // not found
   1386   //
   1387   return NULL;
   1388 }
   1389 
   1390 /**
   1391 
   1392   Load code.
   1393 
   1394   @param  DebuggerPrivate - EBC Debugger private data structure
   1395   @param  MapFileName     - Symbol file name
   1396   @param  FileName        - Code file name
   1397   @param  BufferSize      - Code file buffer size
   1398   @param  Buffer          - Code file buffer
   1399 
   1400   @retval EFI_SUCCESS - Code loaded successfully
   1401 
   1402 **/
   1403 EFI_STATUS
   1404 EdbLoadCode (
   1405   IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
   1406   IN CHAR16                      *MapFileName,
   1407   IN CHAR16                      *FileName,
   1408   IN UINTN                       BufferSize,
   1409   IN VOID                        *Buffer
   1410   )
   1411 {
   1412   EFI_DEBUGGER_SYMBOL_OBJECT *Object;
   1413   UINTN                      ObjectIndex;
   1414   UINTN                      EntryIndex;
   1415   VOID                       *SourceBuffer;
   1416   EFI_STATUS                 Status;
   1417 
   1418   //
   1419   // Find Symbol
   1420   //
   1421   Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, &ObjectIndex);
   1422   if (Object == NULL) {
   1423     EDBPrint (L"SymbolFile is not loaded!\n");
   1424     return EFI_NOT_FOUND;
   1425   } else {
   1426     //
   1427     // Check duplicated File
   1428     //
   1429     SourceBuffer = EdbFindCodeFromObject (DebuggerPrivate, Object, FileName);
   1430     if (SourceBuffer != NULL) {
   1431       //
   1432       // unnload duplicated code
   1433       //
   1434       Status = EdbUnloadCode (DebuggerPrivate, MapFileName, FileName, &SourceBuffer);
   1435       if (EFI_ERROR(Status)) {
   1436         DEBUG ((DEBUG_ERROR, "Unload Duplicated Code File Error!\n"));
   1437         return Status;
   1438       }
   1439       Status = EdbDeleteCodeBuffer (DebuggerPrivate, MapFileName, FileName, SourceBuffer);
   1440       if (EFI_ERROR(Status)) {
   1441         DEBUG ((DEBUG_ERROR, "Delete Duplicated Code File Error!\n"));
   1442         return Status;
   1443       }
   1444     }
   1445   }
   1446 
   1447   //
   1448   // Go through each SymbolEntry
   1449   //
   1450   for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
   1451     //
   1452     // load symbol for function only
   1453     //
   1454     if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
   1455         (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
   1456       continue;
   1457     }
   1458     //
   1459     // skip varbss_init
   1460     //
   1461     if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
   1462       continue;
   1463     }
   1464     //
   1465     // Check the name
   1466     //
   1467     if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
   1468       continue;
   1469     }
   1470     //
   1471     // load code for this symbol
   1472     //
   1473     Object->Entry[EntryIndex].CodBuffer = EdbLoadCodBySymbol (
   1474                                             Object->Entry[EntryIndex].Name,
   1475                                             Buffer,
   1476                                             BufferSize,
   1477                                             &Object->Entry[EntryIndex].CodBufferSize,
   1478                                             &Object->Entry[EntryIndex].FuncOffsetBase
   1479                                             );
   1480     if (Object->Entry[EntryIndex].CodBuffer != NULL) {
   1481       Object->Entry[EntryIndex].SourceBuffer = Buffer;
   1482     }
   1483   }
   1484 
   1485   //
   1486   // patch end '\0' for each code buffer
   1487   //
   1488   for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
   1489     if (Object->Entry[EntryIndex].CodBuffer != NULL) {
   1490       *((UINT8 *)Object->Entry[EntryIndex].CodBuffer + Object->Entry[EntryIndex].CodBufferSize) = 0;
   1491       DEBUG ((DEBUG_ERROR, "  CodeSymbol: %a, FuncOffset: 0x05%x\n", Object->Entry[EntryIndex].Name, Object->Entry[EntryIndex].FuncOffsetBase));
   1492 //      DEBUG ((DEBUG_ERROR, "  [CODE]:\n%a\n", Object->Entry[EntryIndex].CodBuffer));
   1493     }
   1494   }
   1495 
   1496   //
   1497   // Done
   1498   //
   1499   return EFI_SUCCESS;
   1500 }
   1501 
   1502 /**
   1503 
   1504   Unload code.
   1505 
   1506   @param  DebuggerPrivate - EBC Debugger private data structure
   1507   @param  MapFileName     - Symbol file name
   1508   @param  FileName        - Code file name
   1509   @param  Buffer          - Code file buffer
   1510 
   1511   @retval EFI_SUCCESS - Code unloaded successfully
   1512 
   1513 **/
   1514 EFI_STATUS
   1515 EdbUnloadCode (
   1516   IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
   1517   IN CHAR16                      *MapFileName,
   1518   IN CHAR16                      *FileName,
   1519   OUT VOID                       **Buffer
   1520   )
   1521 {
   1522   EFI_DEBUGGER_SYMBOL_OBJECT *Object;
   1523   UINTN                      ObjectIndex;
   1524   UINTN                      EntryIndex;
   1525 
   1526   //
   1527   // Find Symbol
   1528   //
   1529   Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, &ObjectIndex);
   1530   if (Object == NULL) {
   1531     EDBPrint (L"SymbolFile is not loaded!\n");
   1532     return EFI_NOT_FOUND;
   1533   }
   1534 
   1535   //
   1536   // Find code
   1537   //
   1538   *Buffer = EdbFindCodeFromObject (DebuggerPrivate, Object, FileName);
   1539   if (*Buffer == NULL) {
   1540     EDBPrint (L"CodeFile is not loaded!\n");
   1541     return EFI_NOT_FOUND;
   1542   }
   1543 
   1544   //
   1545   // go through each entry
   1546   //
   1547   for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
   1548     if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
   1549         (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
   1550       continue;
   1551     }
   1552     if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
   1553       continue;
   1554     }
   1555     if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
   1556       continue;
   1557     }
   1558     //
   1559     // clean up the buffer
   1560     //
   1561     Object->Entry[EntryIndex].CodBuffer = NULL;
   1562     Object->Entry[EntryIndex].CodBufferSize = 0;
   1563     Object->Entry[EntryIndex].FuncOffsetBase = 0;
   1564     Object->Entry[EntryIndex].SourceBuffer = NULL;
   1565   }
   1566 
   1567   //
   1568   // Done
   1569   //
   1570   return EFI_SUCCESS;
   1571 }
   1572 
   1573 /**
   1574 
   1575   Add code buffer.
   1576 
   1577   @param  DebuggerPrivate - EBC Debugger private data structure
   1578   @param  MapFileName     - Symbol file name
   1579   @param  CodeFileName    - Code file name
   1580   @param  SourceBufferSize- Code buffer size
   1581   @param  SourceBuffer    - Code buffer
   1582 
   1583   @retval EFI_SUCCESS - CodeBuffer added successfully
   1584 
   1585 **/
   1586 EFI_STATUS
   1587 EdbAddCodeBuffer (
   1588   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
   1589   IN     CHAR16                    *MapFileName,
   1590   IN     CHAR16                    *CodeFileName,
   1591   IN     UINTN                     SourceBufferSize,
   1592   IN     VOID                      *SourceBuffer
   1593   )
   1594 {
   1595   UINTN                      Index;
   1596   EFI_DEBUGGER_SYMBOL_OBJECT *Object;
   1597 
   1598   //
   1599   // Find Symbol
   1600   //
   1601   Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, NULL);
   1602   if (Object == NULL) {
   1603     EDBPrint (L"SymbolFile is not loaded!\n");
   1604     return EFI_NOT_FOUND;
   1605   }
   1606 
   1607   //
   1608   // Add it to last entry
   1609   //
   1610   for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
   1611     ;
   1612   }
   1613   Object->SourceBuffer[Index] = SourceBuffer;
   1614 
   1615   return EFI_SUCCESS;
   1616 }
   1617 
   1618 /**
   1619 
   1620   Delete code buffer.
   1621 
   1622   @param  DebuggerPrivate - EBC Debugger private data structure
   1623   @param  MapFileName     - Symbol file name
   1624   @param  CodeFileName    - Code file name
   1625   @param  SourceBuffer    - Code buffer
   1626 
   1627   @retval EFI_SUCCESS - CodeBuffer deleted successfully
   1628 
   1629 **/
   1630 EFI_STATUS
   1631 EdbDeleteCodeBuffer (
   1632   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
   1633   IN     CHAR16                    *MapFileName,
   1634   IN     CHAR16                    *CodeFileName,
   1635   IN     VOID                      *SourceBuffer
   1636   )
   1637 {
   1638   UINTN                      Index;
   1639   EFI_DEBUGGER_SYMBOL_OBJECT *Object;
   1640 
   1641   //
   1642   // Find Symbol
   1643   //
   1644   Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, NULL);
   1645   if (Object == NULL) {
   1646     EDBPrint (L"SymbolFile is not loaded!\n");
   1647     return EFI_NOT_FOUND;
   1648   }
   1649 
   1650   for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
   1651     //
   1652     // free the buffer if match
   1653     //
   1654     if (Object->SourceBuffer[Index] == SourceBuffer) {
   1655       gBS->FreePool (SourceBuffer);
   1656       break;
   1657     }
   1658   }
   1659 
   1660   if (Object->SourceBuffer[Index] == NULL) {
   1661     //
   1662     // not return NOT_FOUND
   1663     //
   1664     return EFI_SUCCESS;
   1665   }
   1666 
   1667   //
   1668   // remove the entry
   1669   //
   1670   Object->SourceBuffer[Index] = NULL;
   1671   for (Index = Index + 1; Object->SourceBuffer[Index] != NULL; Index++) {
   1672     Object->SourceBuffer[Index - 1] = Object->SourceBuffer[Index];
   1673   }
   1674   Object->SourceBuffer[Index - 1] = NULL;
   1675 
   1676   return EFI_SUCCESS;
   1677 }
   1678 
   1679 /**
   1680 
   1681   Find the symbol string according to address.
   1682 
   1683   @param  Address         - Symbol address
   1684 
   1685   @return Symbol string
   1686 
   1687 **/
   1688 CHAR8 *
   1689 FindSymbolStr (
   1690   IN UINTN Address
   1691   )
   1692 {
   1693   UINTN                       ObjectIndex;
   1694   EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
   1695   UINTN                       EntryIndex;
   1696   EFI_DEBUGGER_SYMBOL_ENTRY   *Entry;
   1697 
   1698   //
   1699   // need we display symbol
   1700   //
   1701   if (!mDebuggerPrivate.DebuggerSymbolContext.DisplaySymbol) {
   1702     return NULL;
   1703   }
   1704 
   1705   //
   1706   // Go through each object and entry
   1707   //
   1708   Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
   1709   for (ObjectIndex = 0; ObjectIndex < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
   1710     Entry = Object[ObjectIndex].Entry;
   1711     for (EntryIndex = 0; EntryIndex < Object[ObjectIndex].EntryCount; EntryIndex++) {
   1712       //
   1713       // if Address match, return Name
   1714       //
   1715       if (Address == (Entry[EntryIndex].Rva + Object[ObjectIndex].BaseAddress)) {
   1716         return Entry[EntryIndex].Name;
   1717       }
   1718     }
   1719   }
   1720 
   1721   //
   1722   // not found
   1723   //
   1724   return NULL;
   1725 }
   1726 
   1727 /**
   1728 
   1729   Get line number and offset from this line in code file.
   1730 
   1731   @param  Line            - Line buffer in code file
   1732   @param  Offset          - Offset to functin entry
   1733 
   1734   @return Line number
   1735 
   1736 **/
   1737 UINTN
   1738 EdbGetLineNumberAndOffsetFromThisLine (
   1739   IN VOID     *Line,
   1740   OUT UINTN   *Offset
   1741   )
   1742 {
   1743   UINTN  LineNumber;
   1744   CHAR8  *LineBuffer;
   1745   CHAR8  *FieldBuffer;
   1746 
   1747   LineNumber = (UINTN)-1;
   1748   LineBuffer = Line;
   1749   *Offset = (UINTN)-1;
   1750 
   1751   while (LineBuffer != NULL) {
   1752     //
   1753     // Check candidate
   1754     //
   1755     if (*LineBuffer != ' ') {
   1756       return (UINTN)-1;
   1757     }
   1758 
   1759     //
   1760     // Get Offset
   1761     //
   1762     if (*(LineBuffer + 2) != ' ') {
   1763       if (*Offset == (UINTN)-1) {
   1764         FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 2, " ");
   1765         *Offset = AsciiXtoi (FieldBuffer);
   1766         PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
   1767       }
   1768     }
   1769 
   1770     //
   1771     // 1. assembly instruction
   1772     //
   1773     FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, ":");
   1774     //
   1775     // 2. file path
   1776     //
   1777     FieldBuffer = AsciiStrGetNextTokenField (":");
   1778     PatchForAsciiStrTokenBefore (FieldBuffer, ':');
   1779     if (FieldBuffer == NULL) {
   1780       //
   1781       // candidate found
   1782       //
   1783       LineNumber = 0;
   1784       LineBuffer = AsciiStrGetNextTokenLine ("\n");
   1785       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
   1786       continue;
   1787     }
   1788     //
   1789     // 3. line number
   1790     //
   1791     FieldBuffer = AsciiStrGetNextTokenField (":");
   1792     PatchForAsciiStrTokenBefore (FieldBuffer, ':');
   1793     if (FieldBuffer == NULL) {
   1794       //
   1795       // impossible, TBD?
   1796       //
   1797       LineBuffer = AsciiStrGetNextTokenLine ("\n");
   1798       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
   1799       continue;
   1800     }
   1801 
   1802     LineNumber = AsciiAtoi (FieldBuffer);
   1803     //
   1804     // Not patch after
   1805     //
   1806 
   1807     return LineNumber;
   1808   }
   1809 
   1810   return (UINTN)-1;
   1811 }
   1812 
   1813 typedef enum {
   1814   EdbEbcLineSearchTypeAny,
   1815   EdbEbcLineSearchTypeFirst,
   1816   EdbEbcLineSearchTypeLast,
   1817   EdbEbcLineSearchTypeMax,
   1818 } EDB_EBC_LINE_SEARCH_TYPE;
   1819 
   1820 /**
   1821 
   1822   Get line number from this code file.
   1823 
   1824   @param  Entry           - Symbol entry
   1825   @param  FuncOffset      - Offset to functin entry
   1826   @param  SearchType      - Search type for the code
   1827 
   1828   @return Line number
   1829 
   1830 **/
   1831 UINTN
   1832 EdbGetLineNumberFromCode (
   1833   IN EFI_DEBUGGER_SYMBOL_ENTRY  *Entry,
   1834   IN UINTN                      FuncOffset,
   1835   IN EDB_EBC_LINE_SEARCH_TYPE   SearchType
   1836   )
   1837 {
   1838   CHAR8  *LineBuffer;
   1839   UINTN  LineNumber;
   1840   UINTN  Offset;
   1841   UINTN  CandidateLineNumber;
   1842   UINTN  CandidateOffset;
   1843 
   1844   if (SearchType < 0 || SearchType >= EdbEbcLineSearchTypeMax) {
   1845     return (UINTN)-1;
   1846   }
   1847 
   1848   LineNumber = (UINTN)-1;
   1849   CandidateLineNumber = (UINTN)-1;
   1850   CandidateOffset = (UINTN)-1;
   1851   LineBuffer = AsciiStrGetNewTokenLine (Entry->CodBuffer, "\n");
   1852   while (LineBuffer != NULL) {
   1853     if (*LineBuffer != ' ') {
   1854       LineBuffer = AsciiStrGetNextTokenLine ("\n");
   1855       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
   1856       continue;
   1857     }
   1858 
   1859     //
   1860     // Get Info
   1861     //
   1862     LineNumber = EdbGetLineNumberAndOffsetFromThisLine (LineBuffer, &Offset);
   1863 
   1864     //
   1865     // Check offset
   1866     //
   1867     if (Offset != FuncOffset) {
   1868       //
   1869       // Check last offset match
   1870       //
   1871       if (CandidateOffset == FuncOffset) {
   1872         if (SearchType == EdbEbcLineSearchTypeLast) {
   1873           PatchForAsciiStrTokenAfter (LineBuffer, '\n');
   1874           if (CandidateLineNumber != LineNumber) {
   1875             return CandidateLineNumber;
   1876           } else {
   1877             return (UINTN)-1;
   1878           }
   1879         } else {
   1880           //
   1881           // impossible, TBD?
   1882           //
   1883         }
   1884       }
   1885 
   1886       LineBuffer = AsciiStrGetNextTokenLine ("\n");
   1887       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
   1888       CandidateLineNumber = LineNumber;
   1889       continue;
   1890     }
   1891 
   1892     //
   1893     // Offset match, more check
   1894     //
   1895     if (SearchType == EdbEbcLineSearchTypeAny) {
   1896       PatchForAsciiStrTokenAfter (LineBuffer, '\n');
   1897       return LineNumber;
   1898     }
   1899 
   1900     if (SearchType == EdbEbcLineSearchTypeFirst) {
   1901       //
   1902       // Check last line
   1903       //
   1904       PatchForAsciiStrTokenAfter (LineBuffer, '\n');
   1905       if (CandidateLineNumber != LineNumber) {
   1906         return LineNumber;
   1907       } else {
   1908         return (UINTN)-1;
   1909       }
   1910     }
   1911 
   1912     CandidateLineNumber = LineNumber;
   1913     CandidateOffset = Offset;
   1914 
   1915     LineBuffer = AsciiStrGetNextTokenLine ("\n");
   1916     PatchForAsciiStrTokenBefore (LineBuffer, '\n');
   1917   }
   1918 
   1919   //
   1920   // Check last offset match
   1921   //
   1922   if (CandidateOffset == FuncOffset) {
   1923     if (SearchType == EdbEbcLineSearchTypeLast) {
   1924       return CandidateLineNumber;
   1925     }
   1926   }
   1927 
   1928   return (UINTN)-1;
   1929 }
   1930 
   1931 /**
   1932 
   1933   Get the source string from this code file by line.
   1934 
   1935   @param  Entry           - Symbol entry
   1936   @param  LineNumber      - line number
   1937   @param  FuncEnd         - Function end
   1938 
   1939   @return Funtion start
   1940 
   1941 **/
   1942 VOID *
   1943 EdbGetSourceStrFromCodeByLine (
   1944   IN EFI_DEBUGGER_SYMBOL_ENTRY  *Entry,
   1945   IN UINTN                      LineNumber,
   1946   IN VOID                       **FuncEnd
   1947   )
   1948 {
   1949   CHAR8  *LineBuffer;
   1950   CHAR8  *FieldBuffer;
   1951   VOID   *FuncStart;
   1952   UINTN  Number;
   1953 
   1954   FuncStart = NULL;
   1955   LineBuffer = AsciiStrGetNewTokenLine (Entry->CodBuffer, "\n");
   1956   while (LineBuffer != NULL) {
   1957     if (*LineBuffer != ';') {
   1958       if (FuncStart != NULL) {
   1959         //
   1960         // Over
   1961         //
   1962         *FuncEnd = LineBuffer - 1;
   1963         PatchForAsciiStrTokenAfter (LineBuffer, '\n');
   1964         return FuncStart;
   1965       }
   1966       LineBuffer = AsciiStrGetNextTokenLine ("\n");
   1967       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
   1968       continue;
   1969     }
   1970 
   1971     //
   1972     // Check LineNumber
   1973     //
   1974     FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 1, " ");
   1975     Number = AsciiAtoi (FieldBuffer);
   1976     PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
   1977     if (Number != LineNumber) {
   1978       LineBuffer = AsciiStrGetNextTokenLine ("\n");
   1979       PatchForAsciiStrTokenBefore (LineBuffer, '\n');
   1980       continue;
   1981     }
   1982 
   1983     //
   1984     // Line match, get line number
   1985     //
   1986     if (FuncStart == NULL) {
   1987       FuncStart = LineBuffer;
   1988     }
   1989 
   1990     LineBuffer = AsciiStrGetNextTokenLine ("\n");
   1991     PatchForAsciiStrTokenBefore (LineBuffer, '\n');
   1992   }
   1993 
   1994   return NULL;
   1995 }
   1996 
   1997 /**
   1998 
   1999   Get source string from this code file.
   2000 
   2001   @param  Entry           - Symbol entry
   2002   @param  FuncOffset      - Offset to functin entry
   2003   @param  FuncEnd         - Function end
   2004 
   2005   @retval Funtion start
   2006 
   2007 **/
   2008 VOID *
   2009 EdbGetSourceStrFromCode (
   2010   IN EFI_DEBUGGER_SYMBOL_ENTRY  *Entry,
   2011   IN UINTN                      FuncOffset,
   2012   IN VOID                       **FuncEnd
   2013   )
   2014 {
   2015   UINTN  LineNumber;
   2016 
   2017   //
   2018   // Only search the last line, then display
   2019   //
   2020   LineNumber = EdbGetLineNumberFromCode (Entry, FuncOffset, EdbEbcLineSearchTypeLast);
   2021   if (LineNumber == (UINTN)-1) {
   2022     return NULL;
   2023   }
   2024 
   2025   return EdbGetSourceStrFromCodeByLine (Entry, LineNumber, FuncEnd);
   2026 }
   2027 
   2028 /**
   2029 
   2030   Print source.
   2031 
   2032   @param  Address         - Instruction address
   2033   @param  IsPrint         - Whether need to print
   2034 
   2035   @retval 1 - find the source
   2036   @retval 0 - not find the source
   2037 
   2038 **/
   2039 UINTN
   2040 EdbPrintSource (
   2041   IN UINTN     Address,
   2042   IN BOOLEAN   IsPrint
   2043   )
   2044 {
   2045   UINTN                      SymbolAddress;
   2046   EFI_DEBUGGER_SYMBOL_OBJECT *RetObject;
   2047   EFI_DEBUGGER_SYMBOL_ENTRY  *RetEntry;
   2048   UINTN                      FuncOffset;
   2049   UINT8                      *FuncStart;
   2050   UINT8                      *FuncEnd;
   2051   UINT8                      *FuncIndex;
   2052   CHAR8                      Buffer[EFI_DEBUG_MAX_PRINT_BUFFER];
   2053   UINTN                      BufferSize;
   2054 
   2055   //
   2056   // need we display symbol
   2057   //
   2058   if (!mDebuggerPrivate.DebuggerSymbolContext.DisplaySymbol) {
   2059     return 0 ;
   2060   }
   2061 
   2062   //
   2063   // find the symbol address
   2064   //
   2065   SymbolAddress = EbdFindSymbolAddress (
   2066                     Address,
   2067                     EdbMatchSymbolTypeLowerAddress,
   2068                     &RetObject,
   2069                     &RetEntry
   2070                     );
   2071   if (SymbolAddress == 0) {
   2072     return 0 ;
   2073   }
   2074 
   2075   FuncOffset = Address - SymbolAddress + RetEntry->FuncOffsetBase;
   2076 
   2077   //
   2078   // Get Func String
   2079   //
   2080   FuncStart = EdbGetSourceStrFromCode (RetEntry, FuncOffset, (VOID**) &FuncEnd);
   2081   if (FuncStart == NULL) {
   2082     return 0 ;
   2083   }
   2084 
   2085   //
   2086   // check whether need to real print
   2087   //
   2088   if (!IsPrint) {
   2089     return 1;
   2090   }
   2091 
   2092   *(UINT8 *)FuncEnd = 0;
   2093 
   2094   //
   2095   // seperate buffer by \n, so that \r can be added.
   2096   //
   2097   FuncIndex = FuncStart;
   2098   while (*FuncIndex != 0) {
   2099     if (*FuncIndex == '\n') {
   2100       if ((FuncIndex - FuncStart) < (EFI_DEBUG_MAX_PRINT_BUFFER - 3)) {
   2101         BufferSize = FuncIndex - FuncStart;
   2102       } else {
   2103         BufferSize = EFI_DEBUG_MAX_PRINT_BUFFER - 3;
   2104       }
   2105       if (BufferSize != 0) {
   2106         CopyMem (Buffer, FuncStart, BufferSize);
   2107       }
   2108       Buffer[BufferSize] = 0;
   2109       EDBPrint (L"%a\n", Buffer);
   2110       FuncStart = FuncIndex + 1;
   2111       FuncIndex = FuncStart;
   2112     } else {
   2113       FuncIndex ++;
   2114     }
   2115   }
   2116 
   2117   //
   2118   // Patch the end
   2119   //
   2120   *(UINT8 *)FuncEnd = '\n';
   2121 
   2122   return 1 ;
   2123 }
   2124 
   2125 /**
   2126 
   2127   Get Mapfile and SymbolName from one symbol format: [MapFileName:]SymbolName.
   2128 
   2129   @param  Symbol          - whole Symbol name
   2130   @param  MapfileName     - the mapfile name in the symbol
   2131   @param  SymbolName      - the symbol name in the symbol
   2132 
   2133 **/
   2134 VOID
   2135 GetMapfileAndSymbol (
   2136   IN CHAR16   *Symbol,
   2137   OUT CHAR16  **MapfileName,
   2138   OUT CHAR16  **SymbolName
   2139   )
   2140 {
   2141   CHAR16  *Ch;
   2142 
   2143   *MapfileName = NULL;
   2144   *SymbolName = Symbol;
   2145 
   2146   for (Ch = Symbol; *Ch != 0; Ch++) {
   2147     //
   2148     // Find split char
   2149     //
   2150     if (*Ch == L':') {
   2151       *MapfileName = Symbol;
   2152       *Ch = 0;
   2153       *SymbolName = Ch + 1;
   2154       break;
   2155     }
   2156   }
   2157 
   2158   return ;
   2159 }
   2160 
   2161 /**
   2162 
   2163   Convert a symbol to an address.
   2164 
   2165   @param  Symbol          - Symbol name
   2166   @param  Address         - Symbol address
   2167 
   2168   @retval EFI_SUCCESS    - symbol found and address returned.
   2169   @retval EFI_NOT_FOUND  - symbol not found
   2170   @retval EFI_NO_MAPPING - duplicated symbol not found
   2171 
   2172 **/
   2173 EFI_STATUS
   2174 Symboltoi (
   2175   IN CHAR16   *Symbol,
   2176   OUT UINTN   *Address
   2177   )
   2178 {
   2179   UINTN                       ObjectIndex;
   2180   EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
   2181   UINTN                       EntryIndex;
   2182   EFI_DEBUGGER_SYMBOL_ENTRY   *Entry;
   2183   CHAR16                      *SymbolName;
   2184   CHAR16                      *MapfileName;
   2185 
   2186   //
   2187   // Split one symbol to mapfile name and symbol name
   2188   //
   2189   GetMapfileAndSymbol (Symbol, &MapfileName, &SymbolName);
   2190 
   2191   *Address = 0;
   2192   //
   2193   // Go through each object
   2194   //
   2195   Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
   2196   for (ObjectIndex = 0; ObjectIndex < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
   2197     //
   2198     // Check MapfileName
   2199     //
   2200     if ((MapfileName != NULL) && (StriCmp (Object[ObjectIndex].Name, MapfileName) != 0)) {
   2201       continue;
   2202     }
   2203     //
   2204     // Go through each entry
   2205     //
   2206     Entry = Object[ObjectIndex].Entry;
   2207     for (EntryIndex = 0; EntryIndex < Object[ObjectIndex].EntryCount; EntryIndex++) {
   2208       //
   2209       // Check SymbolName (case sensitive)
   2210       //
   2211       if (StrCmpUnicodeAndAscii (SymbolName, Entry[EntryIndex].Name) == 0) {
   2212         if ((*Address != 0) && (MapfileName == NULL)) {
   2213           //
   2214           // Find the duplicated symbol
   2215           //
   2216           EDBPrint (L"Duplicated Symbol found!\n");
   2217           return EFI_NO_MAPPING;
   2218         } else {
   2219           //
   2220           // record Address
   2221           //
   2222           *Address = (Entry[EntryIndex].Rva + Object[ObjectIndex].BaseAddress);
   2223         }
   2224       }
   2225     }
   2226   }
   2227 
   2228   if (*Address == 0) {
   2229     //
   2230     // Not found
   2231     //
   2232     return EFI_NOT_FOUND;
   2233   }
   2234 
   2235   return EFI_SUCCESS;
   2236 }
   2237