[Arm64] debugging work (#17993)
authorDavid Wrighton <davidwr@microsoft.com>
Thu, 24 May 2018 21:35:47 +0000 (14:35 -0700)
committerGitHub <noreply@github.com>
Thu, 24 May 2018 21:35:47 +0000 (14:35 -0700)
* Fix missing implementation of FuncEvalFrame::UpdateRegDisplay for ARM64
- Implementation is missing. Build new one based ARM implementation

* Enable just my code on arm64

* Fix logging of addresses for DispatchPatchOrSingleStep

* arm64 does not leave the PC at the start of the breakpoint

* Enable interop debugging

* Tweaks for windows arm64 mixed mode debugging support

clrdefinitions.cmake
src/debug/di/process.cpp
src/debug/di/rsthread.cpp
src/debug/ee/arm64/dbghelpers.asm
src/debug/ee/controller.cpp
src/debug/ee/debugger.cpp
src/debug/ee/debugger.inl
src/debug/inc/arm_primitives.h
src/jit/flowgraph.cpp
src/vm/arm64/virtualcallstubcpu.hpp

index e8daf3f..c50cf63 100644 (file)
@@ -149,9 +149,9 @@ if(NOT CMAKE_SYSTEM_NAME STREQUAL NetBSD)
     add_definitions(-DFEATURE_HIJACK)
 endif(NOT CMAKE_SYSTEM_NAME STREQUAL NetBSD)
 add_definitions(-DFEATURE_ICASTABLE)
-if (WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386))
+if (WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM64))
     add_definitions(-DFEATURE_INTEROP_DEBUGGING)
-endif (WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386))
+endif (WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM64))
 if(FEATURE_INTERPRETER)
   add_definitions(-DFEATURE_INTERPRETER)
 endif(FEATURE_INTERPRETER)
index 429a274..8e772eb 100644 (file)
@@ -8963,7 +8963,13 @@ bool CordbProcess::IsBreakOpcodeAtAddress(const void * address)
 {
     // There should have been an int3 there already. Since we already put it in there,
     // we should be able to safely read it out.
+#if defined(DBG_TARGET_ARM) || defined(DBG_TARGET_ARM64)
+    PRD_TYPE opcodeTest = 0;
+#elif defined(DBG_TARGET_AMD64) || defined(DBG_TARGET_X86)
     BYTE opcodeTest = 0;
+#else
+    PORTABILITY_ASSERT("NYI: Architecture specific opcode type to read");
+#endif
 
     HRESULT hr = SafeReadStruct(PTR_TO_CORDB_ADDRESS(address), &opcodeTest);
     SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr); 
