diff options
Diffstat (limited to 'roms/edk2/MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.c')
-rw-r--r-- | roms/edk2/MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.c | 585 |
1 files changed, 585 insertions, 0 deletions
diff --git a/roms/edk2/MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.c b/roms/edk2/MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.c new file mode 100644 index 000000000..611b2de5d --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.c @@ -0,0 +1,585 @@ +/** @file
+
+Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include "Edb.h"
+
+EFI_DEBUGGER_PRIVATE_DATA mDebuggerPrivate = {
+ EFI_DEBUGGER_SIGNATURE, // Signature
+ IsaEbc, // Isa
+ (EBC_DEBUGGER_MAJOR_VERSION << 16) |
+ EBC_DEBUGGER_MINOR_VERSION, // EfiDebuggerRevision
+ (VM_MAJOR_VERSION << 16) |
+ VM_MINOR_VERSION, // EbcVmRevision
+ {
+ EFI_DEBUGGER_CONFIGURATION_VERSION,
+ &mDebuggerPrivate,
+ }, // DebuggerConfiguration
+ NULL, // DebugImageInfoTableHeader
+ NULL, // Vol
+ NULL, // PciRootBridgeIo
+ mDebuggerCommandSet, // DebuggerCommandSet
+ {0}, // DebuggerSymbolContext
+ 0, // DebuggerBreakpointCount
+ {{0}}, // DebuggerBreakpointContext
+ 0, // CallStackEntryCount
+ {{0}}, // CallStackEntry
+ 0, // TraceEntryCount
+ {{0}}, // TraceEntry
+ {0}, // StepContext
+ {0}, // GoTilContext
+ 0, // InstructionScope
+ EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER, // InstructionNumber
+ EFI_DEBUG_FLAG_EBC_BOE | EFI_DEBUG_FLAG_EBC_BOT, // FeatureFlags
+ 0, // StatusFlags
+ FALSE, // EnablePageBreak
+ NULL // BreakEvent
+};
+
+CHAR16 *mExceptionStr[] = {
+ L"EXCEPT_EBC_UNDEFINED",
+ L"EXCEPT_EBC_DIVIDE_ERROR",
+ L"EXCEPT_EBC_DEBUG",
+ L"EXCEPT_EBC_BREAKPOINT",
+ L"EXCEPT_EBC_OVERFLOW",
+ L"EXCEPT_EBC_INVALID_OPCODE",
+ L"EXCEPT_EBC_STACK_FAULT",
+ L"EXCEPT_EBC_ALIGNMENT_CHECK",
+ L"EXCEPT_EBC_INSTRUCTION_ENCODING",
+ L"EXCEPT_EBC_BAD_BREAK",
+ L"EXCEPT_EBC_SINGLE_STEP",
+};
+
+/**
+
+ Clear all the breakpoint.
+
+ @param DebuggerPrivate EBC Debugger private data structure
+ @param NeedRemove Whether need to remove all the breakpoint
+
+**/
+VOID
+EdbClearAllBreakpoint (
+ IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+ IN BOOLEAN NeedRemove
+ )
+{
+ UINTN Index;
+
+ //
+ // Patch all the breakpoint
+ //
+ for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
+ if (DebuggerPrivate->DebuggerBreakpointContext[Index].State) {
+ CopyMem (
+ (VOID *)(UINTN)DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress,
+ &DebuggerPrivate->DebuggerBreakpointContext[Index].OldInstruction,
+ sizeof(UINT16)
+ );
+ }
+ }
+
+ //
+ // Zero Breakpoint context, if need to remove all breakpoint
+ //
+ if (NeedRemove) {
+ DebuggerPrivate->DebuggerBreakpointCount = 0;
+ ZeroMem (DebuggerPrivate->DebuggerBreakpointContext, sizeof(DebuggerPrivate->DebuggerBreakpointContext));
+ }
+
+ //
+ // Done
+ //
+ return ;
+}
+
+/**
+
+ Set all the breakpoint.
+
+ @param DebuggerPrivate EBC Debugger private data structure
+
+**/
+VOID
+EdbSetAllBreakpoint (
+ IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate
+ )
+{
+ UINTN Index;
+ UINT16 Data16;
+
+ //
+ // Set all the breakpoint (BREAK(3) : 0x0300)
+ //
+ Data16 = 0x0300;
+ for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
+ if (DebuggerPrivate->DebuggerBreakpointContext[Index].State) {
+ CopyMem (
+ (VOID *)(UINTN)DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress,
+ &Data16,
+ sizeof(UINT16)
+ );
+ }
+ }
+
+ //
+ // Check if current break is caused by breakpoint set.
+ // If so, we need to patch memory back to let user see the real memory.
+ //
+ if (DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].BreakpointAddress != 0) {
+ CopyMem (
+ (VOID *)(UINTN)DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].BreakpointAddress,
+ &DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].OldInstruction,
+ sizeof(UINT16)
+ );
+ DebuggerPrivate->StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_BP;
+ }
+
+ //
+ // Done
+ //
+ return ;
+}
+
+/**
+
+ Check all the breakpoint, if match, then set status flag, and record current breakpoint.
+ Then clear all breakpoint to let user see a clean memory
+
+ @param DebuggerPrivate EBC Debugger private data structure
+ @param SystemContext EBC system context.
+
+**/
+VOID
+EdbCheckBreakpoint (
+ IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+ IN EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ UINT64 Address;
+ UINTN Index;
+ BOOLEAN IsHitBreakpoint;
+
+ //
+ // Roll back IP for breakpoint instruction (BREAK(3) : 0x0300)
+ //
+ Address = SystemContext.SystemContextEbc->Ip - sizeof(UINT16);
+
+ //
+ // Check if the breakpoint is hit
+ //
+ IsHitBreakpoint = FALSE;
+ for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
+ if ((DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress == Address) &&
+ (DebuggerPrivate->DebuggerBreakpointContext[Index].State)) {
+ IsHitBreakpoint = TRUE;
+ break;
+ }
+ }
+
+ if (IsHitBreakpoint) {
+ //
+ // If hit, record current breakpoint
+ //
+ DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX] = DebuggerPrivate->DebuggerBreakpointContext[Index];
+ DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].State = TRUE;
+ //
+ // Update: IP and Instruction (NOTE: Since we not allow set breakpoint to BREAK 3, this update is safe)
+ //
+ SystemContext.SystemContextEbc->Ip = Address;
+ //
+ // Set Flags
+ //
+ DebuggerPrivate->StatusFlags |= EFI_DEBUG_FLAG_EBC_BP;
+ } else {
+ //
+ // If not hit, check whether current IP is in breakpoint list,
+ // because STEP will be triggered before execute the instruction.
+ // We should not patch it in de-init.
+ //
+ Address = SystemContext.SystemContextEbc->Ip;
+
+ //
+ // Check if the breakpoint is hit
+ //
+ IsHitBreakpoint = FALSE;
+ for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
+ if ((DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress == Address) &&
+ (DebuggerPrivate->DebuggerBreakpointContext[Index].State)) {
+ IsHitBreakpoint = TRUE;
+ break;
+ }
+ }
+
+ if (IsHitBreakpoint) {
+ //
+ // If hit, record current breakpoint
+ //
+ DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX] = DebuggerPrivate->DebuggerBreakpointContext[Index];
+ DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].State = TRUE;
+ //
+ // Do not set Breakpoint flag. We record the address here just let it not patch breakpoint address when de-init.
+ //
+ } else {
+ //
+ // Zero current breakpoint
+ //
+ ZeroMem (
+ &DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX],
+ sizeof(DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX])
+ );
+ }
+ }
+
+ //
+ // Done
+ //
+ return ;
+}
+
+/**
+ clear all the symbol.
+
+ @param DebuggerPrivate EBC Debugger private data structure
+
+**/
+VOID
+EdbClearSymbol (
+ IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate
+ )
+{
+ EFI_DEBUGGER_SYMBOL_CONTEXT *DebuggerSymbolContext;
+ EFI_DEBUGGER_SYMBOL_OBJECT *Object;
+ UINTN ObjectIndex;
+ UINTN Index;
+
+ //
+ // Go throuth each object
+ //
+ DebuggerSymbolContext = &DebuggerPrivate->DebuggerSymbolContext;
+ for (ObjectIndex = 0; ObjectIndex < DebuggerSymbolContext->ObjectCount; ObjectIndex++) {
+ Object = &DebuggerSymbolContext->Object[ObjectIndex];
+ //
+ // Go throuth each entry
+ //
+ for (Index = 0; Index < Object->EntryCount; Index++) {
+ ZeroMem (&Object->Entry[Index], sizeof(Object->Entry[Index]));
+ }
+ ZeroMem (Object->Name, sizeof(Object->Name));
+ Object->EntryCount = 0;
+ Object->BaseAddress = 0;
+ Object->StartEntrypointRVA = 0;
+ Object->MainEntrypointRVA = 0;
+ //
+ // Free source buffer
+ //
+ for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
+ gBS->FreePool (Object->SourceBuffer[Index]);
+ Object->SourceBuffer[Index] = NULL;
+ }
+ }
+ DebuggerSymbolContext->ObjectCount = 0;
+
+ return ;
+}
+
+/**
+
+ Initialize Debugger private data structure
+
+ @param DebuggerPrivate EBC Debugger private data structure
+ @param ExceptionType Exception type.
+ @param SystemContext EBC system context.
+ @param Initialized Whether the DebuggerPrivate data is initialized.
+
+**/
+EFI_STATUS
+InitDebuggerPrivateData (
+ IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN BOOLEAN Initialized
+ )
+{
+ //
+ // clear STEP flag in any condition.
+ //
+ if (SystemContext.SystemContextEbc->Flags & ((UINT64) VMFLAGS_STEP)) {
+ SystemContext.SystemContextEbc->Flags &= ~((UINT64) VMFLAGS_STEP);
+ }
+
+ if (!Initialized) {
+ //
+ // Initialize everything
+ //
+ DebuggerPrivate->InstructionNumber = EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER;
+
+ DebuggerPrivate->DebuggerBreakpointCount = 0;
+ ZeroMem (DebuggerPrivate->DebuggerBreakpointContext, sizeof(DebuggerPrivate->DebuggerBreakpointContext));
+
+// DebuggerPrivate->StatusFlags = 0;
+
+ DebuggerPrivate->DebuggerSymbolContext.DisplaySymbol = TRUE;
+ DebuggerPrivate->DebuggerSymbolContext.DisplayCodeOnly = FALSE;
+ DebuggerPrivate->DebuggerSymbolContext.ObjectCount = 0;
+ } else {
+ //
+ // Already initialized, just check Breakpoint here.
+ //
+ if (ExceptionType == EXCEPT_EBC_BREAKPOINT) {
+ EdbCheckBreakpoint (DebuggerPrivate, SystemContext);
+ }
+
+ //
+ // Clear all breakpoint
+ //
+ EdbClearAllBreakpoint (DebuggerPrivate, FALSE);
+ }
+
+ //
+ // Set Scope to currentl IP. (Note: Check Breakpoint may change Ip)
+ //
+ DebuggerPrivate->InstructionScope = SystemContext.SystemContextEbc->Ip;
+
+ //
+ // Done
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+
+ De-initialize Debugger private data structure.
+
+ @param DebuggerPrivate EBC Debugger private data structure
+ @param ExceptionType Exception type.
+ @param SystemContext EBC system context.
+ @param Initialized Whether the DebuggerPrivate data is initialized.
+
+**/
+EFI_STATUS
+DeinitDebuggerPrivateData (
+ IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN BOOLEAN Initialized
+ )
+{
+ if (!Initialized) {
+ //
+ // If it does not want initialized state, de-init everything
+ //
+ DebuggerPrivate->FeatureFlags = EFI_DEBUG_FLAG_EBC_BOE | EFI_DEBUG_FLAG_EBC_BOT;
+ DebuggerPrivate->CallStackEntryCount = 0;
+ DebuggerPrivate->TraceEntryCount = 0;
+ ZeroMem (DebuggerPrivate->CallStackEntry, sizeof(DebuggerPrivate->CallStackEntry));
+ ZeroMem (DebuggerPrivate->TraceEntry, sizeof(DebuggerPrivate->TraceEntry));
+
+ //
+ // Clear all breakpoint
+ //
+ EdbClearAllBreakpoint (DebuggerPrivate, TRUE);
+
+ //
+ // Clear symbol
+ //
+ EdbClearSymbol (DebuggerPrivate);
+ } else {
+ //
+ // If it wants to keep initialized state, just set breakpoint.
+ //
+ EdbSetAllBreakpoint (DebuggerPrivate);
+ }
+
+ //
+ // Clear Step context
+ //
+ ZeroMem (&mDebuggerPrivate.StepContext, sizeof(mDebuggerPrivate.StepContext));
+ DebuggerPrivate->StatusFlags = 0;
+
+ //
+ // Done
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Print the reason of current break to EbcDebugger.
+
+ @param DebuggerPrivate EBC Debugger private data structure
+ @param ExceptionType Exception type.
+ @param SystemContext EBC system context.
+ @param Initialized Whether the DebuggerPrivate data is initialized.
+
+**/
+VOID
+PrintExceptionReason (
+ IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_SYSTEM_CONTEXT SystemContext,
+ IN BOOLEAN Initialized
+ )
+{
+ //
+ // Print break status
+ //
+ if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_GT) == EFI_DEBUG_FLAG_EBC_GT) {
+ EDBPrint (L"Break on GoTil\n");
+ } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOC) == EFI_DEBUG_FLAG_EBC_BOC) {
+ EDBPrint (L"Break on CALL\n");
+ } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOCX) == EFI_DEBUG_FLAG_EBC_BOCX) {
+ EDBPrint (L"Break on CALLEX\n");
+ } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOR) == EFI_DEBUG_FLAG_EBC_BOR) {
+ EDBPrint (L"Break on RET\n");
+ } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOE) == EFI_DEBUG_FLAG_EBC_BOE) {
+ EDBPrint (L"Break on Entrypoint\n");
+ } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOT) == EFI_DEBUG_FLAG_EBC_BOT) {
+ EDBPrint (L"Break on Thunk\n");
+ } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_STEPOVER) == EFI_DEBUG_FLAG_EBC_STEPOVER) {
+ EDBPrint (L"Break on StepOver\n");
+ } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_STEPOUT) == EFI_DEBUG_FLAG_EBC_STEPOUT) {
+ EDBPrint (L"Break on StepOut\n");
+ } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BP) == EFI_DEBUG_FLAG_EBC_BP) {
+ EDBPrint (L"Break on Breakpoint\n");
+ } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOK) == EFI_DEBUG_FLAG_EBC_BOK) {
+ EDBPrint (L"Break on Key\n");
+ } else {
+ EDBPrint (L"Exception Type - %x", (UINTN)ExceptionType);
+ if ((ExceptionType >= EXCEPT_EBC_UNDEFINED) && (ExceptionType <= EXCEPT_EBC_STEP)) {
+ EDBPrint (L" (%s)\n", mExceptionStr[ExceptionType]);
+ } else {
+ EDBPrint (L"\n");
+ }
+ }
+
+ return ;
+}
+
+/**
+
+ The default Exception Callback for the VM interpreter.
+ In this function, we report status code, and print debug information
+ about EBC_CONTEXT, then dead loop.
+
+ @param ExceptionType Exception type.
+ @param SystemContext EBC system context.
+
+**/
+VOID
+EFIAPI
+EdbExceptionHandler (
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ CHAR16 InputBuffer[EFI_DEBUG_INPUS_BUFFER_SIZE];
+ CHAR16 *CommandArg;
+ EFI_DEBUGGER_COMMAND DebuggerCommand;
+ EFI_DEBUG_STATUS DebugStatus;
+ STATIC BOOLEAN mInitialized;
+
+ mInitialized = FALSE;
+
+ DEBUG ((DEBUG_ERROR, "Hello EBC Debugger!\n"));
+
+ if (!mInitialized) {
+ //
+ // Print version
+ //
+ EDBPrint (
+ L"EBC Interpreter Version - %d.%d\n",
+ (UINTN)VM_MAJOR_VERSION,
+ (UINTN)VM_MINOR_VERSION
+ );
+ EDBPrint (
+ L"EBC Debugger Version - %d.%d\n",
+ (UINTN)EBC_DEBUGGER_MAJOR_VERSION,
+ (UINTN)EBC_DEBUGGER_MINOR_VERSION
+ );
+ }
+ //
+ // Init Private Data
+ //
+ InitDebuggerPrivateData (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
+
+ //
+ // EDBPrint basic info
+ //
+ PrintExceptionReason (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
+
+ EdbShowDisasm (&mDebuggerPrivate, SystemContext);
+ // EFI_BREAKPOINT ();
+
+ if (!mInitialized) {
+ //
+ // Interactive with user
+ //
+ EDBPrint (L"\nPlease enter command now, \'h\' for help.\n");
+ EDBPrint (L"(Using <Command> -b <...> to enable page break.)\n");
+ }
+ mInitialized = TRUE;
+
+ //
+ // Dispatch each command
+ //
+ while (TRUE) {
+ //
+ // Get user input
+ //
+ Input (L"\n\r" EFI_DEBUG_PROMPT_STRING, InputBuffer, EFI_DEBUG_INPUS_BUFFER_SIZE);
+ EDBPrint (L"\n");
+
+ //
+ // Get command
+ //
+ DebuggerCommand = MatchDebuggerCommand (InputBuffer, &CommandArg);
+ if (DebuggerCommand == NULL) {
+ EDBPrint (L"ERROR: Command not found!\n");
+ continue;
+ }
+
+ //
+ // Check PageBreak;
+ //
+ if (CommandArg != NULL) {
+ if (StriCmp (CommandArg, L"-b") == 0) {
+ CommandArg = StrGetNextTokenLine (L" ");
+ mDebuggerPrivate.EnablePageBreak = TRUE;
+ }
+ }
+
+ //
+ // Dispatch command
+ //
+ DebugStatus = DebuggerCommand (CommandArg, &mDebuggerPrivate, ExceptionType, SystemContext);
+ mDebuggerPrivate.EnablePageBreak = FALSE;
+
+ //
+ // Check command return status
+ //
+ if (DebugStatus == EFI_DEBUG_RETURN) {
+ mInitialized = FALSE;
+ break;
+ } else if (DebugStatus == EFI_DEBUG_BREAK) {
+ break;
+ } else if (DebugStatus == EFI_DEBUG_CONTINUE) {
+ continue;
+ } else {
+ ASSERT (FALSE);
+ }
+ }
+
+ //
+ // Deinit Private Data
+ //
+ DeinitDebuggerPrivateData (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
+
+ DEBUG ((DEBUG_ERROR, "Goodbye EBC Debugger!\n"));
+
+ return;
+}
|