mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-11-04 01:03:23 +00:00 
			
		
		
		
	REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			2286 lines
		
	
	
		
			59 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2286 lines
		
	
	
		
			59 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
 | 
						|
Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "Edb.h"
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Load single symbol entry.
 | 
						|
 | 
						|
  @param  Object          - Symbol file object
 | 
						|
  @param  Name            - Symbol name
 | 
						|
  @param  ObjName         - Object name
 | 
						|
  @param  Address         - Symbol address
 | 
						|
  @param  Type            - Symbol type
 | 
						|
 | 
						|
  @retval EFI_SUCCESS - add single symbol entry successfully
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EdbLoadSymbolSingleEntry (
 | 
						|
  IN EFI_DEBUGGER_SYMBOL_OBJECT  *Object,
 | 
						|
  IN CHAR8                       *Name,
 | 
						|
  IN CHAR8                       *ObjName,
 | 
						|
  IN UINTN                       Address,
 | 
						|
  IN EFI_DEBUGGER_SYMBOL_TYPE    Type
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_DEBUGGER_SYMBOL_ENTRY  *Entry;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check Count VS MaxCount
 | 
						|
  //
 | 
						|
  if (Object->EntryCount >= Object->MaxEntryCount) {
 | 
						|
    //
 | 
						|
    // reallocate (for codebuffer too)
 | 
						|
    // TBD
 | 
						|
    //
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Entry = &Object->Entry[Object->EntryCount];
 | 
						|
 | 
						|
  //
 | 
						|
  // Print Debug info
 | 
						|
  //
 | 
						|
  if (sizeof (UINTN) == sizeof (UINT64)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "  Symbol: %a, Address: 0x%016lx (%d)\n", Name, (UINT64)Address, (UINTN)Type));
 | 
						|
  } else {
 | 
						|
    DEBUG ((DEBUG_ERROR, "  Symbol: %a, Address: 0x%08x (%d)\n", Name, Address, (UINTN)Type));
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill the entry - name, RVA, type
 | 
						|
  //
 | 
						|
  AsciiStrnCpyS (Entry->Name, sizeof (Entry->Name), Name, sizeof (Entry->Name) - 1);
 | 
						|
  if (ObjName != NULL) {
 | 
						|
    AsciiStrnCpyS (Entry->ObjName, sizeof (Entry->ObjName), ObjName, sizeof (Entry->ObjName) - 1);
 | 
						|
  }
 | 
						|
 | 
						|
  Entry->Rva  = Address % EFI_DEBUGGER_DEFAULT_LINK_IMAGEBASE;
 | 
						|
  Entry->Type = Type;
 | 
						|
 | 
						|
  //
 | 
						|
  // Increase Count
 | 
						|
  //
 | 
						|
  Object->EntryCount++;
 | 
						|
 | 
						|
  //
 | 
						|
  // Done
 | 
						|
  //
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
typedef enum {
 | 
						|
  EdbEbcMapParseStateUninitialized,
 | 
						|
  EdbEbcMapParseStateSymbolStart,
 | 
						|
  EdbEbcMapParseStateSeHandlerSymbol,
 | 
						|
  EdbEbcMapParseStateFunctionSymbol,
 | 
						|
  EdbEbcMapParseStateVarbssInitSymbol,
 | 
						|
  EdbEbcMapParseStateCrtSymbol,
 | 
						|
  EdbEbcMapParseStateVariableSymbol,
 | 
						|
  EdbEbcMapParseStateStaticFunctionSymbol,
 | 
						|
  EdbEbcMapParseStateMax,
 | 
						|
} EDB_EBC_MAP_PARSE_STATE;
 | 
						|
 | 
						|
typedef enum {
 | 
						|
  EdbEbcSymbolParseStateUninitialized,
 | 
						|
  EdbEbcSymbolParseStateReadyForName,
 | 
						|
  EdbEbcSymbolParseStateReadyForRVA,
 | 
						|
  EdbEbcSymbolParseStateReadyForType,
 | 
						|
  EdbEbcSymbolParseStateReadyForObject,
 | 
						|
  EdbEbcSymbolParseStateMax,
 | 
						|
} EDB_EBC_SYMBOL_PARSE_STATE;
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  The following code depends on the MAP file generated by IEC compiler (actually Microsoft linker).
 | 
						|
 | 
						|
  Sample as follows: EbcTest.map
 | 
						|
===============================================================================
 | 
						|
  EbcTest
 | 
						|
 | 
						|
 Timestamp is 45b02718 (Fri Jan 19 10:04:08 2007)
 | 
						|
 | 
						|
 Preferred load address is 10000000
 | 
						|
 | 
						|
 Start         Length     Name                   Class
 | 
						|
 0001:00000000 00000370H .text                   CODE
 | 
						|
 0002:00000000 00000030H _VARBSS_INIT            CODE
 | 
						|
 0003:00000000 00000004H .CRT$TSA                DATA
 | 
						|
 0003:00000004 00000004H .CRT$TSC                DATA
 | 
						|
 0003:00000008 00000004H .CRT$X                  DATA
 | 
						|
 0003:0000000c 00000008H .CRT$XCU                DATA
 | 
						|
 0003:00000014 00000004H .CRT$Z                  DATA
 | 
						|
 0003:00000020 0000001cH .rdata                  DATA
 | 
						|
 0003:0000003c 00000000H .edata                  DATA
 | 
						|
 0003:0000003c 00000056H .rdata$debug            DATA
 | 
						|
 0004:00000000 00000070H .data                   DATA
 | 
						|
 0004:00000070 00000020H .bss                    DATA
 | 
						|
 | 
						|
  Address         Publics by Value              Rva+Base     Lib:Object
 | 
						|
 | 
						|
 0000:00000000       ___safe_se_handler_table   00000000     <absolute>
 | 
						|
 0000:00000000       ___safe_se_handler_count   00000000     <absolute>
 | 
						|
 0001:00000042       TestSubRoutine             10000442 f   EbcTest.obj
 | 
						|
 0001:0000011a       EfiMain                    1000051a f   EbcTest.obj
 | 
						|
 0001:00000200       TestSubRoutineSub          10000600 f   EbcTestSub.obj
 | 
						|
 0001:00000220       EfiStart                   10000620 f   EbcLib:EbcLib.obj
 | 
						|
 0002:00000000       varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b02717 10000800 f   EbcTest.obj
 | 
						|
 0002:00000020       varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTestSub$c45af77f3 10000820 f   EbcTestSub.obj
 | 
						|
 0003:00000000       CrtThunkBegin              10000a00     EbcLib:EbcLib.obj
 | 
						|
 0003:00000004       CrtThunkEnd                10000a04     EbcLib:EbcLib.obj
 | 
						|
 0003:00000008       CrtBegin                   10000a08     EbcLib:EbcLib.obj
 | 
						|
 0003:00000014       CrtEnd                     10000a14     EbcLib:EbcLib.obj
 | 
						|
 0004:00000070       TestStr                    10000c70     EbcTest.obj
 | 
						|
 0004:00000078       TestVariable1              10000c78     EbcTest.obj
 | 
						|
 0004:00000080       TestSubVariableSub         10000c80     EbcTestSub.obj
 | 
						|
 | 
						|
 entry point at        0001:00000220
 | 
						|
 | 
						|
 Static symbols
 | 
						|
 | 
						|
 0001:00000000       TestSubRoutine2            10000400 f   EbcTest.obj
 | 
						|
===============================================================================
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Load symbol entry by Iec.
 | 
						|
 | 
						|
  @param  Object          - Symbol file object
 | 
						|
  @param  BufferSize      - Symbol file buffer size
 | 
						|
  @param  Buffer          - Symbol file buffer
 | 
						|
 | 
						|
  @retval EFI_SUCCESS - add symbol entry successfully
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EdbLoadSymbolEntryByIec (
 | 
						|
  IN EFI_DEBUGGER_SYMBOL_OBJECT  *Object,
 | 
						|
  IN UINTN                       BufferSize,
 | 
						|
  IN VOID                        *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8                       *LineBuffer;
 | 
						|
  CHAR8                       *FieldBuffer;
 | 
						|
  EDB_EBC_MAP_PARSE_STATE     MapParseState;
 | 
						|
  EDB_EBC_SYMBOL_PARSE_STATE  SymbolParseState;
 | 
						|
  CHAR8                       *Name;
 | 
						|
  CHAR8                       *ObjName;
 | 
						|
  UINTN                       Address;
 | 
						|
  EFI_DEBUGGER_SYMBOL_TYPE    Type;
 | 
						|
 | 
						|
  //
 | 
						|
  // Begin to parse the Buffer
 | 
						|
  //
 | 
						|
  LineBuffer    = AsciiStrGetNewTokenLine (Buffer, "\n\r");
 | 
						|
  MapParseState = EdbEbcMapParseStateUninitialized;
 | 
						|
  //
 | 
						|
  // Check each line
 | 
						|
  //
 | 
						|
  while (LineBuffer != NULL) {
 | 
						|
    FieldBuffer      = AsciiStrGetNewTokenField (LineBuffer, " ");
 | 
						|
    SymbolParseState = EdbEbcSymbolParseStateUninitialized;
 | 
						|
    //
 | 
						|
    // Init entry value
 | 
						|
    //
 | 
						|
    Name    = NULL;
 | 
						|
    ObjName = NULL;
 | 
						|
    Address = 0;
 | 
						|
    Type    = EfiDebuggerSymbolTypeMax;
 | 
						|
    //
 | 
						|
    // Check each field
 | 
						|
    //
 | 
						|
    while (FieldBuffer != NULL) {
 | 
						|
      if (AsciiStrCmp (FieldBuffer, "") == 0) {
 | 
						|
        FieldBuffer = AsciiStrGetNextTokenField (" ");
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // check "Address"
 | 
						|
      //
 | 
						|
      if (AsciiStrCmp (FieldBuffer, "Address") == 0) {
 | 
						|
        MapParseState = EdbEbcMapParseStateSymbolStart;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // check "Static"
 | 
						|
      //
 | 
						|
      if (AsciiStrCmp (FieldBuffer, "Static") == 0) {
 | 
						|
        MapParseState = EdbEbcMapParseStateStaticFunctionSymbol;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      if (MapParseState == EdbEbcMapParseStateUninitialized) {
 | 
						|
        //
 | 
						|
        // Do not parse anything until get "Address" or "Static"
 | 
						|
        //
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      if (AsciiStrCmp (FieldBuffer, "entry") == 0) {
 | 
						|
        //
 | 
						|
        // Skip entry point
 | 
						|
        //
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Now we start to parse this line for Name, Address, and Object
 | 
						|
      //
 | 
						|
      switch (SymbolParseState) {
 | 
						|
        case EdbEbcSymbolParseStateUninitialized:
 | 
						|
          //
 | 
						|
          // Get the Address
 | 
						|
          //
 | 
						|
          SymbolParseState = EdbEbcSymbolParseStateReadyForName;
 | 
						|
          break;
 | 
						|
        case EdbEbcSymbolParseStateReadyForName:
 | 
						|
          //
 | 
						|
          // Get the Name
 | 
						|
          //
 | 
						|
          if (AsciiStrnCmp (FieldBuffer, "___safe_se_handler", AsciiStrLen ("___safe_se_handler")) == 0) {
 | 
						|
            //
 | 
						|
            // skip SeHandler
 | 
						|
            //
 | 
						|
            MapParseState = EdbEbcMapParseStateSeHandlerSymbol;
 | 
						|
            goto ExitFieldParse;
 | 
						|
          } else if (AsciiStrnCmp (FieldBuffer, "varbss_init", AsciiStrLen ("varbss_init")) == 0) {
 | 
						|
            //
 | 
						|
            // check VarbssInit
 | 
						|
            //
 | 
						|
            MapParseState = EdbEbcMapParseStateVarbssInitSymbol;
 | 
						|
            //          goto ExitFieldParse;
 | 
						|
            Name             = FieldBuffer;
 | 
						|
            SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
 | 
						|
          } else if (AsciiStrnCmp (FieldBuffer, "Crt", AsciiStrLen ("Crt")) == 0) {
 | 
						|
            //
 | 
						|
            // check Crt
 | 
						|
            //
 | 
						|
            MapParseState = EdbEbcMapParseStateCrtSymbol;
 | 
						|
            //          goto ExitFieldParse;
 | 
						|
            Name             = FieldBuffer;
 | 
						|
            SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
 | 
						|
          } else {
 | 
						|
            //
 | 
						|
            // Now, it is normal function
 | 
						|
            //
 | 
						|
            switch (MapParseState) {
 | 
						|
              case EdbEbcMapParseStateSeHandlerSymbol:
 | 
						|
                MapParseState = EdbEbcMapParseStateFunctionSymbol;
 | 
						|
                break;
 | 
						|
              case EdbEbcMapParseStateCrtSymbol:
 | 
						|
                MapParseState = EdbEbcMapParseStateVariableSymbol;
 | 
						|
                break;
 | 
						|
              case EdbEbcMapParseStateFunctionSymbol:
 | 
						|
              case EdbEbcMapParseStateVariableSymbol:
 | 
						|
              case EdbEbcMapParseStateStaticFunctionSymbol:
 | 
						|
                break;
 | 
						|
              default:
 | 
						|
                ASSERT (FALSE);
 | 
						|
                break;
 | 
						|
            }
 | 
						|
 | 
						|
            Name             = FieldBuffer;
 | 
						|
            SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
 | 
						|
          }
 | 
						|
 | 
						|
          break;
 | 
						|
        case EdbEbcSymbolParseStateReadyForRVA:
 | 
						|
          //
 | 
						|
          // Get the RVA
 | 
						|
          //
 | 
						|
          Address          = AsciiXtoi (FieldBuffer);
 | 
						|
          SymbolParseState = EdbEbcSymbolParseStateReadyForType;
 | 
						|
          break;
 | 
						|
        case EdbEbcSymbolParseStateReadyForType:
 | 
						|
          //
 | 
						|
          // Get the Type. This is optional, only for "f".
 | 
						|
          //
 | 
						|
          if (AsciiStrCmp (FieldBuffer, "f") == 0) {
 | 
						|
            SymbolParseState = EdbEbcSymbolParseStateReadyForObject;
 | 
						|
            switch (MapParseState) {
 | 
						|
              case EdbEbcMapParseStateFunctionSymbol:
 | 
						|
              case EdbEbcMapParseStateVarbssInitSymbol:
 | 
						|
                Type = EfiDebuggerSymbolFunction;
 | 
						|
                break;
 | 
						|
              case EdbEbcMapParseStateStaticFunctionSymbol:
 | 
						|
                Type = EfiDebuggerSymbolStaticFunction;
 | 
						|
                break;
 | 
						|
              default:
 | 
						|
                ASSERT (FALSE);
 | 
						|
                break;
 | 
						|
            }
 | 
						|
 | 
						|
            break;
 | 
						|
          }
 | 
						|
 | 
						|
        //
 | 
						|
        // Else it should be Object.
 | 
						|
        // let it bypass here
 | 
						|
        //
 | 
						|
        case EdbEbcSymbolParseStateReadyForObject:
 | 
						|
          switch (Type) {
 | 
						|
            case EfiDebuggerSymbolTypeMax:
 | 
						|
              switch (MapParseState) {
 | 
						|
                case EdbEbcMapParseStateVariableSymbol:
 | 
						|
                case EdbEbcMapParseStateCrtSymbol:
 | 
						|
                  Type = EfiDebuggerSymbolGlobalVariable;
 | 
						|
                  break;
 | 
						|
                case EdbEbcMapParseStateSeHandlerSymbol:
 | 
						|
                  //
 | 
						|
                  // do nothing here
 | 
						|
                  //
 | 
						|
                  break;
 | 
						|
                default:
 | 
						|
                  ASSERT (FALSE);
 | 
						|
                  break;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case EfiDebuggerSymbolFunction:
 | 
						|
            case EfiDebuggerSymbolStaticFunction:
 | 
						|
              break;
 | 
						|
            default:
 | 
						|
              ASSERT (FALSE);
 | 
						|
              break;
 | 
						|
          }
 | 
						|
 | 
						|
          //
 | 
						|
          // Get the Object
 | 
						|
          //
 | 
						|
          ObjName          = FieldBuffer;
 | 
						|
          SymbolParseState = EdbEbcSymbolParseStateUninitialized;
 | 
						|
          break;
 | 
						|
        default:
 | 
						|
          ASSERT (FALSE);
 | 
						|
          break;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Get the next field
 | 
						|
      //
 | 
						|
      FieldBuffer = AsciiStrGetNextTokenField (" ");
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Add the entry if we get everything.
 | 
						|
    //
 | 
						|
    if ((Name != NULL) && (Type != EfiDebuggerSymbolTypeMax)) {
 | 
						|
      EdbLoadSymbolSingleEntry (Object, Name, ObjName, Address, Type);
 | 
						|
    }
 | 
						|
 | 
						|
ExitFieldParse:
 | 
						|
    //
 | 
						|
    // Get the next line
 | 
						|
    //
 | 
						|
    LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Done
 | 
						|
  //
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Load symbol entry.
 | 
						|
 | 
						|
  @param  Object          - Symbol file object
 | 
						|
  @param  BufferSize      - Symbol file buffer size
 | 
						|
  @param  Buffer          - Symbol file buffer
 | 
						|
 | 
						|
  @retval EFI_SUCCESS - add symbol entry successfully
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EdbLoadSymbolEntry (
 | 
						|
  IN EFI_DEBUGGER_SYMBOL_OBJECT  *Object,
 | 
						|
  IN UINTN                       BufferSize,
 | 
						|
  IN VOID                        *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // MAP file format depends on the compiler (actually linker).
 | 
						|
  //
 | 
						|
  // It is possible to check the different MAP file format in this routine.
 | 
						|
  // Now only IEC is supported.
 | 
						|
  //
 | 
						|
  return EdbLoadSymbolEntryByIec (Object, BufferSize, Buffer);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Find symbol file by name.
 | 
						|
 | 
						|
  @param  DebuggerPrivate - EBC Debugger private data structure
 | 
						|
  @param  FileName        - Symbol file name
 | 
						|
  @param  Index           - Symbol file index
 | 
						|
 | 
						|
  @return Object
 | 
						|
 | 
						|
**/
 | 
						|
EFI_DEBUGGER_SYMBOL_OBJECT *
 | 
						|
EdbFindSymbolFile (
 | 
						|
  IN EFI_DEBUGGER_PRIVATE_DATA  *DebuggerPrivate,
 | 
						|
  IN CHAR16                     *FileName,
 | 
						|
  IN OUT UINTN                  *Index OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  ObjectIndex;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check each Object
 | 
						|
  //
 | 
						|
  for (ObjectIndex = 0; ObjectIndex < DebuggerPrivate->DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
 | 
						|
    if (StrCmp (FileName, DebuggerPrivate->DebuggerSymbolContext.Object[ObjectIndex].Name) == 0) {
 | 
						|
      //
 | 
						|
      // Name match, found it
 | 
						|
      //
 | 
						|
      if (Index != NULL) {
 | 
						|
        *Index = ObjectIndex;
 | 
						|
      }
 | 
						|
 | 
						|
      return &DebuggerPrivate->DebuggerSymbolContext.Object[ObjectIndex];
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Not found
 | 
						|
  //
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Find symbol by address.
 | 
						|
 | 
						|
  @param  Address         - Symbol address
 | 
						|
  @param  Type            - Search type
 | 
						|
  @param  RetObject       - Symbol object
 | 
						|
  @param  RetEntry        - Symbol entry
 | 
						|
 | 
						|
  @return Nearest symbol address
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
EbdFindSymbolAddress (
 | 
						|
  IN UINTN                        Address,
 | 
						|
  IN EDB_MATCH_SYMBOL_TYPE        Type,
 | 
						|
  OUT EFI_DEBUGGER_SYMBOL_OBJECT  **RetObject,
 | 
						|
  OUT EFI_DEBUGGER_SYMBOL_ENTRY   **RetEntry
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                       Index;
 | 
						|
  UINTN                       SubIndex;
 | 
						|
  UINTN                       CandidateLowerAddress;
 | 
						|
  UINTN                       CandidateUpperAddress;
 | 
						|
  EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
 | 
						|
  EFI_DEBUGGER_SYMBOL_ENTRY   *Entry;
 | 
						|
  EFI_DEBUGGER_SYMBOL_ENTRY   *LowEntry;
 | 
						|
  EFI_DEBUGGER_SYMBOL_ENTRY   *UpperEntry;
 | 
						|
  EFI_DEBUGGER_SYMBOL_OBJECT  *LowObject;
 | 
						|
  EFI_DEBUGGER_SYMBOL_OBJECT  *UpperObject;
 | 
						|
 | 
						|
  if ((Type < 0) || (Type >= EdbMatchSymbolTypeMax)) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Init
 | 
						|
  //
 | 
						|
  CandidateLowerAddress = 0;
 | 
						|
  CandidateUpperAddress = (UINTN)-1;
 | 
						|
  LowEntry              = NULL;
 | 
						|
  UpperEntry            = NULL;
 | 
						|
  LowObject             = NULL;
 | 
						|
  UpperObject           = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Go through each object
 | 
						|
  //
 | 
						|
  Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
 | 
						|
  for (Index = 0; Index < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; Index++, Object++) {
 | 
						|
    if (Object->EntryCount == 0) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Go through each entry
 | 
						|
    //
 | 
						|
    Entry = Object->Entry;
 | 
						|
    for (SubIndex = 0; SubIndex < Object->EntryCount; SubIndex++, Entry++) {
 | 
						|
      if (Address != Entry->Rva + Object->BaseAddress) {
 | 
						|
        //
 | 
						|
        // Check for nearest address
 | 
						|
        //
 | 
						|
        if (Address > Entry->Rva + Object->BaseAddress) {
 | 
						|
          //
 | 
						|
          // Record it if Current RVA < Address
 | 
						|
          //
 | 
						|
          if (CandidateLowerAddress < Entry->Rva + Object->BaseAddress) {
 | 
						|
            CandidateLowerAddress = Entry->Rva + Object->BaseAddress;
 | 
						|
            LowEntry              = Entry;
 | 
						|
            LowObject             = Object;
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // Record it if Current RVA > Address
 | 
						|
          //
 | 
						|
          if (CandidateUpperAddress > Entry->Rva + Object->BaseAddress) {
 | 
						|
            CandidateUpperAddress = Entry->Rva + Object->BaseAddress;
 | 
						|
            UpperEntry            = Entry;
 | 
						|
            UpperObject           = Object;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // address match, return directly
 | 
						|
      //
 | 
						|
      *RetEntry  = Entry;
 | 
						|
      *RetObject = Object;
 | 
						|
      return Address;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // No Match, provide latest symbol
 | 
						|
  //
 | 
						|
 | 
						|
  if ((Address - CandidateLowerAddress) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE) {
 | 
						|
    //
 | 
						|
    // Check for lower address
 | 
						|
    //
 | 
						|
    if (((Type == EdbMatchSymbolTypeNearestAddress) &&
 | 
						|
         ((CandidateUpperAddress - Address) > (Address - CandidateLowerAddress))) ||
 | 
						|
        (Type == EdbMatchSymbolTypeLowerAddress))
 | 
						|
    {
 | 
						|
      //
 | 
						|
      // return nearest lower address
 | 
						|
      //
 | 
						|
      *RetEntry  = LowEntry;
 | 
						|
      *RetObject = LowObject;
 | 
						|
      return CandidateLowerAddress;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if ((CandidateUpperAddress - Address) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE) {
 | 
						|
    //
 | 
						|
    // Check for upper address
 | 
						|
    //
 | 
						|
    if (((Type == EdbMatchSymbolTypeNearestAddress) &&
 | 
						|
         ((CandidateUpperAddress - Address) < (Address - CandidateLowerAddress))) ||
 | 
						|
        (Type == EdbMatchSymbolTypeUpperAddress))
 | 
						|
    {
 | 
						|
      //
 | 
						|
      // return nearest upper address
 | 
						|
      //
 | 
						|
      *RetEntry  = UpperEntry;
 | 
						|
      *RetObject = UpperObject;
 | 
						|
      return CandidateUpperAddress;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // No match and nearest one, return NULL
 | 
						|
  //
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Unload symbol file by name.
 | 
						|
 | 
						|
  @param  DebuggerPrivate - EBC Debugger private data structure
 | 
						|
  @param  FileName        - Symbol file name
 | 
						|
 | 
						|
  @retval EFI_SUCCESS - unload symbol successfully
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EdbUnloadSymbol (
 | 
						|
  IN EFI_DEBUGGER_PRIVATE_DATA  *DebuggerPrivate,
 | 
						|
  IN CHAR16                     *FileName
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
 | 
						|
  UINTN                       ObjectIndex;
 | 
						|
  UINTN                       Index;
 | 
						|
  EFI_DEBUGGER_SYMBOL_ENTRY   *OldEntry;
 | 
						|
  UINTN                       OldEntryCount;
 | 
						|
  UINTN                       MaxEntryCount;
 | 
						|
  VOID                        **OldSourceBuffer;
 | 
						|
 | 
						|
  //
 | 
						|
  // Find Symbol
 | 
						|
  //
 | 
						|
  Object = EdbFindSymbolFile (DebuggerPrivate, FileName, &ObjectIndex);
 | 
						|
  if (Object == NULL) {
 | 
						|
    EDBPrint (L"SymbolFile is not loaded!\n");
 | 
						|
    return EFI_DEBUG_CONTINUE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Record old data
 | 
						|
  //
 | 
						|
  Object          = DebuggerPrivate->DebuggerSymbolContext.Object;
 | 
						|
  OldEntry        = Object->Entry;
 | 
						|
  OldSourceBuffer = Object->SourceBuffer;
 | 
						|
  MaxEntryCount   = Object->MaxEntryCount;
 | 
						|
  OldEntryCount   = Object->EntryCount;
 | 
						|
 | 
						|
  //
 | 
						|
  // Remove the matched Object
 | 
						|
  //
 | 
						|
  for (Index = ObjectIndex; Index < DebuggerPrivate->DebuggerSymbolContext.ObjectCount - 1; Index++) {
 | 
						|
    CopyMem (&Object[Index], &Object[Index + 1], sizeof (EFI_DEBUGGER_SYMBOL_OBJECT));
 | 
						|
  }
 | 
						|
 | 
						|
  ZeroMem (&Object[Index], sizeof (Object[Index]));
 | 
						|
 | 
						|
  //
 | 
						|
  // Move old data to new place
 | 
						|
  //
 | 
						|
  Object[Index].Entry         = OldEntry;
 | 
						|
  Object[Index].SourceBuffer  = OldSourceBuffer;
 | 
						|
  Object[Index].MaxEntryCount = MaxEntryCount;
 | 
						|
  DebuggerPrivate->DebuggerSymbolContext.ObjectCount--;
 | 
						|
 | 
						|
  //
 | 
						|
  // Clean old entry data
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < OldEntryCount; Index++) {
 | 
						|
    ZeroMem (&OldEntry[Index], sizeof (OldEntry[Index]));
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Free OldSourceBuffer
 | 
						|
  //
 | 
						|
  for (Index = 0; OldSourceBuffer[Index] != NULL; Index++) {
 | 
						|
    gBS->FreePool (OldSourceBuffer[Index]);
 | 
						|
    OldSourceBuffer[Index] = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Load symbol file by name.
 | 
						|
 | 
						|
  @param  DebuggerPrivate - EBC Debugger private data structure
 | 
						|
  @param  FileName        - Symbol file name
 | 
						|
  @param  BufferSize      - Symbol file buffer size
 | 
						|
  @param  Buffer          - Symbol file buffer
 | 
						|
 | 
						|
  @retval EFI_SUCCESS - load symbol successfully
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EdbLoadSymbol (
 | 
						|
  IN EFI_DEBUGGER_PRIVATE_DATA  *DebuggerPrivate,
 | 
						|
  IN CHAR16                     *FileName,
 | 
						|
  IN UINTN                      BufferSize,
 | 
						|
  IN VOID                       *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check duplicated File
 | 
						|
  //
 | 
						|
  Object = EdbFindSymbolFile (DebuggerPrivate, FileName, NULL);
 | 
						|
  if (Object != NULL) {
 | 
						|
    Status = EdbUnloadSymbol (DebuggerPrivate, FileName);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "Unload Duplicated Symbol File Error!\n"));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check Count VS MaxCount
 | 
						|
  //
 | 
						|
  if (DebuggerPrivate->DebuggerSymbolContext.ObjectCount >= DebuggerPrivate->DebuggerSymbolContext.MaxObjectCount) {
 | 
						|
    //
 | 
						|
    // reallocate
 | 
						|
    // TBD
 | 
						|
    //
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Object = &DebuggerPrivate->DebuggerSymbolContext.Object[DebuggerPrivate->DebuggerSymbolContext.ObjectCount];
 | 
						|
 | 
						|
  //
 | 
						|
  // Init Object
 | 
						|
  //
 | 
						|
  Object->EntryCount    = 0;
 | 
						|
  Object->MaxEntryCount = EFI_DEBUGGER_SYMBOL_ENTRY_MAX;
 | 
						|
 | 
						|
  //
 | 
						|
  // Load SymbolEntry
 | 
						|
  //
 | 
						|
  DEBUG ((DEBUG_ERROR, "Symbol File: %s\n", FileName));
 | 
						|
  Status = EdbLoadSymbolEntry (Object, BufferSize, Buffer);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Fill Object value
 | 
						|
  //
 | 
						|
  StrnCpyS (
 | 
						|
    Object->Name,
 | 
						|
    sizeof (Object->Name) / sizeof (CHAR16),
 | 
						|
    FileName,
 | 
						|
    (sizeof (Object->Name) / sizeof (CHAR16)) - 1
 | 
						|
    );
 | 
						|
  Object->BaseAddress = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Increase the object count
 | 
						|
  //
 | 
						|
  DebuggerPrivate->DebuggerSymbolContext.ObjectCount++;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Located PDB path name in PE image.
 | 
						|
 | 
						|
  @param  ImageBase - base of PE to search
 | 
						|
 | 
						|
  @return Pointer into image at offset of PDB file name if PDB file name is found,
 | 
						|
  Otherwise a pointer to an empty string.
 | 
						|
 | 
						|
**/
 | 
						|
CHAR8 *
 | 
						|
GetPdbPath (
 | 
						|
  VOID  *ImageBase
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8                            *PdbPath;
 | 
						|
  UINT32                           DirCount;
 | 
						|
  EFI_IMAGE_DOS_HEADER             *DosHdr;
 | 
						|
  EFI_IMAGE_OPTIONAL_HEADER_UNION  *NtHdr;
 | 
						|
  EFI_IMAGE_OPTIONAL_HEADER32      *OptionalHdr32;
 | 
						|
  EFI_IMAGE_OPTIONAL_HEADER64      *OptionalHdr64;
 | 
						|
  EFI_IMAGE_DATA_DIRECTORY         *DirectoryEntry;
 | 
						|
  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY  *DebugEntry;
 | 
						|
  VOID                             *CodeViewEntryPointer;
 | 
						|
 | 
						|
  //
 | 
						|
  // Init value
 | 
						|
  //
 | 
						|
  CodeViewEntryPointer = NULL;
 | 
						|
  PdbPath              = NULL;
 | 
						|
  DosHdr               = ImageBase;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check magic
 | 
						|
  //
 | 
						|
  if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINT8 *)DosHdr + DosHdr->e_lfanew);
 | 
						|
  //
 | 
						|
  // Check Machine, filter for EBC
 | 
						|
  //
 | 
						|
  if (NtHdr->Pe32.FileHeader.Machine != EFI_IMAGE_MACHINE_EBC) {
 | 
						|
    //
 | 
						|
    // If not EBC, return NULL
 | 
						|
    //
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get DirectoryEntry
 | 
						|
  // EBC spec says PE32+, but implementation uses PE32. So check dynamically here.
 | 
						|
  //
 | 
						|
  if (NtHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
 | 
						|
    OptionalHdr32  = (VOID *)&NtHdr->Pe32.OptionalHeader;
 | 
						|
    DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(OptionalHdr32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
 | 
						|
  } else if (NtHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
 | 
						|
    OptionalHdr64  = (VOID *)&NtHdr->Pe32Plus.OptionalHeader;
 | 
						|
    DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(OptionalHdr64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
 | 
						|
  } else {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DirectoryEntry->VirtualAddress == 0) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Go through DirectoryEntry
 | 
						|
  //
 | 
						|
  for (DirCount = 0;
 | 
						|
       (DirCount < DirectoryEntry->Size / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) && CodeViewEntryPointer == NULL;
 | 
						|
       DirCount++
 | 
						|
       )
 | 
						|
  {
 | 
						|
    DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(DirectoryEntry->VirtualAddress + (UINTN)ImageBase + DirCount * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
 | 
						|
    if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
 | 
						|
      //
 | 
						|
      // Match DebugEntry, only CODEVIEW_SIGNATURE_NB10 and CODEVIEW_SIGNATURE_RSDS are supported.
 | 
						|
      //
 | 
						|
      CodeViewEntryPointer = (VOID *)((UINTN)DebugEntry->RVA + (UINTN)ImageBase);
 | 
						|
      switch (*(UINT32 *)CodeViewEntryPointer) {
 | 
						|
        case CODEVIEW_SIGNATURE_NB10:
 | 
						|
          PdbPath = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
 | 
						|
          break;
 | 
						|
        case CODEVIEW_SIGNATURE_RSDS:
 | 
						|
          PdbPath = (CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
 | 
						|
          break;
 | 
						|
        default:
 | 
						|
          break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Done successfully
 | 
						|
  //
 | 
						|
  return PdbPath;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Check whether PDB file and MAP file have same name.
 | 
						|
 | 
						|
  @param  PdbFileName - PDB file name
 | 
						|
  @param  MapFileName - MAP file name
 | 
						|
 | 
						|
  @retval TRUE  - PDB and MAP file name match
 | 
						|
  @retval FALSE - PDB and MAP file name not match
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
MatchPdbAndMap (
 | 
						|
  IN CHAR8   *PdbFileName,
 | 
						|
  IN CHAR16  *MapFileName
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  PdbNameSize;
 | 
						|
  UINTN  MapNameSize;
 | 
						|
  CHAR8  *PurePdbFileName;
 | 
						|
  UINTN  Index;
 | 
						|
 | 
						|
  //
 | 
						|
  // remove dir name
 | 
						|
  //
 | 
						|
  PurePdbFileName = PdbFileName;
 | 
						|
  for (Index = 0; PdbFileName[Index] != 0; Index++) {
 | 
						|
    if (PdbFileName[Index] == '\\') {
 | 
						|
      PurePdbFileName = &PdbFileName[Index + 1];
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  PdbFileName = PurePdbFileName;
 | 
						|
 | 
						|
  //
 | 
						|
  // get size
 | 
						|
  //
 | 
						|
  PdbNameSize = AsciiStrLen (PdbFileName);
 | 
						|
  MapNameSize = StrLen (MapFileName);
 | 
						|
 | 
						|
  if (PdbNameSize != MapNameSize) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // check the name
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < MapNameSize - 4; Index++) {
 | 
						|
    if ((PdbFileName[Index] | 0x20) != (MapFileName[Index] | 0x20)) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// BUGBUG: work-around start
 | 
						|
//
 | 
						|
typedef struct {
 | 
						|
  EFI_DEBUG_IMAGE_INFO    *EfiDebugImageInfoTable;
 | 
						|
  volatile UINT32         UpdateStatus;
 | 
						|
  UINT32                  TableSize;
 | 
						|
} EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD;
 | 
						|
 | 
						|
EFI_DEBUG_IMAGE_INFO_TABLE_HEADER  mDebugImageInfoTableHeader;
 | 
						|
 | 
						|
/**
 | 
						|
For compatibility consideration, we handle 2 cases:
 | 
						|
 | 
						|
1) IA32:
 | 
						|
  Old:                          New:
 | 
						|
  +------------------------+    +------------------------+
 | 
						|
  | EfiDebugImageInfoTable |    | UpdateStatus           |
 | 
						|
  +------------------------+    +------------------------+
 | 
						|
  | UpdateStatus           |    | TableSize              |
 | 
						|
  +------------------------+    +------------------------+
 | 
						|
  | TableSize              |    | EfiDebugImageInfoTable |
 | 
						|
  +------------------------+    +------------------------+
 | 
						|
 | 
						|
2) X64 and IPF:
 | 
						|
  Old:                          New:
 | 
						|
  +------------------------+    +------------------------+
 | 
						|
  | EfiDebugImageInfoTable |    | UpdateStatus           |
 | 
						|
  |                        |    +------------------------+
 | 
						|
  |                        |    | TableSize              |
 | 
						|
  +------------------------+    +------------------------+
 | 
						|
  | UpdateStatus           |    | EfiDebugImageInfoTable |
 | 
						|
  +------------------------+    |                        |
 | 
						|
  | TableSize              |    |                        |
 | 
						|
  +------------------------+    +------------------------+
 | 
						|
 | 
						|
  @param DebugImageInfoTableHeader  Point to the EFI_DEBUG_IMAGE_INFO_TABLE_HEADER structure.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EdbFixDebugImageInfoTable (
 | 
						|
  IN OUT EFI_DEBUG_IMAGE_INFO_TABLE_HEADER  **DebugImageInfoTableHeader
 | 
						|
  )
 | 
						|
{
 | 
						|
  mDebugImageInfoTableHeader.EfiDebugImageInfoTable = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->EfiDebugImageInfoTable;
 | 
						|
  mDebugImageInfoTableHeader.UpdateStatus           = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->UpdateStatus;
 | 
						|
  mDebugImageInfoTableHeader.TableSize              = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->TableSize;
 | 
						|
 | 
						|
  if ((*DebugImageInfoTableHeader)->UpdateStatus > 3) {
 | 
						|
    *DebugImageInfoTableHeader = &mDebugImageInfoTableHeader;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((*DebugImageInfoTableHeader)->TableSize % (EFI_PAGE_SIZE / (sizeof (VOID *))) != 0) {
 | 
						|
    *DebugImageInfoTableHeader = &mDebugImageInfoTableHeader;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// BUGBUG: work-around end
 | 
						|
//
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Patch symbol RVA.
 | 
						|
 | 
						|
  @param  DebuggerPrivate - EBC Debugger private data structure
 | 
						|
  @param  FileName        - Symbol file name
 | 
						|
  @param  SearchType      - Search type for Object
 | 
						|
 | 
						|
  @retval EFI_SUCCESS   - Patch symbol RVA successfully
 | 
						|
  @retval EFI_NOT_FOUND - Symbol RVA base not found
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EdbPatchSymbolRVA (
 | 
						|
  IN EFI_DEBUGGER_PRIVATE_DATA      *DebuggerPrivate,
 | 
						|
  IN CHAR16                         *FileName,
 | 
						|
  IN EDB_EBC_IMAGE_RVA_SEARCH_TYPE  SearchType
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  UINTN                       ImageNumber;
 | 
						|
  EFI_DEBUG_IMAGE_INFO        *ImageTable;
 | 
						|
  CHAR8                       *PdbPath;
 | 
						|
  VOID                        *ImageBase;
 | 
						|
  VOID                        *CandidateImageBase;
 | 
						|
  EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
 | 
						|
 | 
						|
  if ((SearchType < 0) || (SearchType >= EdbEbcImageRvaSearchTypeMax)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the related object
 | 
						|
  //
 | 
						|
  Object = EdbFindSymbolFile (DebuggerPrivate, FileName, NULL);
 | 
						|
  if (Object == NULL) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Try again to get DebugImageInfoTable
 | 
						|
  //
 | 
						|
  if (mDebuggerPrivate.DebugImageInfoTableHeader == NULL) {
 | 
						|
    Status = EfiGetSystemConfigurationTable (
 | 
						|
               &gEfiDebugImageInfoTableGuid,
 | 
						|
               (VOID **)&mDebuggerPrivate.DebugImageInfoTableHeader
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      EDBPrint (L"DebugImageInfoTable not found!\n");
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_ERROR, "DebugImageInfoTableHeader: %x\n", mDebuggerPrivate.DebugImageInfoTableHeader));
 | 
						|
 | 
						|
  //
 | 
						|
  // BUGBUG: work-around start
 | 
						|
  //
 | 
						|
  EdbFixDebugImageInfoTable (&mDebuggerPrivate.DebugImageInfoTableHeader);
 | 
						|
  //
 | 
						|
  // BUGBUG: work-around end
 | 
						|
  //
 | 
						|
 | 
						|
  //
 | 
						|
  // Go through DebugImageInfoTable for each Image
 | 
						|
  //
 | 
						|
  CandidateImageBase = NULL;
 | 
						|
  ImageTable         = mDebuggerPrivate.DebugImageInfoTableHeader->EfiDebugImageInfoTable;
 | 
						|
  for (ImageNumber = 0; ImageNumber < mDebuggerPrivate.DebugImageInfoTableHeader->TableSize; ImageNumber++) {
 | 
						|
    if (ImageTable[ImageNumber].NormalImage == NULL) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    ImageBase = ImageTable[ImageNumber].NormalImage->LoadedImageProtocolInstance->ImageBase;
 | 
						|
    //
 | 
						|
    // Get PDB path
 | 
						|
    //
 | 
						|
    PdbPath = GetPdbPath (ImageBase);
 | 
						|
    if (PdbPath == NULL) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Check PDB name
 | 
						|
    //
 | 
						|
    if (!MatchPdbAndMap (PdbPath, FileName)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    DEBUG ((DEBUG_ERROR, "ImageBase: %x\n", ImageBase));
 | 
						|
 | 
						|
    //
 | 
						|
    // Check SearchType
 | 
						|
    //
 | 
						|
    if ((SearchType == EdbEbcImageRvaSearchTypeAny) || (SearchType == EdbEbcImageRvaSearchTypeFirst)) {
 | 
						|
      //
 | 
						|
      // Assign base address and return
 | 
						|
      //
 | 
						|
      Object->BaseAddress = (UINTN)ImageBase;
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Get CandidateImageBase for EdbEbcImageRvaSearchTypeLast
 | 
						|
    //
 | 
						|
    CandidateImageBase = ImageBase;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check EdbEbcImageRvaSearchTypeLast
 | 
						|
  //
 | 
						|
  if (SearchType == EdbEbcImageRvaSearchTypeLast) {
 | 
						|
    if (CandidateImageBase == NULL) {
 | 
						|
      return EFI_NOT_FOUND;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Assign base address and return
 | 
						|
    //
 | 
						|
    Object->BaseAddress = (UINTN)CandidateImageBase;
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // No match
 | 
						|
  //
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Check whether OBJ file and COD file have same name.
 | 
						|
 | 
						|
  @param  ObjFileName - OBJ file name
 | 
						|
  @param  CodFileName - COD file name
 | 
						|
 | 
						|
  @retval TRUE  - OBJ and COD file name match
 | 
						|
  @retval FALSE - OBJ and COD file name not match
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
MatchObjAndCod (
 | 
						|
  IN CHAR8   *ObjFileName,
 | 
						|
  IN CHAR16  *CodFileName
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  ObjNameSize;
 | 
						|
  UINTN  CodNameSize;
 | 
						|
  CHAR8  *PureObjFileName;
 | 
						|
  UINTN  Index;
 | 
						|
 | 
						|
  //
 | 
						|
  // remove library name
 | 
						|
  //
 | 
						|
  PureObjFileName = ObjFileName;
 | 
						|
  for (Index = 0; ObjFileName[Index] != 0; Index++) {
 | 
						|
    if (ObjFileName[Index] == ':') {
 | 
						|
      PureObjFileName = &ObjFileName[Index + 1];
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  ObjFileName = PureObjFileName;
 | 
						|
 | 
						|
  //
 | 
						|
  // get size
 | 
						|
  //
 | 
						|
  ObjNameSize = AsciiStrLen (ObjFileName);
 | 
						|
  CodNameSize = StrLen (CodFileName);
 | 
						|
 | 
						|
  if (ObjNameSize != CodNameSize) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // check the name
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < CodNameSize - 4; Index++) {
 | 
						|
    if ((ObjFileName[Index] | 0x20) != (CodFileName[Index] | 0x20)) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
typedef enum {
 | 
						|
  EdbEbcCodParseStateUninitialized,
 | 
						|
  EdbEbcCodParseStateSymbolInitialized,
 | 
						|
  EdbEbcCodParseStateSymbolStart,
 | 
						|
  EdbEbcCodParseStateSymbolEnd,
 | 
						|
  EdbEbcCodParseStateMax,
 | 
						|
} EDB_EBC_COD_PARSE_STATE;
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  The following code depends on the COD file generated by IEC compiler.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Load code by symbol by Iec.
 | 
						|
 | 
						|
  @param  Name            - Symbol file name
 | 
						|
  @param  Buffer          - Symbol file buffer
 | 
						|
  @param  BufferSize      - Symbol file buffer size
 | 
						|
  @param  CodeBufferSize  - Code buffer size
 | 
						|
  @param  FuncOffset      - Code funcion offset
 | 
						|
 | 
						|
  @return CodeBuffer
 | 
						|
 | 
						|
**/
 | 
						|
CHAR8 *
 | 
						|
EdbLoadCodBySymbolByIec (
 | 
						|
  IN CHAR8   *Name,
 | 
						|
  IN VOID    *Buffer,
 | 
						|
  IN UINTN   BufferSize,
 | 
						|
  OUT UINTN  *CodeBufferSize,
 | 
						|
  OUT UINTN  *FuncOffset
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8                    *LineBuffer;
 | 
						|
  CHAR8                    *FieldBuffer;
 | 
						|
  VOID                     *BufferStart;
 | 
						|
  VOID                     *BufferEnd;
 | 
						|
  UINTN                    Offset;
 | 
						|
  EDB_EBC_COD_PARSE_STATE  CodParseState;
 | 
						|
  CHAR8                    Char[2];
 | 
						|
 | 
						|
  //
 | 
						|
  // Init
 | 
						|
  //
 | 
						|
  Char[0]       = 9;
 | 
						|
  Char[1]       = 0;
 | 
						|
  LineBuffer    = AsciiStrGetNewTokenLine (Buffer, "\n\r");
 | 
						|
  Offset        = (UINTN)-1;
 | 
						|
  BufferStart   = NULL;
 | 
						|
  BufferEnd     = NULL;
 | 
						|
  CodParseState = EdbEbcCodParseStateUninitialized;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check each line
 | 
						|
  //
 | 
						|
  while (LineBuffer != NULL) {
 | 
						|
    switch (CodParseState) {
 | 
						|
      case EdbEbcCodParseStateUninitialized:
 | 
						|
        //
 | 
						|
        // check mark_begin, begin to check line after this match
 | 
						|
        //
 | 
						|
        if (AsciiStrCmp (LineBuffer, "; mark_begin;") == 0) {
 | 
						|
          CodParseState = EdbEbcCodParseStateSymbolInitialized;
 | 
						|
        }
 | 
						|
 | 
						|
        LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
 | 
						|
        PatchForAsciiStrTokenBefore (LineBuffer, '\n');
 | 
						|
        break;
 | 
						|
 | 
						|
      case EdbEbcCodParseStateSymbolInitialized:
 | 
						|
        //
 | 
						|
        // check mark_end, not check line after this match
 | 
						|
        //
 | 
						|
        if (AsciiStrCmp (LineBuffer, "; mark_end;") == 0) {
 | 
						|
          CodParseState = EdbEbcCodParseStateUninitialized;
 | 
						|
          LineBuffer    = AsciiStrGetNextTokenLine ("\n\r");
 | 
						|
          PatchForAsciiStrTokenBefore (LineBuffer, '\n');
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // not check this line if the first char is as follows
 | 
						|
        //
 | 
						|
        if ((*LineBuffer == 0)   ||
 | 
						|
            (*LineBuffer == '$') ||
 | 
						|
            (*LineBuffer == ';') ||
 | 
						|
            (*LineBuffer == '_') ||
 | 
						|
            (*LineBuffer == ' '))
 | 
						|
        {
 | 
						|
          LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
 | 
						|
          PatchForAsciiStrTokenBefore (LineBuffer, '\n');
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // get function name, function name is followed by char 0x09.
 | 
						|
        //
 | 
						|
        FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, Char);
 | 
						|
        ASSERT (FieldBuffer != NULL);
 | 
						|
        if (AsciiStriCmp (FieldBuffer, Name) == 0) {
 | 
						|
          BufferStart   = FieldBuffer;
 | 
						|
          CodParseState = EdbEbcCodParseStateSymbolStart;
 | 
						|
        }
 | 
						|
 | 
						|
        PatchForAsciiStrTokenAfter (FieldBuffer, 0x9);
 | 
						|
 | 
						|
        //
 | 
						|
        // Get next line
 | 
						|
        //
 | 
						|
        LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
 | 
						|
        PatchForAsciiStrTokenBefore (LineBuffer, '\n');
 | 
						|
        break;
 | 
						|
 | 
						|
      case EdbEbcCodParseStateSymbolStart:
 | 
						|
        //
 | 
						|
        // check mark_end, if this match, means the function is found successfully.
 | 
						|
        //
 | 
						|
        if (AsciiStrCmp (LineBuffer, "; mark_end;") == 0) {
 | 
						|
          CodParseState = EdbEbcCodParseStateSymbolEnd;
 | 
						|
          //
 | 
						|
          // prepare CodeBufferSize, FuncOffset, and FuncStart to return
 | 
						|
          //
 | 
						|
          BufferEnd       = LineBuffer + sizeof ("; mark_end;") - 1;
 | 
						|
          *CodeBufferSize = (UINTN)BufferEnd - (UINTN)BufferStart;
 | 
						|
          *FuncOffset     = Offset;
 | 
						|
          PatchForAsciiStrTokenAfter (LineBuffer, '\n');
 | 
						|
          return BufferStart;
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // Get function offset
 | 
						|
        //
 | 
						|
        if ((Offset == (UINTN)-1) &&
 | 
						|
            (*LineBuffer == ' '))
 | 
						|
        {
 | 
						|
          FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 2, " ");
 | 
						|
          Offset      = AsciiXtoi (FieldBuffer);
 | 
						|
          PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
 | 
						|
        }
 | 
						|
 | 
						|
        //
 | 
						|
        // Get next line
 | 
						|
        //
 | 
						|
        LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
 | 
						|
        PatchForAsciiStrTokenBefore (LineBuffer, '\n');
 | 
						|
        break;
 | 
						|
 | 
						|
      case EdbEbcCodParseStateSymbolEnd:
 | 
						|
        break;
 | 
						|
 | 
						|
      default:
 | 
						|
        break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // no function found
 | 
						|
  //
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Load code by symbol.
 | 
						|
 | 
						|
  @param  Name            - Symbol file name
 | 
						|
  @param  Buffer          - Symbol file buffer
 | 
						|
  @param  BufferSize      - Symbol file buffer size
 | 
						|
  @param  CodeBufferSize  - Code buffer size
 | 
						|
  @param  FuncOffset      - Code funcion offset
 | 
						|
 | 
						|
  @return CodeBuffer
 | 
						|
 | 
						|
**/
 | 
						|
CHAR8 *
 | 
						|
EdbLoadCodBySymbol (
 | 
						|
  IN CHAR8   *Name,
 | 
						|
  IN VOID    *Buffer,
 | 
						|
  IN UINTN   BufferSize,
 | 
						|
  OUT UINTN  *CodeBufferSize,
 | 
						|
  OUT UINTN  *FuncOffset
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // COD file format depends on the compiler.
 | 
						|
  //
 | 
						|
  // It is possible to check the different COD file format in this routine.
 | 
						|
  // Now only IEC is supported.
 | 
						|
  //
 | 
						|
  return EdbLoadCodBySymbolByIec (Name, Buffer, BufferSize, CodeBufferSize, FuncOffset);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Find code from object.
 | 
						|
 | 
						|
  @param  DebuggerPrivate    EBC Debugger private data structure
 | 
						|
  @param  Object          - Symbol object
 | 
						|
  @param  FileName        - File name
 | 
						|
 | 
						|
**/
 | 
						|
VOID *
 | 
						|
EdbFindCodeFromObject (
 | 
						|
  IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
 | 
						|
  IN EFI_DEBUGGER_SYMBOL_OBJECT  *Object,
 | 
						|
  IN CHAR16                      *FileName
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  EntryIndex;
 | 
						|
 | 
						|
  //
 | 
						|
  // Go througn each Entry in this Object
 | 
						|
  //
 | 
						|
  for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
 | 
						|
    //
 | 
						|
    // This check is for Function only
 | 
						|
    //
 | 
						|
    if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
 | 
						|
        (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction))
 | 
						|
    {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Skip match varbss_init function, because they has no source code
 | 
						|
    //
 | 
						|
    if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof ("varbss_init") - 1) == 0) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // check the name
 | 
						|
    //
 | 
						|
    if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // found it, return source buffer
 | 
						|
    //
 | 
						|
    if (Object->Entry[EntryIndex].CodBuffer != NULL) {
 | 
						|
      return Object->Entry[EntryIndex].SourceBuffer;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // not found
 | 
						|
  //
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Load code.
 | 
						|
 | 
						|
  @param  DebuggerPrivate - EBC Debugger private data structure
 | 
						|
  @param  MapFileName     - Symbol file name
 | 
						|
  @param  FileName        - Code file name
 | 
						|
  @param  BufferSize      - Code file buffer size
 | 
						|
  @param  Buffer          - Code file buffer
 | 
						|
 | 
						|
  @retval EFI_SUCCESS - Code loaded successfully
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EdbLoadCode (
 | 
						|
  IN EFI_DEBUGGER_PRIVATE_DATA  *DebuggerPrivate,
 | 
						|
  IN CHAR16                     *MapFileName,
 | 
						|
  IN CHAR16                     *FileName,
 | 
						|
  IN UINTN                      BufferSize,
 | 
						|
  IN VOID                       *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
 | 
						|
  UINTN                       ObjectIndex;
 | 
						|
  UINTN                       EntryIndex;
 | 
						|
  VOID                        *SourceBuffer;
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Find Symbol
 | 
						|
  //
 | 
						|
  Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, &ObjectIndex);
 | 
						|
  if (Object == NULL) {
 | 
						|
    EDBPrint (L"SymbolFile is not loaded!\n");
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Check duplicated File
 | 
						|
    //
 | 
						|
    SourceBuffer = EdbFindCodeFromObject (DebuggerPrivate, Object, FileName);
 | 
						|
    if (SourceBuffer != NULL) {
 | 
						|
      //
 | 
						|
      // unnload duplicated code
 | 
						|
      //
 | 
						|
      Status = EdbUnloadCode (DebuggerPrivate, MapFileName, FileName, &SourceBuffer);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        DEBUG ((DEBUG_ERROR, "Unload Duplicated Code File Error!\n"));
 | 
						|
        return Status;
 | 
						|
      }
 | 
						|
 | 
						|
      Status = EdbDeleteCodeBuffer (DebuggerPrivate, MapFileName, FileName, SourceBuffer);
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        DEBUG ((DEBUG_ERROR, "Delete Duplicated Code File Error!\n"));
 | 
						|
        return Status;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Go through each SymbolEntry
 | 
						|
  //
 | 
						|
  for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
 | 
						|
    //
 | 
						|
    // load symbol for function only
 | 
						|
    //
 | 
						|
    if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
 | 
						|
        (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction))
 | 
						|
    {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // skip varbss_init
 | 
						|
    //
 | 
						|
    if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof ("varbss_init") - 1) == 0) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Check the name
 | 
						|
    //
 | 
						|
    if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // load code for this symbol
 | 
						|
    //
 | 
						|
    Object->Entry[EntryIndex].CodBuffer = EdbLoadCodBySymbol (
 | 
						|
                                            Object->Entry[EntryIndex].Name,
 | 
						|
                                            Buffer,
 | 
						|
                                            BufferSize,
 | 
						|
                                            &Object->Entry[EntryIndex].CodBufferSize,
 | 
						|
                                            &Object->Entry[EntryIndex].FuncOffsetBase
 | 
						|
                                            );
 | 
						|
    if (Object->Entry[EntryIndex].CodBuffer != NULL) {
 | 
						|
      Object->Entry[EntryIndex].SourceBuffer = Buffer;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // patch end '\0' for each code buffer
 | 
						|
  //
 | 
						|
  for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
 | 
						|
    if (Object->Entry[EntryIndex].CodBuffer != NULL) {
 | 
						|
      *((UINT8 *)Object->Entry[EntryIndex].CodBuffer + Object->Entry[EntryIndex].CodBufferSize) = 0;
 | 
						|
      DEBUG ((DEBUG_ERROR, "  CodeSymbol: %a, FuncOffset: 0x05%x\n", Object->Entry[EntryIndex].Name, Object->Entry[EntryIndex].FuncOffsetBase));
 | 
						|
      //      DEBUG ((DEBUG_ERROR, "  [CODE]:\n%a\n", Object->Entry[EntryIndex].CodBuffer));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Done
 | 
						|
  //
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Unload code.
 | 
						|
 | 
						|
  @param  DebuggerPrivate - EBC Debugger private data structure
 | 
						|
  @param  MapFileName     - Symbol file name
 | 
						|
  @param  FileName        - Code file name
 | 
						|
  @param  Buffer          - Code file buffer
 | 
						|
 | 
						|
  @retval EFI_SUCCESS - Code unloaded successfully
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EdbUnloadCode (
 | 
						|
  IN EFI_DEBUGGER_PRIVATE_DATA  *DebuggerPrivate,
 | 
						|
  IN CHAR16                     *MapFileName,
 | 
						|
  IN CHAR16                     *FileName,
 | 
						|
  OUT VOID                      **Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
 | 
						|
  UINTN                       ObjectIndex;
 | 
						|
  UINTN                       EntryIndex;
 | 
						|
 | 
						|
  //
 | 
						|
  // Find Symbol
 | 
						|
  //
 | 
						|
  Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, &ObjectIndex);
 | 
						|
  if (Object == NULL) {
 | 
						|
    EDBPrint (L"SymbolFile is not loaded!\n");
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Find code
 | 
						|
  //
 | 
						|
  *Buffer = EdbFindCodeFromObject (DebuggerPrivate, Object, FileName);
 | 
						|
  if (*Buffer == NULL) {
 | 
						|
    EDBPrint (L"CodeFile is not loaded!\n");
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // go through each entry
 | 
						|
  //
 | 
						|
  for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
 | 
						|
    if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
 | 
						|
        (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction))
 | 
						|
    {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof ("varbss_init") - 1) == 0) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // clean up the buffer
 | 
						|
    //
 | 
						|
    Object->Entry[EntryIndex].CodBuffer      = NULL;
 | 
						|
    Object->Entry[EntryIndex].CodBufferSize  = 0;
 | 
						|
    Object->Entry[EntryIndex].FuncOffsetBase = 0;
 | 
						|
    Object->Entry[EntryIndex].SourceBuffer   = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Done
 | 
						|
  //
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Add code buffer.
 | 
						|
 | 
						|
  @param  DebuggerPrivate - EBC Debugger private data structure
 | 
						|
  @param  MapFileName     - Symbol file name
 | 
						|
  @param  CodeFileName    - Code file name
 | 
						|
  @param  SourceBufferSize- Code buffer size
 | 
						|
  @param  SourceBuffer    - Code buffer
 | 
						|
 | 
						|
  @retval EFI_SUCCESS - CodeBuffer added successfully
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EdbAddCodeBuffer (
 | 
						|
  IN     EFI_DEBUGGER_PRIVATE_DATA  *DebuggerPrivate,
 | 
						|
  IN     CHAR16                     *MapFileName,
 | 
						|
  IN     CHAR16                     *CodeFileName,
 | 
						|
  IN     UINTN                      SourceBufferSize,
 | 
						|
  IN     VOID                       *SourceBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                       Index;
 | 
						|
  EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
 | 
						|
 | 
						|
  //
 | 
						|
  // Find Symbol
 | 
						|
  //
 | 
						|
  Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, NULL);
 | 
						|
  if (Object == NULL) {
 | 
						|
    EDBPrint (L"SymbolFile is not loaded!\n");
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Add it to last entry
 | 
						|
  //
 | 
						|
  for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
 | 
						|
  }
 | 
						|
 | 
						|
  Object->SourceBuffer[Index] = SourceBuffer;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Delete code buffer.
 | 
						|
 | 
						|
  @param  DebuggerPrivate - EBC Debugger private data structure
 | 
						|
  @param  MapFileName     - Symbol file name
 | 
						|
  @param  CodeFileName    - Code file name
 | 
						|
  @param  SourceBuffer    - Code buffer
 | 
						|
 | 
						|
  @retval EFI_SUCCESS - CodeBuffer deleted successfully
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EdbDeleteCodeBuffer (
 | 
						|
  IN     EFI_DEBUGGER_PRIVATE_DATA  *DebuggerPrivate,
 | 
						|
  IN     CHAR16                     *MapFileName,
 | 
						|
  IN     CHAR16                     *CodeFileName,
 | 
						|
  IN     VOID                       *SourceBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                       Index;
 | 
						|
  EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
 | 
						|
 | 
						|
  //
 | 
						|
  // Find Symbol
 | 
						|
  //
 | 
						|
  Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, NULL);
 | 
						|
  if (Object == NULL) {
 | 
						|
    EDBPrint (L"SymbolFile is not loaded!\n");
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
 | 
						|
    //
 | 
						|
    // free the buffer if match
 | 
						|
    //
 | 
						|
    if (Object->SourceBuffer[Index] == SourceBuffer) {
 | 
						|
      gBS->FreePool (SourceBuffer);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (Object->SourceBuffer[Index] == NULL) {
 | 
						|
    //
 | 
						|
    // not return NOT_FOUND
 | 
						|
    //
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // remove the entry
 | 
						|
  //
 | 
						|
  Object->SourceBuffer[Index] = NULL;
 | 
						|
  for (Index = Index + 1; Object->SourceBuffer[Index] != NULL; Index++) {
 | 
						|
    Object->SourceBuffer[Index - 1] = Object->SourceBuffer[Index];
 | 
						|
  }
 | 
						|
 | 
						|
  Object->SourceBuffer[Index - 1] = NULL;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Find the symbol string according to address.
 | 
						|
 | 
						|
  @param  Address         - Symbol address
 | 
						|
 | 
						|
  @return Symbol string
 | 
						|
 | 
						|
**/
 | 
						|
CHAR8 *
 | 
						|
FindSymbolStr (
 | 
						|
  IN UINTN  Address
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                       ObjectIndex;
 | 
						|
  EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
 | 
						|
  UINTN                       EntryIndex;
 | 
						|
  EFI_DEBUGGER_SYMBOL_ENTRY   *Entry;
 | 
						|
 | 
						|
  //
 | 
						|
  // need we display symbol
 | 
						|
  //
 | 
						|
  if (!mDebuggerPrivate.DebuggerSymbolContext.DisplaySymbol) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Go through each object and entry
 | 
						|
  //
 | 
						|
  Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
 | 
						|
  for (ObjectIndex = 0; ObjectIndex < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
 | 
						|
    Entry = Object[ObjectIndex].Entry;
 | 
						|
    for (EntryIndex = 0; EntryIndex < Object[ObjectIndex].EntryCount; EntryIndex++) {
 | 
						|
      //
 | 
						|
      // if Address match, return Name
 | 
						|
      //
 | 
						|
      if (Address == (Entry[EntryIndex].Rva + Object[ObjectIndex].BaseAddress)) {
 | 
						|
        return Entry[EntryIndex].Name;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // not found
 | 
						|
  //
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Get line number and offset from this line in code file.
 | 
						|
 | 
						|
  @param  Line            - Line buffer in code file
 | 
						|
  @param  Offset          - Offset to functin entry
 | 
						|
 | 
						|
  @return Line number
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
EdbGetLineNumberAndOffsetFromThisLine (
 | 
						|
  IN VOID    *Line,
 | 
						|
  OUT UINTN  *Offset
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  LineNumber;
 | 
						|
  CHAR8  *LineBuffer;
 | 
						|
  CHAR8  *FieldBuffer;
 | 
						|
 | 
						|
  LineNumber = (UINTN)-1;
 | 
						|
  LineBuffer = Line;
 | 
						|
  *Offset    = (UINTN)-1;
 | 
						|
 | 
						|
  while (LineBuffer != NULL) {
 | 
						|
    //
 | 
						|
    // Check candidate
 | 
						|
    //
 | 
						|
    if (*LineBuffer != ' ') {
 | 
						|
      return (UINTN)-1;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Get Offset
 | 
						|
    //
 | 
						|
    if (*(LineBuffer + 2) != ' ') {
 | 
						|
      if (*Offset == (UINTN)-1) {
 | 
						|
        FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 2, " ");
 | 
						|
        *Offset     = AsciiXtoi (FieldBuffer);
 | 
						|
        PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // 1. assembly instruction
 | 
						|
    //
 | 
						|
    FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, ":");
 | 
						|
    //
 | 
						|
    // 2. file path
 | 
						|
    //
 | 
						|
    FieldBuffer = AsciiStrGetNextTokenField (":");
 | 
						|
    PatchForAsciiStrTokenBefore (FieldBuffer, ':');
 | 
						|
    if (FieldBuffer == NULL) {
 | 
						|
      //
 | 
						|
      // candidate found
 | 
						|
      //
 | 
						|
      LineNumber = 0;
 | 
						|
      LineBuffer = AsciiStrGetNextTokenLine ("\n");
 | 
						|
      PatchForAsciiStrTokenBefore (LineBuffer, '\n');
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // 3. line number
 | 
						|
    //
 | 
						|
    FieldBuffer = AsciiStrGetNextTokenField (":");
 | 
						|
    PatchForAsciiStrTokenBefore (FieldBuffer, ':');
 | 
						|
    if (FieldBuffer == NULL) {
 | 
						|
      //
 | 
						|
      // impossible, TBD?
 | 
						|
      //
 | 
						|
      LineBuffer = AsciiStrGetNextTokenLine ("\n");
 | 
						|
      PatchForAsciiStrTokenBefore (LineBuffer, '\n');
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    LineNumber = AsciiAtoi (FieldBuffer);
 | 
						|
    //
 | 
						|
    // Not patch after
 | 
						|
    //
 | 
						|
 | 
						|
    return LineNumber;
 | 
						|
  }
 | 
						|
 | 
						|
  return (UINTN)-1;
 | 
						|
}
 | 
						|
 | 
						|
typedef enum {
 | 
						|
  EdbEbcLineSearchTypeAny,
 | 
						|
  EdbEbcLineSearchTypeFirst,
 | 
						|
  EdbEbcLineSearchTypeLast,
 | 
						|
  EdbEbcLineSearchTypeMax,
 | 
						|
} EDB_EBC_LINE_SEARCH_TYPE;
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Get line number from this code file.
 | 
						|
 | 
						|
  @param  Entry           - Symbol entry
 | 
						|
  @param  FuncOffset      - Offset to functin entry
 | 
						|
  @param  SearchType      - Search type for the code
 | 
						|
 | 
						|
  @return Line number
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
EdbGetLineNumberFromCode (
 | 
						|
  IN EFI_DEBUGGER_SYMBOL_ENTRY  *Entry,
 | 
						|
  IN UINTN                      FuncOffset,
 | 
						|
  IN EDB_EBC_LINE_SEARCH_TYPE   SearchType
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8  *LineBuffer;
 | 
						|
  UINTN  LineNumber;
 | 
						|
  UINTN  Offset;
 | 
						|
  UINTN  CandidateLineNumber;
 | 
						|
  UINTN  CandidateOffset;
 | 
						|
 | 
						|
  if ((SearchType < 0) || (SearchType >= EdbEbcLineSearchTypeMax)) {
 | 
						|
    return (UINTN)-1;
 | 
						|
  }
 | 
						|
 | 
						|
  LineNumber          = (UINTN)-1;
 | 
						|
  CandidateLineNumber = (UINTN)-1;
 | 
						|
  CandidateOffset     = (UINTN)-1;
 | 
						|
  LineBuffer          = AsciiStrGetNewTokenLine (Entry->CodBuffer, "\n");
 | 
						|
  while (LineBuffer != NULL) {
 | 
						|
    if (*LineBuffer != ' ') {
 | 
						|
      LineBuffer = AsciiStrGetNextTokenLine ("\n");
 | 
						|
      PatchForAsciiStrTokenBefore (LineBuffer, '\n');
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Get Info
 | 
						|
    //
 | 
						|
    LineNumber = EdbGetLineNumberAndOffsetFromThisLine (LineBuffer, &Offset);
 | 
						|
 | 
						|
    //
 | 
						|
    // Check offset
 | 
						|
    //
 | 
						|
    if (Offset != FuncOffset) {
 | 
						|
      //
 | 
						|
      // Check last offset match
 | 
						|
      //
 | 
						|
      if (CandidateOffset == FuncOffset) {
 | 
						|
        if (SearchType == EdbEbcLineSearchTypeLast) {
 | 
						|
          PatchForAsciiStrTokenAfter (LineBuffer, '\n');
 | 
						|
          if (CandidateLineNumber != LineNumber) {
 | 
						|
            return CandidateLineNumber;
 | 
						|
          } else {
 | 
						|
            return (UINTN)-1;
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // impossible, TBD?
 | 
						|
          //
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      LineBuffer = AsciiStrGetNextTokenLine ("\n");
 | 
						|
      PatchForAsciiStrTokenBefore (LineBuffer, '\n');
 | 
						|
      CandidateLineNumber = LineNumber;
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Offset match, more check
 | 
						|
    //
 | 
						|
    if (SearchType == EdbEbcLineSearchTypeAny) {
 | 
						|
      PatchForAsciiStrTokenAfter (LineBuffer, '\n');
 | 
						|
      return LineNumber;
 | 
						|
    }
 | 
						|
 | 
						|
    if (SearchType == EdbEbcLineSearchTypeFirst) {
 | 
						|
      //
 | 
						|
      // Check last line
 | 
						|
      //
 | 
						|
      PatchForAsciiStrTokenAfter (LineBuffer, '\n');
 | 
						|
      if (CandidateLineNumber != LineNumber) {
 | 
						|
        return LineNumber;
 | 
						|
      } else {
 | 
						|
        return (UINTN)-1;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    CandidateLineNumber = LineNumber;
 | 
						|
    CandidateOffset     = Offset;
 | 
						|
 | 
						|
    LineBuffer = AsciiStrGetNextTokenLine ("\n");
 | 
						|
    PatchForAsciiStrTokenBefore (LineBuffer, '\n');
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check last offset match
 | 
						|
  //
 | 
						|
  if (CandidateOffset == FuncOffset) {
 | 
						|
    if (SearchType == EdbEbcLineSearchTypeLast) {
 | 
						|
      return CandidateLineNumber;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return (UINTN)-1;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Get the source string from this code file by line.
 | 
						|
 | 
						|
  @param  Entry           - Symbol entry
 | 
						|
  @param  LineNumber      - line number
 | 
						|
  @param  FuncEnd         - Function end
 | 
						|
 | 
						|
  @return Funtion start
 | 
						|
 | 
						|
**/
 | 
						|
VOID *
 | 
						|
EdbGetSourceStrFromCodeByLine (
 | 
						|
  IN EFI_DEBUGGER_SYMBOL_ENTRY  *Entry,
 | 
						|
  IN UINTN                      LineNumber,
 | 
						|
  IN VOID                       **FuncEnd
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8  *LineBuffer;
 | 
						|
  CHAR8  *FieldBuffer;
 | 
						|
  VOID   *FuncStart;
 | 
						|
  UINTN  Number;
 | 
						|
 | 
						|
  FuncStart  = NULL;
 | 
						|
  LineBuffer = AsciiStrGetNewTokenLine (Entry->CodBuffer, "\n");
 | 
						|
  while (LineBuffer != NULL) {
 | 
						|
    if (*LineBuffer != ';') {
 | 
						|
      if (FuncStart != NULL) {
 | 
						|
        //
 | 
						|
        // Over
 | 
						|
        //
 | 
						|
        *FuncEnd = LineBuffer - 1;
 | 
						|
        PatchForAsciiStrTokenAfter (LineBuffer, '\n');
 | 
						|
        return FuncStart;
 | 
						|
      }
 | 
						|
 | 
						|
      LineBuffer = AsciiStrGetNextTokenLine ("\n");
 | 
						|
      PatchForAsciiStrTokenBefore (LineBuffer, '\n');
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Check LineNumber
 | 
						|
    //
 | 
						|
    FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 1, " ");
 | 
						|
    Number      = AsciiAtoi (FieldBuffer);
 | 
						|
    PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
 | 
						|
    if (Number != LineNumber) {
 | 
						|
      LineBuffer = AsciiStrGetNextTokenLine ("\n");
 | 
						|
      PatchForAsciiStrTokenBefore (LineBuffer, '\n');
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Line match, get line number
 | 
						|
    //
 | 
						|
    if (FuncStart == NULL) {
 | 
						|
      FuncStart = LineBuffer;
 | 
						|
    }
 | 
						|
 | 
						|
    LineBuffer = AsciiStrGetNextTokenLine ("\n");
 | 
						|
    PatchForAsciiStrTokenBefore (LineBuffer, '\n');
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Get source string from this code file.
 | 
						|
 | 
						|
  @param  Entry           - Symbol entry
 | 
						|
  @param  FuncOffset      - Offset to functin entry
 | 
						|
  @param  FuncEnd         - Function end
 | 
						|
 | 
						|
  @retval Funtion start
 | 
						|
 | 
						|
**/
 | 
						|
VOID *
 | 
						|
EdbGetSourceStrFromCode (
 | 
						|
  IN EFI_DEBUGGER_SYMBOL_ENTRY  *Entry,
 | 
						|
  IN UINTN                      FuncOffset,
 | 
						|
  IN VOID                       **FuncEnd
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN  LineNumber;
 | 
						|
 | 
						|
  //
 | 
						|
  // Only search the last line, then display
 | 
						|
  //
 | 
						|
  LineNumber = EdbGetLineNumberFromCode (Entry, FuncOffset, EdbEbcLineSearchTypeLast);
 | 
						|
  if (LineNumber == (UINTN)-1) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  return EdbGetSourceStrFromCodeByLine (Entry, LineNumber, FuncEnd);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Print source.
 | 
						|
 | 
						|
  @param  Address         - Instruction address
 | 
						|
  @param  IsPrint         - Whether need to print
 | 
						|
 | 
						|
  @retval 1 - find the source
 | 
						|
  @retval 0 - not find the source
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
EdbPrintSource (
 | 
						|
  IN UINTN    Address,
 | 
						|
  IN BOOLEAN  IsPrint
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                       SymbolAddress;
 | 
						|
  EFI_DEBUGGER_SYMBOL_OBJECT  *RetObject;
 | 
						|
  EFI_DEBUGGER_SYMBOL_ENTRY   *RetEntry;
 | 
						|
  UINTN                       FuncOffset;
 | 
						|
  UINT8                       *FuncStart;
 | 
						|
  UINT8                       *FuncEnd;
 | 
						|
  UINT8                       *FuncIndex;
 | 
						|
  CHAR8                       Buffer[EFI_DEBUG_MAX_PRINT_BUFFER];
 | 
						|
  UINTN                       BufferSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // need we display symbol
 | 
						|
  //
 | 
						|
  if (!mDebuggerPrivate.DebuggerSymbolContext.DisplaySymbol) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // find the symbol address
 | 
						|
  //
 | 
						|
  SymbolAddress = EbdFindSymbolAddress (
 | 
						|
                    Address,
 | 
						|
                    EdbMatchSymbolTypeLowerAddress,
 | 
						|
                    &RetObject,
 | 
						|
                    &RetEntry
 | 
						|
                    );
 | 
						|
  if ((SymbolAddress == 0) || (RetEntry == NULL)) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  FuncOffset = Address - SymbolAddress + RetEntry->FuncOffsetBase;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get Func String
 | 
						|
  //
 | 
						|
  FuncStart = EdbGetSourceStrFromCode (RetEntry, FuncOffset, (VOID **)&FuncEnd);
 | 
						|
  if (FuncStart == NULL) {
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // check whether need to real print
 | 
						|
  //
 | 
						|
  if (!IsPrint) {
 | 
						|
    return 1;
 | 
						|
  }
 | 
						|
 | 
						|
  *(UINT8 *)FuncEnd = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // seperate buffer by \n, so that \r can be added.
 | 
						|
  //
 | 
						|
  FuncIndex = FuncStart;
 | 
						|
  while (*FuncIndex != 0) {
 | 
						|
    if (*FuncIndex == '\n') {
 | 
						|
      if ((FuncIndex - FuncStart) < (EFI_DEBUG_MAX_PRINT_BUFFER - 3)) {
 | 
						|
        BufferSize = FuncIndex - FuncStart;
 | 
						|
      } else {
 | 
						|
        BufferSize = EFI_DEBUG_MAX_PRINT_BUFFER - 3;
 | 
						|
      }
 | 
						|
 | 
						|
      if (BufferSize != 0) {
 | 
						|
        CopyMem (Buffer, FuncStart, BufferSize);
 | 
						|
      }
 | 
						|
 | 
						|
      Buffer[BufferSize] = 0;
 | 
						|
      EDBPrint (L"%a\n", Buffer);
 | 
						|
      FuncStart = FuncIndex + 1;
 | 
						|
      FuncIndex = FuncStart;
 | 
						|
    } else {
 | 
						|
      FuncIndex++;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Patch the end
 | 
						|
  //
 | 
						|
  *(UINT8 *)FuncEnd = '\n';
 | 
						|
 | 
						|
  return 1;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Get Mapfile and SymbolName from one symbol format: [MapFileName:]SymbolName.
 | 
						|
 | 
						|
  @param  Symbol          - whole Symbol name
 | 
						|
  @param  MapfileName     - the mapfile name in the symbol
 | 
						|
  @param  SymbolName      - the symbol name in the symbol
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
GetMapfileAndSymbol (
 | 
						|
  IN CHAR16   *Symbol,
 | 
						|
  OUT CHAR16  **MapfileName,
 | 
						|
  OUT CHAR16  **SymbolName
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR16  *Ch;
 | 
						|
 | 
						|
  *MapfileName = NULL;
 | 
						|
  *SymbolName  = Symbol;
 | 
						|
 | 
						|
  for (Ch = Symbol; *Ch != 0; Ch++) {
 | 
						|
    //
 | 
						|
    // Find split char
 | 
						|
    //
 | 
						|
    if (*Ch == L':') {
 | 
						|
      *MapfileName = Symbol;
 | 
						|
      *Ch          = 0;
 | 
						|
      *SymbolName  = Ch + 1;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Convert a symbol to an address.
 | 
						|
 | 
						|
  @param  Symbol          - Symbol name
 | 
						|
  @param  Address         - Symbol address
 | 
						|
 | 
						|
  @retval EFI_SUCCESS    - symbol found and address returned.
 | 
						|
  @retval EFI_NOT_FOUND  - symbol not found
 | 
						|
  @retval EFI_NO_MAPPING - duplicated symbol not found
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
Symboltoi (
 | 
						|
  IN CHAR16  *Symbol,
 | 
						|
  OUT UINTN  *Address
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                       ObjectIndex;
 | 
						|
  EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
 | 
						|
  UINTN                       EntryIndex;
 | 
						|
  EFI_DEBUGGER_SYMBOL_ENTRY   *Entry;
 | 
						|
  CHAR16                      *SymbolName;
 | 
						|
  CHAR16                      *MapfileName;
 | 
						|
 | 
						|
  //
 | 
						|
  // Split one symbol to mapfile name and symbol name
 | 
						|
  //
 | 
						|
  GetMapfileAndSymbol (Symbol, &MapfileName, &SymbolName);
 | 
						|
 | 
						|
  *Address = 0;
 | 
						|
  //
 | 
						|
  // Go through each object
 | 
						|
  //
 | 
						|
  Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
 | 
						|
  for (ObjectIndex = 0; ObjectIndex < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
 | 
						|
    //
 | 
						|
    // Check MapfileName
 | 
						|
    //
 | 
						|
    if ((MapfileName != NULL) && (StriCmp (Object[ObjectIndex].Name, MapfileName) != 0)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Go through each entry
 | 
						|
    //
 | 
						|
    Entry = Object[ObjectIndex].Entry;
 | 
						|
    for (EntryIndex = 0; EntryIndex < Object[ObjectIndex].EntryCount; EntryIndex++) {
 | 
						|
      //
 | 
						|
      // Check SymbolName (case sensitive)
 | 
						|
      //
 | 
						|
      if (StrCmpUnicodeAndAscii (SymbolName, Entry[EntryIndex].Name) == 0) {
 | 
						|
        if ((*Address != 0) && (MapfileName == NULL)) {
 | 
						|
          //
 | 
						|
          // Find the duplicated symbol
 | 
						|
          //
 | 
						|
          EDBPrint (L"Duplicated Symbol found!\n");
 | 
						|
          return EFI_NO_MAPPING;
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // record Address
 | 
						|
          //
 | 
						|
          *Address = (Entry[EntryIndex].Rva + Object[ObjectIndex].BaseAddress);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (*Address == 0) {
 | 
						|
    //
 | 
						|
    // Not found
 | 
						|
    //
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |