/*** alpha_reg.c - processor-specific register structures * * Copyright 1990-2001, Microsoft Corporation * Copyright 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; }