@@ -9025,6 +9031,14 @@ CordbProcess::SetUnmanagedBreakpointInternal(CORDB_ADDRESS address, ULONG32 bufs
 #if defined(DBG_TARGET_X86) || defined(DBG_TARGET_AMD64)
     const BYTE patch = CORDbg_BREAK_INSTRUCTION;
     BYTE opcode;
+#elif defined(DBG_TARGET_ARM64)
+    const PRD_TYPE patch = CORDbg_BREAK_INSTRUCTION;
+    PRD_TYPE opcode;
+#else
+    PORTABILITY_ASSERT("NYI: CordbProcess::SetUnmanagedBreakpoint, interop debugging NYI on this platform");
+    hr = E_NOTIMPL;
+    goto ErrExit;
+#endif
 
     // Make sure args are good
     if ((buffer == NULL) || (bufsize < sizeof(patch)) || (bufLen == NULL))
@@ -9056,23 +9070,21 @@ CordbProcess::SetUnmanagedBreakpointInternal(CORDB_ADDRESS address, ULONG32 bufs
         goto ErrExit;
 
     // It's all successful, so now update our out-params & internal bookkeaping.
-    opcode = (BYTE) p->opcode;
+#if defined(DBG_TARGET_X86) || defined(DBG_TARGET_AMD64)
+    opcode = (BYTE)p->opcode;
     buffer[0] = opcode;
+#elif defined(DBG_TARGET_ARM64)
+    opcode = p->opcode;
+    memcpy_s(buffer, bufsize, &opcode, sizeof(opcode));
+#else
+    PORTABILITY_ASSERT("NYI: CordbProcess::SetUnmanagedBreakpoint, interop debugging NYI on this platform");
+#endif
     *bufLen = sizeof(opcode);
 
     p->pAddress = CORDB_ADDRESS_TO_PTR(address);
     p->opcode = opcode;
 
     _ASSERTE(SUCCEEDED(hr));
-#elif defined(DBG_TARGET_WIN64)
-    PORTABILITY_ASSERT("NYI: CordbProcess::SetUnmanagedBreakpoint, interop debugging NYI on this platform");
-    hr =  E_NOTIMPL;
-    goto ErrExit;
-#else
-    hr =  E_NOTIMPL;
-    goto ErrExit;
-#endif // DBG_TARGET_X8_
-
 
 ErrExit:
     // If we failed, then free the patch
@@ -12705,8 +12717,16 @@ void CordbProcess::HandleDebugEventForInteropDebugging(const DEBUG_EVENT * pEven
         tempDebugContext.ContextFlags = DT_CONTEXT_FULL;
         DbiGetThreadContext(pUnmanagedThread->m_handle, &tempDebugContext);
         CordbUnmanagedThread::LogContext(&tempDebugContext);
+#if defined(DBG_TARGET_X86) || defined(DBG_TARGET_AMD64)
+        const ULONG_PTR breakpointOpcodeSize = 1;
+#elif defined(DBG_TARGET_ARM64)
+        const ULONG_PTR breakpointOpcodeSize = 4;
+#else
+        const ULONG_PTR breakpointOpcodeSize = 1;
+        PORTABILITY_ASSERT("NYI: Breakpoint size offset for this platform");
+#endif
         _ASSERTE(CORDbgGetIP(&tempDebugContext) == pEvent->u.Exception.ExceptionRecord.ExceptionAddress ||
-            (DWORD)CORDbgGetIP(&tempDebugContext) == ((DWORD)pEvent->u.Exception.ExceptionRecord.ExceptionAddress)+1);
+            (DWORD)CORDbgGetIP(&tempDebugContext) == ((DWORD)pEvent->u.Exception.ExceptionRecord.ExceptionAddress)+breakpointOpcodeSize);
     }
 #endif
 
index 81f632b..92ed90e 100644 (file)
@@ -2836,9 +2836,11 @@ CordbUnmanagedThread::~CordbUnmanagedThread()
 #define WINNT_TLS_OFFSET_X86    0xe10     // TLS[0] at fs:[WINNT_TLS_OFFSET]
 #define WINNT_TLS_OFFSET_AMD64  0x1480
 #define WINNT_TLS_OFFSET_ARM    0xe10
+#define WINNT_TLS_OFFSET_ARM64  0x1480
 #define WINNT5_TLSEXPANSIONPTR_OFFSET_X86   0xf94 // TLS[64] at [fs:[WINNT5_TLSEXPANSIONPTR_OFFSET]]
 #define WINNT5_TLSEXPANSIONPTR_OFFSET_AMD64 0x1780
 #define WINNT5_TLSEXPANSIONPTR_OFFSET_ARM   0xf94
+#define WINNT5_TLSEXPANSIONPTR_OFFSET_ARM64 0x1780
 
 HRESULT CordbUnmanagedThread::LoadTLSArrayPtr(void)
 {
@@ -3771,6 +3773,13 @@ VOID CordbUnmanagedThread::LogContext(DT_CONTEXT* pContext)
         DBG_ADDR(pContext->Rip),
         DBG_ADDR(pContext->Rsp),
         pContext->EFlags));    // EFlags is still 32bits on AMD64
+#elif defined(DBG_TARGET_ARM64)
+    LOG((LF_CORDB, LL_INFO10000,
+        "CUT::LC: Pc=" FMT_ADDR ", Sp=" FMT_ADDR ", Lr=" FMT_ADDR ", Cpsr=" FMT_ADDR "\n",
+        DBG_ADDR(pContext->Pc),
+        DBG_ADDR(pContext->Sp),
+        DBG_ADDR(pContext->Lr),
+        DBG_ADDR(pContext->Cpsr)));
 #else   // DBG_TARGET_X86
     PORTABILITY_ASSERT("LogContext needs a PC and stack pointer.");
 #endif  // DBG_TARGET_X86
