mirror of https://github.com/acidanthera/audk.git
313 lines
8.5 KiB
C
313 lines
8.5 KiB
C
/** @file
|
|
|
|
Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
|
|
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.
|
|
|
|
|
|
**/
|
|
|
|
#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;
|
|
}
|