Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

554 lines
14 KiB

//----------------------------------------------------------------------------
//
// ARM machine implementation.
//
// Copyright (C) Microsoft Corporation, 2001-2002.
//
//----------------------------------------------------------------------------
#include "ntsdp.hpp"
char g_ArmSp[] = "sp";
char g_ArmLr[] = "lr";
char g_ArmPc[] = "pc";
char g_ArmPsr[] = "psr";
char g_ArmPsrN[] = "nf";
char g_ArmPsrZ[] = "zf";
char g_ArmPsrC[] = "cf";
char g_ArmPsrV[] = "vf";
char g_ArmPsrQ[] = "qf";
char g_ArmPsrI[] = "if";
char g_ArmPsrF[] = "ff";
char g_ArmPsrT[] = "tf";
char g_ArmPsrMode[] = "mode";
REGDEF g_ArmRegs[] =
{
g_R0, ARM_R0, g_R1, ARM_R1, g_R2, ARM_R2, g_R3, ARM_R3,
g_R4, ARM_R4, g_R5, ARM_R5, g_R6, ARM_R6,
g_R7, ARM_R7, g_R8, ARM_R8, g_R9, ARM_R9, g_R10, ARM_R10,
g_R11, ARM_R11, g_R12, ARM_R12,
g_ArmSp, ARM_SP, g_ArmLr, ARM_LR, g_ArmPc, ARM_PC, g_ArmPsr, ARM_PSR,
g_ArmPsrN, ARM_PSR_N, g_ArmPsrZ, ARM_PSR_Z, g_ArmPsrC, ARM_PSR_C,
g_ArmPsrV, ARM_PSR_V, g_ArmPsrQ, ARM_PSR_Q, g_ArmPsrI, ARM_PSR_I,
g_ArmPsrF, ARM_PSR_F, g_ArmPsrT, ARM_PSR_T,
g_ArmPsrMode, ARM_PSR_MODE,
NULL, 0,
};
REGSUBDEF g_ArmSubRegs[] =
{
{ ARM_PSR_N, ARM_PSR, 31, 1 },
{ ARM_PSR_Z, ARM_PSR, 30, 1 },
{ ARM_PSR_C, ARM_PSR, 29, 1 },
{ ARM_PSR_V, ARM_PSR, 28, 1 },
{ ARM_PSR_Q, ARM_PSR, 27, 1 },
{ ARM_PSR_I, ARM_PSR, 7, 1 },
{ ARM_PSR_F, ARM_PSR, 6, 1 },
{ ARM_PSR_T, ARM_PSR, 5, 1 },
{ ARM_PSR_MODE, ARM_PSR, 0, 5 },
{ REG_ERROR, REG_ERROR, 0, 0 },
};
RegisterGroup g_ArmGroup =
{
0, g_ArmRegs, g_ArmSubRegs, NULL
};
// First ExecTypes entry must be the actual processor type.
ULONG g_ArmExecTypes[] =
{
IMAGE_FILE_MACHINE_ARM
};
// This array must be sorted by CV reg value.
CvRegMap g_ArmCvRegMap[] =
{
{CV_ARM_R0, ARM_R0},
{CV_ARM_R1, ARM_R1},
{CV_ARM_R2, ARM_R2},
{CV_ARM_R3, ARM_R3},
{CV_ARM_R4, ARM_R4},
{CV_ARM_R5, ARM_R5},
{CV_ARM_R6, ARM_R6},
{CV_ARM_R7, ARM_R7},
{CV_ARM_R8, ARM_R8},
{CV_ARM_R9, ARM_R9},
{CV_ARM_R10, ARM_R10},
{CV_ARM_R11, ARM_R11},
{CV_ARM_R12, ARM_R12},
{CV_ARM_SP, ARM_SP},
{CV_ARM_LR, ARM_LR},
{CV_ARM_PC, ARM_PC},
{CV_ARM_CPSR, ARM_PSR},
};
ArmMachineInfo::ArmMachineInfo(TargetInfo* Target)
: MachineInfo(Target)
{
m_FullName = "ARM 32-bit";
m_AbbrevName = "arm";
m_PageSize = ARM_PAGE_SIZE;
m_PageShift = ARM_PAGE_SHIFT;
m_NumExecTypes = 1;
m_ExecTypes = g_ArmExecTypes;
m_Ptr64 = FALSE;
m_RetRegIndex = ARM_R0;
m_MaxDataBreakpoints = 0;
m_SymPrefix = NULL;
m_AllMask = REGALL_INT32;
m_SizeCanonicalContext = sizeof(ARM_CONTEXT);
m_SverCanonicalContext = NT_SVER_NT4;
m_CvRegMapSize = DIMA(g_ArmCvRegMap);
m_CvRegMap = g_ArmCvRegMap;
}
HRESULT
ArmMachineInfo::Initialize(void)
{
m_NumGroups = 1;
m_Groups[0] = &g_ArmGroup;
return MachineInfo::Initialize();
}
void
ArmMachineInfo::
InitializeContext(ULONG64 Pc,
PDBGKD_ANY_CONTROL_REPORT ControlReport)
{
// No ARM KD support.
}
void
ArmMachineInfo::GetSystemTypeInfo(PSYSTEM_TYPE_INFO Info)
{
Info->SizeTargetContext = sizeof(ARM_CONTEXT);
Info->OffsetTargetContextFlags =
FIELD_OFFSET(ARM_CONTEXT, ContextFlags);
// NT doesn't run on the ARM so these NT-related
// data structure constants are not meaningful.
Info->SizeControlReport = 0;
Info->OffsetSpecialRegisters = 0;
Info->SizeKspecialRegisters = 0;
Info->TriagePrcbOffset = 0;
Info->SizePageFrameNumber = sizeof(ULONG);
Info->SizePte = sizeof(ULONG);
Info->SharedUserDataOffset = 0;
Info->UmSharedUserDataOffset = 0;
Info->UmSharedSysCallOffset = 0;
Info->UmSharedSysCallSize = 0;
Info->SizeDynamicFunctionTable = 0;
Info->SizeRuntimeFunction = 0;
}
void
ArmMachineInfo::GetDefaultKdData(PKDDEBUGGER_DATA64 KdData)
{
// No KD data to fill in.
}
HRESULT
ArmMachineInfo::KdGetContextState(ULONG State)
{
// MCTX_CONTEXT and MCTX_FULL are the same for Arm.
if (State >= MCTX_CONTEXT && m_ContextState < MCTX_FULL)
{
HRESULT Status;
Status = m_Target->GetContext(m_Target->m_RegContextThread->m_Handle,
&m_Context);
if (Status != S_OK)
{
return Status;
}
m_ContextState = MCTX_FULL;
}
return S_OK;
}
HRESULT
ArmMachineInfo::KdSetContext(void)
{
return m_Target->SetContext(m_Target->m_RegContextThread->m_Handle,
&m_Context);
}
HRESULT
ArmMachineInfo::ConvertContextFrom(PCROSS_PLATFORM_CONTEXT Context,
ULONG FromSver,
ULONG FromSize, PVOID From)
{
if (FromSize < sizeof(ARM_CONTEXT))
{
return E_INVALIDARG;
}
memcpy(Context, From, sizeof(ARM_CONTEXT));
return S_OK;
}
HRESULT
ArmMachineInfo::ConvertContextTo(PCROSS_PLATFORM_CONTEXT Context,
ULONG ToSver, ULONG ToSize, PVOID To)
{
if (ToSize < sizeof(ARM_CONTEXT))
{
return E_INVALIDARG;
}
memcpy(To, Context, sizeof(ARM_CONTEXT));
return S_OK;
}
void
ArmMachineInfo::InitializeContextFlags(PCROSS_PLATFORM_CONTEXT Context,
ULONG Version)
{
Context->ArmContext.ContextFlags = ARM_CONTEXT_FULL;
}
HRESULT
ArmMachineInfo::GetContextFromThreadStack(ULONG64 ThreadBase,
PCROSS_PLATFORM_CONTEXT Context,
ULONG64 Stack)
{
return E_NOTIMPL;
}
HRESULT
ArmMachineInfo::GetContextFromFiber(ProcessInfo* Process,
ULONG64 FiberBase,
PCROSS_PLATFORM_CONTEXT Context,
BOOL Verbose)
{
return E_NOTIMPL;
}
HRESULT
ArmMachineInfo::GetContextFromTrapFrame(ULONG64 TrapBase,
PCROSS_PLATFORM_CONTEXT Context,
BOOL Verbose)
{
return E_NOTIMPL;
}
void
ArmMachineInfo::GetScopeFrameFromContext(PCROSS_PLATFORM_CONTEXT Context,
PDEBUG_STACK_FRAME ScopeFrame)
{
ZeroMemory(ScopeFrame, sizeof(*ScopeFrame));
ScopeFrame->InstructionOffset = Context->ArmContext.Pc;
ScopeFrame->FrameOffset = Context->ArmContext.R11;
ScopeFrame->StackOffset = Context->ArmContext.Sp;
}
HRESULT
ArmMachineInfo::GetScopeFrameRegister(ULONG Reg,
PDEBUG_STACK_FRAME ScopeFrame,
PULONG64 Value)
{
HRESULT Status;
REGVAL RegVal;
switch(Reg)
{
case ARM_SP:
*Value = ScopeFrame->StackOffset;
return S_OK;
case ARM_R11:
*Value = ScopeFrame->FrameOffset;
return S_OK;
default:
RegVal.I64 = 0;
if ((Status = FullGetVal(Reg, &RegVal)) != S_OK)
{
return Status;
}
*Value = RegVal.I64;
return S_OK;
}
}
HRESULT
ArmMachineInfo::SetScopeFrameRegister(ULONG Reg,
PDEBUG_STACK_FRAME ScopeFrame,
ULONG64 Value)
{
REGVAL RegVal;
switch(Reg)
{
case ARM_SP:
ScopeFrame->StackOffset = Value;
return S_OK;
case ARM_R11:
ScopeFrame->FrameOffset = Value;
return S_OK;
default:
RegVal.Type = GetType(Reg);
RegVal.I64 = Value;
return FullSetVal(Reg, &RegVal);
}
}
int
ArmMachineInfo::GetType(ULONG Reg)
{
if (Reg < ARM_INT_FIRST || Reg > ARM_INT_LAST)
{
return REGVAL_SUB32;
}
else
{
return REGVAL_INT32;
}
}
HRESULT
ArmMachineInfo::GetVal(ULONG Reg, REGVAL *Val)
{
HRESULT Status;
if (Reg < ARM_INT_FIRST || Reg > ARM_INT_LAST)
{
return E_INVALIDARG;
}
if ((Status = GetContextState(MCTX_FULL)) != S_OK)
{
return Status;
}
Val->Type = GetType(Reg);
Val->I64 = *(&m_Context.ArmContext.R0 + (Reg - ARM_INT_FIRST));
return S_OK;
}
HRESULT
ArmMachineInfo::SetVal(ULONG Reg, REGVAL *Val)
{
HRESULT Status;
if (m_ContextIsReadOnly)
{
return HRESULT_FROM_WIN32(ERROR_WRITE_FAULT);
}
if (Reg < ARM_INT_FIRST || Reg > ARM_INT_LAST)
{
return E_INVALIDARG;
}
// Optimize away some common cases where registers are
// set to their current value.
if (m_ContextState >= MCTX_PC && Reg == ARM_PC &&
Val->I64 == m_Context.ArmContext.Pc)
{
return S_OK;
}
if ((Status = GetContextState(MCTX_DIRTY)) != S_OK)
{
return Status;
}
*(&m_Context.ArmContext.R0 + (Reg - ARM_INT_FIRST)) = Val->I32;
NotifyChangeDebuggeeState(DEBUG_CDS_REGISTERS,
RegCountFromIndex(Reg));
return S_OK;
}
void
ArmMachineInfo::GetPC(PADDR Address)
{
ADDRFLAT(Address, EXTEND64(GetReg32(ARM_PC)));
}
void
ArmMachineInfo::SetPC(PADDR Address)
{
SetReg32(ARM_PC, (ULONG)Flat(*Address));
}
void
ArmMachineInfo::GetFP(PADDR Address)
{
ADDRFLAT(Address, EXTEND64(GetReg32(ARM_R11)));
}
void
ArmMachineInfo::GetSP(PADDR Address)
{
ADDRFLAT(Address, EXTEND64(GetReg32(ARM_SP)));
}
ULONG64
ArmMachineInfo::GetArgReg(void)
{
return EXTEND64(GetReg32(ARM_R0));
}
ULONG64
ArmMachineInfo::GetRetReg(void)
{
return EXTEND64(GetReg32(ARM_R0));
}
void
ArmMachineInfo::OutputAll(ULONG Mask, ULONG OutMask)
{
if (GetContextState(MCTX_FULL) != S_OK)
{
ErrOut("Unable to retrieve register information\n");
return;
}
if (Mask & (REGALL_INT32 | REGALL_INT64))
{
MaskOut(OutMask, " r0=%08x r1=%08x r2=%08x "
"r3=%08x r4=%08x r5=%08x\n",
m_Context.ArmContext.R0, m_Context.ArmContext.R1,
m_Context.ArmContext.R2, m_Context.ArmContext.R3,
m_Context.ArmContext.R4, m_Context.ArmContext.R5);
MaskOut(OutMask, " r6=%08x r7=%08x r8=%08x "
"r9=%08x r10=%08x r11=%08x\n",
m_Context.ArmContext.R6, m_Context.ArmContext.R7,
m_Context.ArmContext.R8, m_Context.ArmContext.R9,
m_Context.ArmContext.R10, m_Context.ArmContext.R11);
MaskOut(OutMask, "r12=%08x sp=%08x lr=%08x "
"pc=%08x psr=%08x %s%s%s%s%s %s\n",
m_Context.ArmContext.R12, m_Context.ArmContext.Sp,
m_Context.ArmContext.Lr, m_Context.ArmContext.Pc,
m_Context.ArmContext.Psr,
(m_Context.ArmContext.Psr & ARM_FLAG_N) ? "N" : "-",
(m_Context.ArmContext.Psr & ARM_FLAG_Z) ? "Z" : "-",
(m_Context.ArmContext.Psr & ARM_FLAG_C) ? "C" : "-",
(m_Context.ArmContext.Psr & ARM_FLAG_V) ? "V" : "-",
(m_Context.ArmContext.Psr & ARM_FLAG_Q) ? "Q" : "-",
(m_Context.ArmContext.Psr & ARM_FLAG_T) ? "Thumb" : "ARM");
}
}
HRESULT
ArmMachineInfo::SetAndOutputTrapFrame(ULONG64 TrapBase,
PCROSS_PLATFORM_CONTEXT Context)
{
return SetAndOutputContext(Context, TRUE, REGALL_INT32);
}
TRACEMODE
ArmMachineInfo::GetTraceMode(void)
{
return TRACE_NONE;
}
void
ArmMachineInfo::SetTraceMode(TRACEMODE Mode)
{
// No explicit trace mode needed.
}
BOOL
ArmMachineInfo::IsStepStatusSupported(ULONG Status)
{
switch (Status)
{
case DEBUG_STATUS_STEP_INTO:
case DEBUG_STATUS_STEP_OVER:
return TRUE;
default:
return FALSE;
}
}
ULONG
ArmMachineInfo::ExecutingMachine(void)
{
return m_ExecTypes[0];
}
HRESULT
ArmMachineInfo::SetPageDirectory(ThreadInfo* Thread,
ULONG Idx, ULONG64 PageDir,
PULONG NextIdx)
{
return E_NOTIMPL;
}
HRESULT
ArmMachineInfo::GetVirtualTranslationPhysicalOffsets(ThreadInfo* Thread,
ULONG64 Virt,
PULONG64 Offsets,
ULONG OffsetsSize,
PULONG Levels,
PULONG PfIndex,
PULONG64 LastVal)
{
return E_NOTIMPL;
}
HRESULT
ArmMachineInfo::GetBaseTranslationVirtualOffset(PULONG64 Offset)
{
return E_NOTIMPL;
}
void
ArmMachineInfo::DecodePte(ULONG64 Pte, PULONG64 PageFrameNumber,
PULONG Flags)
{
// XXX
*PageFrameNumber = 0;
*Flags = 0;
}
void
ArmMachineInfo::OutputFunctionEntry(PVOID RawEntry)
{
ErrOut("ARM function entries not implemented\n");
}
HRESULT
ArmMachineInfo::ReadDynamicFunctionTable(ProcessInfo* Process,
ULONG64 Table,
PULONG64 NextTable,
PULONG64 MinAddress,
PULONG64 MaxAddress,
PULONG64 BaseAddress,
PULONG64 TableData,
PULONG TableSize,
PWSTR OutOfProcessDll,
PCROSS_PLATFORM_DYNAMIC_FUNCTION_TABLE RawTable)
{
return E_NOTIMPL;
}
PVOID
ArmMachineInfo::FindDynamicFunctionEntry(PCROSS_PLATFORM_DYNAMIC_FUNCTION_TABLE Table,
ULONG64 Address,
PVOID TableData,
ULONG TableSize)
{
return NULL;
}
HRESULT
ArmMachineInfo::ReadKernelProcessorId
(ULONG Processor, PDEBUG_PROCESSOR_IDENTIFICATION_ALL Id)
{
// No ARM KD support.
return E_NOTIMPL;
}