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

1004 lines
22 KiB
C

/*++
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:
EdbHook.c
Abstract:
--*/
#include "Edb.h"
//
// Hook support function
//
VOID
EbcDebuggerCheckHookFlag (
IN VM_CONTEXT *VmPtr,
IN UINT32 Flag
)
/*++
Routine Description:
Check the Hook flag, and trigger exception if match.
Arguments:
VmPtr - EbcDebuggerCheckHookFlag
Flag - Feature flag
Returns:
None
--*/
{
if ((mDebuggerPrivate.FeatureFlags & Flag) == Flag) {
mDebuggerPrivate.StatusFlags = Flag;
EbcDebugSignalException (
EXCEPT_EBC_BREAKPOINT,
EXCEPTION_FLAG_NONE,
VmPtr
);
}
return ;
}
VOID
EbcDebuggerPushCallstackSource (
IN UINT64 SourceEntry,
IN EFI_DEBUGGER_BRANCH_TYPE Type
)
/*++
Routine Description:
It will record soruce address for Callstack entry.
Arguments:
SourceEntry - Source address
Type - Branch type
Returns:
None
--*/
{
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 ;
}
VOID
EbcDebuggerPushCallstackParameter (
IN UINT64 ParameterAddress,
IN EFI_DEBUGGER_BRANCH_TYPE Type
)
/*++
Routine Description:
It will record parameter for Callstack entry.
Arguments:
ParameterAddress - The address for the parameter
Type - Branch type
Returns:
None
--*/
{
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 ;
}
VOID
EbcDebuggerPushCallstackDest (
IN UINT64 DestEntry,
IN EFI_DEBUGGER_BRANCH_TYPE Type
)
/*++
Routine Description:
It will record source address for callstack entry.
Arguments:
DestEntry - Source address
Type - Branch type
Returns:
None
--*/
{
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++) {
mDebuggerPrivate.CallStackEntry[Index] = mDebuggerPrivate.CallStackEntry[Index + 1];
}
mDebuggerPrivate.CallStackEntry[EFI_DEBUGGER_CALLSTACK_MAX - 1].DestAddress = DestEntry;
mDebuggerPrivate.CallStackEntryCount = EFI_DEBUGGER_CALLSTACK_MAX;
}
return ;
}
VOID
EbcDebuggerPopCallstack (
VOID
)
/*++
Routine Description:
It will throw the newest Callstack entry.
Arguments:
None
Returns:
None
--*/
{
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 ;
}
VOID
EbcDebuggerPushTraceSourceEntry (
IN UINT64 SourceEntry,
IN EFI_DEBUGGER_BRANCH_TYPE Type
)
/*++
Routine Description:
It will record source address for trace entry.
Arguments:
SourceEntry - Source address
Type - Branch type
Returns:
None
--*/
{
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 ;
}
VOID
EbcDebuggerPushTraceDestEntry (
IN UINT64 DestEntry,
IN EFI_DEBUGGER_BRANCH_TYPE Type
)
/*++
Routine Description:
It will record destination address for trace entry.
Arguments:
DestEntry - Destination address
Type - Branch type
Returns:
None
--*/
{
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 ;
}
VOID
EbcDebuggerPushStepEntry (
IN UINT64 Entry,
IN UINT64 FramePtr,
IN UINT32 Flag
)
/*++
Routine Description:
It will record address for StepEntry, if STEPOVER or STEPOUT is enabled.
Arguments:
Entry - Break Address
FramePtr - Break Frame pointer
Flag - for STEPOVER or STEPOUT
Returns:
None
--*/
{
//
// 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;
}
}
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;
}
}
//
// Hook function implementation
//
VOID
EbcDebuggerHookInit (
IN EFI_HANDLE Handle,
IN EFI_DEBUG_SUPPORT_PROTOCOL *EbcDebugProtocol
)
/*++
Routine Description:
The hook in InitializeEbcDriver.
It will init the EbcDebuggerPrivate data structure.
Arguments:
Handle - The EbcDebugProtocol handle.
EbcDebugProtocol - The EbcDebugProtocol interface.
Returns:
None
--*/
{
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
);
//
// Create break event
//
Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
EbcDebuggerBreakEventFunc,
NULL,
&mDebuggerPrivate.BreakEvent
);
Status = gBS->SetTimer (
mDebuggerPrivate.BreakEvent,
TimerPeriodic,
EFI_DEBUG_BREAK_TIMER_INTERVAL
);
return ;
}
VOID
EbcDebuggerHookUnload (
VOID
)
/*++
Routine Description:
The hook in UnloadImage for EBC Interpreter.
It clean up the environment.
Arguments:
None
Returns:
None
--*/
{
UINTN Index;
UINTN SubIndex;
EFI_DEBUGGER_SYMBOL_OBJECT *Object;
//
// Close the break event
//
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 ;
}
VOID
EbcDebuggerHookEbcUnloadImage (
IN EFI_HANDLE Handle
)
/*++
Routine Description:
The hook in EbcUnloadImage.
Currently do nothing here.
Arguments:
Handle - The EbcImage handle.
Returns:
None
--*/
{
return ;
}
VOID
EbcDebuggerHookExecuteEbcImageEntryPoint (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
The hook in ExecuteEbcImageEntryPoint.
It will record the call-stack entry. (-1 means EbcImageEntryPoint call)
and trigger Exception if BOE enabled.
Arguments:
VmPtr - pointer to VM context.
Returns:
None
--*/
{
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 ;
}
VOID
EbcDebuggerHookEbcInterpret (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
The hook in ExecuteEbcImageEntryPoint.
It will record the call-stack entry. (-2 means EbcInterpret call)
and trigger Exception if BOT enabled.
Arguments:
VmPtr - pointer to VM context.
Returns:
None
--*/
{
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 ;
}
VOID
EbcDebuggerHookExecuteStart (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
The hook in EbcExecute, before ExecuteFunction.
It will trigger Exception if GoTil, StepOver, or StepOut hit.
Arguments:
VmPtr - pointer to VM context.
Returns:
None
--*/
{
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 ;
}
VOID
EbcDebuggerHookExecuteEnd (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
The hook in EbcExecute, after ExecuteFunction.
It will record StepOut Entry if need.
Arguments:
VmPtr - pointer to VM context.
Returns:
None
--*/
{
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 ;
}
VOID
EbcDebuggerHookCALLStart (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
The hook in ExecuteCALL, before move IP.
It will trigger Exception if BOC enabled,
and record Callstack, and trace information.
Arguments:
VmPtr - pointer to VM context.
Returns:
None
--*/
{
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 ;
}
VOID
EbcDebuggerHookCALLEnd (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
The hook in ExecuteCALL, after move IP.
It will record Callstack, trace information
and record StepOver/StepOut Entry if need.
Arguments:
VmPtr - pointer to VM context.
Returns:
None
--*/
{
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 ;
}
VOID
EbcDebuggerHookCALLEXStart (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
The hook in ExecuteCALL, before call EbcLLCALLEX.
It will trigger Exception if BOCX enabled,
and record Callstack information.
Arguments:
VmPtr - pointer to VM context.
Returns:
None
--*/
{
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 ;
}
VOID
EbcDebuggerHookCALLEXEnd (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
The hook in ExecuteCALL, after call EbcLLCALLEX.
It will record trace information.
Arguments:
VmPtr - pointer to VM context.
Returns:
None
--*/
{
// EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
return ;
}
VOID
EbcDebuggerHookRETStart (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
The hook in ExecuteRET, before move IP.
It will trigger Exception if BOR enabled,
and record Callstack, and trace information.
Arguments:
VmPtr - pointer to VM context.
Returns:
None
--*/
{
EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOR);
EbcDebuggerPopCallstack ();
EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcRet);
return ;
}
VOID
EbcDebuggerHookRETEnd (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
The hook in ExecuteRET, after move IP.
It will record trace information.
Arguments:
VmPtr - pointer to VM context.
Returns:
None
--*/
{
EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcRet);
return ;
}
VOID
EbcDebuggerHookJMPStart (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
The hook in ExecuteJMP, before move IP.
It will record trace information.
Arguments:
VmPtr - pointer to VM context.
Returns:
None
--*/
{
EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp);
return ;
}
VOID
EbcDebuggerHookJMPEnd (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
The hook in ExecuteJMP, after move IP.
It will record trace information.
Arguments:
VmPtr - pointer to VM context.
Returns:
None
--*/
{
EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp);
return ;
}
VOID
EbcDebuggerHookJMP8Start (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
The hook in ExecuteJMP8, before move IP.
It will record trace information.
Arguments:
VmPtr - pointer to VM context.
Returns:
None
--*/
{
EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp8);
return ;
}
VOID
EbcDebuggerHookJMP8End (
IN VM_CONTEXT *VmPtr
)
/*++
Routine Description:
The hook in ExecuteJMP8, after move IP.
It will record trace information.
Arguments:
VmPtr - pointer to VM context.
Returns:
None
--*/
{
EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp8);
return ;
}