summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c')
-rw-r--r--MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c2669
1 files changed, 2669 insertions, 0 deletions
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c
new file mode 100644
index 0000000000..9573c43a9d
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c
@@ -0,0 +1,2669 @@
+/*++
+
+Copyright (c) 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ EdbSymbol.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+EFI_STATUS
+EdbLoadSymbolSingleEntry (
+ IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,
+ IN CHAR8 *Name,
+ IN CHAR8 *ObjName,
+ IN UINTN Address,
+ IN EFI_DEBUGGER_SYMBOL_TYPE Type
+ )
+/*++
+
+Routine Description:
+
+ Load single symbol entry
+
+Arguments:
+
+ Object - Symbol file object
+ Name - Symbol name
+ ObjName - Object name
+ Address - Symbol address
+ Type - Symbol type
+
+Returns:
+
+ EFI_SUCCESS - add single symbol entry successfully
+
+--*/
+{
+ 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
+===============================================================================
+
+--*/
+EFI_STATUS
+EdbLoadSymbolEntryByIec (
+ IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Load symbol entry by Iec
+
+Arguments:
+
+ DebuggerPrivate - EBC Debugger private data structure
+ Object - Symbol file object
+ BufferSize - Symbol file buffer size
+ Buffer - Symbol file buffer
+
+Returns:
+
+ EFI_SUCCESS - add symbol entry successfully
+
+--*/
+{
+ CHAR8 *LineBuffer;
+ CHAR8 *FieldBuffer;
+ EFI_DEBUGGER_SYMBOL_ENTRY *Entry;
+ EDB_EBC_MAP_PARSE_STATE MapParseState;
+ EDB_EBC_SYMBOL_PARSE_STATE SymbolParseState;
+ CHAR8 *Name;
+ CHAR8 *ObjName;
+ UINTN Address;
+ EFI_DEBUGGER_SYMBOL_TYPE Type;
+
+ Entry = Object->Entry;
+
+ //
+ // 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;
+}
+
+EFI_STATUS
+EdbLoadSymbolEntry (
+ IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Load symbol entry
+
+Arguments:
+
+ Object - Symbol file object
+ BufferSize - Symbol file buffer size
+ Buffer - Symbol file buffer
+
+Returns:
+
+ EFI_SUCCESS - add symbol entry successfully
+
+--*/
+{
+ //
+ // 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);
+}
+
+EFI_DEBUGGER_SYMBOL_OBJECT *
+EdbFindSymbolFile (
+ IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+ IN CHAR16 *FileName,
+ IN OUT UINTN *Index OPTIONAL
+ )
+/*++
+
+Routine Description:
+
+ Find symbol file by name
+
+Arguments:
+
+ DebuggerPrivate - EBC Debugger private data structure
+ FileName - Symbol file name
+ Index - Symbol file index
+
+Returns:
+
+ Object
+
+--*/
+{
+ 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;
+}
+
+UINTN
+EbdFindSymbolAddress (
+ IN UINTN Address,
+ IN EDB_MATCH_SYMBOL_TYPE Type,
+ OUT EFI_DEBUGGER_SYMBOL_OBJECT **RetObject,
+ OUT EFI_DEBUGGER_SYMBOL_ENTRY **RetEntry
+ )
+/*++
+
+Routine Description:
+
+ Find symbol by address
+
+Arguments:
+
+ Address - Symbol address
+ Type - Search type
+ RetObject - Symbol object
+ RetEntry - Symbol entry
+
+Returns:
+
+ Nearest symbol address
+
+--*/
+{
+ 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;
+}
+
+EFI_STATUS
+EdbUnloadSymbol (
+ IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+ IN CHAR16 *FileName
+ )
+/*++
+
+Routine Description:
+
+ Unload symbol file by name
+
+Arguments:
+
+ DebuggerPrivate - EBC Debugger private data structure
+ FileName - Symbol file name
+
+Returns:
+
+ EFI_SUCCESS - unload symbol successfully
+
+--*/
+{
+ 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;
+}
+
+EFI_STATUS
+EdbLoadSymbol (
+ IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+ IN CHAR16 *FileName,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Load symbol file by name
+
+Arguments:
+
+ DebuggerPrivate - EBC Debugger private data structure
+ FileName - Symbol file name
+ BufferSize - Symbol file buffer size
+ Buffer - Symbol file buffer
+
+Returns:
+
+ EFI_SUCCESS - load symbol successfully
+
+--*/
+{
+ 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;
+}
+
+CHAR8 *
+GetPdbPath (
+ VOID *ImageBase
+ )
+/*++
+
+Routine Description:
+
+ Located PDB path name in PE image
+
+Arguments:
+
+ ImageBase - base of PE to search
+
+Returns:
+
+ Pointer into image at offset of PDB file name if PDB file name is found,
+ Otherwise a pointer to an empty string.
+
+--*/
+{
+ 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;
+}
+
+BOOLEAN
+MatchPdbAndMap (
+ IN CHAR8 *PdbFileName,
+ IN CHAR16 *MapFileName
+ )
+/*++
+
+Routine Description:
+
+ Check whether PDB file and MAP file have same name
+
+Arguments:
+
+ PdbFileName - PDB file name
+ MapFileName - MAP file name
+
+Returns:
+
+ TRUE - PDB and MAP file name match
+ FALSE - PDB and MAP file name not match
+
+--*/
+{
+ 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;
+
+VOID
+EdbFixDebugImageInfoTable (
+ IN OUT EFI_DEBUG_IMAGE_INFO_TABLE_HEADER **DebugImageInfoTableHeader
+ )
+/*
+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 | | |
+ +------------------------+ +------------------------+
+
+*/
+{
+ 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
+//
+
+EFI_STATUS
+EdbPatchSymbolRVA (
+ IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+ IN CHAR16 *FileName,
+ IN EDB_EBC_IMAGE_RVA_SEARCH_TYPE SearchType
+ )
+/*++
+
+Routine Description:
+
+ Patch symbol RVA
+
+Arguments:
+
+ DebuggerPrivate - EBC Debugger private data structure
+ FileName - Symbol file name
+ SearchType - Search type for Object
+
+Returns:
+
+ EFI_SUCCESS - Patch symbol RVA successfully
+ EFI_NOT_FOUND - Symbol RVA base not found
+
+--*/
+{
+ 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;
+}
+
+BOOLEAN
+MatchObjAndCod (
+ IN CHAR8 *ObjFileName,
+ IN CHAR16 *CodFileName
+ )
+/*++
+
+Routine Description:
+
+ Check whether OBJ file and COD file have same name
+
+Arguments:
+
+ ObjFileName - OBJ file name
+ CodFileName - COD file name
+
+Returns:
+
+ TRUE - OBJ and COD file name match
+ FALSE - OBJ and COD file name not match
+
+--*/
+{
+ 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.
+
+ Sample as follows: EbcTest.cod
+===============================================================================
+; -- Machine type EFI
+; mark_description "Intel(R) C Compiler for EFI Byte Code, Version 1.2 Build 20040123";
+; mark_description "XXX";
+;ident "Intel(R) C Compiler for EFI Byte Code, Version 1.2 Build 20040123"
+;ident "XXX"
+ .686P
+ .387
+_TEXT SEGMENT PARA PUBLIC USE32 'CODE'
+_TEXT ENDS
+_DATA SEGMENT PARA PUBLIC USE32 'DATA'
+ ALIGN 010H
+_DATA ENDS
+_BSS SEGMENT PARA PUBLIC USE32 'BSS'
+ ALIGN 010H
+_BSS ENDS
+_VARBSS SEGMENT PARA PUBLIC USE32 'BSS'
+ ALIGN 010H
+_VARBSS ENDS
+ ASSUME CS:FLAT,DS:FLAT,SS:FLAT
+_DATA SEGMENT PARA PUBLIC USE32 'DATA'
+TestVariable2 DD 000000003H,000000000H ; u64
+_DATA ENDS
+_DATA SEGMENT PARA PUBLIC USE32 'DATA'
+_DATA ENDS
+_TEXT SEGMENT PARA PUBLIC USE32 'CODE'
+; -- Begin EfiMain
+; mark_begin;
+ PUBLIC EfiMain
+EfiMain PROC NEAR
+$B3$1:; 11a
+$LN45:
+
+;117 ; {
+
+ 0011a 60 00 70 80 MOVqw R0, R0(+0,-112) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:117
+$LN46:
+
+;118 ; UINT16 test = 0x1234;
+
+ 0011e 77 58 58 00 34
+ 12 MOVIww @R0(+0,+88), +4660 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:118
+$LN47:
+
+;121 ; EFI_STATUS Status;
+;121 ;
+;121 ; SystemTable->ConOut->OutputString (
+
+ 00124 72 87 01 12 MOVnw R7, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:121
+ 00128 72 f7 85 21 MOVnw R7, @R7(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:121
+$LN48:
+
+;122 ; SystemTable->ConOut,
+
+ 0012c 72 84 01 12 MOVnw R4, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
+ 00130 72 c8 85 21 MOVnw @R0, @R4(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
+ 00134 b9 34 00 00 00
+ 00 MOVreld R4, __STRING$1 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
+ 0013a b2 48 01 10 MOVnw @R0(+1,+0), R4 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
+ 0013e 83 2f 01 00 00
+ 10 CALLEX @R7(+1,+0) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
+$B3$2:; 144
+$LN49:
+
+;125 ; L"Hello EBC Test!\n\r"
+;125 ; );
+;125 ; EFI_BREAKPOINT ();
+
+ 00144 00 03 BREAK 3 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:125
+$B3$3:; 146
+$LN50:
+
+;126 ; TestVariable1 = 6;
+
+ 00146 b9 37 00 00 00
+ 00 MOVreld R7, TestVariable1 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:126
+ 0014c 78 0f 06 00 MOVInw @R7, (0,6) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:126
+$LN51:
+
+;127 ; TestSubRoutineSub (1, 5);
+
+ 00150 78 08 01 00 MOVInw @R0, (0,1) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127
+ 00154 78 48 01 10 05
+ 00 MOVInw @R0(1,0), (0,5) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127
+ 0015a 83 10 00 00 00
+ 00 CALL TestSubRoutineSub ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127
+$B3$4:; 160
+$LN52:
+
+;129 ;
+;129 ; SystemTable->ConOut->OutputString (
+
+ 00160 72 87 01 12 MOVnw R7, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:129
+ 00164 72 f7 85 21 MOVnw R7, @R7(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:129
+$LN53:
+
+;130 ; SystemTable->ConOut,
+
+ 00168 72 84 01 12 MOVnw R4, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:130
+ 0016c 72 c8 85 21 MOVnw @R0, @R4(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:130
+$LN54:
+
+;131 ; TestStr
+
+ 00170 b9 34 00 00 00
+ 00 MOVreld R4, TestStr ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131
+ 00176 b2 c8 01 10 MOVnw @R0(+1, +0), @R4 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131
+ 0017a 83 2f 01 00 00
+ 10 CALLEX @R7(+1,+0) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131
+$B3$5:; 180
+$LN55:
+
+;134 ; );
+;134 ;
+;134 ; test = test & 0xFF;
+
+ 00180 de 88 58 00 58
+ 00 MOVww @R0(+0,+88), @R0(+0,+88) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:134
+$LN56:
+
+;139 ; if (test != 0x34) {
+;139 ; // EFI_BREAKPOINT ();
+;139 ; }
+;139 ;
+;139 ; Status = TestSubRoutine (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+
+ 00186 78 08 01 00 MOVInw @R0, (0,1) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+ 0018a 78 48 01 10 02
+ 00 MOVInw @R0(1,0), (0,2) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+ 00190 78 48 02 10 03
+ 00 MOVInw @R0(2,0), (0,3) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+ 00196 78 48 03 10 04
+ 00 MOVInw @R0(3,0), (0,4) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+ 0019c 78 48 04 20 05
+ 00 MOVInw @R0(4,0), (0,5) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+ 001a2 78 48 05 20 06
+ 00 MOVInw @R0(5,0), (0,6) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+ 001a8 78 48 06 20 07
+ 00 MOVInw @R0(6,0), (0,7) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+ 001ae 78 48 07 20 08
+ 00 MOVInw @R0(7,0), (0,8) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+ 001b4 78 48 08 20 09
+ 00 MOVInw @R0(8,0), (0,9) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+ 001ba 78 48 09 20 0a
+ 00 MOVInw @R0(9,0), (0,10) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+ 001c0 83 10 00 00 00
+ 00 CALL TestSubRoutine ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+$B3$10:; 1c6
+ 001c6 b2 78 60 00 MOVnw @R0(+0,+96), R7 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+$B3$6:; 1ca
+$LN57:
+ 001ca f2 88 50 00 60
+ 00 MOVnw @R0(+0,+80), @R0(+0,+96) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+$LN58:
+
+;141 ;
+;141 ; SystemTable->ConOut->OutputString (
+
+ 001d0 72 87 01 12 MOVnw R7, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:141
+ 001d4 72 f7 85 21 MOVnw R7, @R7(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:141
+$LN59:
+
+;142 ; SystemTable->ConOut,
+
+ 001d8 72 84 01 12 MOVnw R4, @R0(+1,+128) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
+ 001dc 72 c8 85 21 MOVnw @R0, @R4(+5,+24) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
+ 001e0 b9 34 00 00 00
+ 00 MOVreld R4, __STRING$2 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
+ 001e6 b2 48 01 10 MOVnw @R0(+1,+0), R4 ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
+ 001ea 83 2f 01 00 00
+ 10 CALLEX @R7(+1,+0) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
+$B3$7:; 1f0
+$LN60:
+
+;146 ; L"Goodbye EBC Test!\n\r"
+;146 ; );
+;146 ;
+;146 ; return Status;
+
+ 001f0 72 87 50 00 MOVnw R7, @R0(+0,+80) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146
+ 001f4 60 00 70 00 MOVqw R0, R0(+0,+112) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146
+ 001f8 04 00 RET ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146
+; mark_end;
+EfiMain ENDP
+_TEXT ENDS
+_DATA SEGMENT PARA PUBLIC USE32 'DATA'
+ DB 3 DUP (0) ; pad
+__STRING$2 DW 71 ; u16
+ DW 111 ; u16
+ DW 111 ; u16
+ DW 100 ; u16
+ DW 98 ; u16
+ DW 121 ; u16
+ DW 101 ; u16
+ DW 32 ; u16
+ DW 69 ; u16
+ DW 66 ; u16
+ DW 67 ; u16
+ DW 32 ; u16
+ DW 84 ; u16
+ DW 101 ; u16
+ DW 115 ; u16
+ DW 116 ; u16
+ DW 33 ; u16
+ DW 10 ; u16
+ DW 13 ; u16
+ DW 0 ; u16
+__STRING$1 DW 72 ; u16
+ DW 101 ; u16
+ DW 108 ; u16
+ DW 108 ; u16
+ DW 111 ; u16
+ DW 32 ; u16
+ DW 69 ; u16
+ DW 66 ; u16
+ DW 67 ; u16
+ DW 32 ; u16
+ DW 84 ; u16
+ DW 101 ; u16
+ DW 115 ; u16
+ DW 116 ; u16
+ DW 33 ; u16
+ DW 10 ; u16
+ DW 13 ; u16
+ DW 0 ; u16
+_DATA ENDS
+_DATA SEGMENT PARA PUBLIC USE32 'DATA'
+_DATA ENDS
+; -- End EfiMain
+_DATA SEGMENT PARA PUBLIC USE32 'DATA'
+__STRING$0 DW 55 ; u16
+ DW 56 ; u16
+ DW 57 ; u16
+ DW 52 ; u16
+ DW 53 ; u16
+ DW 54 ; u16
+ DW 49 ; u16
+ DW 50 ; u16
+ DW 51 ; u16
+ DW 13 ; u16
+ DW 10 ; u16
+ DW 0 ; u16
+_DATA ENDS
+_VARBSS SEGMENT PARA PUBLIC USE32 'BSS'
+ PUBLIC TestStr
+TestStr DD 2 DUP (?) ; pad
+ PUBLIC TestVariable1
+TestVariable1 DD 2 DUP (?) ; pad
+_VARBSS ENDS
+_VARBSS_INIT SEGMENT DWORD PUBLIC USE32 'CODE'
+; -- Begin varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2
+ PUBLIC varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2
+varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2 PROC NEAR
+ 00000 b9 34 00 00 00
+ 00 MOVreld R4, TestStr
+ 00006 b9 35 00 00 00
+ 00 MOVreld R5, __STRING$0
+ 0000c 33 5c MOVnd @R4, R5
+ 0000e b9 34 00 00 00
+ 00 MOVreld R4, TestVariable1
+ 00014 78 0c 04 00 MOVInw @R4, (0,4)
+ 00018 04 00 RET
+; -- End varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2
+_VARBSS_INIT ENDS
+_DATA SEGMENT PARA PUBLIC USE32 'DATA'
+_DATA ENDS
+EXTRN TestSubRoutineSub:PROC
+ END
+
+===============================================================================
+
+--*/
+CHAR8 *
+EdbLoadCodBySymbolByIec (
+ IN CHAR8 *Name,
+ IN VOID *Buffer,
+ IN UINTN BufferSize,
+ OUT UINTN *CodeBufferSize,
+ OUT UINTN *FuncOffset
+ )
+/*++
+
+Routine Description:
+
+ Load code by symbol by Iec
+
+Arguments:
+
+ Name - Symbol file name
+ BufferSize - Symbol file buffer size
+ Buffer - Symbol file buffer
+ CodeBufferSize - Code buffer size
+ FuncOffset - Code funcion offset
+
+Returns:
+
+ CodeBuffer
+
+--*/
+{
+ CHAR8 *LineBuffer;
+ CHAR8 *FieldBuffer;
+ VOID *BufferStart;
+ VOID *BufferEnd;
+ UINTN Offset;
+ EDB_EBC_COD_PARSE_STATE CodParseState;
+ CHAR8 Char[2] = {9, 0};
+
+ //
+ // Init
+ //
+ 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);
+ 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;
+}
+
+CHAR8 *
+EdbLoadCodBySymbol (
+ IN CHAR8 *Name,
+ IN VOID *Buffer,
+ IN UINTN BufferSize,
+ OUT UINTN *CodeBufferSize,
+ OUT UINTN *FuncOffset
+ )
+/*++
+
+Routine Description:
+
+ Load code by symbol
+
+Arguments:
+
+ Name - Symbol file name
+ BufferSize - Symbol file buffer size
+ Buffer - Symbol file buffer
+ CodeBufferSize - Code buffer size
+ FuncOffset - Code funcion offset
+
+Returns:
+
+ CodeBuffer
+
+--*/
+{
+ //
+ // 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);
+}
+
+VOID *
+EdbFindCodeFromObject (
+ IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+ IN EFI_DEBUGGER_SYMBOL_OBJECT *Object,
+ IN CHAR16 *FileName
+ )
+/*++
+
+Routine Description:
+
+ Find code from object
+
+Arguments:
+
+ Object - Symbol object
+ FileName - File name
+
+Returns:
+
+ CodeBuffer
+
+--*/
+{
+ 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;
+}
+
+EFI_STATUS
+EdbLoadCode (
+ IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+ IN CHAR16 *MapFileName,
+ IN CHAR16 *FileName,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Load code
+
+Arguments:
+
+ DebuggerPrivate - EBC Debugger private data structure
+ MapFileName - Symbol file name
+ FileName - Code file name
+ BufferSize - Code file buffer size
+ Buffer - Code file buffer
+
+Returns:
+
+ EFI_SUCCESS - Code loaded successfully
+
+--*/
+{
+ 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;
+}
+
+EFI_STATUS
+EdbUnloadCode (
+ IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+ IN CHAR16 *MapFileName,
+ IN CHAR16 *FileName,
+ OUT VOID **Buffer
+ )
+/*++
+
+Routine Description:
+
+ Unload code
+
+Arguments:
+
+ DebuggerPrivate - EBC Debugger private data structure
+ MapFileName - Symbol file name
+ FileName - Code file name
+ Buffer - Code file buffer
+
+Returns:
+
+ EFI_SUCCESS - Code unloaded successfully
+
+--*/
+{
+ 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;
+}
+
+EFI_STATUS
+EdbAddCodeBuffer (
+ IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+ IN CHAR16 *MapFileName,
+ IN CHAR16 *CodeFileName,
+ IN UINTN SourceBufferSize,
+ IN VOID *SourceBuffer
+ )
+/*++
+
+Routine Description:
+
+ Add code buffer
+
+Arguments:
+
+ DebuggerPrivate - EBC Debugger private data structure
+ MapFileName - Symbol file name
+ CodeFileName - Code file name
+ SourceBufferSize- Code buffer size
+ SourceBuffer - Code buffer
+
+Returns:
+
+ EFI_SUCCESS - CodeBuffer added successfully
+
+--*/
+{
+ 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;
+}
+
+EFI_STATUS
+EdbDeleteCodeBuffer (
+ IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+ IN CHAR16 *MapFileName,
+ IN CHAR16 *CodeFileName,
+ IN VOID *SourceBuffer
+ )
+/*++
+
+Routine Description:
+
+ Delete code buffer
+
+Arguments:
+
+ DebuggerPrivate - EBC Debugger private data structure
+ MapFileName - Symbol file name
+ CodeFileName - Code file name
+ SourceBuffer - Code buffer
+
+Returns:
+
+ EFI_SUCCESS - CodeBuffer deleted successfully
+
+--*/
+{
+ 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;
+}
+
+CHAR8 *
+FindSymbolStr (
+ IN UINTN Address
+ )
+/*++
+
+Routine Description:
+
+ Find the symbol string according to address
+
+Arguments:
+
+ Address - Symbol address
+
+Returns:
+
+ Symbol string
+
+--*/
+{
+ 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;
+}
+
+UINTN
+EdbGetLineNumberAndOffsetFromThisLine (
+ IN VOID *Line,
+ OUT UINTN *Offset
+ )
+/*++
+
+Routine Description:
+
+ Get line number and offset from this line in code file
+
+Arguments:
+
+ Line - Line buffer in code file
+ Offset - Offset to functin entry
+
+Returns:
+
+ Line number
+
+--*/
+{
+ 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;
+
+UINTN
+EdbGetLineNumberFromCode (
+ IN EFI_DEBUGGER_SYMBOL_ENTRY *Entry,
+ IN UINTN FuncOffset,
+ IN EDB_EBC_LINE_SEARCH_TYPE SearchType
+ )
+/*++
+
+Routine Description:
+
+ Get line number from this code file
+
+Arguments:
+
+ Entry - Symbol entry
+ FuncOffset - Offset to functin entry
+ SearchType - Search type for the code
+
+Returns:
+
+ Line number
+
+--*/
+{
+ 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;
+}
+
+VOID *
+EdbGetSourceStrFromCodeByLine (
+ IN EFI_DEBUGGER_SYMBOL_ENTRY *Entry,
+ IN UINTN LineNumber,
+ IN VOID **FuncEnd
+ )
+/*++
+
+Routine Description:
+
+ Get the source string from this code file by line
+
+Arguments:
+
+ Entry - Symbol entry
+ LineNumber - line number
+ FuncEnd - Function end
+
+Returns:
+
+ Funtion start
+
+--*/
+{
+ 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;
+}
+
+VOID *
+EdbGetSourceStrFromCode (
+ IN EFI_DEBUGGER_SYMBOL_ENTRY *Entry,
+ IN UINTN FuncOffset,
+ IN VOID **FuncEnd
+ )
+/*++
+
+Routine Description:
+
+ Get source string from this code file
+
+Arguments:
+
+ Entry - Symbol entry
+ FuncOffset - Offset to functin entry
+ FuncEnd - Function end
+
+Returns:
+
+ Funtion start
+
+--*/
+{
+ 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);
+}
+
+UINTN
+EdbPrintSource (
+ IN UINTN Address,
+ IN BOOLEAN IsPrint
+ )
+/*++
+
+Routine Description:
+
+ Print source
+
+Arguments:
+
+ Address - Instruction address
+ IsPrint - Whether need to print
+
+Returns:
+
+ 1 - find the source
+ 0 - not find the source
+
+--*/
+{
+ 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) {
+ 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 ;
+}
+
+VOID
+GetMapfileAndSymbol (
+ IN CHAR16 *Symbol,
+ OUT CHAR16 **MapfileName,
+ OUT CHAR16 **SymbolName
+ )
+/*++
+
+Routine Description:
+
+ Get Mapfile and SymbolName from one symbol format: [MapFileName:]SymbolName
+
+Arguments:
+
+ Symbol - whole Symbol name
+ MapfileName - the mapfile name in the symbol
+ SymbolName - the symbol name in the symbol
+
+Returns:
+
+ None
+
+--*/
+{
+ 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 ;
+}
+
+EFI_STATUS
+Symboltoi (
+ IN CHAR16 *Symbol,
+ OUT UINTN *Address
+ )
+/*++
+
+Routine Description:
+
+ Convert a symbol to an address
+
+Arguments:
+
+ Symbol - Symbol name
+ Address - Symbol address
+
+Returns:
+
+ EFI_SUCCESS - symbol found and address returned.
+ EFI_NOT_FOUND - symbol not found
+ EFI_NO_MAPPING - duplicated symbol not found
+
+--*/
+{
+ 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;
+}