Use out-of-proc libunwind to unwind native stack from DAC
authorEugene <Eugene.Zemtsov@microsoft.com>
Fri, 21 Aug 2015 04:11:31 +0000 (21:11 -0700)
committerEugene Zemtsov <Eugene.Zemtsov@microsoft.com>
Tue, 15 Sep 2015 20:44:42 +0000 (13:44 -0700)
Implementation of PAL_VirtualUnwindOutOfProc that uses ptrace libunwind
to be able to unwind native stack in debugee. This allows to get valid managed
stack for threads that passed HelperMethodFrames.

13 files changed:
src/debug/daccess/dacfn.cpp
src/debug/di/shimdatatarget.cpp
src/debug/di/shimdatatarget.h
src/debug/di/shimprocess.cpp
src/inc/cordebug.idl
src/inc/daccess.h
src/pal/inc/pal.h
src/pal/inc/rt/palrt.h
src/pal/prebuilt/idl/cordebug_i.c
src/pal/prebuilt/inc/cordebug.h
src/pal/src/CMakeLists.txt
src/pal/src/exception/seh-unwind.cpp
src/vm/amd64/gmsamd64.cpp

index 1ad5b20..5bec3b4 100644 (file)
@@ -218,6 +218,25 @@ DacWriteAll(TADDR addr, PVOID buffer, ULONG32 size, bool throwEx)
     return S_OK;
 }
 
+HRESULT 
+DacGetPid(DWORD *pid)
+{
+    if (!g_dacImpl)
+    {
+        DacError(E_UNEXPECTED);
+        UNREACHABLE();
+    }
+
+    ReleaseHolder<ICorDebugDataTarget4> dt;
+    HRESULT hr = g_dacImpl->m_pTarget->QueryInterface(IID_ICorDebugDataTarget4, (void **)&dt);
+    if (SUCCEEDED(hr))
+    {
+        hr = dt->GetPid(pid);
+    }
+
+    return hr;
+}
+
 // DacAllocVirtual - Allocate memory from the target process
 // Note: this is only available to clients supporting the legacy
 // ICLRDataTarget2 interface.  It's currently used by SOS for notification tables.
