CloverBootloader/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbHook.c

834 lines
21 KiB
C
Raw Normal View History

/** @file
Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "Edb.h"
/**
Check the Hook flag, and trigger exception if match.
@param VmPtr - EbcDebuggerCheckHookFlag
@param Flag - Feature flag
**/
VOID
EbcDebuggerCheckHookFlag (
IN VM_CONTEXT *VmPtr,
IN UINT32 Flag
)
{
if ((mDebuggerPrivate.FeatureFlags & Flag) == Flag) {
mDebuggerPrivate.StatusFlags = Flag;
EbcDebugSignalException (
EXCEPT_EBC_BREAKPOINT,
EXCEPTION_FLAG_NONE,
VmPtr
);
}
return ;
}
/**
It will record soruce address for Callstack entry.
@param SourceEntry - Source address
@param Type - Branch type
**/
VOID
EbcDebuggerPushCallstackSource (
IN UINT64 SourceEntry,
IN EFI_DEBUGGER_BRANCH_TYPE Type
)
{
if (mDebuggerPrivate.CallStackEntryCount > EFI_DEBUGGER_CALLSTACK_MAX) {
ASSERT (FALSE);
mDebuggerPrivate.CallStackEntryCount = EFI_DEBUGGER_CALLSTACK_MAX;
}
//
// Record the new callstack entry
//
mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].SourceAddress = SourceEntry;
mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].Type = Type;
//
// Do not change CallStackEntryCount
//
return ;
}
/**
It will record parameter for Callstack entry.
@param ParameterAddress - The address for the parameter
@param Type - Branch type
**/
VOID
EbcDebuggerPushCallstackParameter (
IN UINT64 ParameterAddress,
IN EFI_DEBUGGER_BRANCH_TYPE Type
)
{
if (mDebuggerPrivate.CallStackEntryCount > EFI_DEBUGGER_CALLSTACK_MAX) {
ASSERT (FALSE);
mDebuggerPrivate.CallStackEntryCount = EFI_DEBUGGER_CALLSTACK_MAX;
}
//
// Record the new callstack parameter
//
mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].ParameterAddr = (UINTN)ParameterAddress;
CopyMem(
mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].Parameter,
(VOID *)(UINTN)ParameterAddress,
sizeof(mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].Parameter)
);
//
// Do not change CallStackEntryCount
//
return ;
}
/**
It will record source address for callstack entry.
@param DestEntry - Source address
@param Type - Branch type
**/
VOID
EbcDebuggerPushCallstackDest (
IN UINT64 DestEntry,
IN EFI_DEBUGGER_BRANCH_TYPE Type
)
{
UINTN Index;
if (mDebuggerPrivate.CallStackEntryCount < EFI_DEBUGGER_CALLSTACK_MAX) {
//
// If there is empty entry for callstack, add it
//
ASSERT (mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].Type == Type);
mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].DestAddress = DestEntry;
mDebuggerPrivate.CallStackEntryCount ++;
} else {
//
// If there is no empty entry for callstack, throw the oldest one
//
ASSERT (mDebuggerPrivate.CallStackEntry[EFI_DEBUGGER_TRACE_MAX].Type == Type);
for (Index = 0; Index < EFI_DEBUGGER_CALLSTACK_MAX; Index++) {
CopyMem(&mDebuggerPrivate.CallStackEntry[Index],
&mDebuggerPrivate.CallStackEntry[Index + 1],
sizeof (mDebuggerPrivate.CallStackEntry[Index])
);
}
mDebuggerPrivate.CallStackEntry[EFI_DEBUGGER_CALLSTACK_MAX - 1].DestAddress = DestEntry;
mDebuggerPrivate.CallStackEntryCount = EFI_DEBUGGER_CALLSTACK_MAX;
}
return ;
}
/**
It will throw the newest Callstack entry.
**/
VOID
EbcDebuggerPopCallstack (
VOID
)
{
if ((mDebuggerPrivate.CallStackEntryCount > 0) &&
(mDebuggerPrivate.CallStackEntryCount <= EFI_DEBUGGER_CALLSTACK_MAX)) {
//
// Throw the newest one
//
mDebuggerPrivate.CallStackEntryCount --;
mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].SourceAddress = 0;
mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].DestAddress = 0;
} else if (mDebuggerPrivate.CallStackEntryCount == 0) {
//
// NOT assert here because it is reasonable, because when we start to build
// callstack, we do not know how many function already called.
//
} else {
ASSERT (FALSE);
}
return ;
}
/**
It will record source address for trace entry.
@param SourceEntry - Source address
@param Type - Branch type
**/
VOID
EbcDebuggerPushTraceSourceEntry (
IN UINT64 SourceEntry,
IN EFI_DEBUGGER_BRANCH_TYPE Type
)
{
if (mDebuggerPrivate.TraceEntryCount > EFI_DEBUGGER_TRACE_MAX) {
ASSERT (FALSE);
mDebuggerPrivate.TraceEntryCount = EFI_DEBUGGER_TRACE_MAX;
}
//
// Record the new trace entry
//
mDebuggerPrivate.TraceEntry[mDebuggerPrivate.TraceEntryCount].SourceAddress = SourceEntry;
mDebuggerPrivate.TraceEntry[mDebuggerPrivate.TraceEntryCount].Type = Type;
//
// Do not change TraceEntryCount
//
return ;
}
/**
It will record destination address for trace entry.
@param DestEntry - Destination address
@param Type - Branch type
**/
VOID
EbcDebuggerPushTraceDestEntry (
IN UINT64 DestEntry,
IN EFI_DEBUGGER_BRANCH_TYPE Type
)
{
UINTN Index;
if (mDebuggerPrivate.TraceEntryCount < EFI_DEBUGGER_TRACE_MAX) {
//
// If there is empty entry for trace, add it
//
ASSERT (mDebuggerPrivate.TraceEntry[mDebuggerPrivate.TraceEntryCount].Type == Type);
mDebuggerPrivate.TraceEntry[mDebuggerPrivate.TraceEntryCount].DestAddress = DestEntry;
mDebuggerPrivate.TraceEntryCount ++;
} else {
//
// If there is no empty entry for trace, throw the oldest one
//
ASSERT (mDebuggerPrivate.TraceEntry[EFI_DEBUGGER_TRACE_MAX].Type == Type);
for (Index = 0; Index < EFI_DEBUGGER_TRACE_MAX; Index++) {
mDebuggerPrivate.TraceEntry[Index] = mDebuggerPrivate.TraceEntry[Index + 1];
}
mDebuggerPrivate.TraceEntry[EFI_DEBUGGER_CALLSTACK_MAX - 1].DestAddress = DestEntry;
mDebuggerPrivate.TraceEntryCount = EFI_DEBUGGER_TRACE_MAX;
}
return ;
}
/**
It will record address for StepEntry, if STEPOVER or STEPOUT is enabled.
@param Entry - Break Address
@param FramePtr - Break Frame pointer
@param Flag - for STEPOVER or STEPOUT
**/
VOID
EbcDebuggerPushStepEntry (
IN UINT64 Entry,
IN UINT64 FramePtr,
IN UINT32 Flag
)
{
//
// Check StepOver
//
if ((Flag == EFI_DEBUG_FLAG_EBC_STEPOVER) &&
((mDebuggerPrivate.FeatureFlags & EFI_DEBUG_FLAG_EBC_STEPOVER) == EFI_DEBUG_FLAG_EBC_STEPOVER)) {
mDebuggerPrivate.StepContext.BreakAddress = Entry;
mDebuggerPrivate.StepContext.FramePointer = FramePtr;
mDebuggerPrivate.FeatureFlags &= ~EFI_DEBUG_FLAG_EBC_B_STEPOVER;
}
//
// Check StepOut
//
if ((Flag == EFI_DEBUG_FLAG_EBC_STEPOUT) &&
((mDebuggerPrivate.FeatureFlags & EFI_DEBUG_FLAG_EBC_STEPOUT) == EFI_DEBUG_FLAG_EBC_STEPOUT)) {
mDebuggerPrivate.StepContext.BreakAddress = Entry;
mDebuggerPrivate.StepContext.FramePointer = FramePtr;
mDebuggerPrivate.FeatureFlags &= ~EFI_DEBUG_FLAG_EBC_B_STEPOUT;
}
}
/**
Notify the callback function when an event is triggered.
@param Event Indicates the event that invoke this function.
@param Context Indicates the calling context.
**/
VOID
EFIAPI
EbcDebuggerBreakEventFunc (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
if ((mDebuggerPrivate.FeatureFlags & EFI_DEBUG_FLAG_EBC_BOK) != EFI_DEBUG_FLAG_EBC_BOK) {
return ;
}
Status = gBS->CheckEvent (gST->ConIn->WaitForKey);
if (Status == EFI_SUCCESS) {
mDebuggerPrivate.StatusFlags = EFI_DEBUG_FLAG_EBC_BOK;
}
}
/**
The hook in InitializeEbcDriver.
It will init the EbcDebuggerPrivate data structure.
@param Handle - The EbcDebugProtocol handle.
@param EbcDebugProtocol - The EbcDebugProtocol interface.
**/
VOID
EbcDebuggerHookInit (
IN EFI_HANDLE Handle,
IN EFI_DEBUG_SUPPORT_PROTOCOL *EbcDebugProtocol
)
{
EFI_STATUS Status;
UINTN Index;
EFI_DEBUGGER_SYMBOL_OBJECT *Object;
EFI_DEBUGGER_SYMBOL_ENTRY *Entry;
//
// Register all exception handler
//
for (Index = EXCEPT_EBC_UNDEFINED; Index <= EXCEPT_EBC_STEP; Index++) {
EbcDebugProtocol->RegisterExceptionCallback (
EbcDebugProtocol,
0,
NULL,
Index
);
EbcDebugProtocol->RegisterExceptionCallback (
EbcDebugProtocol,
0,
EdbExceptionHandler,
Index
);
}
//
// Init Symbol
//
Object = AllocateZeroPool(sizeof(EFI_DEBUGGER_SYMBOL_OBJECT) * EFI_DEBUGGER_SYMBOL_OBJECT_MAX);
ASSERT (Object != NULL);
mDebuggerPrivate.DebuggerSymbolContext.Object = Object;
mDebuggerPrivate.DebuggerSymbolContext.ObjectCount = 0;
mDebuggerPrivate.DebuggerSymbolContext.MaxObjectCount = EFI_DEBUGGER_SYMBOL_OBJECT_MAX;
for (Index = 0; Index < EFI_DEBUGGER_SYMBOL_OBJECT_MAX; Index++) {
Entry = AllocateZeroPool(sizeof(EFI_DEBUGGER_SYMBOL_ENTRY) * EFI_DEBUGGER_SYMBOL_ENTRY_MAX);
ASSERT (Entry != NULL);
Object[Index].Entry = Entry;
Object[Index].MaxEntryCount = EFI_DEBUGGER_SYMBOL_ENTRY_MAX;
Object[Index].SourceBuffer = AllocateZeroPool(sizeof(VOID *) * (EFI_DEBUGGER_SYMBOL_ENTRY_MAX + 1));
ASSERT (Object[Index].SourceBuffer != NULL);
}
//
// locate PciRootBridgeIo
//
Status = gBS->LocateProtocol (
&gEfiPciRootBridgeIoProtocolGuid,
NULL,
(VOID**) &mDebuggerPrivate.PciRootBridgeIo
);
//
// locate DebugImageInfoTable
//
Status = EfiGetSystemConfigurationTable (
&gEfiDebugImageInfoTableGuid,
(VOID**) &mDebuggerPrivate.DebugImageInfoTableHeader
);
//
// Register Debugger Configuration Protocol, for config in shell
//
Status = gBS->InstallProtocolInterface (
&Handle,
&gEfiDebuggerConfigurationProtocolGuid,
EFI_NATIVE_INTERFACE,
&mDebuggerPrivate.DebuggerConfiguration
);
//
//
// Create break event
//
Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
EbcDebuggerBreakEventFunc,
NULL,
&mDebuggerPrivate.BreakEvent
);
if (!EFI_ERROR(Status)) {
Status = gBS->SetTimer (
mDebuggerPrivate.BreakEvent,
TimerPeriodic,
EFI_DEBUG_BREAK_TIMER_INTERVAL
);
}
return ;
}
/**
The hook in UnloadImage for EBC Interpreter.
It clean up the environment.
**/
VOID
EbcDebuggerHookUnload (
VOID
)
{
UINTN Index;
UINTN SubIndex;
EFI_DEBUGGER_SYMBOL_OBJECT *Object;
//
// Close the break event
//
if (mDebuggerPrivate.BreakEvent != NULL) {
gBS->CloseEvent (mDebuggerPrivate.BreakEvent);
}
//
// Clean up the symbol
//
Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
for (Index = 0; Index < EFI_DEBUGGER_SYMBOL_OBJECT_MAX; Index++) {
//
// Clean up Entry
//
gBS->FreePool(Object[Index].Entry);
Object[Index].Entry = NULL;
Object[Index].EntryCount = 0;
//
// Clean up source buffer
//
for (SubIndex = 0; Object[Index].SourceBuffer[SubIndex] != NULL; SubIndex++) {
gBS->FreePool(Object[Index].SourceBuffer[SubIndex]);
Object[Index].SourceBuffer[SubIndex] = NULL;
}
gBS->FreePool(Object[Index].SourceBuffer);
Object[Index].SourceBuffer = NULL;
}
//
// Clean up Object
//
gBS->FreePool(Object);
mDebuggerPrivate.DebuggerSymbolContext.Object = NULL;
mDebuggerPrivate.DebuggerSymbolContext.ObjectCount = 0;
//
// Done
//
return ;
}
/**
The hook in EbcUnloadImage.
Currently do nothing here.
@param Handle - The EbcImage handle.
**/
VOID
EbcDebuggerHookEbcUnloadImage (
IN EFI_HANDLE Handle
)
{
return ;
}
/**
The hook in ExecuteEbcImageEntryPoint.
It will record the call-stack entry. (-1 means EbcImageEntryPoint call)
and trigger Exception if BOE enabled.
@param VmPtr - pointer to VM context.
**/
VOID
EbcDebuggerHookExecuteEbcImageEntryPoint (
IN VM_CONTEXT *VmPtr
)
{
EbcDebuggerPushCallstackSource ((UINT64)(UINTN)-1, EfiDebuggerBranchTypeEbcCall);
EbcDebuggerPushCallstackParameter ((UINT64)(UINTN)VmPtr->Gpr[0], EfiDebuggerBranchTypeEbcCall);
EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOE);
return ;
}
/**
The hook in ExecuteEbcImageEntryPoint.
It will record the call-stack entry. (-2 means EbcInterpret call)
and trigger Exception if BOT enabled.
@param VmPtr - pointer to VM context.
**/
VOID
EbcDebuggerHookEbcInterpret (
IN VM_CONTEXT *VmPtr
)
{
EbcDebuggerPushCallstackSource ((UINT64)(UINTN)-2, EfiDebuggerBranchTypeEbcCall);
EbcDebuggerPushCallstackParameter ((UINT64)(UINTN)VmPtr->Gpr[0], EfiDebuggerBranchTypeEbcCall);
EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOT);
return ;
}
/**
The hook in EbcExecute, before ExecuteFunction.
It will trigger Exception if GoTil, StepOver, or StepOut hit.
@param VmPtr - pointer to VM context.
**/
VOID
EbcDebuggerHookExecuteStart (
IN VM_CONTEXT *VmPtr
)
{
EFI_TPL CurrentTpl;
//
// Check Ip for GoTil
//
if (mDebuggerPrivate.GoTilContext.BreakAddress == (UINT64)(UINTN)VmPtr->Ip) {
mDebuggerPrivate.StatusFlags = EFI_DEBUG_FLAG_EBC_GT;
mDebuggerPrivate.GoTilContext.BreakAddress = 0;
EbcDebugSignalException (
EXCEPT_EBC_BREAKPOINT,
EXCEPTION_FLAG_NONE,
VmPtr
);
mDebuggerPrivate.StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_GT;
return ;
}
//
// Check ReturnAddress for StepOver
//
if ((mDebuggerPrivate.StepContext.BreakAddress == (UINT64)(UINTN)VmPtr->Ip) &&
(mDebuggerPrivate.StepContext.FramePointer == (UINT64)(UINTN)VmPtr->FramePtr)) {
mDebuggerPrivate.StatusFlags = EFI_DEBUG_FLAG_EBC_STEPOVER;
mDebuggerPrivate.StepContext.BreakAddress = 0;
mDebuggerPrivate.StepContext.FramePointer = 0;
EbcDebugSignalException (
EXCEPT_EBC_BREAKPOINT,
EXCEPTION_FLAG_NONE,
VmPtr
);
mDebuggerPrivate.StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_STEPOVER;
}
//
// Check FramePtr for StepOut
//
if (mDebuggerPrivate.StepContext.BreakAddress == (UINT64)(UINTN)VmPtr->FramePtr) {
mDebuggerPrivate.StatusFlags = EFI_DEBUG_FLAG_EBC_STEPOUT;
mDebuggerPrivate.StepContext.BreakAddress = 0;
mDebuggerPrivate.StepContext.FramePointer = 0;
EbcDebugSignalException (
EXCEPT_EBC_BREAKPOINT,
EXCEPTION_FLAG_NONE,
VmPtr
);
mDebuggerPrivate.StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_STEPOUT;
}
//
// Check Flags for BreakOnKey
//
if (mDebuggerPrivate.StatusFlags == EFI_DEBUG_FLAG_EBC_BOK) {
//
// Only break when the current TPL <= TPL_APPLICATION
//
CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
gBS->RestoreTPL (CurrentTpl);
if (CurrentTpl <= TPL_APPLICATION) {
EbcDebugSignalException (
EXCEPT_EBC_BREAKPOINT,
EXCEPTION_FLAG_NONE,
VmPtr
);
mDebuggerPrivate.StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_BOK;
}
}
return ;
}
/**
The hook in EbcExecute, after ExecuteFunction.
It will record StepOut Entry if need.
@param VmPtr - pointer to VM context.
**/
VOID
EbcDebuggerHookExecuteEnd (
IN VM_CONTEXT *VmPtr
)
{
UINTN Address;
//
// Use FramePtr as checkpoint for StepOut
//
CopyMem(&Address, (VOID *)((UINTN)VmPtr->FramePtr), sizeof(Address));
EbcDebuggerPushStepEntry (Address, (UINT64)(UINTN)VmPtr->FramePtr, EFI_DEBUG_FLAG_EBC_STEPOUT);
return ;
}
/**
The hook in ExecuteCALL, before move IP.
It will trigger Exception if BOC enabled,
and record Callstack, and trace information.
@param VmPtr - pointer to VM context.
**/
VOID
EbcDebuggerHookCALLStart (
IN VM_CONTEXT *VmPtr
)
{
EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOC);
EbcDebuggerPushCallstackSource ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
EbcDebuggerPushCallstackParameter ((UINT64)(UINTN)VmPtr->Gpr[0], EfiDebuggerBranchTypeEbcCall);
EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
return ;
}
/**
The hook in ExecuteCALL, after move IP.
It will record Callstack, trace information
and record StepOver/StepOut Entry if need.
@param VmPtr - pointer to VM context.
**/
VOID
EbcDebuggerHookCALLEnd (
IN VM_CONTEXT *VmPtr
)
{
UINT64 Address;
UINTN FramePtr;
EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
//
// Get Old FramePtr
//
CopyMem(&FramePtr, (VOID *)((UINTN)VmPtr->FramePtr), sizeof(FramePtr));
//
// Use ReturnAddress as checkpoint for StepOver
//
CopyMem(&Address, (VOID *)(UINTN)VmPtr->Gpr[0], sizeof(Address));
EbcDebuggerPushStepEntry (Address, FramePtr, EFI_DEBUG_FLAG_EBC_STEPOVER);
//
// Use FramePtr as checkpoint for StepOut
//
Address = 0;
CopyMem(&Address, (VOID *)(FramePtr), sizeof(UINTN));
EbcDebuggerPushStepEntry (Address, FramePtr, EFI_DEBUG_FLAG_EBC_STEPOUT);
return ;
}
/**
The hook in ExecuteCALL, before call EbcLLCALLEX.
It will trigger Exception if BOCX enabled,
and record Callstack information.
@param VmPtr - pointer to VM context.
**/
VOID
EbcDebuggerHookCALLEXStart (
IN VM_CONTEXT *VmPtr
)
{
EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOCX);
// EbcDebuggerPushCallstackSource ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
// EbcDebuggerPushCallstackParameter ((UINT64)(UINTN)VmPtr->R[0], EfiDebuggerBranchTypeEbcCallEx);
EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
return ;
}
/**
The hook in ExecuteCALL, after call EbcLLCALLEX.
It will record trace information.
@param VmPtr - pointer to VM context.
**/
VOID
EbcDebuggerHookCALLEXEnd (
IN VM_CONTEXT *VmPtr
)
{
// EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
return ;
}
/**
The hook in ExecuteRET, before move IP.
It will trigger Exception if BOR enabled,
and record Callstack, and trace information.
@param VmPtr - pointer to VM context.
**/
VOID
EbcDebuggerHookRETStart (
IN VM_CONTEXT *VmPtr
)
{
EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOR);
EbcDebuggerPopCallstack ();
EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcRet);
return ;
}
/**
The hook in ExecuteRET, after move IP.
It will record trace information.
@param VmPtr - pointer to VM context.
**/
VOID
EbcDebuggerHookRETEnd (
IN VM_CONTEXT *VmPtr
)
{
EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcRet);
return ;
}
/**
The hook in ExecuteJMP, before move IP.
It will record trace information.
@param VmPtr - pointer to VM context.
**/
VOID
EbcDebuggerHookJMPStart (
IN VM_CONTEXT *VmPtr
)
{
EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp);
return ;
}
/**
The hook in ExecuteJMP, after move IP.
It will record trace information.
@param VmPtr - pointer to VM context.
**/
VOID
EbcDebuggerHookJMPEnd (
IN VM_CONTEXT *VmPtr
)
{
EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp);
return ;
}
/**
The hook in ExecuteJMP8, before move IP.
It will record trace information.
@param VmPtr - pointer to VM context.
**/
VOID
EbcDebuggerHookJMP8Start (
IN VM_CONTEXT *VmPtr
)
{
EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp8);
return ;
}
/**
The hook in ExecuteJMP8, after move IP.
It will record trace information.
@param VmPtr - pointer to VM context.
**/
VOID
EbcDebuggerHookJMP8End (
IN VM_CONTEXT *VmPtr
)
{
EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp8);
return ;
}