mirror of https://github.com/acidanthera/audk.git
554 lines
13 KiB
C
554 lines
13 KiB
C
/** @file
|
|
|
|
Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
|
|
**/
|
|
|
|
#include "Edb.h"
|
|
|
|
/**
|
|
|
|
Check whether current IP is EBC BREAK3 instruction.
|
|
|
|
@param Address EBC IP address.
|
|
|
|
@retval TRUE Current IP is EBC BREAK3 instruction
|
|
@retval FALSE Current IP is not EBC BREAK3 instruction
|
|
|
|
**/
|
|
BOOLEAN
|
|
IsEBCBREAK3 (
|
|
IN UINTN Address
|
|
)
|
|
{
|
|
if (GET_OPCODE (Address) != OPCODE_BREAK) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (GET_OPERANDS (Address) != 3) {
|
|
return FALSE;
|
|
} else {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
|
|
Check whether the Address is already set in breakpoint.
|
|
|
|
@param DebuggerPrivate EBC Debugger private data structure
|
|
@param Address Breakpoint Address
|
|
|
|
@retval TRUE breakpoint is found
|
|
@retval FALSE breakpoint is not found
|
|
|
|
**/
|
|
BOOLEAN
|
|
DebuggerBreakpointIsDuplicated (
|
|
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
|
|
IN UINTN Address
|
|
)
|
|
{
|
|
UINTN Index;
|
|
|
|
//
|
|
// Go through each breakpoint context
|
|
//
|
|
for (Index = 0; Index < DebuggerPrivate->DebuggerBreakpointCount; Index++) {
|
|
if (DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress == Address) {
|
|
//
|
|
// Found it
|
|
//
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Not found
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
|
|
Add this breakpoint.
|
|
|
|
@param DebuggerPrivate EBC Debugger private data structure
|
|
@param Address Breakpoint Address
|
|
|
|
@retval EFI_SUCCESS breakpoint added successfully
|
|
@retval EFI_ALREADY_STARTED breakpoint is already added
|
|
@retval EFI_OUT_OF_RESOURCES all the breakpoint entries are used
|
|
|
|
**/
|
|
EFI_STATUS
|
|
DebuggerBreakpointAdd (
|
|
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
|
|
IN UINTN Address
|
|
)
|
|
{
|
|
//
|
|
// Check duplicated breakpoint
|
|
//
|
|
if (DebuggerBreakpointIsDuplicated (DebuggerPrivate, Address)) {
|
|
EDBPrint (L"Breakpoint duplicated!\n");
|
|
return EFI_ALREADY_STARTED;
|
|
}
|
|
|
|
//
|
|
// Check whether the address is a breakpoint 3 instruction
|
|
//
|
|
if (IsEBCBREAK3 (Address)) {
|
|
EDBPrint (L"Breakpoint can not be set on BREAK 3 instruction!\n");
|
|
return EFI_ALREADY_STARTED;
|
|
}
|
|
|
|
if (DebuggerPrivate->DebuggerBreakpointCount >= EFI_DEBUGGER_BREAKPOINT_MAX) {
|
|
EDBPrint (L"Breakpoint out of resource!\n");
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Set the breakpoint
|
|
//
|
|
DebuggerPrivate->DebuggerBreakpointContext[DebuggerPrivate->DebuggerBreakpointCount].BreakpointAddress = Address;
|
|
DebuggerPrivate->DebuggerBreakpointContext[DebuggerPrivate->DebuggerBreakpointCount].State = TRUE;
|
|
DebuggerPrivate->DebuggerBreakpointContext[DebuggerPrivate->DebuggerBreakpointCount].OldInstruction = 0;
|
|
CopyMem (
|
|
&DebuggerPrivate->DebuggerBreakpointContext[DebuggerPrivate->DebuggerBreakpointCount].OldInstruction,
|
|
(VOID *)Address,
|
|
sizeof (UINT16)
|
|
);
|
|
|
|
DebuggerPrivate->DebuggerBreakpointCount++;
|
|
|
|
//
|
|
// Done
|
|
//
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
Delete this breakpoint.
|
|
|
|
@param DebuggerPrivate EBC Debugger private data structure
|
|
@param Index Breakpoint Index
|
|
|
|
@retval EFI_SUCCESS breakpoint deleted successfully
|
|
@retval EFI_NOT_FOUND breakpoint not found
|
|
|
|
**/
|
|
EFI_STATUS
|
|
DebuggerBreakpointDel (
|
|
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
|
|
IN UINTN Index
|
|
)
|
|
{
|
|
UINTN BpIndex;
|
|
|
|
if ((Index >= EFI_DEBUGGER_BREAKPOINT_MAX) ||
|
|
(Index >= DebuggerPrivate->DebuggerBreakpointCount))
|
|
{
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Delete this breakpoint
|
|
//
|
|
for (BpIndex = Index; BpIndex < DebuggerPrivate->DebuggerBreakpointCount - 1; BpIndex++) {
|
|
CopyMem (
|
|
&DebuggerPrivate->DebuggerBreakpointContext[BpIndex],
|
|
&DebuggerPrivate->DebuggerBreakpointContext[BpIndex + 1],
|
|
sizeof (DebuggerPrivate->DebuggerBreakpointContext[BpIndex])
|
|
);
|
|
}
|
|
|
|
ZeroMem (
|
|
&DebuggerPrivate->DebuggerBreakpointContext[BpIndex],
|
|
sizeof (DebuggerPrivate->DebuggerBreakpointContext[BpIndex])
|
|
);
|
|
|
|
DebuggerPrivate->DebuggerBreakpointCount--;
|
|
|
|
//
|
|
// Done
|
|
//
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
Disable this breakpoint.
|
|
|
|
@param DebuggerPrivate EBC Debugger private data structure
|
|
@param Index Breakpoint Index
|
|
|
|
@retval EFI_SUCCESS breakpoint disabled successfully
|
|
@retval EFI_NOT_FOUND breakpoint not found
|
|
|
|
**/
|
|
EFI_STATUS
|
|
DebuggerBreakpointDis (
|
|
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
|
|
IN UINTN Index
|
|
)
|
|
{
|
|
if ((Index >= EFI_DEBUGGER_BREAKPOINT_MAX) ||
|
|
(Index >= DebuggerPrivate->DebuggerBreakpointCount))
|
|
{
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Disable this breakpoint
|
|
//
|
|
DebuggerPrivate->DebuggerBreakpointContext[Index].State = FALSE;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
Enable this breakpoint.
|
|
|
|
@param DebuggerPrivate - EBC Debugger private data structure
|
|
@param Index - Breakpoint Index
|
|
|
|
@retval EFI_SUCCESS - breakpoint enabled successfully
|
|
@retval EFI_NOT_FOUND - breakpoint not found
|
|
|
|
**/
|
|
EFI_STATUS
|
|
DebuggerBreakpointEn (
|
|
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
|
|
IN UINTN Index
|
|
)
|
|
{
|
|
if ((Index >= EFI_DEBUGGER_BREAKPOINT_MAX) ||
|
|
(Index >= DebuggerPrivate->DebuggerBreakpointCount))
|
|
{
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Enable this breakpoint
|
|
//
|
|
DebuggerPrivate->DebuggerBreakpointContext[Index].State = TRUE;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
|
|
DebuggerCommand - BreakpointList.
|
|
|
|
@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
|
|
DebuggerBreakpointList (
|
|
IN CHAR16 *CommandArg,
|
|
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
|
|
IN EFI_EXCEPTION_TYPE ExceptionType,
|
|
IN OUT EFI_SYSTEM_CONTEXT SystemContext
|
|
)
|
|
{
|
|
UINTN Index;
|
|
|
|
//
|
|
// Check breakpoint cound
|
|
//
|
|
if (DebuggerPrivate->DebuggerBreakpointCount == 0) {
|
|
EDBPrint (L"No Breakpoint\n");
|
|
return EFI_DEBUG_CONTINUE;
|
|
} else if (DebuggerPrivate->DebuggerBreakpointCount > EFI_DEBUGGER_BREAKPOINT_MAX) {
|
|
EDBPrint (L"Breakpoint too many!\n");
|
|
DebuggerPrivate->DebuggerBreakpointCount = 0;
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
|
|
//
|
|
// Go through each breakpoint
|
|
//
|
|
EDBPrint (L"Breakpoint :\n");
|
|
EDBPrint (L" Index Address Status\n");
|
|
EDBPrint (L"======= ================== ========\n");
|
|
// EDBPrint (L" 1 0xFFFFFFFF00000000 *\n");
|
|
// EDBPrint (L" 12 0x00000000FFFFFFFF\n");
|
|
for (Index = 0; Index < DebuggerPrivate->DebuggerBreakpointCount; Index++) {
|
|
//
|
|
// Print the breakpoint
|
|
//
|
|
EDBPrint (L" %2d 0x%016lx", Index, DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress);
|
|
if (DebuggerPrivate->DebuggerBreakpointContext[Index].State) {
|
|
EDBPrint (L" *\n");
|
|
} else {
|
|
EDBPrint (L"\n");
|
|
}
|
|
}
|
|
|
|
//
|
|
// Done
|
|
//
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
|
|
/**
|
|
|
|
DebuggerCommand - BreakpointSet.
|
|
|
|
@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
|
|
DebuggerBreakpointSet (
|
|
IN CHAR16 *CommandArg,
|
|
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
|
|
IN EFI_EXCEPTION_TYPE ExceptionType,
|
|
IN OUT EFI_SYSTEM_CONTEXT SystemContext
|
|
)
|
|
{
|
|
UINTN Address;
|
|
EFI_STATUS Status;
|
|
|
|
if (CommandArg == NULL) {
|
|
EDBPrint (L"BreakpointSet Argument error!\n");
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
|
|
//
|
|
// Get breakpoint address
|
|
//
|
|
Status = Symboltoi (CommandArg, &Address);
|
|
if (EFI_ERROR (Status)) {
|
|
if (Status == EFI_NOT_FOUND) {
|
|
Address = Xtoi (CommandArg);
|
|
} else {
|
|
//
|
|
// Something wrong, let Symboltoi print error info.
|
|
//
|
|
EDBPrint (L"Command Argument error!\n");
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Add breakpoint
|
|
//
|
|
Status = DebuggerBreakpointAdd (DebuggerPrivate, Address);
|
|
if (EFI_ERROR (Status)) {
|
|
EDBPrint (L"BreakpointSet error!\n");
|
|
}
|
|
|
|
//
|
|
// Done
|
|
//
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
|
|
/**
|
|
|
|
DebuggerCommand - BreakpointClear
|
|
|
|
@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
|
|
DebuggerBreakpointClear (
|
|
IN CHAR16 *CommandArg,
|
|
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
|
|
IN EFI_EXCEPTION_TYPE ExceptionType,
|
|
IN OUT EFI_SYSTEM_CONTEXT SystemContext
|
|
)
|
|
{
|
|
UINTN Index;
|
|
EFI_STATUS Status;
|
|
|
|
if (CommandArg == NULL) {
|
|
EDBPrint (L"BreakpointClear Argument error!\n");
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
|
|
if (StriCmp (CommandArg, L"*") == 0) {
|
|
//
|
|
// delete all breakpoint
|
|
//
|
|
DebuggerPrivate->DebuggerBreakpointCount = 0;
|
|
ZeroMem (DebuggerPrivate->DebuggerBreakpointContext, sizeof (DebuggerPrivate->DebuggerBreakpointContext));
|
|
EDBPrint (L"All the Breakpoint is cleared\n");
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
|
|
//
|
|
// Get breakpoint index
|
|
//
|
|
Index = Atoi (CommandArg);
|
|
if (Index == (UINTN)-1) {
|
|
EDBPrint (L"BreakpointClear Argument error!\n");
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
|
|
if ((Index >= EFI_DEBUGGER_BREAKPOINT_MAX) ||
|
|
(Index >= DebuggerPrivate->DebuggerBreakpointCount))
|
|
{
|
|
EDBPrint (L"BreakpointClear error!\n");
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
|
|
//
|
|
// Delete breakpoint
|
|
//
|
|
Status = DebuggerBreakpointDel (DebuggerPrivate, Index);
|
|
if (EFI_ERROR (Status)) {
|
|
EDBPrint (L"BreakpointClear error!\n");
|
|
}
|
|
|
|
//
|
|
// Done
|
|
//
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
|
|
/**
|
|
|
|
DebuggerCommand - BreakpointDisable
|
|
|
|
@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
|
|
DebuggerBreakpointDisable (
|
|
IN CHAR16 *CommandArg,
|
|
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
|
|
IN EFI_EXCEPTION_TYPE ExceptionType,
|
|
IN OUT EFI_SYSTEM_CONTEXT SystemContext
|
|
)
|
|
{
|
|
UINTN Index;
|
|
EFI_STATUS Status;
|
|
|
|
if (CommandArg == NULL) {
|
|
EDBPrint (L"BreakpointDisable Argument error!\n");
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
|
|
if (StriCmp (CommandArg, L"*") == 0) {
|
|
//
|
|
// disable all breakpoint
|
|
//
|
|
for (Index = 0; Index < DebuggerPrivate->DebuggerBreakpointCount; Index++) {
|
|
Status = DebuggerBreakpointDis (DebuggerPrivate, Index);
|
|
}
|
|
|
|
EDBPrint (L"All the Breakpoint is disabled\n");
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
|
|
//
|
|
// Get breakpoint index
|
|
//
|
|
Index = Atoi (CommandArg);
|
|
if (Index == (UINTN)-1) {
|
|
EDBPrint (L"BreakpointDisable Argument error!\n");
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
|
|
//
|
|
// Disable breakpoint
|
|
//
|
|
Status = DebuggerBreakpointDis (DebuggerPrivate, Index);
|
|
if (EFI_ERROR (Status)) {
|
|
EDBPrint (L"BreakpointDisable error!\n");
|
|
}
|
|
|
|
//
|
|
// Done
|
|
//
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
|
|
/**
|
|
DebuggerCommand - BreakpointEnable.
|
|
|
|
@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
|
|
DebuggerBreakpointEnable (
|
|
IN CHAR16 *CommandArg,
|
|
IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
|
|
IN EFI_EXCEPTION_TYPE ExceptionType,
|
|
IN OUT EFI_SYSTEM_CONTEXT SystemContext
|
|
)
|
|
{
|
|
UINTN Index;
|
|
EFI_STATUS Status;
|
|
|
|
if (CommandArg == NULL) {
|
|
EDBPrint (L"BreakpointEnable Argument error!\n");
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
|
|
if (StriCmp (CommandArg, L"*") == 0) {
|
|
//
|
|
// enable all breakpoint
|
|
//
|
|
for (Index = 0; Index < DebuggerPrivate->DebuggerBreakpointCount; Index++) {
|
|
Status = DebuggerBreakpointEn (DebuggerPrivate, Index);
|
|
}
|
|
|
|
EDBPrint (L"All the Breakpoint is enabled\n");
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
|
|
//
|
|
// Get breakpoint index
|
|
//
|
|
Index = Atoi (CommandArg);
|
|
if (Index == (UINTN)-1) {
|
|
EDBPrint (L"BreakpointEnable Argument error!\n");
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|
|
|
|
//
|
|
// Enable breakpoint
|
|
//
|
|
Status = DebuggerBreakpointEn (DebuggerPrivate, Index);
|
|
if (EFI_ERROR (Status)) {
|
|
EDBPrint (L"BreakpointEnable error!\n");
|
|
}
|
|
|
|
//
|
|
// Done
|
|
//
|
|
return EFI_DEBUG_CONTINUE;
|
|
}
|