windows-nt/Source/XPSP1/NT/sdktools/debuggers/ntsd64/alpha_reg.cpp
2020-09-26 16:20:57 +08:00

1657 lines
47 KiB
C++

/*** alpha_reg.c - processor-specific register structures
*
* Copyright <C> 1990-2001, Microsoft Corporation
* Copyright <C> 1992, Digital Equipment Corporation
*
* Purpose:
* Structures used to parse and access register and flag
* fields.
*
* Revision History:
*
* [-] 08-Aug-1992 Miche Baker-Harvey Created for Alpha
* [-] 01-Jul-1990 Richk Created.
*
*************************************************************************/
#include "ntsdp.hpp"
#include "alpha_strings.h"
#include "alpha_optable.h"
// See Get/SetRegVal comments in machine.hpp.
#define RegValError Do_not_use_GetSetRegVal_in_machine_implementations
#define GetRegVal(index, val) RegValError
#define GetRegVal32(index) RegValError
#define GetRegVal64(index) RegValError
#define SetRegVal(index, val) RegValError
#define SetRegVal32(index, val) RegValError
#define SetRegVal64(index, val) RegValError
#define IS_FLOATING_SAVED(Register) ((SAVED_FLOATING_MASK >> Register) & 1L)
#define IS_INTEGER_SAVED(Register) ((SAVED_INTEGER_MASK >> Register) & 1L)
//
// Define saved register masks.
#define SAVED_FLOATING_MASK 0xfff00000 // saved floating registers
#define SAVED_INTEGER_MASK 0xf3ffff02 // saved integer registers
//
// Instruction opcode values are defined in alphaops.h
//
REGDEF AlphaRegs[] =
{
g_F0, ALPHA_F0, g_F1, ALPHA_F1, g_F2, ALPHA_F2, g_F3, ALPHA_F3,
g_F4, ALPHA_F4, g_F5, ALPHA_F5, g_F6, ALPHA_F6, g_F7, ALPHA_F7,
g_F8, ALPHA_F8, g_F9, ALPHA_F9, g_F10, ALPHA_F10, g_F11, ALPHA_F11,
g_F12, ALPHA_F12, g_F13, ALPHA_F13, g_F14, ALPHA_F14, g_F15, ALPHA_F15,
g_F16, ALPHA_F16, g_F17, ALPHA_F17, g_F18, ALPHA_F18, g_F19, ALPHA_F19,
g_F20, ALPHA_F20, g_F21, ALPHA_F21, g_F22, ALPHA_F22, g_F23, ALPHA_F23,
g_F24, ALPHA_F24, g_F25, ALPHA_F25, g_F26, ALPHA_F26, g_F27, ALPHA_F27,
g_F28, ALPHA_F28, g_F29, ALPHA_F29, g_F30, ALPHA_F30, g_F31, ALPHA_F31,
g_AlphaV0, ALPHA_V0, g_AlphaT0, ALPHA_T0, g_AlphaT1, ALPHA_T1, g_AlphaT2, ALPHA_T2,
g_AlphaT3, ALPHA_T3, g_AlphaT4, ALPHA_T4, g_AlphaT5, ALPHA_T5, g_AlphaT6, ALPHA_T6,
g_AlphaT7, ALPHA_T7, g_AlphaS0, ALPHA_S0, g_AlphaS1, ALPHA_S1, g_AlphaS2, ALPHA_S2,
g_AlphaS3, ALPHA_S3, g_AlphaS4, ALPHA_S4, g_AlphaS5, ALPHA_S5, g_AlphaFP, ALPHA_FP,
g_AlphaA0, ALPHA_A0, g_AlphaA1, ALPHA_A1, g_AlphaA2, ALPHA_A2, g_AlphaA3, ALPHA_A3,
g_AlphaA4, ALPHA_A4, g_AlphaA5, ALPHA_A5, g_AlphaT8, ALPHA_T8, g_AlphaT9, ALPHA_T9,
g_AlphaT10, ALPHA_T10, g_AlphaT11, ALPHA_T11, g_AlphaRA, ALPHA_RA,
g_AlphaT12, ALPHA_T12, g_AlphaAT, ALPHA_AT, g_AlphaGP, ALPHA_GP,
g_AlphaSP, ALPHA_SP, g_AlphaZero, ALPHA_ZERO,
szFpcr, ALPHA_FPCR, szSoftFpcr, ALPHA_SFTFPCR, szFir, ALPHA_FIR,
szPsr, ALPHA_PSR,
szFlagMode, ALPHA_MODE, szFlagIe, ALPHA_IE, szFlagIrql, ALPHA_IRQL,
NULL, 0,
};
//
// PSR & IE definitions are from ksalpha.h
// which is generated automatically.
// Steal from \\bbox2\alphado\nt\public\sdk\inc\ksalpha.h
// NB: our masks are already shifted:
//
REGSUBDEF AlphaSubRegs[] =
{
{ ALPHA_MODE, ALPHA_PSR, ALPHA_PSR_MODE, ALPHA_PSR_MODE_MASK },
{ ALPHA_IE, ALPHA_PSR, ALPHA_PSR_IE, ALPHA_PSR_IE_MASK },
{ ALPHA_IRQL, ALPHA_PSR, ALPHA_PSR_IRQL, ALPHA_PSR_IRQL_MASK },
{ REG_ERROR, REG_ERROR, 0, 0 },
};
RegisterGroup g_AlphaGroup =
{
NULL, 0, AlphaRegs, AlphaSubRegs, NULL
};
// First ExecTypes entry must be the actual processor type.
ULONG g_Axp32ExecTypes[] =
{
IMAGE_FILE_MACHINE_ALPHA
};
// First ExecTypes entry must be the actual processor type.
ULONG g_Axp64ExecTypes[] =
{
IMAGE_FILE_MACHINE_AXP64
};
Axp32MachineInfo g_Axp32Machine;
Axp64MachineInfo g_Axp64Machine;
HRESULT
AlphaMachineInfo::InitializeConstants(void)
{
HRESULT Status;
m_Groups = &g_AlphaGroup;
m_AllMask = REGALL_INT64;
m_MaxDataBreakpoints = 0;
m_SymPrefix = NULL;
// 32/64-bit values are set in the specific Initialize.
// Alpha-generic values are here.
C_ASSERT(sizeof(ALPHA_CONTEXT) == sizeof(ALPHA_NT5_CONTEXT));
m_SizeTargetContext = sizeof(ALPHA_NT5_CONTEXT);
m_OffsetTargetContextFlags = FIELD_OFFSET(ALPHA_NT5_CONTEXT, ContextFlags);
m_SizeCanonicalContext = sizeof(ALPHA_NT5_CONTEXT);
m_SverCanonicalContext = NT_SVER_NT4;
m_SizeControlReport = sizeof(ALPHA_DBGKD_CONTROL_REPORT);
m_OffsetSpecialRegisters = 0;
m_SizeKspecialRegisters = 0;
if ((Status = opTableInit()) != S_OK)
{
return Status;
}
return MachineInfo::InitializeConstants();
}
void
AlphaMachineInfo::
InitializeContext(ULONG64 Pc,
PDBGKD_ANY_CONTROL_REPORT ControlReport)
{
m_Context.AlphaNt5Context.Fir = Pc;
m_ContextState = Pc ? MCTX_PC : MCTX_NONE;
if (Pc && ControlReport != NULL)
{
CacheReportInstructions
(Pc, ControlReport->AlphaControlReport.InstructionCount,
ControlReport->AlphaControlReport.InstructionStream);
}
}
HRESULT
AlphaMachineInfo::KdGetContextState(ULONG State)
{
// MCTX_CONTEXT and MCTX_FULL are the same for Alpha.
if (State >= MCTX_CONTEXT && m_ContextState < MCTX_FULL)
{
HRESULT Status;
Status = g_Target->GetContext(g_RegContextThread->Handle, &m_Context);
if (Status != S_OK)
{
return Status;
}
m_ContextState = MCTX_FULL;
}
return S_OK;
}
HRESULT
AlphaMachineInfo::KdSetContext(void)
{
return g_Target->SetContext(g_RegContextThread->Handle, &m_Context);
}
HRESULT
AlphaMachineInfo::ConvertContextFrom(PCROSS_PLATFORM_CONTEXT Context,
ULONG FromSver,
ULONG FromSize, PVOID From)
{
if (FromSize < sizeof(ALPHA_NT5_CONTEXT))
{
return E_INVALIDARG;
}
PALPHA_CONTEXT Ctx = (PALPHA_CONTEXT)From;
// ALPHA_CONTEXT has been floating around for a while
// for use by the debugger. The system hasn't used it
// so they shouldn't ever end up here but go ahead
// and try and detect them based on the flags.
if (Ctx->ContextFlags != ALPHA_CONTEXT_FULL)
{
// This doesn't look like an ALPHA_CONTEXT, check
// ALPHA_NT5_CONTEXT.
if (((PALPHA_NT5_CONTEXT)From)->ContextFlags !=
ALPHA_CONTEXT_FULL)
{
return E_INVALIDARG;
}
// It looks like an ALPHA_NT5_CONTEXT so don't convert.
memcpy(Context, From, sizeof(ALPHA_NT5_CONTEXT));
}
else
{
PULONG High;
PULONG Low;
PULONGLONG Full;
int Count;
Low = &Ctx->FltF0;
High = &Ctx->HighFltF0;
Full = &Context->AlphaNt5Context.FltF0;
for (Count = 0; Count < 32; Count++)
{
Full[Count] = Low[Count] + ((ULONGLONG)High[Count] << 32);
}
Low = &Ctx->IntV0;
High = &Ctx->HighIntV0;
Full = &Context->AlphaNt5Context.IntV0;
for (Count = 0; Count < 32; Count++)
{
Full[Count] = Low[Count] + ((ULONGLONG)High[Count] << 32);
}
Context->AlphaNt5Context.ContextFlags = Ctx->ContextFlags;
Context->AlphaNt5Context.Psr = Ctx->Psr;
Context->AlphaNt5Context.Fpcr =
Ctx->Fpcr + ((ULONGLONG)Ctx->HighFpcr << 32);
Context->AlphaNt5Context.SoftFpcr =
Ctx->SoftFpcr + ((ULONGLONG)Ctx->HighSoftFpcr << 32);
Context->AlphaNt5Context.Fir =
Ctx->Fir + ((ULONGLONG)Ctx->HighFir << 32);
}
return S_OK;
}
HRESULT
AlphaMachineInfo::ConvertContextTo(PCROSS_PLATFORM_CONTEXT Context,
ULONG ToSver, ULONG ToSize, PVOID To)
{
if (ToSize < sizeof(ALPHA_NT5_CONTEXT))
{
return E_INVALIDARG;
}
memcpy(To, Context, sizeof(ALPHA_NT5_CONTEXT));
return S_OK;
}
void
AlphaMachineInfo::InitializeContextFlags(PCROSS_PLATFORM_CONTEXT Context,
ULONG Version)
{
Context->AlphaNt5Context.ContextFlags = ALPHA_CONTEXT_FULL;
}
int
AlphaMachineInfo::GetType(ULONG index)
{
if (
#if ALPHA_FLT_BASE > 0
index >= ALPHA_FLT_BASE &&
#endif
index <= ALPHA_FLT_LAST)
{
return REGVAL_FLOAT8;
}
else if (index >= ALPHA_INT64_BASE && index <= ALPHA_INT64_LAST)
{
return REGVAL_INT64;
}
else if (index >= ALPHA_INT32_BASE && index <= ALPHA_INT32_LAST)
{
return REGVAL_INT32;
}
else
{
return REGVAL_SUB32;
}
}
/*** RegGetVal - get register value
*
* Purpose:
* Returns the value of the register from the processor
* context structure.
*
* Input:
* regnum - register specification
*
* Returns:
* value of the register from the context structure
*
*************************************************************************/
BOOL
AlphaMachineInfo::GetVal (
ULONG regnum,
REGVAL *val
)
{
if (GetContextState(MCTX_FULL) != S_OK)
{
return FALSE;
}
val->type = GetType(regnum);
// All registers except PSR are 64 bits and PSR is followed by
// ContextFlags so it's safe to always just grab 64 bits for
// the value.
val->i64 = *(&m_Context.AlphaNt5Context.FltF0 + regnum);
return TRUE;
}
/*** RegSetVal - set register value
*
* Purpose:
* Set the value of the register in the processor context
* structure.
*
* Input:
* regnum - register specification
* regvalue - new value to set the register
*
* Output:
* None.
*
*************************************************************************/
BOOL
AlphaMachineInfo::SetVal (
ULONG regnum,
REGVAL *val
)
{
if (m_ContextIsReadOnly)
{
return FALSE;
}
// Optimize away some common cases where registers are
// set to their current value.
if (m_ContextState >= MCTX_PC && regnum == ALPHA_FIR &&
val->i64 == m_Context.AlphaNt5Context.Fir)
{
return TRUE;
}
if (GetContextState(MCTX_DIRTY) != S_OK)
{
return FALSE;
}
if (regnum == ALPHA_PSR)
{
// Be careful to only write 32 bits for PSR to preserve
// ContextFlags.
*(ULONG *)(&m_Context.AlphaNt5Context.FltF0 + regnum) = val->i32;
}
else
{
*(&m_Context.AlphaNt5Context.FltF0 + regnum) = val->i64;
}
NotifyChangeDebuggeeState(DEBUG_CDS_REGISTERS,
RegCountFromIndex(regnum));
return TRUE;
}
/*** RegOutputAll - output all registers and present instruction
*
* Purpose:
* Function of "r" command.
*
* To output the current register state of the processor.
* All integer registers are output as well as processor status
* registers. Important flag fields are also output separately.
* OutDisCurrent is called to output the current instruction(s).
*
* Input:
* None.
*
* Output:
* None.
*
*************************************************************************/
VOID
AlphaMachineInfo::OutputAll(ULONG Mask, ULONG OutMask)
{
int regindex;
int regnumber;
ULONGLONG regvalue;
if (GetContextState(MCTX_FULL) != S_OK)
{
ErrOut("Unable to retrieve register information\n");
return;
}
if (Mask & (REGALL_INT32 | REGALL_INT64))
{
for (regindex = 0; regindex < 34; regindex++)
{
regnumber = GetIntRegNumber(regindex);
regvalue = GetReg64(regnumber);
if ( (Mask & REGALL_INT64) || regindex == 32 || regindex == 33)
{
MaskOut(OutMask, "%4s=%08lx %08lx",
RegNameFromIndex(regnumber),
(ULONG)(regvalue >> 32),
(ULONG)(regvalue & 0xffffffff));
if (regindex % 3 == 2)
{
MaskOut(OutMask, "\n");
}
else
{
MaskOut(OutMask, " ");
}
}
else
{
MaskOut(OutMask, "%4s=%08lx%c",
RegNameFromIndex(regnumber),
(ULONG)(regvalue & 0xffffffff),
NeedUpper(regvalue) ? '*' : ' ' );
if (regindex % 5 == 4)
{
MaskOut(OutMask, "\n");
}
else
{
MaskOut(OutMask, " ");
}
}
}
//
// print out the fpcr as 64 bits regardless,
// and the FIR and Fpcr's - assuming we know they follow
// the floating and integer registers.
//
if (m_Ptr64)
{
regnumber = ALPHA_FIR;
MaskOut(OutMask, "%4s=%s\n",
RegNameFromIndex(regnumber),
FormatAddr64(GetReg64(regnumber)));
}
else
{
regnumber = ALPHA_FIR;
MaskOut(OutMask, "%4s=%08lx\n",
RegNameFromIndex(regnumber),
GetReg32(regnumber));
}
regnumber = ALPHA_PSR;
MaskOut(OutMask, "%4s=%08lx\n",
RegNameFromIndex(regnumber), GetReg32(regnumber));
MaskOut(OutMask, "mode=%1lx ie=%1lx irql=%1lx \n",
GetSubReg32(ALPHA_MODE),
GetSubReg32(ALPHA_IE),
GetSubReg32(ALPHA_IRQL));
}
if (Mask & REGALL_FLOAT)
{
ULONG i;
REGVAL val;
//
// Print them all out
//
for (i = 0 ; i < 16; i ++)
{
GetVal(i + ALPHA_FLT_BASE, &val);
MaskOut(OutMask, "%4s = %16e\t",
RegNameFromIndex(i), val.f8);
GetVal(i + ALPHA_FLT_BASE + 16, &val);
MaskOut(OutMask, "%4s = %16e\n",
RegNameFromIndex(i+16), val.f8);
}
}
}
TRACEMODE
AlphaMachineInfo::GetTraceMode (void)
{
return TRACE_NONE;
}
void
AlphaMachineInfo::SetTraceMode (TRACEMODE Mode)
{
;
}
BOOL
AlphaMachineInfo::IsStepStatusSupported(ULONG Status)
{
switch (Status)
{
case DEBUG_STATUS_STEP_INTO:
case DEBUG_STATUS_STEP_OVER:
return TRUE;
default:
return FALSE;
}
}
ULONG
AlphaMachineInfo::ExecutingMachine(void)
{
return g_TargetMachineType;
}
void
AlphaMachineInfo::ValidateCxr(PCROSS_PLATFORM_CONTEXT Context)
{
return;
}
BOOL
AlphaMachineInfo::DisplayTrapFrame(ULONG64 FrameAddress,
OUT PCROSS_PLATFORM_CONTEXT Context)
{
#define HIGH(x) ((ULONG) ((x>>32) & 0xFFFFFFFF))
#define LOW(x) ((ULONG) (x & 0xFFFFFFFF))
#define HIGHANDLOW(x) HIGH(x), LOW(x)
ALPHA_KTRAP_FRAME TrapContents;
ULONG64 Address=FrameAddress;
ULONG result;
ULONG64 DisasmAddr;
ULONG64 Displacement;
CHAR Buffer[80];
ULONG64 IntSp, IntFp;
if (!FrameAddress ||
g_Target->ReadVirtual(Address, &TrapContents,
sizeof(ALPHA_KTRAP_FRAME), &result) != S_OK)
{
dprintf("USAGE: !trap base_of_trap_frame\n");
return FALSE;
}
dprintf("v0 = %08lx %08lx a0 = %08lx %08lx\n" ,
HIGHANDLOW(TrapContents.IntV0),HIGHANDLOW(TrapContents.IntA0));
dprintf("t0 = %08lx %08lx a1 = %08lx %08lx\n" ,
HIGHANDLOW(TrapContents.IntT0),HIGHANDLOW(TrapContents.IntA1));
dprintf("t1 = %08lx %08lx a2 = %08lx %08lx\n" ,
HIGHANDLOW(TrapContents.IntT1),HIGHANDLOW(TrapContents.IntA2));
dprintf("t2 = %08lx %08lx a3 = %08lx %08lx\n" ,
HIGHANDLOW(TrapContents.IntT2),HIGHANDLOW(TrapContents.IntA3));
dprintf("t3 = %08lx %08lx a4 = %08lx %08lx\n" ,
HIGHANDLOW(TrapContents.IntT3),HIGHANDLOW(TrapContents.IntA4));
dprintf("t4 = %08lx %08lx a5 = %08lx %08lx\n" ,
HIGHANDLOW(TrapContents.IntT4),HIGHANDLOW(TrapContents.IntA5));
dprintf("t5 = %08lx %08lx t8 = %08lx %08lx\n" ,
HIGHANDLOW(TrapContents.IntT5),HIGHANDLOW(TrapContents.IntT8));
dprintf("t6 = %08lx %08lx t9 = %08lx %08lx\n" ,
HIGHANDLOW(TrapContents.IntT6),HIGHANDLOW(TrapContents.IntT9));
dprintf("t7 = %08lx %08lx t10 = %08lx %08lx\n" ,
HIGHANDLOW(TrapContents.IntT7),HIGHANDLOW(TrapContents.IntT10));
dprintf(" t11 = %08lx %08lx\n" ,
HIGHANDLOW(TrapContents.IntT11));
dprintf(" ra = %08lx %08lx\n" ,
HIGHANDLOW(TrapContents.IntRa));
dprintf(" t12 = %08lx %08lx\n" ,
HIGHANDLOW(TrapContents.IntT12));
dprintf(" at = %08lx %08lx\n" ,
HIGHANDLOW(TrapContents.IntAt));
dprintf(" gp = %08lx %08lx\n" ,
HIGHANDLOW(TrapContents.IntGp));
dprintf("fp = %08lx %08lx sp = %08lx %08lx\n",
HIGHANDLOW(IntFp = TrapContents.IntFp),HIGHANDLOW(IntSp = TrapContents.IntSp));
dprintf("fir= %08lx %08lx\n",
HIGHANDLOW(TrapContents.Fir));
DisasmAddr = (TrapContents.Fir);
g_LastRegFrame.InstructionOffset = DisasmAddr;
g_LastRegFrame.StackOffset = IntSp;
g_LastRegFrame.FrameOffset = IntFp;
GetSymbolStdCall(DisasmAddr, Buffer, sizeof(Buffer), &Displacement, NULL);
dprintf("%s+0x%I64lx\n",Buffer,Displacement);
ADDR tempAddr;
Type(tempAddr) = ADDR_FLAT | FLAT_COMPUTED;
Off(tempAddr) = Flat(tempAddr) = DisasmAddr;
if (Disassemble(&tempAddr, Buffer, FALSE))
{
dprintf(Buffer);
}
else
{
dprintf("%08I64lx ???????????????\n", DisasmAddr);
}
if (Context)
{
// Fill up the context struct
if (g_EffMachine == IMAGE_FILE_MACHINE_ALPHA)
{
#define COPY(fld) Context->AlphaContext.fld = (ULONG) TrapContents.fld
COPY(IntSp); COPY(IntFp); COPY(Fir);
COPY(IntRa); COPY(IntAt); COPY(IntGp);
COPY(IntV0); COPY(IntA0); COPY(IntT0); COPY(IntA1); COPY(IntA2);
COPY(IntT1); COPY(IntT2); COPY(IntT3); COPY(IntT4); COPY(IntT5);
COPY(IntT6); COPY(IntT6); COPY(IntT7); COPY(IntT8); COPY(IntT9);
COPY(IntT10); COPY(IntT11); COPY(IntT12);
COPY(IntA3); COPY(IntA4); COPY(IntA5);
#undef COPY
}
else
{
}
}
return TRUE;
#undef HIGHANDLOW
#undef HIGH
#undef LOW
}
HRESULT
AlphaMachineInfo::ReadKernelProcessorId
(ULONG Processor, PDEBUG_PROCESSOR_IDENTIFICATION_ALL Id)
{
HRESULT Status;
ULONG64 Pcr;
ULONG Data[2];
if ((Status = g_Target->
GetProcessorSystemDataOffset(Processor, DEBUG_DATA_KPCR_OFFSET,
&Pcr)) != S_OK)
{
return Status;
}
Pcr += m_Ptr64 ?
FIELD_OFFSET(AXP64_PARTIAL_KPCR, ProcessorType) :
FIELD_OFFSET(ALPHA_PARTIAL_KPCR, ProcessorType);
if ((Status = g_Target->
ReadAllVirtual(Pcr, Data, sizeof(Data))) != S_OK)
{
return Status;
}
Id->Alpha.Type = Data[0];
Id->Alpha.Revision = Data[1];
return S_OK;
}
#define MAXENTRYTYPE 2
const char *g_AlphaEntryTypeName[] =
{
"ALPHA_RF_NOT_CONTIGUOUS", // 0
"ALPHA_RF_ALT_ENT_PROLOG", // 1
"ALPHA_RF_NULL_CONTEXT", // 2
"***INVALID***"
};
#define ALPHA_RF_ALT_PROLOG64(RF) (((ULONG64)(RF)->ExceptionHandler) & (~3))
void
AlphaMachineInfo::OutputFunctionEntry64
(PIMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY Entry)
{
BOOL Secondary = FALSE;
BOOL FixedReturn = FALSE;
ULONG EntryType = 0;
ULONG NullCount = 0;
if ((ALPHA_RF_PROLOG_END_ADDRESS(Entry) < ALPHA_RF_BEGIN_ADDRESS(Entry)) ||
(ALPHA_RF_PROLOG_END_ADDRESS(Entry) > ALPHA_RF_END_ADDRESS(Entry)))
{
Secondary = TRUE;
EntryType = ALPHA_RF_ENTRY_TYPE(Entry);
if (EntryType > MAXENTRYTYPE)
{
EntryType = MAXENTRYTYPE;
}
}
else if (ALPHA_RF_IS_FIXED_RETURN(Entry))
{
FixedReturn = TRUE;
}
NullCount = ALPHA_RF_NULL_CONTEXT_COUNT(Entry);
dprintf("BeginAddress = %s\n", FormatAddr64(Entry->BeginAddress));
dprintf("EndAddress = %s", FormatAddr64(Entry->EndAddress));
if (NullCount)
{
dprintf(" %d null-context instructions", NullCount);
}
dprintf("\n");
dprintf("ExceptionHandler = %s",
FormatAddr64(Entry->ExceptionHandler));
if (Entry->ExceptionHandler != 0)
{
if (Secondary)
{
ULONG64 AlternateProlog = ALPHA_RF_ALT_PROLOG64(Entry);
switch(EntryType)
{
case ALPHA_RF_NOT_CONTIGUOUS:
case ALPHA_RF_ALT_ENT_PROLOG:
if ((AlternateProlog >=
ALPHA_RF_BEGIN_ADDRESS(Entry)) &&
(AlternateProlog <= Entry->EndAddress))
{
dprintf(" alternate PrologEndAddress");
}
break;
case ALPHA_RF_NULL_CONTEXT:
dprintf(" stack adjustment");
break;
}
}
else if (FixedReturn)
{
dprintf(" fixed return address");
}
}
dprintf("\n");
dprintf("HandlerData = %s", FormatAddr64(Entry->HandlerData));
if (Secondary)
{
dprintf(" type %d: %s", EntryType, g_AlphaEntryTypeName[EntryType]);
}
dprintf("\n");
dprintf("PrologEndAddress = %s\n",
FormatAddr64(Entry->PrologEndAddress));
}
HRESULT
Axp32MachineInfo::InitializeConstants(void)
{
m_FullName = "Alpha 32-bit";
m_AbbrevName = "alpha";
m_PageSize = ALPHA_PAGE_SIZE;
m_PageShift = ALPHA_PAGE_SHIFT;
m_NumExecTypes = 1;
m_ExecTypes = g_Axp32ExecTypes;
m_Ptr64 = FALSE;
return AlphaMachineInfo::InitializeConstants();
}
HRESULT
Axp32MachineInfo::InitializeForTarget(void)
{
m_OffsetPrcbProcessorState =
FIELD_OFFSET(ALPHA_PARTIAL_KPRCB, ProcessorState);
m_OffsetPrcbNumber =
FIELD_OFFSET(ALPHA_PARTIAL_KPRCB, Number);
m_TriagePrcbOffset = EXTEND64(ALPHA_TRIAGE_PRCB_ADDRESS);
m_SizePrcb = ALPHA_KPRCB_SIZE;
m_OffsetKThreadApcProcess =
FIELD_OFFSET(CROSS_PLATFORM_THREAD, AlphaThread.ApcState.Process);
m_OffsetKThreadTeb =
FIELD_OFFSET(CROSS_PLATFORM_THREAD, AlphaThread.Teb);
m_OffsetKThreadInitialStack =
FIELD_OFFSET(CROSS_PLATFORM_THREAD, AlphaThread.InitialStack);
m_OffsetEprocessPeb = g_SystemVersion > NT_SVER_W2K ?
ALPHA_NT51_PEB_IN_EPROCESS : ALPHA_NT5_PEB_IN_EPROCESS;
m_OffsetEprocessDirectoryTableBase =
ALPHA_DIRECTORY_TABLE_BASE_IN_EPROCESS;
m_SizeEThread = ALPHA_ETHREAD_SIZE;
m_SizeEProcess = g_SystemVersion > NT_SVER_W2K ?
ALPHA_NT51_EPROCESS_SIZE : ALPHA_NT5_EPROCESS_SIZE;
m_SizePartialKThread = sizeof(ALPHA_THREAD);
m_SharedUserDataOffset = IS_KERNEL_TARGET() ?
EXTEND64(ALPHA_KI_USER_SHARED_DATA) : MM_SHARED_USER_DATA_VA;
return MachineInfo::InitializeForTarget();
}
HRESULT
Axp32MachineInfo::GetContextFromThreadStack(ULONG64 ThreadBase,
PCROSS_PLATFORM_THREAD Thread,
PCROSS_PLATFORM_CONTEXT Context,
PDEBUG_STACK_FRAME Frame,
PULONG RunningOnProc)
{
if (Thread->AlphaThread.State == 2)
{
return E_NOTIMPL;
}
HRESULT Status;
ALPHA_KEXCEPTION_FRAME ExFrame;
if ((Status = g_Target->ReadAllVirtual(Thread->AlphaThread.KernelStack,
&ExFrame, sizeof(ExFrame))) != S_OK)
{
return Status;
}
//
// Successfully read an exception frame from the stack.
//
Context->AlphaNt5Context.IntSp =
Thread->AlphaThread.KernelStack;
Context->AlphaNt5Context.Fir = ExFrame.SwapReturn;
Context->AlphaNt5Context.IntRa = ExFrame.SwapReturn;
Context->AlphaNt5Context.IntS0 = ExFrame.IntS0;
Context->AlphaNt5Context.IntS1 = ExFrame.IntS1;
Context->AlphaNt5Context.IntS2 = ExFrame.IntS2;
Context->AlphaNt5Context.IntS3 = ExFrame.IntS3;
Context->AlphaNt5Context.IntS4 = ExFrame.IntS4;
Context->AlphaNt5Context.IntS5 = ExFrame.IntS5;
Context->AlphaNt5Context.Psr = ExFrame.Psr;
Frame->FrameOffset = Context->AlphaNt5Context.IntSp;
Frame->StackOffset = Context->AlphaNt5Context.IntSp;
Frame->InstructionOffset = ExFrame.SwapReturn;
return S_OK;
}
VOID
Axp32MachineInfo::GetPC (
PADDR Address
)
{
// sign extend the address!
ADDRFLAT(Address, EXTEND64(GetReg32(ALPHA_FIR)));
}
VOID
Axp32MachineInfo::SetPC (
PADDR paddr
)
{
// sign extend the address!
SetReg64(ALPHA_FIR, EXTEND64(Flat(*paddr)));
}
VOID
Axp32MachineInfo::GetFP (
PADDR Address
)
{
ADDRFLAT(Address, GetReg32(FP_REG));
}
void
Axp32MachineInfo::GetSP(PADDR Address)
{
ADDRFLAT(Address, GetReg32(SP_REG));
}
ULONG64
Axp32MachineInfo::GetArgReg(void)
{
return GetReg32(ALPHA_INT64_BASE + A0_REG);
}
HRESULT
Axp32MachineInfo::SetPageDirectory(ULONG Idx, ULONG64 PageDir,
PULONG NextIdx)
{
*NextIdx = PAGE_DIR_COUNT;
if (PageDir == 0)
{
HRESULT Status;
if ((Status = g_Target->ReadImplicitProcessInfoPointer
(m_OffsetEprocessDirectoryTableBase, &PageDir)) != S_OK)
{
return Status;
}
}
// DirectoryTableBase values on Alpha are the raw PTE entries
// so turn it into a clean physical address.
PageDir = ((ULONG)PageDir >> ALPHA_VALID_PFN_SHIFT) <<
ALPHA_PAGE_SHIFT;
// There is only one page directory so update all the slots.
m_PageDirectories[PAGE_DIR_USER] = PageDir;
m_PageDirectories[PAGE_DIR_SESSION] = PageDir;
m_PageDirectories[PAGE_DIR_KERNEL] = PageDir;
return S_OK;
}
#define ALPHA_PAGE_FILE_INDEX(Entry) \
(((ULONG)(Entry) >> 8) & MAX_PAGING_FILE_MASK)
#define ALPHA_PAGE_FILE_OFFSET(Entry) \
((ULONG64)((Entry) >> 12) << ALPHA_PAGE_SHIFT)
HRESULT
Axp32MachineInfo::GetVirtualTranslationPhysicalOffsets(ULONG64 Virt,
PULONG64 Offsets,
ULONG OffsetsSize,
PULONG Levels,
PULONG PfIndex,
PULONG64 LastVal)
{
HRESULT Status;
*Levels = 0;
if (m_Translating)
{
return E_UNEXPECTED;
}
m_Translating = TRUE;
//
// Reset the page directory in case it was 0
//
if (m_PageDirectories[PAGE_DIR_SINGLE] == 0)
{
if ((Status = SetDefaultPageDirectories(1 << PAGE_DIR_SINGLE)) != S_OK)
{
m_Translating = FALSE;
return Status;
}
}
KdOut("Axp32VtoP: Virt %s, pagedir %s\n",
FormatAddr64(Virt),
FormatAddr64(m_PageDirectories[PAGE_DIR_SINGLE]));
(*Levels)++;
if (Offsets != NULL && OffsetsSize > 0)
{
*Offsets++ = m_PageDirectories[PAGE_DIR_SINGLE];
OffsetsSize--;
}
//
// Certain ranges of the system are mapped directly.
//
if ((Virt >= EXTEND64(ALPHA_PHYSICAL_START)) &&
(Virt <= EXTEND64(ALPHA_PHYSICAL_END)))
{
*LastVal = Virt - EXTEND64(ALPHA_PHYSICAL_START);
KdOut("Axp32VtoP: Direct phys %s\n", FormatAddr64(*LastVal));
(*Levels)++;
if (Offsets != NULL && OffsetsSize > 0)
{
*Offsets++ = *LastVal;
OffsetsSize--;
}
m_Translating = FALSE;
return S_OK;
}
ULONG64 Addr;
ULONG Entry;
Addr = (((ULONG)Virt >> ALPHA_PDE_SHIFT) * sizeof(Entry)) +
m_PageDirectories[PAGE_DIR_SINGLE];
KdOut("Axp32VtoP: PDE %s\n", FormatAddr64(Addr));
(*Levels)++;
if (Offsets != NULL && OffsetsSize > 0)
{
*Offsets++ = Addr;
OffsetsSize--;
}
if ((Status = g_Target->
ReadAllPhysical(Addr, &Entry, sizeof(Entry))) != S_OK)
{
KdOut("Axp32VtoP: PDE read error 0x%X\n", Status);
m_Translating = FALSE;
return Status;
}
if (Entry == 0)
{
KdOut("Axp32VtoP: zero PDE\n");
m_Translating = FALSE;
return HR_PAGE_NOT_AVAILABLE;
}
else if (!(Entry & 1))
{
Addr = ((((ULONG)Virt >> ALPHA_PTE_SHIFT) & ALPHA_PTE_MASK) *
sizeof(Entry)) + ALPHA_PAGE_FILE_OFFSET(Entry);
KdOut("Axp32VtoP: pagefile PTE %d:%s\n",
ALPHA_PAGE_FILE_INDEX(Entry), FormatAddr64(Addr));
if ((Status = g_Target->
ReadPageFile(ALPHA_PAGE_FILE_INDEX(Entry), Addr,
&Entry, sizeof(Entry))) != S_OK)
{
KdOut("Axp32VtoP: PDE not present, 0x%X\n", Status);
m_Translating = FALSE;
return Status;
}
}
else
{
Addr = ((((ULONG)Virt >> ALPHA_PTE_SHIFT) & ALPHA_PTE_MASK) *
sizeof(Entry)) +
((Entry >> ALPHA_VALID_PFN_SHIFT) << ALPHA_PAGE_SHIFT);
KdOut("Axp32VtoP: PTE %s\n", FormatAddr64(Addr));
(*Levels)++;
if (Offsets != NULL && OffsetsSize > 0)
{
*Offsets++ = Addr;
OffsetsSize--;
}
if ((Status = g_Target->
ReadAllPhysical(Addr, &Entry, sizeof(Entry))) != S_OK)
{
KdOut("Axp32VtoP: PTE read error 0x%X\n", Status);
m_Translating = FALSE;
return Status;
}
}
if (!(Entry & 0x1) &&
((Entry & ALPHA_MM_PTE_PROTOTYPE_MASK) ||
!(Entry & ALPHA_MM_PTE_TRANSITION_MASK)))
{
if (Entry == 0)
{
KdOut("Axp32VtoP: zero PTE\n");
Status = HR_PAGE_NOT_AVAILABLE;
}
else if (Entry & ALPHA_MM_PTE_PROTOTYPE_MASK)
{
KdOut("Axp32VtoP: prototype PTE\n");
Status = HR_PAGE_NOT_AVAILABLE;
}
else
{
*PfIndex = ALPHA_PAGE_FILE_INDEX(Entry);
*LastVal = (Virt & (ALPHA_PAGE_SIZE - 1)) +
ALPHA_PAGE_FILE_OFFSET(Entry);
KdOut("Axp32VtoP: PTE not present, pagefile %d:%s\n",
*PfIndex, FormatAddr64(*LastVal));
Status = HR_PAGE_IN_PAGE_FILE;
}
m_Translating = FALSE;
return Status;
}
//
// This is a page which is either present or in transition.
// Return the physical address for the request virtual address.
//
*LastVal = ((Entry >> ALPHA_VALID_PFN_SHIFT) << ALPHA_PAGE_SHIFT) |
(Virt & (ALPHA_PAGE_SIZE - 1));
KdOut("Axp32VtoP: Mapped phys %s\n", FormatAddr64(*LastVal));
(*Levels)++;
if (Offsets != NULL && OffsetsSize > 0)
{
*Offsets++ = *LastVal;
OffsetsSize--;
}
m_Translating = FALSE;
return S_OK;
}
HRESULT
Axp32MachineInfo::GetBaseTranslationVirtualOffset(PULONG64 Offset)
{
*Offset = EXTEND64(ALPHA_BASE_VIRT);
return S_OK;
}
void
Axp32MachineInfo::OutputFunctionEntry(PVOID RawEntry)
{
// Assume Alpha function entries are always kept as
// 64-bit entries. That's what imagehlp does right now.
OutputFunctionEntry64((PIMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY)RawEntry);
}
HRESULT
Axp32MachineInfo::ReadDynamicFunctionTable(ULONG64 Table,
PULONG64 NextTable,
PULONG64 MinAddress,
PULONG64 MaxAddress,
PULONG64 BaseAddress,
PULONG64 TableData,
PULONG TableSize,
PWSTR OutOfProcessDll,
PCROSS_PLATFORM_DYNAMIC_FUNCTION_TABLE RawTable)
{
HRESULT Status;
if ((Status = g_Target->
ReadAllVirtual(Table, &RawTable->AlphaTable,
sizeof(RawTable->AlphaTable))) != S_OK)
{
return Status;
}
*NextTable = EXTEND64(RawTable->AlphaTable.Links.Flink);
*MinAddress = EXTEND64(RawTable->AlphaTable.MinimumAddress);
*MaxAddress = EXTEND64(RawTable->AlphaTable.MaximumAddress);
*BaseAddress = EXTEND64(RawTable->AlphaTable.MinimumAddress);
*TableData = EXTEND64(RawTable->AlphaTable.FunctionTable);
*TableSize = RawTable->AlphaTable.EntryCount *
sizeof(IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY);
OutOfProcessDll[0] = 0;
return S_OK;
}
PVOID
Axp32MachineInfo::FindDynamicFunctionEntry(PCROSS_PLATFORM_DYNAMIC_FUNCTION_TABLE Table,
ULONG64 Address,
PVOID TableData,
ULONG TableSize)
{
ULONG i;
PIMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY Func;
// Always return AXP64 function entries.
static IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY s_RetFunc;
Func = (PIMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY)TableData;
for (i = 0; i < TableSize / sizeof(IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY); i++)
{
if (Address >= ALPHA_RF_BEGIN_ADDRESS(Func) &&
Address < ALPHA_RF_END_ADDRESS(Func))
{
// The table data is temporary so copy the data into
// a static buffer for longer-term storage.
s_RetFunc.BeginAddress = EXTEND64(Func->BeginAddress);
s_RetFunc.EndAddress = EXTEND64(Func->EndAddress);
s_RetFunc.ExceptionHandler = EXTEND64(Func->ExceptionHandler);
s_RetFunc.HandlerData = EXTEND64(Func->HandlerData);
s_RetFunc.PrologEndAddress = EXTEND64(Func->PrologEndAddress);
return (PVOID)&s_RetFunc;
}
Func++;
}
return NULL;
}
HRESULT
Axp64MachineInfo::InitializeConstants(void)
{
m_FullName = "Alpha 64-bit";
m_AbbrevName = "axp64";
m_PageSize = AXP64_PAGE_SIZE;
m_PageShift = AXP64_PAGE_SHIFT;
m_NumExecTypes = 1;
m_ExecTypes = g_Axp64ExecTypes;
m_Ptr64 = TRUE;
return AlphaMachineInfo::InitializeConstants();
}
HRESULT
Axp64MachineInfo::InitializeForTarget(void)
{
m_OffsetPrcbProcessorState =
FIELD_OFFSET(AXP64_PARTIAL_KPRCB, ProcessorState);
m_OffsetPrcbNumber =
FIELD_OFFSET(AXP64_PARTIAL_KPRCB, Number);
m_TriagePrcbOffset = AXP64_TRIAGE_PRCB_ADDRESS;
m_SizePrcb = AXP64_KPRCB_SIZE;
m_OffsetKThreadApcProcess =
FIELD_OFFSET(CROSS_PLATFORM_THREAD, Axp64Thread.ApcState.Process);
m_OffsetKThreadTeb =
FIELD_OFFSET(CROSS_PLATFORM_THREAD, Axp64Thread.Teb);
m_OffsetKThreadInitialStack =
FIELD_OFFSET(CROSS_PLATFORM_THREAD, Axp64Thread.InitialStack);
m_OffsetEprocessPeb = AXP64_PEB_IN_EPROCESS;
m_OffsetEprocessDirectoryTableBase =
AXP64_DIRECTORY_TABLE_BASE_IN_EPROCESS;
m_SizeEThread = AXP64_ETHREAD_SIZE;
m_SizeEProcess = AXP64_EPROCESS_SIZE;
m_SizePartialKThread = sizeof(AXP64_THREAD);
m_SharedUserDataOffset = IS_KERNEL_TARGET() ?
AXP64_KI_USER_SHARED_DATA : MM_SHARED_USER_DATA_VA;
return MachineInfo::InitializeForTarget();
}
HRESULT
Axp64MachineInfo::GetContextFromThreadStack(ULONG64 ThreadBase,
PCROSS_PLATFORM_THREAD Thread,
PCROSS_PLATFORM_CONTEXT Context,
PDEBUG_STACK_FRAME Frame,
PULONG RunningOnProc)
{
if (Thread->Axp64Thread.State == 2)
{
return E_NOTIMPL;
}
HRESULT Status;
ALPHA_KEXCEPTION_FRAME ExFrame;
if ((Status = g_Target->ReadAllVirtual(Thread->Axp64Thread.KernelStack,
&ExFrame, sizeof(ExFrame))) != S_OK)
{
return Status;
}
//
// Successfully read an exception frame from the stack.
//
Context->AlphaNt5Context.IntSp =
Thread->Axp64Thread.KernelStack;
Context->AlphaNt5Context.Fir = ExFrame.SwapReturn;
Context->AlphaNt5Context.IntRa = ExFrame.SwapReturn;
Context->AlphaNt5Context.IntS0 = ExFrame.IntS0;
Context->AlphaNt5Context.IntS1 = ExFrame.IntS1;
Context->AlphaNt5Context.IntS2 = ExFrame.IntS2;
Context->AlphaNt5Context.IntS3 = ExFrame.IntS3;
Context->AlphaNt5Context.IntS4 = ExFrame.IntS4;
Context->AlphaNt5Context.IntS5 = ExFrame.IntS5;
Context->AlphaNt5Context.Psr = ExFrame.Psr;
Frame->FrameOffset = Context->AlphaNt5Context.IntSp;
Frame->StackOffset = Context->AlphaNt5Context.IntSp;
Frame->InstructionOffset = ExFrame.SwapReturn;
return S_OK;
}
VOID
Axp64MachineInfo::GetPC (
PADDR Address
)
{
ADDRFLAT(Address, GetReg64(ALPHA_FIR));
}
VOID
Axp64MachineInfo::SetPC (
PADDR paddr
)
{
SetReg64(ALPHA_FIR, Flat(*paddr));
}
VOID
Axp64MachineInfo::GetFP (
PADDR Address
)
{
ADDRFLAT(Address, GetReg64(FP_REG));
}
void
Axp64MachineInfo::GetSP(PADDR Address)
{
ADDRFLAT(Address, GetReg64(SP_REG));
}
ULONG64
Axp64MachineInfo::GetArgReg(void)
{
return GetReg64(ALPHA_INT64_BASE + A0_REG);
}
HRESULT
Axp64MachineInfo::SetPageDirectory(ULONG Idx, ULONG64 PageDir,
PULONG NextIdx)
{
if (PageDir == 0)
{
HRESULT Status;
if ((Status = g_Target->ReadImplicitProcessInfoPointer
(m_OffsetEprocessDirectoryTableBase, &PageDir)) != S_OK)
{
return Status;
}
}
// DirectoryTableBase values on Alpha are the raw PTE entries
// so turn it into a clean physical address.
PageDir = (PageDir >> AXP64_VALID_PFN_SHIFT) <<
AXP64_PAGE_SHIFT;
// There is only one page directory so update all the slots.
m_PageDirectories[PAGE_DIR_USER] = PageDir;
m_PageDirectories[PAGE_DIR_SESSION] = PageDir;
m_PageDirectories[PAGE_DIR_KERNEL] = PageDir;
return S_OK;
}
#define AXP64_PAGE_FILE_INDEX(Entry) \
(((ULONG)(Entry) >> 28) & MAX_PAGING_FILE_MASK)
#define AXP64_PAGE_FILE_OFFSET(Entry) \
(((Entry) >> 32) << AXP64_PAGE_SHIFT)
HRESULT
Axp64MachineInfo::GetVirtualTranslationPhysicalOffsets(ULONG64 Virt,
PULONG64 Offsets,
ULONG OffsetsSize,
PULONG Levels,
PULONG PfIndex,
PULONG64 LastVal)
{
HRESULT Status;
*Levels = 0;
if (m_Translating)
{
return E_UNEXPECTED;
}
m_Translating = TRUE;
//
// Reset the page directory in case it was 0
//
if (m_PageDirectories[PAGE_DIR_SINGLE] == 0)
{
if ((Status = SetDefaultPageDirectories(1 << PAGE_DIR_SINGLE)) != S_OK)
{
m_Translating = FALSE;
return Status;
}
}
KdOut("Axp64VtoP: Virt %s, pagedir %s\n",
FormatAddr64(Virt),
FormatAddr64(m_PageDirectories[PAGE_DIR_SINGLE]));
(*Levels)++;
if (Offsets != NULL && OffsetsSize > 0)
{
*Offsets++ = m_PageDirectories[PAGE_DIR_SINGLE];
OffsetsSize--;
}
//
// Certain ranges of the system are mapped directly.
//
if ((Virt >= AXP64_PHYSICAL1_START) && (Virt <= AXP64_PHYSICAL1_END))
{
*LastVal = Virt - AXP64_PHYSICAL1_START;
KdOut("Axp64VtoP: Direct phys 1 %s\n", FormatAddr64(*LastVal));
(*Levels)++;
if (Offsets != NULL && OffsetsSize > 0)
{
*Offsets++ = *LastVal;
OffsetsSize--;
}
m_Translating = FALSE;
return S_OK;
}
if ((Virt >= AXP64_PHYSICAL2_START) && (Virt <= AXP64_PHYSICAL2_END))
{
*LastVal = Virt - AXP64_PHYSICAL2_START;
KdOut("Axp64VtoP: Direct phys 2 %s\n", FormatAddr64(*LastVal));
(*Levels)++;
if (Offsets != NULL && OffsetsSize > 0)
{
*Offsets++ = *LastVal;
OffsetsSize--;
}
m_Translating = FALSE;
return S_OK;
}
ULONG64 Addr;
ULONG64 Entry;
Addr = (((Virt >> AXP64_PDE1_SHIFT) & AXP64_PDE_MASK) * sizeof(Entry)) +
m_PageDirectories[PAGE_DIR_SINGLE];
KdOut("Axp64VtoP: PDE1 %s\n", FormatAddr64(Addr));
(*Levels)++;
if (Offsets != NULL && OffsetsSize > 0)
{
*Offsets++ = Addr;
OffsetsSize--;
}
if ((Status = g_Target->
ReadAllPhysical(Addr, &Entry, sizeof(Entry))) != S_OK)
{
KdOut("Axp64VtoP: PDE1 read error 0x%X\n", Status);
m_Translating = FALSE;
return Status;
}
if (Entry == 0)
{
KdOut("Axp64VtoP: zero PDE1\n");
m_Translating = FALSE;
return HR_PAGE_NOT_AVAILABLE;
}
else if (!(Entry & 1))
{
Addr = (((Virt >> AXP64_PDE2_SHIFT) & AXP64_PDE_MASK) *
sizeof(Entry)) + AXP64_PAGE_FILE_OFFSET(Entry);
KdOut("Axp64VtoP: pagefile PDE2 %d:%s\n",
AXP64_PAGE_FILE_INDEX(Entry), FormatAddr64(Addr));
if ((Status = g_Target->
ReadPageFile(AXP64_PAGE_FILE_INDEX(Entry), Addr,
&Entry, sizeof(Entry))) != S_OK)
{
KdOut("Axp64VtoP: PDE1 not present, 0x%X\n", Status);
m_Translating = FALSE;
return Status;
}
}
else
{
Addr = (((Virt >> AXP64_PDE2_SHIFT) & AXP64_PDE_MASK) *
sizeof(Entry)) +
((Entry >> AXP64_VALID_PFN_SHIFT) << AXP64_PAGE_SHIFT);
KdOut("Axp64VtoP: PDE2 %s\n", FormatAddr64(Addr));
(*Levels)++;
if (Offsets != NULL && OffsetsSize > 0)
{
*Offsets++ = Addr;
OffsetsSize--;
}
if ((Status = g_Target->
ReadAllPhysical(Addr, &Entry, sizeof(Entry))) != S_OK)
{
KdOut("Axp64VtoP: PDE2 read error 0x%X\n", Status);
m_Translating = FALSE;
return Status;
}
}
if (Entry == 0)
{
KdOut("Axp64VtoP: zero PDE2\n");
m_Translating = FALSE;
return HR_PAGE_NOT_AVAILABLE;
}
else if (!(Entry & 1))
{
Addr = (((Virt >> AXP64_PTE_SHIFT) & AXP64_PTE_MASK) *
sizeof(Entry)) + AXP64_PAGE_FILE_OFFSET(Entry);
KdOut("Axp64VtoP: pagefile PTE %d:%s\n",
AXP64_PAGE_FILE_INDEX(Entry), FormatAddr64(Addr));
if ((Status = g_Target->
ReadPageFile(AXP64_PAGE_FILE_INDEX(Entry), Addr,
&Entry, sizeof(Entry))) != S_OK)
{
KdOut("Axp64VtoP: PDE2 not present, 0x%X\n", Status);
m_Translating = FALSE;
return Status;
}
}
else
{
Addr = (((Virt >> AXP64_PTE_SHIFT) & AXP64_PTE_MASK) * sizeof(Entry)) +
((Entry >> AXP64_VALID_PFN_SHIFT) << AXP64_PAGE_SHIFT);
KdOut("Axp64VtoP: PTE %s\n", FormatAddr64(Addr));
(*Levels)++;
if (Offsets != NULL && OffsetsSize > 0)
{
*Offsets++ = Addr;
OffsetsSize--;
}
if ((Status = g_Target->
ReadAllPhysical(Addr, &Entry, sizeof(Entry))) != S_OK)
{
KdOut("Axp64VtoP: PTE read error 0x%X\n", Status);
m_Translating = FALSE;
return Status;
}
}
if (!(Entry & 0x1) &&
((Entry & AXP64_MM_PTE_PROTOTYPE_MASK) ||
!(Entry & AXP64_MM_PTE_TRANSITION_MASK)))
{
if (Entry == 0)
{
KdOut("Axp64VtoP: zero PTE\n");
Status = HR_PAGE_NOT_AVAILABLE;
}
else if (Entry & AXP64_MM_PTE_PROTOTYPE_MASK)
{
KdOut("Axp64VtoP: prototype PTE\n");
Status = HR_PAGE_NOT_AVAILABLE;
}
else
{
*PfIndex = AXP64_PAGE_FILE_INDEX(Entry);
*LastVal = (Virt & (AXP64_PAGE_SIZE - 1)) +
AXP64_PAGE_FILE_OFFSET(Entry);
KdOut("Axp64VtoP: PTE not present, pagefile %d:%s\n",
*PfIndex, FormatAddr64(*LastVal));
Status = HR_PAGE_IN_PAGE_FILE;
}
m_Translating = FALSE;
return Status;
}
//
// This is a page which is either present or in transition.
// Return the physical address for the request virtual address.
//
*LastVal = ((Entry >> AXP64_VALID_PFN_SHIFT) << AXP64_PAGE_SHIFT) |
(Virt & (AXP64_PAGE_SIZE - 1));
KdOut("Axp64VtoP: Mapped phys %s\n", FormatAddr64(*LastVal));
(*Levels)++;
if (Offsets != NULL && OffsetsSize > 0)
{
*Offsets++ = *LastVal;
OffsetsSize--;
}
m_Translating = FALSE;
return S_OK;
}
HRESULT
Axp64MachineInfo::GetBaseTranslationVirtualOffset(PULONG64 Offset)
{
*Offset = AXP64_BASE_VIRT;
return S_OK;
}
void
Axp64MachineInfo::OutputFunctionEntry(PVOID RawEntry)
{
OutputFunctionEntry64((PIMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY)RawEntry);
}
HRESULT
Axp64MachineInfo::ReadDynamicFunctionTable(ULONG64 Table,
PULONG64 NextTable,
PULONG64 MinAddress,
PULONG64 MaxAddress,
PULONG64 BaseAddress,
PULONG64 TableData,
PULONG TableSize,
PWSTR OutOfProcessDll,
PCROSS_PLATFORM_DYNAMIC_FUNCTION_TABLE RawTable)
{
HRESULT Status;
if ((Status = g_Target->
ReadAllVirtual(Table, &RawTable->Axp64Table,
sizeof(RawTable->Axp64Table))) != S_OK)
{
return Status;
}
*NextTable = RawTable->Axp64Table.Links.Flink;
*MinAddress = RawTable->Axp64Table.MinimumAddress;
*MaxAddress = RawTable->Axp64Table.MaximumAddress;
*BaseAddress = RawTable->Axp64Table.MinimumAddress;
*TableData = RawTable->Axp64Table.FunctionTable;
*TableSize = RawTable->Axp64Table.EntryCount *
sizeof(IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY);
OutOfProcessDll[0] = 0;
return S_OK;
}
PVOID
Axp64MachineInfo::FindDynamicFunctionEntry(PCROSS_PLATFORM_DYNAMIC_FUNCTION_TABLE Table,
ULONG64 Address,
PVOID TableData,
ULONG TableSize)
{
ULONG i;
PIMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY Func;
static IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY s_RetFunc;
Func = (PIMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY)TableData;
for (i = 0; i < TableSize / sizeof(IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY); i++)
{
if (Address >= ALPHA_RF_BEGIN_ADDRESS(Func) &&
Address < ALPHA_RF_END_ADDRESS(Func))
{
// The table data is temporary so copy the data into
// a static buffer for longer-term storage.
s_RetFunc.BeginAddress = Func->BeginAddress;
s_RetFunc.EndAddress = Func->EndAddress;
s_RetFunc.ExceptionHandler = Func->ExceptionHandler;
s_RetFunc.HandlerData = Func->HandlerData;
s_RetFunc.PrologEndAddress = Func->PrologEndAddress;
return (PVOID)&s_RetFunc;
}
Func++;
}
return NULL;
}