/** @file Copyright (c) 2007, Intel Corporation. All rights reserved.
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; }