@@ -3914,8 +3923,8 @@ HRESULT CordbUnmanagedThread::SetupFirstChanceHijack(EHijackReason::EHijackReaso
         GetProcess()->GetDAC()->Hijack(VMPTR_Thread::NullPtr(),
                                        GetOSTid(),
                                        pExceptionRecord,
-                                       (CONTEXT*) GetHijackCtx(),
-                                       sizeof(CONTEXT),
+                                       (T_CONTEXT*) GetHijackCtx(),
+                                       sizeof(T_CONTEXT),
                                        reason,
                                        NULL,
                                        &LSContextAddr);
@@ -3961,7 +3970,7 @@ HRESULT CordbUnmanagedThread::SetupGenericHijack(DWORD eventCode, const EXCEPTIO
         return HRESULT_FROM_WIN32(GetLastError());
     }
 
-#if defined(DBG_TARGET_AMD64)
+#if defined(DBG_TARGET_AMD64) || defined(DBG_TARGET_ARM64)
 
     // On X86 Debugger::GenericHijackFunc() ensures the stack is walkable
     // by simply using the EBP chain, therefore we can execute the hijack
@@ -3988,8 +3997,8 @@ HRESULT CordbUnmanagedThread::SetupGenericHijack(DWORD eventCode, const EXCEPTIO
                     pThread->m_vmThreadToken,
                     dwThreadId,
                     pRecord, 
-                    (CONTEXT*) GetHijackCtx(),
-                    sizeof(CONTEXT),
+                    (T_CONTEXT*) GetHijackCtx(),
+                    sizeof(T_CONTEXT),
                     EHijackReason::kGenericHijack, 
                     NULL,
                     NULL);
@@ -4009,7 +4018,7 @@ HRESULT CordbUnmanagedThread::SetupGenericHijack(DWORD eventCode, const EXCEPTIO
     }
     // else (non-threadstore threads) fallthrough
 
-#endif // DBG_TARGET_AMD64
+#endif // DBG_TARGET_AMD64 || defined(DBG_TARGET_ARM64)
 
     // Remember that we've hijacked the guy.
     SetState(CUTS_GenericHijacked);
@@ -4379,6 +4388,11 @@ void CordbUnmanagedThread::SaveRaiseExceptionEntryContext()
     m_raiseExceptionExceptionFlags = (DWORD)m_raiseExceptionEntryContext.Rdx;
     m_raiseExceptionNumberParameters = (DWORD)m_raiseExceptionEntryContext.R8;
     pExceptionInformation = (REMOTE_PTR)m_raiseExceptionEntryContext.R9;
+#elif defined(DBG_TARGET_ARM64)
+    m_raiseExceptionExceptionCode = (DWORD)m_raiseExceptionEntryContext.X0;
+    m_raiseExceptionExceptionFlags = (DWORD)m_raiseExceptionEntryContext.X1;
+    m_raiseExceptionNumberParameters = (DWORD)m_raiseExceptionEntryContext.X2;
+    pExceptionInformation = (REMOTE_PTR)m_raiseExceptionEntryContext.X3;
 #elif defined(DBG_TARGET_X86)
     hr = m_pProcess->SafeReadStruct(PTR_TO_CORDB_ADDRESS((BYTE*)m_raiseExceptionEntryContext.Esp+4), &m_raiseExceptionExceptionCode);
     if(FAILED(hr))
@@ -4501,11 +4515,14 @@ HRESULT ApplyRemotePatch(CordbProcess * pProcess, const void * pRemoteAddress)
 {
 #if defined(DBG_TARGET_X86) || defined(DBG_TARGET_AMD64)
     const BYTE patch = CORDbg_BREAK_INSTRUCTION;
-    HRESULT hr = pProcess->SafeWriteStruct(PTR_TO_CORDB_ADDRESS(pRemoteAddress), &patch);
-    SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr);
+#elif defined(DBG_TARGET_ARM64)
+    const PRD_TYPE patch = CORDbg_BREAK_INSTRUCTION;
 #else
+    const BYTE patch = 0;
     PORTABILITY_ASSERT("NYI: ApplyRemotePatch for this platform");
 #endif
+    HRESULT hr = pProcess->SafeWriteStruct(PTR_TO_CORDB_ADDRESS(pRemoteAddress), &patch);
+    SIMPLIFYING_ASSUMPTION_SUCCEEDED(hr);
     return S_OK;
 }
 
