/** @file | |
Copyright (c) 2007, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "Edb.h" | |
CHAR16 *mBranchTypeStr[] = { | |
L"(CALL)", | |
L"(CALLEX)", | |
L"(RET)", | |
L"(JMP)", | |
L"(JMP8)", | |
}; | |
/** | |
Comvert Branch Type to string. | |
@param Type Branch Type | |
@retval String string of Branch Type. | |
**/ | |
CHAR16 * | |
EdbBranchTypeToStr ( | |
IN EFI_DEBUGGER_BRANCH_TYPE Type | |
) | |
{ | |
if (Type < 0 || Type >= EfiDebuggerBranchTypeEbcMax) { | |
return L"(Unknown Type)"; | |
} | |
return mBranchTypeStr [Type]; | |
} | |
/** | |
DebuggerCommand - CallStack. | |
@param CommandArg The argument for this command | |
@param DebuggerPrivate EBC Debugger private data structure | |
@param ExceptionType Exception type. | |
@param SystemContext EBC system context. | |
@retval EFI_DEBUG_CONTINUE formal return value | |
**/ | |
EFI_DEBUG_STATUS | |
DebuggerCallStack ( | |
IN CHAR16 *CommandArg, | |
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, | |
IN EFI_EXCEPTION_TYPE ExceptionType, | |
IN OUT EFI_SYSTEM_CONTEXT SystemContext | |
) | |
{ | |
INTN Index; | |
UINTN SubIndex; | |
CHAR8 *FuncName; | |
EFI_DEBUGGER_CALLSTACK_CONTEXT *CallStackEntry; | |
BOOLEAN ShowParameter; | |
UINTN ParameterNumber; | |
ShowParameter = FALSE; | |
ParameterNumber = EFI_DEBUGGER_CALL_DEFAULT_PARAMETER; | |
// | |
// Check argument | |
// | |
if (CommandArg != NULL) { | |
if (StriCmp (CommandArg, L"c") == 0) { | |
// | |
// Clear Call-Stack | |
// | |
DebuggerPrivate->CallStackEntryCount = 0; | |
ZeroMem (DebuggerPrivate->CallStackEntry, sizeof(DebuggerPrivate->CallStackEntry)); | |
EDBPrint (L"Call-Stack is cleared\n"); | |
return EFI_DEBUG_CONTINUE; | |
} else if (StriCmp (CommandArg, L"p") == 0) { | |
// | |
// Print Call-Stack with parameter | |
// | |
ShowParameter = TRUE; | |
CommandArg = StrGetNextTokenLine (L" "); | |
if (CommandArg != NULL) { | |
// | |
// Try to get the parameter number | |
// | |
ParameterNumber = Atoi (CommandArg); | |
if (ParameterNumber > 16) { | |
EDBPrint (L"Call-Stack argument Invalid\n"); | |
return EFI_DEBUG_CONTINUE; | |
} | |
} | |
} else { | |
EDBPrint (L"Call-Stack argument Invalid\n"); | |
return EFI_DEBUG_CONTINUE; | |
} | |
} | |
// | |
// Check CallStack Entry Count | |
// | |
if (DebuggerPrivate->CallStackEntryCount == 0) { | |
EDBPrint (L"No Call-Stack\n"); | |
return EFI_DEBUG_CONTINUE; | |
} else if (DebuggerPrivate->CallStackEntryCount > EFI_DEBUGGER_CALLSTACK_MAX) { | |
EDBPrint (L"Call-Stack Crash, re-initialize!\n"); | |
DebuggerPrivate->CallStackEntryCount = 0; | |
return EFI_DEBUG_CONTINUE; | |
} | |
// | |
// Go through each CallStack entry and print | |
// | |
EDBPrint (L"Call-Stack (TOP):\n"); | |
EDBPrint (L" Caller Callee Name\n"); | |
EDBPrint (L" ================== ================== ========\n"); | |
//EDBPrint (L" 0x00000000FFFFFFFF 0xFFFFFFFF00000000 EfiMain\n"); | |
for (Index = (INTN)(DebuggerPrivate->CallStackEntryCount - 1); Index >= 0; Index--) { | |
// | |
// Get CallStack and print | |
// | |
CallStackEntry = &DebuggerPrivate->CallStackEntry[Index]; | |
EDBPrint ( | |
L" 0x%016lx 0x%016lx", | |
CallStackEntry->SourceAddress, | |
CallStackEntry->DestAddress | |
); | |
FuncName = FindSymbolStr ((UINTN)CallStackEntry->DestAddress); | |
if (FuncName != NULL) { | |
EDBPrint (L" %a()", FuncName); | |
} | |
EDBPrint (L"\n"); | |
if (ShowParameter) { | |
// | |
// Print parameter | |
// | |
if (sizeof(UINTN) == sizeof(UINT64)) { | |
EDBPrint ( | |
L" Parameter Address (0x%016lx) (\n", | |
CallStackEntry->ParameterAddr | |
); | |
if (ParameterNumber == 0) { | |
EDBPrint (L" )\n"); | |
continue; | |
} | |
// | |
// Print each parameter | |
// | |
for (SubIndex = 0; SubIndex < ParameterNumber - 1; SubIndex++) { | |
if (SubIndex % 2 == 0) { | |
EDBPrint (L" "); | |
} | |
EDBPrint ( | |
L"0x%016lx, ", | |
CallStackEntry->Parameter[SubIndex] | |
); | |
if (SubIndex % 2 == 1) { | |
EDBPrint (L"\n"); | |
} | |
} | |
if (SubIndex % 2 == 0) { | |
EDBPrint (L" "); | |
} | |
EDBPrint ( | |
L"0x%016lx\n", | |
CallStackEntry->Parameter[SubIndex] | |
); | |
EDBPrint (L" )\n"); | |
// | |
// break only for parameter | |
// | |
if ((((DebuggerPrivate->CallStackEntryCount - Index) % (16 / ParameterNumber)) == 0) && | |
(Index != 0)) { | |
if (SetPageBreak ()) { | |
break; | |
} | |
} | |
} else { | |
EDBPrint ( | |
L" Parameter Address (0x%08x) (\n", | |
CallStackEntry->ParameterAddr | |
); | |
if (ParameterNumber == 0) { | |
EDBPrint (L" )\n"); | |
continue; | |
} | |
// | |
// Print each parameter | |
// | |
for (SubIndex = 0; SubIndex < ParameterNumber - 1; SubIndex++) { | |
if (SubIndex % 4 == 0) { | |
EDBPrint (L" "); | |
} | |
EDBPrint ( | |
L"0x%08x, ", | |
CallStackEntry->Parameter[SubIndex] | |
); | |
if (SubIndex % 4 == 3) { | |
EDBPrint (L"\n"); | |
} | |
} | |
if (SubIndex % 4 == 0) { | |
EDBPrint (L" "); | |
} | |
EDBPrint ( | |
L"0x%08x\n", | |
CallStackEntry->Parameter[SubIndex] | |
); | |
EDBPrint (L" )\n"); | |
// | |
// break only for parameter | |
// | |
if ((((DebuggerPrivate->CallStackEntryCount - Index) % (32 / ParameterNumber)) == 0) && | |
(Index != 0)) { | |
if (SetPageBreak ()) { | |
break; | |
} | |
} | |
} | |
} | |
} | |
// | |
// Done | |
// | |
return EFI_DEBUG_CONTINUE; | |
} | |
/** | |
DebuggerCommand - InstructionBranch. | |
@param CommandArg The argument for this command | |
@param DebuggerPrivate EBC Debugger private data structure | |
@param ExceptionType Exception type. | |
@param SystemContext EBC system context. | |
@retval EFI_DEBUG_CONTINUE formal return value | |
**/ | |
EFI_DEBUG_STATUS | |
DebuggerInstructionBranch ( | |
IN CHAR16 *CommandArg, | |
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, | |
IN EFI_EXCEPTION_TYPE ExceptionType, | |
IN OUT EFI_SYSTEM_CONTEXT SystemContext | |
) | |
{ | |
UINTN Index; | |
// | |
// Check argument | |
// | |
if (CommandArg != NULL) { | |
if (StriCmp (CommandArg, L"c") == 0) { | |
// | |
// Clear Trace | |
// | |
DebuggerPrivate->TraceEntryCount = 0; | |
ZeroMem (DebuggerPrivate->TraceEntry, sizeof(DebuggerPrivate->TraceEntry)); | |
EDBPrint (L"Instruction Trace is cleared\n"); | |
} else { | |
EDBPrint (L"Trace argument Invalid\n"); | |
} | |
return EFI_DEBUG_CONTINUE; | |
} | |
// | |
// Check Trace Entry Count | |
// | |
if (DebuggerPrivate->TraceEntryCount == 0) { | |
EDBPrint (L"No Instruction Trace\n"); | |
return EFI_DEBUG_CONTINUE; | |
} else if (DebuggerPrivate->TraceEntryCount > EFI_DEBUGGER_TRACE_MAX) { | |
EDBPrint (L"Instruction Trace Crash, re-initialize!\n"); | |
DebuggerPrivate->TraceEntryCount = 0; | |
return EFI_DEBUG_CONTINUE; | |
} | |
// | |
// Go through each Trace entry and print | |
// | |
EDBPrint (L"Instruction Trace (->Latest):\n"); | |
EDBPrint (L" Source Addr Destination Addr Type\n"); | |
EDBPrint (L" ================== ================== ========\n"); | |
//EDBPrint (L" 0x00000000FFFFFFFF 0xFFFFFFFF00000000 (CALLEX)\n"); | |
for (Index = 0; Index < DebuggerPrivate->TraceEntryCount; Index++) { | |
EDBPrint ( | |
L" 0x%016lx 0x%016lx %s\n", | |
DebuggerPrivate->TraceEntry[Index].SourceAddress, | |
DebuggerPrivate->TraceEntry[Index].DestAddress, | |
EdbBranchTypeToStr (DebuggerPrivate->TraceEntry[Index].Type) | |
); | |
} | |
// | |
// Done | |
// | |
return EFI_DEBUG_CONTINUE; | |
} |