index 59f56e7..d7bfbdc 100644 (file)
@@ -36,6 +36,10 @@ HRESULT STDMETHODCALLTYPE ShimDataTarget::QueryInterface(
     {
         *pInterface = static_cast<ICorDebugMutableDataTarget *>(this);
     }
+    else if (InterfaceId == IID_ICorDebugDataTarget4)
+    {
+        *pInterface = static_cast<ICorDebugDataTarget4 *>(this);
+    }
     else
     {
         *pInterface = NULL;
@@ -71,9 +75,15 @@ ULONG STDMETHODCALLTYPE ShimDataTarget::Release()
 //
 // Return Value: 
 //     The OS PID of the process this data target is representing.
-DWORD ShimDataTarget::GetPid()
+HRESULT STDMETHODCALLTYPE ShimDataTarget::GetPid(DWORD *pdwProcessId)
 {
-    return m_processId;
+    if (pdwProcessId == NULL)  
+    {
+        return E_INVALIDARG;
+    }
+
+    *pdwProcessId = m_processId;
+    return S_OK;
 }
 
 //---------------------------------------------------------------------------------------
index 1fabad4..9e3502b 100644 (file)
@@ -21,7 +21,7 @@ typedef HRESULT (*FPContinueStatusChanged)(void * pUserData, DWORD dwThreadId, C
 //---------------------------------------------------------------------------------------
 // Data target for a live process. This is used by Shim. 
 // 
-class ShimDataTarget : public ICorDebugMutableDataTarget
+class ShimDataTarget : public ICorDebugMutableDataTarget, ICorDebugDataTarget4
 {
 public:
     virtual ~ShimDataTarget() {}
@@ -36,9 +36,6 @@ public:
     // is unavailable because it's running
     void SetError(HRESULT hr);
 
-    // Get the OS Process ID that this DataTarget is for.
-    DWORD GetPid();
-
     //
     // IUnknown.
     //
@@ -85,6 +82,13 @@ public:
 
     // @dbgtodo - add Native Patch Table support
 
+    //
+    // ICorDebugDataTarget4
+    //    
+
+    // Get the OS Process ID that this DataTarget is for.
+    virtual HRESULT STDMETHODCALLTYPE GetPid(DWORD *pdwProcessId); 
+
 protected:
     // Pid of the target process.
     DWORD m_processId;
index 6e0350b..e4b511a 100644 (file)
@@ -133,7 +133,9 @@ void ShimProcess::SetProcess(ICorDebugProcess * pProcess)
     if (pProcess != NULL)
     {
         // Verify that DataTarget + new process have the same pid?
-        _ASSERTE(m_pProcess->GetPid() == m_pLiveDataTarget->GetPid());
+        DWORD pid = 0;
+        _ASSERTE(SUCCEEDED(m_pLiveDataTarget->GetPid(&pid)));
+        _ASSERTE(m_pProcess->GetPid() == pid);
     }
 }
 
@@ -738,7 +740,11 @@ HRESULT ShimProcess::HandleWin32DebugEvent(const DEBUG_EVENT * pEvent)
             // This assert could be our only warning of various catastrophic failures in the left-side.
             if (!dwFirstChance && (pRecord->ExceptionCode == STATUS_BREAKPOINT) && !m_fIsInteropDebugging)
             {            
-                DWORD pid = (m_pLiveDataTarget == NULL) ? 0 : m_pLiveDataTarget->GetPid();
+                DWORD pid = 0;
+                if (m_pLiveDataTarget != NULL) 
+                {
+                    m_pLiveDataTarget->GetPid(&pid);
+                }
                 CONSISTENCY_CHECK_MSGF(false, 
                     ("Unhandled breakpoint exception in debuggee (pid=%d (0x%x)) on thread %d(0x%x)\n"
                     "This may mean there was an assert in the debuggee on that thread.\n"
@@ -1742,7 +1748,11 @@ void ShimProcess::PreDispatchEvent(bool fRealCreateProcessEvent /*= false*/)
 CORDB_ADDRESS ShimProcess::GetCLRInstanceBaseAddress()
 {
     CORDB_ADDRESS baseAddress = CORDB_ADDRESS(NULL);
-    DWORD dwPid = m_pLiveDataTarget->GetPid();
+    DWORD dwPid = 0;
+    if (FAILED(m_pLiveDataTarget->GetPid(&dwPid)))
+    {
+        return baseAddress;
+    }
 #if defined(FEATURE_CORESYSTEM)
     // Debugger attaching to CoreCLR via CoreCLRCreateCordbObject should have already specified CLR module address.
     // Code that help to find it now lives in dbgshim.
index 3ba81c3..f5f975b 100644 (file)
@@ -811,6 +811,24 @@ interface ICorDebugDataTarget3 : IUnknown
 };
 
 /*
+ * Data target that knows how to obtain debugee's process id. 
+ * Debugee is not necessarily a living process at that time or on the same machine.
+ */
+[
+    object,
+    uuid(E799DC06-E099-4713-BDD9-906D3CC02CF2),
+    local,
+    pointer_default(unique)
+]
+interface ICorDebugDataTarget4 : IUnknown
+{
+    /*
+    * gives back a process id
+    */
+    HRESULT GetPid([out] DWORD *pdwProcessId);
+};
+
+/*
  * Mutable extension to the data target.  This version of ICorDebugDataTarget 
  * can be implemented by targets that wish to support modification of the target 
  * process (such as for live invasive debugging).
@@ -879,6 +897,7 @@ interface ICorDebugMutableDataTarget : ICorDebugDataTarget
 
 };
 
+
 /*
  * Interface used by the data access services layer to locate metadata 
  * of assemblies in a target. 
index 704a1ea..241c25e 100644 (file)
@@ -663,6 +663,7 @@ HRESULT DacFreeVirtual(TADDR mem, ULONG32 size, ULONG32 typeFlags,
 PVOID   DacInstantiateTypeByAddress(TADDR addr, ULONG32 size, bool throwEx);
 PVOID   DacInstantiateTypeByAddressNoReport(TADDR addr, ULONG32 size, bool throwEx);
 PVOID   DacInstantiateClassByVTable(TADDR addr, ULONG32 minSize, bool throwEx);
+HRESULT DacGetPid(DWORD *pid);
 
 // Copy a null-terminated ascii or unicode string from the target to the host.
 // Note that most of the work here is to find the null terminator.  If you know the exact length,
index 43fc069..4ed5e92 100644 (file)
@@ -3442,6 +3442,15 @@ size_t
 PALAPI
 PAL_GetLogicalProcessorCacheSizeFromOS();
 
+typedef BOOL (*ReadMemoryWordCallback)(SIZE_T address, SIZE_T *value);
+
+PALIMPORT BOOL PALAPI PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers);
+
+PALIMPORT BOOL PALAPI PAL_VirtualUnwindOutOfProc(CONTEXT *context, 
+                                                 KNONVOLATILE_CONTEXT_POINTERS *contextPointers, 
+                                                 DWORD pid, 
+                                                 ReadMemoryWordCallback readMemCallback);
+
 #define GetLogicalProcessorCacheSizeFromOS PAL_GetLogicalProcessorCacheSizeFromOS
 
 #ifdef PLATFORM_UNIX
index 7f3cdbd..2d67e10 100644 (file)
@@ -1710,8 +1710,6 @@ typedef LONG (WINAPI *PTOP_LEVEL_EXCEPTION_FILTER)(
     );
 typedef PTOP_LEVEL_EXCEPTION_FILTER LPTOP_LEVEL_EXCEPTION_FILTER;
 
-BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers);
-
 /******************* ntdef ************************************/
 
 #ifndef ANYSIZE_ARRAY
index 2b8b1f5..8a947cc 100644 (file)
@@ -98,6 +98,9 @@ MIDL_DEFINE_GUID(IID, IID_ICorDebugLoadedModule,0x817F343A,0x6630,0x4578,0x96,0x
 MIDL_DEFINE_GUID(IID, IID_ICorDebugDataTarget3,0xD05E60C3,0x848C,0x4E7D,0x89,0x4E,0x62,0x33,0x20,0xFF,0x6A,0xFA);
 
 
+MIDL_DEFINE_GUID(IID, IID_ICorDebugDataTarget4,0xE799DC06,0xE099,0x4713,0xBD,0xD9,0x90,0x6D,0x3C,0xC0,0x2C,0xF2);
+
+
 MIDL_DEFINE_GUID(IID, IID_ICorDebugMutableDataTarget,0xA1B8A756,0x3CB6,0x4CCB,0x97,0x9F,0x3D,0xF9,0x99,0x67,0x3A,0x59);
 
 
index db8bf6d..153d390 100644 (file)
@@ -122,6 +122,13 @@ typedef interface ICorDebugDataTarget3 ICorDebugDataTarget3;
 #endif         /* __ICorDebugDataTarget3_FWD_DEFINED__ */
 
 
+#ifndef __ICorDebugDataTarget4_FWD_DEFINED__
+#define __ICorDebugDataTarget4_FWD_DEFINED__
+typedef interface ICorDebugDataTarget4 ICorDebugDataTarget4;
+
+#endif         /* __ICorDebugDataTarget4_FWD_DEFINED__ */
+
+
 #ifndef __ICorDebugMutableDataTarget_FWD_DEFINED__
 #define __ICorDebugMutableDataTarget_FWD_DEFINED__
 typedef interface ICorDebugMutableDataTarget ICorDebugMutableDataTarget;
@@ -2831,6 +2838,86 @@ EXTERN_C const IID IID_ICorDebugDataTarget3;
 #endif         /* __ICorDebugDataTarget3_INTERFACE_DEFINED__ */
 
 
+#ifndef __ICorDebugDataTarget4_INTERFACE_DEFINED__
+#define __ICorDebugDataTarget4_INTERFACE_DEFINED__
+
+/* interface ICorDebugDataTarget4 */
+/* [unique][local][uuid][object] */ 
+
+
+EXTERN_C const IID IID_ICorDebugDataTarget4;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+    
+    MIDL_INTERFACE("E799DC06-E099-4713-BDD9-906D3CC02CF2")
+    ICorDebugDataTarget4 : public IUnknown
+    {
+    public:
+        virtual HRESULT STDMETHODCALLTYPE GetPid( 
+            /* [out] */ DWORD *pdwProcessId) = 0;
+        
+    };
+    
+    
+#else  /* C style interface */
+
+    typedef struct ICorDebugDataTarget4Vtbl
+    {
+        BEGIN_INTERFACE
+        
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( 
+            ICorDebugDataTarget4 * This,
+            /* [in] */ REFIID riid,
+            /* [annotation][iid_is][out] */ 
+            _COM_Outptr_  void **ppvObject);
+        
+        ULONG ( STDMETHODCALLTYPE *AddRef )( 
+            ICorDebugDataTarget4 * This);
+        
+        ULONG ( STDMETHODCALLTYPE *Release )( 
+            ICorDebugDataTarget4 * This);
+        
+        HRESULT ( STDMETHODCALLTYPE *GetPid )( 
+            ICorDebugDataTarget4 * This,
+            /* [out] */ DWORD *pdwProcessId);
+        
+        END_INTERFACE
+    } ICorDebugDataTarget4Vtbl;
+
+    interface ICorDebugDataTarget4
+    {
+        CONST_VTBL struct ICorDebugDataTarget4Vtbl *lpVtbl;
+    };
+
+    
+
+#ifdef COBJMACROS
+
+
+#define ICorDebugDataTarget4_QueryInterface(This,riid,ppvObject)       \
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) 
+
+#define ICorDebugDataTarget4_AddRef(This)      \
+    ( (This)->lpVtbl -> AddRef(This) ) 
+
+#define ICorDebugDataTarget4_Release(This)     \
+    ( (This)->lpVtbl -> Release(This) ) 
+
+
+#define ICorDebugDataTarget4_GetPid(This,pdwProcessId) \
+    ( (This)->lpVtbl -> GetPid(This,pdwProcessId) ) 
+
+#endif /* COBJMACROS */
+
+
+#endif         /* C style interface */
+
+
+
+
+#endif         /* __ICorDebugDataTarget4_INTERFACE_DEFINED__ */
+
+
 #ifndef __ICorDebugMutableDataTarget_INTERFACE_DEFINED__
 #define __ICorDebugMutableDataTarget_INTERFACE_DEFINED__
 
@@ -3063,15 +3150,15 @@ EXTERN_C const IID IID_ICorDebugMetaDataLocator;
 #endif         /* __ICorDebugMetaDataLocator_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0014 */
+/* interface __MIDL_itf_cordebug_0000_0015 */
 /* [local] */ 
 
 #pragma warning(push)
 #pragma warning(disable:28718) 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0014_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0014_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0015_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0015_v0_0_s_ifspec;
 
 #ifndef __ICorDebugManagedCallback_INTERFACE_DEFINED__
 #define __ICorDebugManagedCallback_INTERFACE_DEFINED__
@@ -3525,15 +3612,15 @@ EXTERN_C const IID IID_ICorDebugManagedCallback;
 #endif         /* __ICorDebugManagedCallback_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0015 */
+/* interface __MIDL_itf_cordebug_0000_0016 */
 /* [local] */ 
 
 #pragma warning(pop)
 #pragma warning(push)
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0015_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0015_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0016_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0016_v0_0_s_ifspec;
 
 #ifndef __ICorDebugManagedCallback3_INTERFACE_DEFINED__
 #define __ICorDebugManagedCallback3_INTERFACE_DEFINED__
@@ -3617,14 +3704,14 @@ EXTERN_C const IID IID_ICorDebugManagedCallback3;
 #endif         /* __ICorDebugManagedCallback3_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0016 */
+/* interface __MIDL_itf_cordebug_0000_0017 */
 /* [local] */ 
 
 #pragma warning(disable:28718) 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0016_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0016_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0017_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0017_v0_0_s_ifspec;
 
 #ifndef __ICorDebugManagedCallback2_INTERFACE_DEFINED__
 #define __ICorDebugManagedCallback2_INTERFACE_DEFINED__
@@ -3839,14 +3926,14 @@ EXTERN_C const IID IID_ICorDebugManagedCallback2;
 #endif         /* __ICorDebugManagedCallback2_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0017 */
+/* interface __MIDL_itf_cordebug_0000_0018 */
 /* [local] */ 
 
 #pragma warning(pop)
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0017_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0017_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0018_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0018_v0_0_s_ifspec;
 
 #ifndef __ICorDebugUnmanagedCallback_INTERFACE_DEFINED__
 #define __ICorDebugUnmanagedCallback_INTERFACE_DEFINED__
@@ -3930,7 +4017,7 @@ EXTERN_C const IID IID_ICorDebugUnmanagedCallback;
 #endif         /* __ICorDebugUnmanagedCallback_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0018 */
+/* interface __MIDL_itf_cordebug_0000_0019 */
 /* [local] */ 
 
 typedef 
@@ -3950,8 +4037,8 @@ enum CorDebugHandleType
 #pragma warning(disable:28718) 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0018_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0018_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0019_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0019_v0_0_s_ifspec;
 
 #ifndef __ICorDebug_INTERFACE_DEFINED__
 #define __ICorDebug_INTERFACE_DEFINED__
@@ -4139,14 +4226,14 @@ EXTERN_C const IID IID_ICorDebug;
 #endif         /* __ICorDebug_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0019 */
+/* interface __MIDL_itf_cordebug_0000_0020 */
 /* [local] */ 
 
 #pragma warning(pop)
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0019_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0019_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0020_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0020_v0_0_s_ifspec;
 
 #ifndef __ICorDebugRemoteTarget_INTERFACE_DEFINED__
 #define __ICorDebugRemoteTarget_INTERFACE_DEFINED__
@@ -4358,7 +4445,7 @@ EXTERN_C const IID IID_ICorDebugRemote;
 #endif         /* __ICorDebugRemote_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0021 */
+/* interface __MIDL_itf_cordebug_0000_0022 */
 /* [local] */ 
 
 typedef struct _COR_VERSION
@@ -4371,8 +4458,8 @@ typedef struct _COR_VERSION
 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0021_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0021_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0022_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0022_v0_0_s_ifspec;
 
 #ifndef __ICorDebug2_INTERFACE_DEFINED__
 #define __ICorDebug2_INTERFACE_DEFINED__
@@ -4534,7 +4621,7 @@ EXTERN_C const IID IID_ICorDebug2;
 #endif         /* __ICorDebug2_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0022 */
+/* interface __MIDL_itf_cordebug_0000_0023 */
 /* [local] */ 
 
 typedef 
@@ -4546,8 +4633,8 @@ enum CorDebugThreadState
 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0022_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0022_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0023_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0023_v0_0_s_ifspec;
 
 #ifndef __ICorDebugController_INTERFACE_DEFINED__
 #define __ICorDebugController_INTERFACE_DEFINED__
@@ -4729,15 +4816,15 @@ EXTERN_C const IID IID_ICorDebugController;
 #endif         /* __ICorDebugController_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0023 */
+/* interface __MIDL_itf_cordebug_0000_0024 */
 /* [local] */ 
 
 #pragma warning(push)
 #pragma warning(disable:28718) 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0023_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0023_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0024_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0024_v0_0_s_ifspec;
 
 #ifndef __ICorDebugAppDomain_INTERFACE_DEFINED__
 #define __ICorDebugAppDomain_INTERFACE_DEFINED__
@@ -4989,14 +5076,14 @@ EXTERN_C const IID IID_ICorDebugAppDomain;
 #endif         /* __ICorDebugAppDomain_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0024 */
+/* interface __MIDL_itf_cordebug_0000_0025 */
 /* [local] */ 
 
 #pragma warning(pop)
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0024_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0024_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0025_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0025_v0_0_s_ifspec;
 
 #ifndef __ICorDebugAppDomain2_INTERFACE_DEFINED__
 #define __ICorDebugAppDomain2_INTERFACE_DEFINED__
@@ -5494,15 +5581,15 @@ EXTERN_C const IID IID_ICorDebugAppDomain4;
 #endif         /* __ICorDebugAppDomain4_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0028 */
+/* interface __MIDL_itf_cordebug_0000_0029 */
 /* [local] */ 
 
 #pragma warning(push)
 #pragma warning(disable:28718) 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0028_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0028_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0029_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0029_v0_0_s_ifspec;
 
 #ifndef __ICorDebugAssembly_INTERFACE_DEFINED__
 #define __ICorDebugAssembly_INTERFACE_DEFINED__
@@ -5632,14 +5719,14 @@ EXTERN_C const IID IID_ICorDebugAssembly;
 #endif         /* __ICorDebugAssembly_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0029 */
+/* interface __MIDL_itf_cordebug_0000_0030 */
 /* [local] */ 
 
 #pragma warning(pop)
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0029_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0029_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0030_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0030_v0_0_s_ifspec;
 
 #ifndef __ICorDebugAssembly2_INTERFACE_DEFINED__
 #define __ICorDebugAssembly2_INTERFACE_DEFINED__
@@ -5811,7 +5898,7 @@ EXTERN_C const IID IID_ICorDebugAssembly3;
 #endif         /* __ICorDebugAssembly3_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0031 */
+/* interface __MIDL_itf_cordebug_0000_0032 */
 /* [local] */ 
 
 #ifndef _DEF_COR_TYPEID_
@@ -5832,8 +5919,8 @@ typedef struct _COR_HEAPOBJECT
 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0031_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0031_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0032_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0032_v0_0_s_ifspec;
 
 #ifndef __ICorDebugHeapEnum_INTERFACE_DEFINED__
 #define __ICorDebugHeapEnum_INTERFACE_DEFINED__
@@ -5947,7 +6034,7 @@ EXTERN_C const IID IID_ICorDebugHeapEnum;
 #endif         /* __ICorDebugHeapEnum_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0032 */
+/* interface __MIDL_itf_cordebug_0000_0033 */
 /* [local] */ 
 
 typedef 
@@ -5985,8 +6072,8 @@ typedef struct _COR_HEAPINFO
 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0032_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0032_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0033_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0033_v0_0_s_ifspec;
 
 #ifndef __ICorDebugHeapSegmentEnum_INTERFACE_DEFINED__
 #define __ICorDebugHeapSegmentEnum_INTERFACE_DEFINED__
@@ -6100,7 +6187,7 @@ EXTERN_C const IID IID_ICorDebugHeapSegmentEnum;
 #endif         /* __ICorDebugHeapSegmentEnum_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0033 */
+/* interface __MIDL_itf_cordebug_0000_0034 */
 /* [local] */ 
 
 typedef 
@@ -6136,8 +6223,8 @@ typedef struct COR_GC_REFERENCE
 #endif // _DEF_COR_GC_REFERENCE_
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0033_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0033_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0034_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0034_v0_0_s_ifspec;
 
 #ifndef __ICorDebugGCReferenceEnum_INTERFACE_DEFINED__
 #define __ICorDebugGCReferenceEnum_INTERFACE_DEFINED__
@@ -6251,7 +6338,7 @@ EXTERN_C const IID IID_ICorDebugGCReferenceEnum;
 #endif         /* __ICorDebugGCReferenceEnum_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0034 */
+/* interface __MIDL_itf_cordebug_0000_0035 */
 /* [local] */ 
 
 #ifndef _DEF_COR_ARRAY_LAYOUT_
@@ -6296,8 +6383,8 @@ typedef struct COR_FIELD
 #pragma warning(disable:28718) 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0034_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0034_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0035_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0035_v0_0_s_ifspec;
 
 #ifndef __ICorDebugProcess_INTERFACE_DEFINED__
 #define __ICorDebugProcess_INTERFACE_DEFINED__
@@ -6647,14 +6734,14 @@ EXTERN_C const IID IID_ICorDebugProcess;
 #endif         /* __ICorDebugProcess_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0035 */
+/* interface __MIDL_itf_cordebug_0000_0036 */
 /* [local] */ 
 
 #pragma warning(pop)
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0035_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0035_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0036_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0036_v0_0_s_ifspec;
 
 #ifndef __ICorDebugProcess2_INTERFACE_DEFINED__
 #define __ICorDebugProcess2_INTERFACE_DEFINED__
@@ -7098,7 +7185,7 @@ EXTERN_C const IID IID_ICorDebugProcess5;
 #endif         /* __ICorDebugProcess5_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0038 */
+/* interface __MIDL_itf_cordebug_0000_0039 */
 /* [local] */ 
 
 typedef 
@@ -7134,8 +7221,8 @@ enum CorDebugStateChange
 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0038_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0038_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0039_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0039_v0_0_s_ifspec;
 
 #ifndef __ICorDebugDebugEvent_INTERFACE_DEFINED__
 #define __ICorDebugDebugEvent_INTERFACE_DEFINED__
@@ -7227,7 +7314,7 @@ EXTERN_C const IID IID_ICorDebugDebugEvent;
 #endif         /* __ICorDebugDebugEvent_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0039 */
+/* interface __MIDL_itf_cordebug_0000_0040 */
 /* [local] */ 
 
 typedef 
@@ -7249,8 +7336,8 @@ enum CorDebugCodeInvokePurpose
 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0039_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0039_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0040_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0040_v0_0_s_ifspec;
 
 #ifndef __ICorDebugProcess6_INTERFACE_DEFINED__
 #define __ICorDebugProcess6_INTERFACE_DEFINED__
@@ -7398,7 +7485,7 @@ EXTERN_C const IID IID_ICorDebugProcess6;
 #endif         /* __ICorDebugProcess6_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0040 */
+/* interface __MIDL_itf_cordebug_0000_0041 */
 /* [local] */ 
 
 typedef 
@@ -7410,8 +7497,8 @@ enum WriteableMetadataUpdateMode
 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0040_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0040_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0041_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0041_v0_0_s_ifspec;
 
 #ifndef __ICorDebugProcess7_INTERFACE_DEFINED__
 #define __ICorDebugProcess7_INTERFACE_DEFINED__
@@ -10493,7 +10580,7 @@ EXTERN_C const IID IID_ICorDebugILFrame3;
 #endif         /* __ICorDebugILFrame3_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0064 */
+/* interface __MIDL_itf_cordebug_0000_0065 */
 /* [local] */ 
 
 typedef 
@@ -10505,8 +10592,8 @@ enum ILCodeKind
 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0064_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0064_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0065_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0065_v0_0_s_ifspec;
 
 #ifndef __ICorDebugILFrame4_INTERFACE_DEFINED__
 #define __ICorDebugILFrame4_INTERFACE_DEFINED__
@@ -10870,15 +10957,15 @@ EXTERN_C const IID IID_ICorDebugNativeFrame;
 #endif         /* __ICorDebugNativeFrame_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0066 */
+/* interface __MIDL_itf_cordebug_0000_0067 */
 /* [local] */ 
 
 #pragma warning(push)
 #pragma warning(disable:28718) 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0066_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0066_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0067_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0067_v0_0_s_ifspec;
 
 #ifndef __ICorDebugNativeFrame2_INTERFACE_DEFINED__
 #define __ICorDebugNativeFrame2_INTERFACE_DEFINED__
@@ -11448,14 +11535,14 @@ EXTERN_C const IID IID_ICorDebugModule;
 #endif         /* __ICorDebugModule_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0070 */
+/* interface __MIDL_itf_cordebug_0000_0071 */
 /* [local] */ 
 
 #pragma warning(pop)
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0070_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0070_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0071_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0071_v0_0_s_ifspec;
 
 #ifndef __ICorDebugModule2_INTERFACE_DEFINED__
 #define __ICorDebugModule2_INTERFACE_DEFINED__
@@ -14252,15 +14339,15 @@ EXTERN_C const IID IID_ICorDebugBoxValue;
 #endif         /* __ICorDebugBoxValue_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0094 */
+/* interface __MIDL_itf_cordebug_0000_0095 */
 /* [local] */ 
 
 #pragma warning(push)
 #pragma warning(disable:28718) 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0094_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0094_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0095_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0095_v0_0_s_ifspec;
 
 #ifndef __ICorDebugStringValue_INTERFACE_DEFINED__
 #define __ICorDebugStringValue_INTERFACE_DEFINED__
@@ -14400,14 +14487,14 @@ EXTERN_C const IID IID_ICorDebugStringValue;
 #endif         /* __ICorDebugStringValue_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0095 */
+/* interface __MIDL_itf_cordebug_0000_0096 */
 /* [local] */ 
 
 #pragma warning(pop)
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0095_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0095_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0096_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0096_v0_0_s_ifspec;
 
 #ifndef __ICorDebugArrayValue_INTERFACE_DEFINED__
 #define __ICorDebugArrayValue_INTERFACE_DEFINED__
@@ -16840,15 +16927,15 @@ EXTERN_C const IID IID_ICorDebugBlockingObjectEnum;
 #endif         /* __ICorDebugBlockingObjectEnum_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0116 */
+/* interface __MIDL_itf_cordebug_0000_0117 */
 /* [local] */ 
 
 #pragma warning(push)
 #pragma warning(disable:28718)
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0116_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0116_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0117_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0117_v0_0_s_ifspec;
 
 #ifndef __ICorDebugMDA_INTERFACE_DEFINED__
 #define __ICorDebugMDA_INTERFACE_DEFINED__
@@ -16988,7 +17075,7 @@ EXTERN_C const IID IID_ICorDebugMDA;
 #endif         /* __ICorDebugMDA_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0117 */
+/* interface __MIDL_itf_cordebug_0000_0118 */
 /* [local] */ 
 
 #pragma warning(pop)
@@ -16996,8 +17083,8 @@ EXTERN_C const IID IID_ICorDebugMDA;
 #pragma warning(disable:28718) 
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0117_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0117_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0118_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0118_v0_0_s_ifspec;
 
 #ifndef __ICorDebugEditAndContinueErrorInfo_INTERFACE_DEFINED__
 #define __ICorDebugEditAndContinueErrorInfo_INTERFACE_DEFINED__
@@ -17113,14 +17200,14 @@ EXTERN_C const IID IID_ICorDebugEditAndContinueErrorInfo;
 #endif         /* __ICorDebugEditAndContinueErrorInfo_INTERFACE_DEFINED__ */
 
 
-/* interface __MIDL_itf_cordebug_0000_0118 */
+/* interface __MIDL_itf_cordebug_0000_0119 */
 /* [local] */ 
 
 #pragma warning(pop)
 
 
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0118_v0_0_c_ifspec;
-extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0118_v0_0_s_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0119_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0119_v0_0_s_ifspec;
 
 #ifndef __ICorDebugEditAndContinueSnapshot_INTERFACE_DEFINED__
 #define __ICorDebugEditAndContinueSnapshot_INTERFACE_DEFINED__
index ce364b3..c814e10 100644 (file)
@@ -207,6 +207,13 @@ if(CMAKE_SYSTEM_NAME STREQUAL Linux)
   if(PAL_CMAKE_PLATFORM_ARCH_ARM)
     target_link_libraries(coreclrpal
       gcc_s
+      unwind-arm
+    )
+  endif()
+
+  if(PAL_CMAKE_PLATFORM_ARCH_AMD64)
+    target_link_libraries(coreclrpal
+      unwind-x86_64
     )
   endif()
     
@@ -215,6 +222,8 @@ if(CMAKE_SYSTEM_NAME STREQUAL Linux)
     rt
     dl
     unwind
+    unwind-ptrace
+    unwind-generic
   )
 endif(CMAKE_SYSTEM_NAME STREQUAL Linux)
 
index 465c459..cf899f7 100644 (file)
@@ -26,12 +26,20 @@ Abstract:
 #endif // !FEATURE_PAL_SXS
 
 #include "pal/context.h"
+#include "pal.h"
 #include <dlfcn.h>
 #include <exception>
+    
 #if HAVE_LIBUNWIND_H
+#ifndef __LINUX__
 #define UNW_LOCAL_ONLY
+#endif // !__LINUX__       
 #include <libunwind.h>
-#endif
+#ifdef __LINUX__
+#include <libunwind-ptrace.h>
+#endif // __LINUX__    
+#endif // HAVE_LIBUNWIND_H
+
 
 //----------------------------------------------------------------------
 // Virtual Unwinding
@@ -226,6 +234,7 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP
     int st;
     unw_context_t unwContext;
     unw_cursor_t cursor;
+
 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(_ARM64_)
     DWORD64 curPc;
 #endif
@@ -251,7 +260,6 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP
         return FALSE;
     }
 #endif
-
     st = unw_init_local(&cursor, &unwContext);
     if (st < 0)
     {
@@ -308,13 +316,230 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP
     {
         GetContextPointers(&cursor, &unwContext, contextPointers);
     }
-
     return TRUE;
 }
+
 #else
 #error don't know how to unwind on this platform
 #endif
 
+
+#ifdef __LINUX__
+
+
+static struct LibunwindCallbacksInfoType
+{
+     CONTEXT *Context;
+     ReadMemoryWordCallback readMemCallback;
+} LibunwindCallbacksInfo;
+
+static int get_dyn_info_list_addr(unw_addr_space_t as, unw_word_t *dilap, void *arg)
+{
+    return -UNW_ENOINFO;
+}
+
+static int access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *valp, int write, void *arg)
+{
+    if (write)
+    {
+        ASSERT("Memory write must never be called by libunwind during stackwalk");
+        return -UNW_EINVAL;
+    }
+
+    // access_mem sometimes gets called by _UPT_find_proc_info, in such cases arg has a pointer to libunwind internal data
+    // returned by _UPT_create. It makes it impossible to use arg for passing readMemCallback. That's why we have to use global variable.
+    if (LibunwindCallbacksInfo.readMemCallback((SIZE_T)addr, (SIZE_T *)valp))
+    {
+        return UNW_ESUCCESS;
+    }
+    else 
+    {
+        return -UNW_EUNSPEC;
+    }
+}
+
+static int access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, int write, void *arg)
+{
+    if (write)
+    {
+        ASSERT("Register write must never be called by libunwind during stackwalk");
+        return -UNW_EREADONLYREG;
+    }
+
+    CONTEXT *winContext = LibunwindCallbacksInfo.Context;
+
+    switch (regnum) 
+    {
+#if defined(_AMD64_)
+        case UNW_REG_IP:       *valp = (unw_word_t) winContext->Rip; break;
+        case UNW_REG_SP:       *valp = (unw_word_t) winContext->Rsp; break;
+        case UNW_X86_64_RBP:   *valp = (unw_word_t) winContext->Rbp; break;
+        case UNW_X86_64_RBX:   *valp = (unw_word_t) winContext->Rbx; break;
+        case UNW_X86_64_R12:   *valp = (unw_word_t) winContext->R12; break;
+        case UNW_X86_64_R13:   *valp = (unw_word_t) winContext->R13; break;
+        case UNW_X86_64_R14:   *valp = (unw_word_t) winContext->R14; break;
+        case UNW_X86_64_R15:   *valp = (unw_word_t) winContext->R15; break;
+#elif defined(_ARM_)
+        case UNW_ARM_R13:      *valp = (unw_word_t) winContext->Sp; break;
+        case UNW_ARM_R14:      *valp = (unw_word_t) winContext->Lr; break;
+        case UNW_ARM_R15:      *valp = (unw_word_t) winContext->Pc; break;
+        case UNW_ARM_R4:       *valp = (unw_word_t) winContext->R4; break;
+        case UNW_ARM_R5:       *valp = (unw_word_t) winContext->R5; break;
+        case UNW_ARM_R6:       *valp = (unw_word_t) winContext->R6; break;
+        case UNW_ARM_R7:       *valp = (unw_word_t) winContext->R7; break;
+        case UNW_ARM_R8:       *valp = (unw_word_t) winContext->R8; break;
+        case UNW_ARM_R9:       *valp = (unw_word_t) winContext->R9; break;
+        case UNW_ARM_R10:      *valp = (unw_word_t) winContext->R10; break;
+        case UNW_ARM_R11:      *valp = (unw_word_t) winContext->R11; break;
+#elif defined(_ARM64_)
+        case UNW_REG_IP:       *valp = (unw_word_t) winContext->Pc; break;
+        case UNW_REG_SP:       *valp = (unw_word_t) winContext->Sp; break;
+        case UNW_AARCH64_X29:  *valp = (unw_word_t) winContext->Fp; break;
+        case UNW_AARCH64_X30:  *valp = (unw_word_t) winContext->Lr; break;
+        case UNW_AARCH64_X19:  *valp = (unw_word_t) winContext->X19; break;
+        case UNW_AARCH64_X20:  *valp = (unw_word_t) winContext->X20; break;
+        case UNW_AARCH64_X21:  *valp = (unw_word_t) winContext->X21; break;
+        case UNW_AARCH64_X22:  *valp = (unw_word_t) winContext->X22; break;
+        case UNW_AARCH64_X23:  *valp = (unw_word_t) winContext->X23; break;
+        case UNW_AARCH64_X24:  *valp = (unw_word_t) winContext->X24; break;
+        case UNW_AARCH64_X25:  *valp = (unw_word_t) winContext->X25; break;
+        case UNW_AARCH64_X26:  *valp = (unw_word_t) winContext->X26; break;
+        case UNW_AARCH64_X27:  *valp = (unw_word_t) winContext->X27; break;
+        case UNW_AARCH64_X28:  *valp = (unw_word_t) winContext->X28; break;
+#else
+#error unsupported architecture
+#endif
+        default:
+            ASSERT("Attempt to read an unknown register.");
+            return -UNW_EBADREG;
+    }
+    return UNW_ESUCCESS;
+}
+
+static int access_fpreg(unw_addr_space_t as, unw_regnum_t regnum, unw_fpreg_t *fpvalp, int write, void *arg)
+{
+    ASSERT("Not supposed to be ever called");
+    return -UNW_EINVAL;
+}
+
+static int resume(unw_addr_space_t as, unw_cursor_t *cp, void *arg)
+{
+    ASSERT("Not supposed to be ever called");
+    return -UNW_EINVAL;
+}
+
+static int get_proc_name(unw_addr_space_t as, unw_word_t addr, char *bufp, size_t buf_len, unw_word_t *offp, void *arg)
+{
+    ASSERT("Not supposed to be ever called");
+    return -UNW_EINVAL;  
+}
+
+static unw_accessors_t unwind_accessors =
+{
+    .find_proc_info = _UPT_find_proc_info,
+    .put_unwind_info = _UPT_put_unwind_info,
+    .get_dyn_info_list_addr = get_dyn_info_list_addr,
+    .access_mem = access_mem,
+    .access_reg = access_reg,
+    .access_fpreg = access_fpreg,
+    .resume = resume,
+    .get_proc_name = get_proc_name
+};
+
+BOOL PAL_VirtualUnwindOutOfProc(CONTEXT *context, 
+                                KNONVOLATILE_CONTEXT_POINTERS *contextPointers, 
+                                DWORD pid, 
+                                ReadMemoryWordCallback readMemCallback)
+{
+    // This function can be executed only by one thread at a time. 
+    // The reason for this is that we need to pass context and read mem function to libunwind callbacks
+    // but "arg" is already used by the pointer returned from _UPT_create(). 
+    // So we resort to using global variables and a lock.
+    struct Lock 
+    {
+        CRITICAL_SECTION cs;
+        Lock()
+        {        
+            // ctor of a static variable is a thread-safe way to initialize critical section exactly once (clang,gcc)
+            InitializeCriticalSection(&cs);
+        }
+    };
+    struct LockHolder
+    {
+        CRITICAL_SECTION *cs;
+        LockHolder(CRITICAL_SECTION *cs)
+        {
+            this->cs = cs;
+            EnterCriticalSection(cs);
+        }
+
+        ~LockHolder()
+        {
+            LeaveCriticalSection(cs);
+            cs = NULL;
+        }
+    };    
+    static Lock lock;
+    LockHolder lockHolder(&lock.cs);
+
+    int st;
+    unw_context_t unwContext;
+    unw_cursor_t cursor;
+    unw_addr_space_t addrSpace = 0;
+    void *libunwindUptPtr = NULL;
+    BOOL result = FALSE;
+
+    LibunwindCallbacksInfo.Context = context;
+    LibunwindCallbacksInfo.readMemCallback = readMemCallback;
+    WinContextToUnwindContext(context, &unwContext);
+    addrSpace = unw_create_addr_space(&unwind_accessors, 0);
+    libunwindUptPtr = _UPT_create(pid);
+    st = unw_init_remote(&cursor, addrSpace, libunwindUptPtr);
+    if (st < 0)
+    {
+        result = FALSE;
+        goto Exit;
+    }
+
+    st = unw_step(&cursor);
+    if (st < 0)
+    {
+        result = FALSE;
+        goto Exit;
+    }
+
+    UnwindContextToWinContext(&cursor, context);
+
+    if (contextPointers != NULL)
+    {
+        GetContextPointers(&cursor, &unwContext, contextPointers);
+    }
+    result = TRUE;
+
+Exit:
+    if (libunwindUptPtr != nullptr) 
+    {
+        _UPT_destroy(libunwindUptPtr);
+    }
+    if (addrSpace != 0) 
+    {
+        unw_destroy_addr_space(addrSpace);
+    }    
+    return result;
+}
+#else // __LINUX__
+
+BOOL PAL_VirtualUnwindOutOfProc(CONTEXT *context, 
+                                KNONVOLATILE_CONTEXT_POINTERS *contextPointers, 
+                                DWORD pid, 
+                                ReadMemoryWordCallback readMemCallback)
+{
+    //UNIXTODO: Implement for Mac flavor of libunwind
+    return FALSE;
+}
+
+#endif // !__LINUX__
+
 /*++
 Function:
     RtlpRaiseException
index 197e8fd..49f45c9 100644 (file)
 #include "common.h"
 #include "gmscpu.h"
 
-
+#if defined(DACCESS_COMPILE)
+static BOOL DacReadAllAdapter(SIZE_T address, SIZE_T *value)
+{
+    HRESULT hr = DacReadAll((TADDR)address, (PVOID)value, sizeof(*value), false);
+    return SUCCEEDED(hr);
+}
+#endif //DACCESS_COMPILE
 
 void LazyMachState::unwindLazyState(LazyMachState* baseState,
                                     MachState* unwoundState,
@@ -56,7 +62,25 @@ void LazyMachState::unwindLazyState(LazyMachState* baseState,
 #ifndef FEATURE_PAL
         pvControlPc = Thread::VirtualUnwindCallFrame(&ctx, &nonVolRegPtrs);
 #else // !FEATURE_PAL
+        
+#if defined(DACCESS_COMPILE)
+        DWORD pid;
+        HRESULT hr = DacGetPid(&pid);
+        if (SUCCEEDED(hr))
+        {
+            if (!PAL_VirtualUnwindOutOfProc(&ctx, &nonVolRegPtrs, pid, DacReadAllAdapter))
+            {
+                DacError(E_FAIL);   
+            }
+        } 
+        else 
+        {
+            DacError(hr);
+        }
+#else
         PAL_VirtualUnwind(&ctx, &nonVolRegPtrs);
+#endif  // DACCESS_COMPILE    
+
         pvControlPc = GetIP(&ctx);
 #endif // !FEATURE_PAL