@@ -4516,6 +4533,13 @@ HRESULT ApplyRemotePatch(CordbProcess * pProcess, const void * pRemoteAddress, P
 #if defined(DBG_TARGET_X86) || defined(DBG_TARGET_AMD64)
     // Read out opcode. 1 byte on x86
     BYTE opcode;
+#elif defined(DBG_TARGET_ARM64)
+    // Read out opcode. 4 bytes on arm64
+    PRD_TYPE opcode;
+#else
+    BYTE opcode;
+    PORTABILITY_ASSERT("NYI: ApplyRemotePatch for this platform");
+#endif
 
     HRESULT hr = pProcess->SafeReadStruct(PTR_TO_CORDB_ADDRESS(pRemoteAddress), &opcode);
     if (FAILED(hr))
@@ -4524,9 +4548,6 @@ HRESULT ApplyRemotePatch(CordbProcess * pProcess, const void * pRemoteAddress, P
     }
     
     *pOpcode = (PRD_TYPE) opcode;
-#else
-    PORTABILITY_ASSERT("NYI: ApplyRemotePatch for this platform");
-#endif
     ApplyRemotePatch(pProcess, pRemoteAddress);
     return S_OK;
 }
@@ -4539,14 +4560,18 @@ HRESULT RemoveRemotePatch(CordbProcess * pProcess, const void * pRemoteAddress,
 #if defined(DBG_TARGET_X86) || defined(DBG_TARGET_AMD64)
     // Replace the BP w/ the opcode.
     BYTE opcode2 = (BYTE) opcode;
+#elif defined(DBG_TARGET_ARM64)
+    // 4 bytes on arm64
+    PRD_TYPE opcode2 = opcode;
+#else
+    PRD_TYPE opcode2 = opcode;
+    PORTABILITY_ASSERT("NYI: RemoveRemotePatch for this platform");
+#endif
 
     pProcess->SafeWriteStruct(PTR_TO_CORDB_ADDRESS(pRemoteAddress), &opcode2);
 
     // This may fail because the module has been unloaded.  In which case, the patch is also 
     // gone so it makes sense to return success.
-#else
-    PORTABILITY_ASSERT("NYI: RemoveRemotePatch for this platform");
-#endif
     return S_OK;
 }
 #endif // FEATURE_INTEROP_DEBUGGING
index ded1a0d..16cab70 100644 (file)
 ExceptionHijackEnd
     NESTED_END ExceptionHijack
 
+;
+; Flares for interop debugging.
+; Flares are exceptions (breakpoints) at well known addresses which the RS
+; listens for when interop debugging.
+;
+
+    LEAF_ENTRY SignalHijackStartedFlare
+    EMIT_BREAKPOINT
+    ; make sure that the basic block is unique
+    add     x0, x1, x1
+    ret     lr
+    LEAF_END
+
+    LEAF_ENTRY ExceptionForRuntimeHandoffStartFlare
+    EMIT_BREAKPOINT
+    ; make sure that the basic block is unique
+    add     x0, x2, x2
+    ret     lr
+    LEAF_END
+
+    LEAF_ENTRY ExceptionForRuntimeHandoffCompleteFlare
+    EMIT_BREAKPOINT
+    ; make sure that the basic block is unique
+    add     x0, x3, x3
+    ret     lr
+    LEAF_END
+
+    LEAF_ENTRY SignalHijackCompleteFlare
+    EMIT_BREAKPOINT
+    ; make sure that the basic block is unique
+    add     x0, x4, x4
+    ret     lr
+    LEAF_END
+
+    LEAF_ENTRY ExceptionNotForRuntimeFlare
+    EMIT_BREAKPOINT
+    ; make sure that the basic block is unique
+    add     x0, x5, x5
+    ret     lr
+    LEAF_END
+
+    LEAF_ENTRY NotifyRightSideOfSyncCompleteFlare
+    EMIT_BREAKPOINT
+    ; make sure that the basic block is unique
+    add     x0, x6, x6
+    ret     lr
+    LEAF_END
+
     ; must be at end of file
     END
     
