summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene <Eugene.Zemtsov@microsoft.com>2015-08-20 21:11:31 -0700
committerEugene Zemtsov <Eugene.Zemtsov@microsoft.com>2015-09-15 13:44:42 -0700
commitd0f71d0b22e9012263e4a078d24738c75e384a90 (patch)
tree0bb4840e2f42e39592bcbe18d0c0c68a4db0f376
parenteb3260e67bc653b56a80fbf0e8a07d78e3a404c1 (diff)
downloadcoreclr-d0f71d0b22e9012263e4a078d24738c75e384a90.tar.gz
coreclr-d0f71d0b22e9012263e4a078d24738c75e384a90.tar.bz2
coreclr-d0f71d0b22e9012263e4a078d24738c75e384a90.zip
Use out-of-proc libunwind to unwind native stack from DAC
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.
-rw-r--r--src/debug/daccess/dacfn.cpp19
-rw-r--r--src/debug/di/shimdatatarget.cpp14
-rw-r--r--src/debug/di/shimdatatarget.h12
-rw-r--r--src/debug/di/shimprocess.cpp16
-rw-r--r--src/inc/cordebug.idl19
-rw-r--r--src/inc/daccess.h1
-rw-r--r--src/pal/inc/pal.h9
-rw-r--r--src/pal/inc/rt/palrt.h2
-rw-r--r--src/pal/prebuilt/idl/cordebug_i.c3
-rw-r--r--src/pal/prebuilt/inc/cordebug.h255
-rw-r--r--src/pal/src/CMakeLists.txt9
-rw-r--r--src/pal/src/exception/seh-unwind.cpp231
-rw-r--r--src/vm/amd64/gmsamd64.cpp26
13 files changed, 517 insertions, 99 deletions
diff --git a/src/debug/daccess/dacfn.cpp b/src/debug/daccess/dacfn.cpp
index 1ad5b20ab0..5bec3b4ca1 100644
--- a/src/debug/daccess/dacfn.cpp
+++ b/src/debug/daccess/dacfn.cpp
@@ -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.
diff --git a/src/debug/di/shimdatatarget.cpp b/src/debug/di/shimdatatarget.cpp
index 59f56e798e..d7bfbdc11d 100644
--- a/src/debug/di/shimdatatarget.cpp
+++ b/src/debug/di/shimdatatarget.cpp
@@ -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;
}
//---------------------------------------------------------------------------------------
diff --git a/src/debug/di/shimdatatarget.h b/src/debug/di/shimdatatarget.h
index 1fabad4778..9e3502bb48 100644
--- a/src/debug/di/shimdatatarget.h
+++ b/src/debug/di/shimdatatarget.h
@@ -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;
diff --git a/src/debug/di/shimprocess.cpp b/src/debug/di/shimprocess.cpp
index 6e0350b8eb..e4b511abec 100644
--- a/src/debug/di/shimprocess.cpp
+++ b/src/debug/di/shimprocess.cpp
@@ -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.
diff --git a/src/inc/cordebug.idl b/src/inc/cordebug.idl
index 3ba81c32af..f5f975bf26 100644
--- a/src/inc/cordebug.idl
+++ b/src/inc/cordebug.idl
@@ -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.
diff --git a/src/inc/daccess.h b/src/inc/daccess.h
index 704a1ea425..241c25ea21 100644
--- a/src/inc/daccess.h
+++ b/src/inc/daccess.h
@@ -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,
diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h
index 43fc0694f5..4ed5e9267e 100644
--- a/src/pal/inc/pal.h
+++ b/src/pal/inc/pal.h
@@ -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
diff --git a/src/pal/inc/rt/palrt.h b/src/pal/inc/rt/palrt.h
index 7f3cdbdc14..2d67e108b3 100644
--- a/src/pal/inc/rt/palrt.h
+++ b/src/pal/inc/rt/palrt.h
@@ -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
diff --git a/src/pal/prebuilt/idl/cordebug_i.c b/src/pal/prebuilt/idl/cordebug_i.c
index 2b8b1f5c02..8a947ccf49 100644
--- a/src/pal/prebuilt/idl/cordebug_i.c
+++ b/src/pal/prebuilt/idl/cordebug_i.c
@@ -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);
diff --git a/src/pal/prebuilt/inc/cordebug.h b/src/pal/prebuilt/inc/cordebug.h
index db8bf6d24d..153d3901ee 100644
--- a/src/pal/prebuilt/inc/cordebug.h
+++ b/src/pal/prebuilt/inc/cordebug.h
@@ -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__
diff --git a/src/pal/src/CMakeLists.txt b/src/pal/src/CMakeLists.txt
index ce364b3c64..c814e10aac 100644
--- a/src/pal/src/CMakeLists.txt
+++ b/src/pal/src/CMakeLists.txt
@@ -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)
diff --git a/src/pal/src/exception/seh-unwind.cpp b/src/pal/src/exception/seh-unwind.cpp
index 465c459dda..cf899f7f7f 100644
--- a/src/pal/src/exception/seh-unwind.cpp
+++ b/src/pal/src/exception/seh-unwind.cpp
@@ -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
diff --git a/src/vm/amd64/gmsamd64.cpp b/src/vm/amd64/gmsamd64.cpp
index 197e8fde24..49f45c96e5 100644
--- a/src/vm/amd64/gmsamd64.cpp
+++ b/src/vm/amd64/gmsamd64.cpp
@@ -10,7 +10,13 @@
#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