index 76c7699..8a56e17 100644 (file)
@@ -2867,7 +2867,7 @@ DPOSS_ACTION DebuggerController::DispatchPatchOrSingleStep(Thread *thread, CONTE
 
     CONTRACT_VIOLATION(ThrowsViolation);
 
-    LOG((LF_CORDB|LF_ENC,LL_INFO1000,"DC:DPOSS at 0x%x trigger:0x%x\n", address, which));
+    LOG((LF_CORDB|LF_ENC,LL_INFO1000,"DC:DPOSS at 0x%p trigger:0x%x\n", address, which));
 
     // We should only have an exception if some managed thread was running.
     // Thus we should never be here when we're stopped.
index 1e69d2b..b6570a2 100644 (file)
@@ -13720,6 +13720,10 @@ LONG Debugger::FirstChanceSuspendHijackWorker(CONTEXT *pContext,
     SPEW(fprintf(stderr, "0x%x D::FCHF: code=0x%08x, addr=0x%08x, Eip=0x%08x, Esp=0x%08x, EFlags=0x%08x\n",
         tid, pExceptionRecord->ExceptionCode, pExceptionRecord->ExceptionAddress, pContext->Eip, pContext->Esp,
         pContext->EFlags));
+#elif defined(_TARGET_ARM64_)
+    SPEW(fprintf(stderr, "0x%x D::FCHF: code=0x%08x, addr=0x%08x, Pc=0x%p, Sp=0x%p, EFlags=0x%08x\n",
+        tid, pExceptionRecord->ExceptionCode, pExceptionRecord->ExceptionAddress, pContext->Pc, pContext->Sp,
+        pContext->EFlags));
 #endif
 
     // This memory is used as IPC during the hijack. We will place a pointer to this in
@@ -13829,7 +13833,7 @@ LONG Debugger::FirstChanceSuspendHijackWorker(CONTEXT *pContext,
     }
 } 
 
-#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
+#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)
 void GenericHijackFuncHelper()
 {
 #if DOSPEW
@@ -13970,7 +13974,7 @@ void Debugger::SignalHijackStarted(void)
 {
     WRAPPER_NO_CONTRACT;
 
-#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
+#if defined(FEATURE_INTEROP_DEBUGGING)
     SignalHijackStartedFlare();
 #else
     _ASSERTE(!"@todo - port the flares to the platform your running on.");
@@ -13987,7 +13991,7 @@ void Debugger::ExceptionForRuntimeHandoffStart(void)
 {
     WRAPPER_NO_CONTRACT;
 
-#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
+#if defined(FEATURE_INTEROP_DEBUGGING)
     ExceptionForRuntimeHandoffStartFlare();
 #else
     _ASSERTE(!"@todo - port the flares to the platform your running on.");
@@ -14005,7 +14009,7 @@ void Debugger::ExceptionForRuntimeHandoffComplete(void)
 {
     WRAPPER_NO_CONTRACT;
 
-#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
+#if defined(FEATURE_INTEROP_DEBUGGING)
     ExceptionForRuntimeHandoffCompleteFlare();
 #else
     _ASSERTE(!"@todo - port the flares to the platform your running on.");
@@ -14021,7 +14025,7 @@ void Debugger::SignalHijackComplete(void)
 {
     WRAPPER_NO_CONTRACT;
 
-#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
+#if defined(FEATURE_INTEROP_DEBUGGING)
     SignalHijackCompleteFlare();
 #else
     _ASSERTE(!"@todo - port the flares to the platform your running on.");
@@ -14037,7 +14041,7 @@ void Debugger::ExceptionNotForRuntime(void)
 {
     WRAPPER_NO_CONTRACT;
 
-#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
+#if defined(FEATURE_INTEROP_DEBUGGING)
     ExceptionNotForRuntimeFlare();
 #else
     _ASSERTE(!"@todo - port the flares to the platform your running on.");
@@ -14053,7 +14057,7 @@ void Debugger::NotifyRightSideOfSyncComplete(void)
 {
     WRAPPER_NO_CONTRACT;
     STRESS_LOG0(LF_CORDB, LL_INFO100000, "D::NRSOSC: Sending flare...\n");
-#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
+#if defined(FEATURE_INTEROP_DEBUGGING)
     NotifyRightSideOfSyncCompleteFlare();
 #else
     _ASSERTE(!"@todo - port the flares to the platform your running on.");
index 612aacd..4542182 100644 (file)
@@ -295,7 +295,47 @@ inline void FuncEvalFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
     pRD->volatileCurrContextPointers.R12 = &(pDE->m_context.R12);
 
     SyncRegDisplayToCurrentContext(pRD);
-#else 
+
+#elif defined(_TARGET_ARM64_)
+    pRD->IsCallerContextValid = FALSE;
+    pRD->IsCallerSPValid = FALSE;        // Don't add usage of this flag.  This is only temporary.
+
+    memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(T_CONTEXT));
+
+    pRD->pCurrentContextPointers->X19 = &(pDE->m_context.X19);
+    pRD->pCurrentContextPointers->X20 = &(pDE->m_context.X20);
+    pRD->pCurrentContextPointers->X21 = &(pDE->m_context.X21);
+    pRD->pCurrentContextPointers->X22 = &(pDE->m_context.X22);
+    pRD->pCurrentContextPointers->X23 = &(pDE->m_context.X23);
+    pRD->pCurrentContextPointers->X24 = &(pDE->m_context.X24);
+    pRD->pCurrentContextPointers->X25 = &(pDE->m_context.X25);
+    pRD->pCurrentContextPointers->X26 = &(pDE->m_context.X26);
+    pRD->pCurrentContextPointers->X27 = &(pDE->m_context.X27);
+    pRD->pCurrentContextPointers->X28 = &(pDE->m_context.X28);
+    pRD->pCurrentContextPointers->Lr = &(pDE->m_context.Lr);
+    pRD->pCurrentContextPointers->Fp = &(pDE->m_context.Fp);
+
+    pRD->volatileCurrContextPointers.X0 = &(pDE->m_context.X0);
+    pRD->volatileCurrContextPointers.X1 = &(pDE->m_context.X1);
+    pRD->volatileCurrContextPointers.X2 = &(pDE->m_context.X2);
+    pRD->volatileCurrContextPointers.X3 = &(pDE->m_context.X3);
+    pRD->volatileCurrContextPointers.X4 = &(pDE->m_context.X4);
+    pRD->volatileCurrContextPointers.X5 = &(pDE->m_context.X5);
+    pRD->volatileCurrContextPointers.X6 = &(pDE->m_context.X6);
+    pRD->volatileCurrContextPointers.X7 = &(pDE->m_context.X7);
+    pRD->volatileCurrContextPointers.X8 = &(pDE->m_context.X8);
+    pRD->volatileCurrContextPointers.X9 = &(pDE->m_context.X9);
+    pRD->volatileCurrContextPointers.X10 = &(pDE->m_context.X10);
+    pRD->volatileCurrContextPointers.X11 = &(pDE->m_context.X11);
+    pRD->volatileCurrContextPointers.X12 = &(pDE->m_context.X12);
+    pRD->volatileCurrContextPointers.X13 = &(pDE->m_context.X13);
+    pRD->volatileCurrContextPointers.X14 = &(pDE->m_context.X14);
+    pRD->volatileCurrContextPointers.X15 = &(pDE->m_context.X15);
+    pRD->volatileCurrContextPointers.X16 = &(pDE->m_context.X16);
+    pRD->volatileCurrContextPointers.X17 = &(pDE->m_context.X17);
+
+    SyncRegDisplayToCurrentContext(pRD); 
+#else
     PORTABILITY_ASSERT("FuncEvalFrame::UpdateRegDisplay is not implemented on this platform.");
 #endif
 }
index 7c53635..72634c4 100644 (file)
@@ -71,8 +71,12 @@ inline void CORDbgAdjustPCForBreakInstruction(DT_CONTEXT* pContext)
 {
     LIMITED_METHOD_CONTRACT;
 
+#if defined(DBG_TARGET_ARM64)
+    pContext->Pc -= CORDbg_BREAK_INSTRUCTION_SIZE;
+#else
     // @ARMTODO: ARM appears to leave the PC at the start of the breakpoint (at least according to Windbg,
     // which may be adjusting the view).
+#endif
     return;
 }
 
index 0fbd577..b8f68f9 100644 (file)
@@ -8937,12 +8937,6 @@ void Compiler::fgAddInternal()
         dbgHandle = info.compCompHnd->getJustMyCodeHandle(info.compMethodHnd, &pDbgHandle);
     }
 
-#ifdef _TARGET_ARM64_
-    // TODO-ARM64-NYI: don't do just-my-code
-    dbgHandle  = nullptr;
-    pDbgHandle = nullptr;
-#endif // _TARGET_ARM64_
-
     noway_assert(!dbgHandle || !pDbgHandle);
 
     if (dbgHandle || pDbgHandle)
index 68c9125..3f22518 100644 (file)
@@ -412,7 +412,6 @@ VirtualCallStubManager::StubKind VirtualCallStubManager::predictStubKind(PCODE s
     SUPPORTS_DAC;
 #ifdef DACCESS_COMPILE
 
-    _ASSERTE(!"ARM64:NYI");
     return SK_BREAKPOINT;  // Dac always uses the slower lookup
 
 #else