mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-09 17:44:48 +09:00
[cdac] Make DAC load and use cDAC when available (#100946)
- If `DOTNET_ENABLE_CDAC` environment variable is `1`, Look for `cdacreader` next to DAC and load it if found - Implement `ISOSDacInterface` in cDAC - currently returns `E_NOTIMPL` for everything - Make DAC delegate to cDAC (if available) for GetThreadStoreData and GetBreakingChangeVersion - Initialize cDAC with function for reading from the target
This commit is contained in:
parent
e6f1fd8297
commit
e126f8ff2e
15 changed files with 755 additions and 72 deletions
|
@ -1,5 +1,7 @@
|
|||
add_definitions(-DFEATURE_NO_HOST)
|
||||
|
||||
add_subdirectory(${CLR_SRC_NATIVE_DIR}/managed/cdacreader/cmake ${CLR_ARTIFACTS_OBJ_DIR}/cdacreader)
|
||||
|
||||
include_directories(BEFORE ${VM_DIR})
|
||||
include_directories(BEFORE ${VM_DIR}/${ARCH_SOURCES_DIR})
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
@ -12,6 +14,7 @@ if(CLR_CMAKE_HOST_UNIX)
|
|||
endif(CLR_CMAKE_HOST_UNIX)
|
||||
|
||||
set(DACCESS_SOURCES
|
||||
cdac.cpp
|
||||
dacdbiimpl.cpp
|
||||
dacdbiimpllocks.cpp
|
||||
dacdbiimplstackwalk.cpp
|
||||
|
@ -40,6 +43,7 @@ convert_to_absolute_path(DACCESS_SOURCES ${DACCESS_SOURCES})
|
|||
add_library_clr(daccess ${DACCESS_SOURCES})
|
||||
set_target_properties(daccess PROPERTIES DAC_COMPONENT TRUE)
|
||||
target_precompile_headers(daccess PRIVATE [["stdafx.h"]])
|
||||
target_link_libraries(daccess PRIVATE cdacreader_api)
|
||||
|
||||
add_dependencies(daccess eventing_headers)
|
||||
|
||||
|
|
88
src/coreclr/debug/daccess/cdac.cpp
Normal file
88
src/coreclr/debug/daccess/cdac.cpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
#include "cdac.h"
|
||||
#include <sospriv.h>
|
||||
#include <sstring.h>
|
||||
#include "dbgutil.h"
|
||||
#include <cdac_reader.h>
|
||||
|
||||
#define CDAC_LIB_NAME MAKEDLLNAME_W(W("cdacreader"))
|
||||
|
||||
namespace
|
||||
{
|
||||
bool TryLoadCDACLibrary(HMODULE *phCDAC)
|
||||
{
|
||||
// Load cdacreader from next to DAC binary
|
||||
PathString path;
|
||||
if (FAILED(GetClrModuleDirectory(path)))
|
||||
return false;
|
||||
|
||||
path.Append(CDAC_LIB_NAME);
|
||||
*phCDAC = CLRLoadLibrary(path.GetUnicode());
|
||||
if (*phCDAC == NULL)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int ReadFromTargetCallback(uint64_t addr, uint8_t* dest, uint32_t count, void* context)
|
||||
{
|
||||
CDAC* cdac = reinterpret_cast<CDAC*>(context);
|
||||
return cdac->ReadFromTarget(addr, dest, count);
|
||||
}
|
||||
}
|
||||
|
||||
CDAC CDAC::Create(uint64_t descriptorAddr, ICorDebugDataTarget* target)
|
||||
{
|
||||
HMODULE cdacLib;
|
||||
if (!TryLoadCDACLibrary(&cdacLib))
|
||||
return CDAC::Invalid();
|
||||
|
||||
return CDAC{cdacLib, descriptorAddr, target};
|
||||
}
|
||||
|
||||
CDAC::CDAC(HMODULE module, uint64_t descriptorAddr, ICorDebugDataTarget* target)
|
||||
: m_module(module)
|
||||
, m_target{target}
|
||||
{
|
||||
if (m_module == NULL)
|
||||
{
|
||||
m_cdac_handle = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
decltype(&cdac_reader_init) init = reinterpret_cast<decltype(&cdac_reader_init)>(::GetProcAddress(m_module, "cdac_reader_init"));
|
||||
decltype(&cdac_reader_get_sos_interface) getSosInterface = reinterpret_cast<decltype(&cdac_reader_get_sos_interface)>(::GetProcAddress(m_module, "cdac_reader_get_sos_interface"));
|
||||
_ASSERTE(init != nullptr && getSosInterface != nullptr);
|
||||
|
||||
init(descriptorAddr, &ReadFromTargetCallback, this, &m_cdac_handle);
|
||||
getSosInterface(m_cdac_handle, &m_sos);
|
||||
}
|
||||
|
||||
CDAC::~CDAC()
|
||||
{
|
||||
if (m_cdac_handle != NULL)
|
||||
{
|
||||
decltype(&cdac_reader_free) free = reinterpret_cast<decltype(&cdac_reader_free)>(::GetProcAddress(m_module, "cdac_reader_free"));
|
||||
_ASSERTE(free != nullptr);
|
||||
free(m_cdac_handle);
|
||||
}
|
||||
|
||||
if (m_module != NULL)
|
||||
::FreeLibrary(m_module);
|
||||
}
|
||||
|
||||
IUnknown* CDAC::SosInterface()
|
||||
{
|
||||
return m_sos;
|
||||
}
|
||||
|
||||
int CDAC::ReadFromTarget(uint64_t addr, uint8_t* dest, uint32_t count)
|
||||
{
|
||||
HRESULT hr = ReadFromDataTarget(m_target, addr, dest, count);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
return S_OK;
|
||||
}
|
69
src/coreclr/debug/daccess/cdac.h
Normal file
69
src/coreclr/debug/daccess/cdac.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
#ifndef CDAC_H
|
||||
#define CDAC_H
|
||||
|
||||
class CDAC final
|
||||
{
|
||||
public: // static
|
||||
static CDAC Create(uint64_t descriptorAddr, ICorDebugDataTarget *pDataTarget);
|
||||
|
||||
static CDAC Invalid()
|
||||
{
|
||||
return CDAC{nullptr, 0, nullptr};
|
||||
}
|
||||
|
||||
public:
|
||||
CDAC(const CDAC&) = delete;
|
||||
CDAC& operator=(const CDAC&) = delete;
|
||||
|
||||
CDAC(CDAC&& other)
|
||||
: m_module{ other.m_module }
|
||||
, m_cdac_handle{ other.m_cdac_handle }
|
||||
, m_target{ other.m_target }
|
||||
, m_sos{ other.m_sos.Extract() }
|
||||
{
|
||||
other.m_module = NULL;
|
||||
other.m_cdac_handle = 0;
|
||||
other.m_target = NULL;
|
||||
other.m_sos = NULL;
|
||||
}
|
||||
|
||||
CDAC& operator=(CDAC&& other)
|
||||
{
|
||||
m_module = other.m_module;
|
||||
m_cdac_handle = other.m_cdac_handle;
|
||||
m_target = other.m_target;
|
||||
m_sos = other.m_sos.Extract();
|
||||
|
||||
other.m_module = NULL;
|
||||
other.m_cdac_handle = 0;
|
||||
other.m_target = NULL;
|
||||
other.m_sos = NULL;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
~CDAC();
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return m_module != NULL && m_cdac_handle != 0;
|
||||
}
|
||||
|
||||
// This does not AddRef the returned interface
|
||||
IUnknown* SosInterface();
|
||||
int ReadFromTarget(uint64_t addr, uint8_t* dest, uint32_t count);
|
||||
|
||||
private:
|
||||
CDAC(HMODULE module, uint64_t descriptorAddr, ICorDebugDataTarget* target);
|
||||
|
||||
private:
|
||||
HMODULE m_module;
|
||||
intptr_t m_cdac_handle;
|
||||
ICorDebugDataTarget* m_target;
|
||||
NonVMComHolder<IUnknown> m_sos;
|
||||
};
|
||||
|
||||
#endif // CDAC_H
|
|
@ -23,6 +23,8 @@
|
|||
#include "dwreport.h"
|
||||
#include "primitives.h"
|
||||
#include "dbgutil.h"
|
||||
#include "cdac.h"
|
||||
#include <clrconfignocache.h>
|
||||
|
||||
#ifdef USE_DAC_TABLE_RVA
|
||||
#include <dactablerva.h>
|
||||
|
@ -3034,6 +3036,7 @@ private:
|
|||
//----------------------------------------------------------------------------
|
||||
|
||||
ClrDataAccess::ClrDataAccess(ICorDebugDataTarget * pTarget, ICLRDataTarget * pLegacyTarget/*=0*/)
|
||||
: m_cdac{CDAC::Invalid()}
|
||||
{
|
||||
SUPPORTS_DAC_HOST_ONLY; // ctor does no marshalling - don't check with DacCop
|
||||
|
||||
|
@ -3123,7 +3126,6 @@ ClrDataAccess::ClrDataAccess(ICorDebugDataTarget * pTarget, ICLRDataTarget * pLe
|
|||
// see ClrDataAccess::VerifyDlls for details.
|
||||
m_fEnableDllVerificationAsserts = false;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
ClrDataAccess::~ClrDataAccess(void)
|
||||
|
@ -5491,6 +5493,28 @@ ClrDataAccess::Initialize(void)
|
|||
IfFailRet(GetDacGlobalValues());
|
||||
IfFailRet(DacGetHostVtPtrs());
|
||||
|
||||
CLRConfigNoCache enable = CLRConfigNoCache::Get("ENABLE_CDAC");
|
||||
if (enable.IsSet())
|
||||
{
|
||||
DWORD val;
|
||||
if (enable.TryAsInteger(10, val) && val == 1)
|
||||
{
|
||||
// TODO: [cdac] Get contract descriptor from exported symbol
|
||||
uint64_t contractDescriptorAddr = 0;
|
||||
//if (TryGetSymbol(m_pTarget, m_globalBase, "DotNetRuntimeContractDescriptor", &contractDescriptorAddr))
|
||||
{
|
||||
m_cdac = CDAC::Create(contractDescriptorAddr, m_pTarget);
|
||||
if (m_cdac.IsValid())
|
||||
{
|
||||
// Get SOS interfaces from the cDAC if available.
|
||||
IUnknown* unk = m_cdac.SosInterface();
|
||||
(void)unk->QueryInterface(__uuidof(ISOSDacInterface), (void**)&m_cdacSos);
|
||||
(void)unk->QueryInterface(__uuidof(ISOSDacInterface9), (void**)&m_cdacSos9);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// DAC is now setup and ready to use
|
||||
//
|
||||
|
|
|
@ -794,6 +794,7 @@ class DacStreamManager;
|
|||
|
||||
#endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
|
||||
|
||||
#include "cdac.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -1208,7 +1209,7 @@ public:
|
|||
CLRDATA_ADDRESS *allocLimit);
|
||||
|
||||
// ISOSDacInterface13
|
||||
virtual HRESULT STDMETHODCALLTYPE TraverseLoaderHeap(CLRDATA_ADDRESS loaderHeapAddr, LoaderHeapKind kind, VISITHEAP pCallback);
|
||||
virtual HRESULT STDMETHODCALLTYPE TraverseLoaderHeap(CLRDATA_ADDRESS loaderHeapAddr, LoaderHeapKind kind, VISITHEAP pCallback);
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDomainLoaderAllocator(CLRDATA_ADDRESS domainAddress, CLRDATA_ADDRESS *pLoaderAllocator);
|
||||
virtual HRESULT STDMETHODCALLTYPE GetLoaderAllocatorHeapNames(int count, const char **ppNames, int *pNeeded);
|
||||
virtual HRESULT STDMETHODCALLTYPE GetLoaderAllocatorHeaps(CLRDATA_ADDRESS loaderAllocator, int count, CLRDATA_ADDRESS *pLoaderHeaps, LoaderHeapKind *pKinds, int *pNeeded);
|
||||
|
@ -1221,13 +1222,15 @@ public:
|
|||
virtual HRESULT STDMETHODCALLTYPE GetStaticBaseAddress(CLRDATA_ADDRESS methodTable, CLRDATA_ADDRESS *nonGCStaticsAddress, CLRDATA_ADDRESS *GCStaticsAddress);
|
||||
virtual HRESULT STDMETHODCALLTYPE GetThreadStaticBaseAddress(CLRDATA_ADDRESS methodTable, CLRDATA_ADDRESS thread, CLRDATA_ADDRESS *nonGCStaticsAddress, CLRDATA_ADDRESS *GCStaticsAddress);
|
||||
virtual HRESULT STDMETHODCALLTYPE GetMethodTableInitializationFlags(CLRDATA_ADDRESS methodTable, MethodTableInitializationFlags *initializationStatus);
|
||||
|
||||
|
||||
//
|
||||
// ClrDataAccess.
|
||||
//
|
||||
|
||||
HRESULT Initialize(void);
|
||||
|
||||
HRESULT GetThreadStoreDataImpl(struct DacpThreadStoreData *data);
|
||||
|
||||
BOOL IsExceptionFromManagedCode(EXCEPTION_RECORD * pExceptionRecord);
|
||||
#ifndef TARGET_UNIX
|
||||
HRESULT GetWatsonBuckets(DWORD dwThreadId, GenericModeBlock * pGM);
|
||||
|
@ -1414,6 +1417,10 @@ public:
|
|||
ULONG32 m_instanceAge;
|
||||
bool m_debugMode;
|
||||
|
||||
CDAC m_cdac;
|
||||
NonVMComHolder<ISOSDacInterface> m_cdacSos;
|
||||
NonVMComHolder<ISOSDacInterface9> m_cdacSos9;
|
||||
|
||||
#ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS
|
||||
|
||||
protected:
|
||||
|
@ -1964,7 +1971,7 @@ public:
|
|||
|
||||
virtual ~DacMemoryEnumerator() {}
|
||||
virtual HRESULT Init() = 0;
|
||||
|
||||
|
||||
HRESULT STDMETHODCALLTYPE Skip(unsigned int count);
|
||||
HRESULT STDMETHODCALLTYPE Reset();
|
||||
HRESULT STDMETHODCALLTYPE GetCount(unsigned int *pCount);
|
||||
|
|
|
@ -38,6 +38,8 @@ typedef DPTR(InteropLib::ABI::ManagedObjectWrapperLayout) PTR_ManagedObjectWrapp
|
|||
#include "rejit.h"
|
||||
#include "request_common.h"
|
||||
|
||||
#include "cdac.h"
|
||||
|
||||
// GC headers define these to EE-specific stuff that we don't want.
|
||||
#undef EnterCriticalSection
|
||||
#undef LeaveCriticalSection
|
||||
|
@ -299,31 +301,64 @@ HRESULT ClrDataAccess::GetThreadStoreData(struct DacpThreadStoreData *threadStor
|
|||
{
|
||||
SOSDacEnter();
|
||||
|
||||
ThreadStore* threadStore = ThreadStore::s_pThreadStore;
|
||||
if (!threadStore)
|
||||
if (m_cdacSos != NULL)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
// Try the cDAC first - it will return E_NOTIMPL if it doesn't support this method yet. Fall back to the DAC.
|
||||
hr = m_cdacSos->GetThreadStoreData(threadStoreData);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
hr = GetThreadStoreDataImpl(threadStoreData);
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
else
|
||||
{
|
||||
// Assert that the data is the same as what we get from the DAC.
|
||||
DacpThreadStoreData threadStoreDataLocal;
|
||||
HRESULT hrLocal = GetThreadStoreDataImpl(&threadStoreDataLocal);
|
||||
_ASSERTE(hr == hrLocal);
|
||||
_ASSERTE(threadStoreData->threadCount == threadStoreDataLocal.threadCount);
|
||||
_ASSERTE(threadStoreData->unstartedThreadCount == threadStoreDataLocal.unstartedThreadCount);
|
||||
_ASSERTE(threadStoreData->backgroundThreadCount == threadStoreDataLocal.backgroundThreadCount);
|
||||
_ASSERTE(threadStoreData->pendingThreadCount == threadStoreDataLocal.pendingThreadCount);
|
||||
_ASSERTE(threadStoreData->deadThreadCount == threadStoreDataLocal.deadThreadCount);
|
||||
_ASSERTE(threadStoreData->fHostConfig == threadStoreDataLocal.fHostConfig);
|
||||
_ASSERTE(threadStoreData->firstThread == threadStoreDataLocal.firstThread);
|
||||
_ASSERTE(threadStoreData->finalizerThread == threadStoreDataLocal.finalizerThread);
|
||||
_ASSERTE(threadStoreData->gcThread == threadStoreDataLocal.gcThread);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// initialize the fields of our local structure
|
||||
threadStoreData->threadCount = threadStore->m_ThreadCount;
|
||||
threadStoreData->unstartedThreadCount = threadStore->m_UnstartedThreadCount;
|
||||
threadStoreData->backgroundThreadCount = threadStore->m_BackgroundThreadCount;
|
||||
threadStoreData->pendingThreadCount = threadStore->m_PendingThreadCount;
|
||||
threadStoreData->deadThreadCount = threadStore->m_DeadThreadCount;
|
||||
threadStoreData->fHostConfig = FALSE;
|
||||
|
||||
// identify the "important" threads
|
||||
threadStoreData->firstThread = HOST_CDADDR(threadStore->m_ThreadList.GetHead());
|
||||
threadStoreData->finalizerThread = HOST_CDADDR(g_pFinalizerThread);
|
||||
threadStoreData->gcThread = HOST_CDADDR(g_pSuspensionThread);
|
||||
hr = GetThreadStoreDataImpl(threadStoreData);
|
||||
}
|
||||
|
||||
SOSDacLeave();
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT ClrDataAccess::GetThreadStoreDataImpl(struct DacpThreadStoreData *threadStoreData)
|
||||
{
|
||||
ThreadStore* threadStore = ThreadStore::s_pThreadStore;
|
||||
if (!threadStore)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
// initialize the fields of our local structure
|
||||
threadStoreData->threadCount = threadStore->m_ThreadCount;
|
||||
threadStoreData->unstartedThreadCount = threadStore->m_UnstartedThreadCount;
|
||||
threadStoreData->backgroundThreadCount = threadStore->m_BackgroundThreadCount;
|
||||
threadStoreData->pendingThreadCount = threadStore->m_PendingThreadCount;
|
||||
threadStoreData->deadThreadCount = threadStore->m_DeadThreadCount;
|
||||
threadStoreData->fHostConfig = FALSE;
|
||||
|
||||
// identify the "important" threads
|
||||
threadStoreData->firstThread = HOST_CDADDR(threadStore->m_ThreadList.GetHead());
|
||||
threadStoreData->finalizerThread = HOST_CDADDR(g_pFinalizerThread);
|
||||
threadStoreData->gcThread = HOST_CDADDR(g_pSuspensionThread);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
ClrDataAccess::GetStressLogAddress(CLRDATA_ADDRESS *stressLog)
|
||||
{
|
||||
|
@ -4951,7 +4986,15 @@ HRESULT ClrDataAccess::GetBreakingChangeVersion(int* pVersion)
|
|||
if (pVersion == nullptr)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*pVersion = SOS_BREAKING_CHANGE_VERSION;
|
||||
if (m_cdacSos9 != nullptr && SUCCEEDED(m_cdacSos9->GetBreakingChangeVersion(pVersion)))
|
||||
{
|
||||
_ASSERTE(*pVersion == SOS_BREAKING_CHANGE_VERSION);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pVersion = SOS_BREAKING_CHANGE_VERSION;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -5406,10 +5449,10 @@ HRESULT STDMETHODCALLTYPE ClrDataAccess::GetStaticBaseAddress(CLRDATA_ADDRESS me
|
|||
{
|
||||
if (!nonGCStaticsAddress && !GCStaticsAddress)
|
||||
return E_POINTER;
|
||||
|
||||
|
||||
if (!methodTable)
|
||||
return E_INVALIDARG;
|
||||
|
||||
|
||||
SOSDacEnter();
|
||||
|
||||
PTR_MethodTable mTable = PTR_MethodTable(TO_TADDR(methodTable));
|
||||
|
@ -5440,13 +5483,13 @@ HRESULT STDMETHODCALLTYPE ClrDataAccess::GetThreadStaticBaseAddress(CLRDATA_ADDR
|
|||
{
|
||||
if (!nonGCStaticsAddress && !GCStaticsAddress)
|
||||
return E_POINTER;
|
||||
|
||||
|
||||
if (!methodTable)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (!threadPtr)
|
||||
return E_INVALIDARG;
|
||||
|
||||
|
||||
SOSDacEnter();
|
||||
|
||||
PTR_MethodTable mTable = PTR_MethodTable(TO_TADDR(methodTable));
|
||||
|
|
|
@ -85,6 +85,10 @@
|
|||
<!-- CoreRun is not used for testing anymore, but we still use it for benchmarking and profiling -->
|
||||
<RuntimeFiles Include="$(CoreCLRArtifactsPath)\corerun*" />
|
||||
<RuntimeFiles Include="$(CoreCLRArtifactsPath)\PDB\corerun*" />
|
||||
<!-- Include cDAC reader library
|
||||
TODO: [cdac] Remove once cdacreader is added to shipping shared framework -->
|
||||
<RuntimeFiles Include="$(CoreCLRArtifactsPath)\*cdacreader*" />
|
||||
<RuntimeFiles Include="$(CoreCLRArtifactsPath)\PDB\*cdacreader*" />
|
||||
</ItemGroup>
|
||||
<!-- If the build has native sanitizers, copy over the non-sanitized diagnostic binaries so they can be loaded by a debugger -->
|
||||
<ItemGroup Condition="'$(EnableNativeSanitizers)' != ''">
|
||||
|
|
|
@ -9,8 +9,20 @@ extern "C"
|
|||
{
|
||||
#endif
|
||||
|
||||
int cdac_reader_init(intptr_t descriptor, intptr_t* handle);
|
||||
// Initialize the cDAC reader
|
||||
// descriptor: the address of the descriptor in the target process
|
||||
// read_from_target: a callback that reads memory from the target process
|
||||
// read_context: a context pointer that will be passed to read_from_target
|
||||
// handle: returned opaque the handle to the reader. This should be passed to other functions in this API.
|
||||
int cdac_reader_init(uint64_t descriptor, int(*read_from_target)(uint64_t, uint8_t*, uint32_t, void*), void* read_context, /*out*/ intptr_t* handle);
|
||||
|
||||
// Free the cDAC reader
|
||||
// handle: handle to the reader
|
||||
int cdac_reader_free(intptr_t handle);
|
||||
|
||||
// Get the SOS interface from the cDAC reader
|
||||
// handle: handle to the reader
|
||||
// obj: returned SOS interface that can be QI'd to ISOSDacInterface*
|
||||
int cdac_reader_get_sos_interface(intptr_t handle, IUnknown** obj);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -12,9 +12,9 @@ internal static class Entrypoints
|
|||
private const string CDAC = "cdac_reader_";
|
||||
|
||||
[UnmanagedCallersOnly(EntryPoint = $"{CDAC}init")]
|
||||
private static unsafe int Init(nint descriptor, IntPtr* handle)
|
||||
private static unsafe int Init(ulong descriptor, delegate* unmanaged<ulong, byte*, uint, void*, int> readFromTarget, void* readContext, IntPtr* handle)
|
||||
{
|
||||
Target target = new(descriptor);
|
||||
Target target = new(descriptor, readFromTarget, readContext);
|
||||
GCHandle gcHandle = GCHandle.Alloc(target);
|
||||
*handle = GCHandle.ToIntPtr(gcHandle);
|
||||
return 0;
|
||||
|
@ -42,7 +42,7 @@ internal static class Entrypoints
|
|||
if (target == null)
|
||||
return -1;
|
||||
|
||||
SOSDacImpl impl = new(target);
|
||||
Legacy.SOSDacImpl impl = new(target);
|
||||
nint ptr = cw.GetOrCreateComInterfaceForObject(impl, CreateComInterfaceFlags.None);
|
||||
*obj = ptr;
|
||||
return 0;
|
||||
|
|
293
src/native/managed/cdacreader/src/Legacy/ISOSDacInterface.cs
Normal file
293
src/native/managed/cdacreader/src/Legacy/ISOSDacInterface.cs
Normal file
|
@ -0,0 +1,293 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.Marshalling;
|
||||
|
||||
namespace Microsoft.Diagnostics.DataContractReader.Legacy;
|
||||
|
||||
// This file contains managed declarations for the SOS-DAC interfaces.
|
||||
// See src/coreclr/inc/sospriv.idl
|
||||
|
||||
#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value
|
||||
internal struct DacpThreadStoreData
|
||||
{
|
||||
public int threadCount;
|
||||
public int unstartedThreadCount;
|
||||
public int backgroundThreadCount;
|
||||
public int pendingThreadCount;
|
||||
public int deadThreadCount;
|
||||
public ulong firstThread;
|
||||
public ulong finalizerThread;
|
||||
public ulong gcThread;
|
||||
public int fHostConfig; // Uses hosting flags defined above
|
||||
};
|
||||
|
||||
internal struct DacpThreadData
|
||||
{
|
||||
public int corThreadId;
|
||||
public int osThreadId;
|
||||
public int state;
|
||||
public uint preemptiveGCDisabled;
|
||||
public ulong allocContextPtr;
|
||||
public ulong allocContextLimit;
|
||||
public ulong context;
|
||||
public ulong domain;
|
||||
public ulong pFrame;
|
||||
public int lockCount;
|
||||
public ulong firstNestedException; // Pass this pointer to DacpNestedExceptionInfo
|
||||
public ulong teb;
|
||||
public ulong fiberData;
|
||||
public ulong lastThrownObjectHandle;
|
||||
public ulong nextThread;
|
||||
}
|
||||
#pragma warning restore CS0649 // Field is never assigned to, and will always have its default value
|
||||
|
||||
[GeneratedComInterface]
|
||||
[Guid("436f00f2-b42a-4b9f-870c-e73db66ae930")]
|
||||
internal unsafe partial interface ISOSDacInterface
|
||||
{
|
||||
// All functions are explicitly PreserveSig so that we can just return E_NOTIMPL instead of throwing
|
||||
// as the cDAC slowly replaces parts of the DAC.
|
||||
|
||||
// ThreadStore
|
||||
[PreserveSig]
|
||||
int GetThreadStoreData(DacpThreadStoreData* data);
|
||||
|
||||
// AppDomains
|
||||
[PreserveSig]
|
||||
int GetAppDomainStoreData(/*struct DacpAppDomainStoreData*/ void* data);
|
||||
[PreserveSig]
|
||||
int GetAppDomainList(uint count, [In, Out, MarshalUsing(CountElementName = nameof(count))] ulong[] values, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int GetAppDomainData(ulong addr, /*struct DacpAppDomainData*/ void* data);
|
||||
[PreserveSig]
|
||||
int GetAppDomainName(ulong addr, uint count, char* name, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int GetDomainFromContext(ulong context, ulong* domain);
|
||||
|
||||
// Assemblies
|
||||
[PreserveSig]
|
||||
int GetAssemblyList(ulong appDomain, int count, [In, Out, MarshalUsing(CountElementName = nameof(count))] ulong[] values, int* pNeeded);
|
||||
[PreserveSig]
|
||||
int GetAssemblyData(ulong baseDomainPtr, ulong assembly, /*struct DacpAssemblyData*/ void* data);
|
||||
[PreserveSig]
|
||||
int GetAssemblyName(ulong assembly, uint count, char* name, uint* pNeeded);
|
||||
|
||||
// Modules
|
||||
[PreserveSig]
|
||||
int GetModule(ulong addr, /*IXCLRDataModule*/ void** mod);
|
||||
[PreserveSig]
|
||||
int GetModuleData(ulong moduleAddr, /*struct DacpModuleData*/ void* data);
|
||||
[PreserveSig]
|
||||
int TraverseModuleMap(/*ModuleMapType*/ int mmt, ulong moduleAddr, /*MODULEMAPTRAVERSE*/ void* pCallback, void* token);
|
||||
[PreserveSig]
|
||||
int GetAssemblyModuleList(ulong assembly, uint count, [In, Out, MarshalUsing(CountElementName = nameof(count))] ulong[] modules, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int GetILForModule(ulong moduleAddr, int rva, ulong* il);
|
||||
|
||||
// Threads
|
||||
[PreserveSig]
|
||||
int GetThreadData(ulong thread, DacpThreadData *data);
|
||||
[PreserveSig]
|
||||
int GetThreadFromThinlockID(uint thinLockId, ulong* pThread);
|
||||
[PreserveSig]
|
||||
int GetStackLimits(ulong threadPtr, ulong* lower, ulong* upper, ulong* fp);
|
||||
|
||||
// MethodDescs
|
||||
[PreserveSig]
|
||||
int GetMethodDescData(ulong methodDesc, ulong ip, /*struct DacpMethodDescData*/ void* data, uint cRevertedRejitVersions, /*struct DacpReJitData*/ void* rgRevertedRejitData, uint* pcNeededRevertedRejitData);
|
||||
[PreserveSig]
|
||||
int GetMethodDescPtrFromIP(ulong ip, ulong* ppMD);
|
||||
[PreserveSig]
|
||||
int GetMethodDescName(ulong methodDesc, uint count, char* name, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int GetMethodDescPtrFromFrame(ulong frameAddr, ulong* ppMD);
|
||||
[PreserveSig]
|
||||
int GetMethodDescFromToken(ulong moduleAddr, /*mdToken*/ uint token, ulong* methodDesc);
|
||||
[PreserveSig]
|
||||
int GetMethodDescTransparencyData(ulong methodDesc, /*struct DacpMethodDescTransparencyData*/ void* data);
|
||||
|
||||
// JIT Data
|
||||
[PreserveSig]
|
||||
int GetCodeHeaderData(ulong ip, /*struct DacpCodeHeaderData*/ void* data);
|
||||
[PreserveSig]
|
||||
int GetJitManagerList(uint count, /*struct DacpJitManagerInfo*/ void* managers, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int GetJitHelperFunctionName(ulong ip, uint count, byte* name, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int GetJumpThunkTarget(/*T_CONTEXT*/void* ctx, ulong* targetIP, ulong* targetMD);
|
||||
|
||||
// ThreadPool
|
||||
[PreserveSig]
|
||||
int GetThreadpoolData(/*struct DacpThreadpoolData*/ void* data);
|
||||
[PreserveSig]
|
||||
int GetWorkRequestData(ulong addrWorkRequest, /*struct DacpWorkRequestData*/ void* data);
|
||||
[PreserveSig]
|
||||
int GetHillClimbingLogEntry(ulong addr, /*struct DacpHillClimbingLogEntry*/ void* data);
|
||||
|
||||
// Objects
|
||||
[PreserveSig]
|
||||
int GetObjectData(ulong objAddr, /*struct DacpObjectData*/ void* data);
|
||||
[PreserveSig]
|
||||
int GetObjectStringData(ulong obj, uint count, char* stringData, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int GetObjectClassName(ulong obj, uint count, char* className, uint* pNeeded);
|
||||
|
||||
// MethodTable
|
||||
[PreserveSig]
|
||||
int GetMethodTableName(ulong mt, uint count, char* mtName, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int GetMethodTableData(ulong mt, /*struct DacpMethodTableData*/ void* data);
|
||||
[PreserveSig]
|
||||
int GetMethodTableSlot(ulong mt, uint slot, ulong* value);
|
||||
[PreserveSig]
|
||||
int GetMethodTableFieldData(ulong mt, /*struct DacpMethodTableFieldData*/ void* data);
|
||||
[PreserveSig]
|
||||
int GetMethodTableTransparencyData(ulong mt, /*struct DacpMethodTableTransparencyData*/ void* data);
|
||||
|
||||
// EEClass
|
||||
[PreserveSig]
|
||||
int GetMethodTableForEEClass(ulong eeClass, ulong* value);
|
||||
|
||||
// FieldDesc
|
||||
[PreserveSig]
|
||||
int GetFieldDescData(ulong fieldDesc, /*struct DacpFieldDescData*/ void* data);
|
||||
|
||||
// Frames
|
||||
[PreserveSig]
|
||||
int GetFrameName(ulong vtable, uint count, char* frameName, uint* pNeeded);
|
||||
|
||||
// PEFiles
|
||||
[PreserveSig]
|
||||
int GetPEFileBase(ulong addr, ulong* peBase);
|
||||
[PreserveSig]
|
||||
int GetPEFileName(ulong addr, uint count, char* fileName, uint* pNeeded);
|
||||
|
||||
// GC
|
||||
[PreserveSig]
|
||||
int GetGCHeapData(/*struct DacpGcHeapData*/ void* data);
|
||||
[PreserveSig]
|
||||
int GetGCHeapList(uint count, [In, Out, MarshalUsing(CountElementName = nameof(count))] ulong[] heaps, uint* pNeeded); // svr only
|
||||
[PreserveSig]
|
||||
int GetGCHeapDetails(ulong heap, /*struct DacpGcHeapDetails */ void* details); // wks only
|
||||
[PreserveSig]
|
||||
int GetGCHeapStaticData(/*struct DacpGcHeapDetails */ void* data);
|
||||
[PreserveSig]
|
||||
int GetHeapSegmentData(ulong seg, /*struct DacpHeapSegmentData */ void* data);
|
||||
[PreserveSig]
|
||||
int GetOOMData(ulong oomAddr, /*struct DacpOomData */ void* data);
|
||||
[PreserveSig]
|
||||
int GetOOMStaticData(/*struct DacpOomData */ void* data);
|
||||
[PreserveSig]
|
||||
int GetHeapAnalyzeData(ulong addr, /*struct DacpGcHeapAnalyzeData */ void* data);
|
||||
[PreserveSig]
|
||||
int GetHeapAnalyzeStaticData(/*struct DacpGcHeapAnalyzeData */ void* data);
|
||||
|
||||
// DomainLocal
|
||||
[PreserveSig]
|
||||
int GetDomainLocalModuleData(ulong addr, /*struct DacpDomainLocalModuleData */ void* data);
|
||||
[PreserveSig]
|
||||
int GetDomainLocalModuleDataFromAppDomain(ulong appDomainAddr, int moduleID, /*struct DacpDomainLocalModuleData */ void* data);
|
||||
[PreserveSig]
|
||||
int GetDomainLocalModuleDataFromModule(ulong moduleAddr, /*struct DacpDomainLocalModuleData */ void* data);
|
||||
|
||||
// ThreadLocal
|
||||
[PreserveSig]
|
||||
int GetThreadLocalModuleData(ulong thread, uint index, /*struct DacpThreadLocalModuleData */ void* data);
|
||||
|
||||
// SyncBlock
|
||||
[PreserveSig]
|
||||
int GetSyncBlockData(uint number, /*struct DacpSyncBlockData */ void* data);
|
||||
[PreserveSig]
|
||||
int GetSyncBlockCleanupData(ulong addr, /*struct DacpSyncBlockCleanupData */ void* data);
|
||||
|
||||
// Handles
|
||||
[PreserveSig]
|
||||
int GetHandleEnum(/*ISOSHandleEnum*/ void** ppHandleEnum);
|
||||
[PreserveSig]
|
||||
int GetHandleEnumForTypes([In, MarshalUsing(CountElementName = nameof(count))] uint[] types, uint count, /*ISOSHandleEnum*/ void** ppHandleEnum);
|
||||
[PreserveSig]
|
||||
int GetHandleEnumForGC(uint gen, /*ISOSHandleEnum*/ void** ppHandleEnum);
|
||||
|
||||
// EH
|
||||
[PreserveSig]
|
||||
int TraverseEHInfo(ulong ip, /*DUMPEHINFO*/ void* pCallback, void* token);
|
||||
[PreserveSig]
|
||||
int GetNestedExceptionData(ulong exception, ulong* exceptionObject, ulong* nextNestedException);
|
||||
|
||||
// StressLog
|
||||
[PreserveSig]
|
||||
int GetStressLogAddress(ulong* stressLog);
|
||||
|
||||
// Heaps
|
||||
[PreserveSig]
|
||||
int TraverseLoaderHeap(ulong loaderHeapAddr, /*VISITHEAP*/ void* pCallback);
|
||||
[PreserveSig]
|
||||
int GetCodeHeapList(ulong jitManager, uint count, /*struct DacpJitCodeHeapInfo*/ void* codeHeaps, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int TraverseVirtCallStubHeap(ulong pAppDomain, /*VCSHeapType*/ int heaptype, /*VISITHEAP*/ void* pCallback);
|
||||
|
||||
// Other
|
||||
[PreserveSig]
|
||||
int GetUsefulGlobals(/*struct DacpUsefulGlobalsData */ void* data);
|
||||
[PreserveSig]
|
||||
int GetClrWatsonBuckets(ulong thread, void* pGenericModeBlock);
|
||||
[PreserveSig]
|
||||
int GetTLSIndex(uint* pIndex);
|
||||
[PreserveSig]
|
||||
int GetDacModuleHandle(/*HMODULE*/ void* phModule);
|
||||
|
||||
// COM
|
||||
[PreserveSig]
|
||||
int GetRCWData(ulong addr, /*struct DacpRCWData */ void* data);
|
||||
[PreserveSig]
|
||||
int GetRCWInterfaces(ulong rcw, uint count, /*struct DacpCOMInterfacePointerData*/ void* interfaces, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int GetCCWData(ulong ccw, /*struct DacpCCWData */ void* data);
|
||||
[PreserveSig]
|
||||
int GetCCWInterfaces(ulong ccw, uint count, /*struct DacpCOMInterfacePointerData*/ void* interfaces, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int TraverseRCWCleanupList(ulong cleanupListPtr, /*VISITRCWFORCLEANUP*/ void* pCallback, void* token);
|
||||
|
||||
// GC Reference Functions
|
||||
|
||||
/* GetStackReferences
|
||||
* Enumerates all references on a given callstack.
|
||||
*/
|
||||
[PreserveSig]
|
||||
int GetStackReferences(int osThreadID, /*ISOSStackRefEnum*/ void** ppEnum);
|
||||
[PreserveSig]
|
||||
int GetRegisterName(int regName, uint count, char* buffer, uint* pNeeded);
|
||||
|
||||
[PreserveSig]
|
||||
int GetThreadAllocData(ulong thread, /*struct DacpAllocData */ void* data);
|
||||
[PreserveSig]
|
||||
int GetHeapAllocData(uint count, /*struct DacpGenerationAllocData */ void* data, uint* pNeeded);
|
||||
|
||||
// For BindingDisplay plugin
|
||||
[PreserveSig]
|
||||
int GetFailedAssemblyList(ulong appDomain, int count, [In, Out, MarshalUsing(CountElementName = nameof(count))] ulong[] values, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int GetPrivateBinPaths(ulong appDomain, int count, char* paths, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int GetAssemblyLocation(ulong assembly, int count, char* location, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int GetAppDomainConfigFile(ulong appDomain, int count, char* configFile, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int GetApplicationBase(ulong appDomain, int count, char* appBase, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int GetFailedAssemblyData(ulong assembly, uint* pContext, int* pResult);
|
||||
[PreserveSig]
|
||||
int GetFailedAssemblyLocation(ulong assesmbly, uint count, char* location, uint* pNeeded);
|
||||
[PreserveSig]
|
||||
int GetFailedAssemblyDisplayName(ulong assembly, uint count, char* name, uint* pNeeded);
|
||||
};
|
||||
|
||||
[GeneratedComInterface]
|
||||
[Guid("4eca42d8-7e7b-4c8a-a116-7bfbf6929267")]
|
||||
internal partial interface ISOSDacInterface9
|
||||
{
|
||||
int GetBreakingChangeVersion();
|
||||
}
|
119
src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs
Normal file
119
src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs
Normal file
|
@ -0,0 +1,119 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.Marshalling;
|
||||
|
||||
namespace Microsoft.Diagnostics.DataContractReader.Legacy;
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of ISOSDacInterface* interfaces intended to be passed out to consumers
|
||||
/// interacting with the DAC via those COM interfaces.
|
||||
/// </summary>
|
||||
[GeneratedComClass]
|
||||
internal sealed partial class SOSDacImpl : ISOSDacInterface, ISOSDacInterface9
|
||||
{
|
||||
private readonly Target _target;
|
||||
|
||||
public SOSDacImpl(Target target)
|
||||
{
|
||||
_target = target;
|
||||
}
|
||||
|
||||
public unsafe int GetAppDomainConfigFile(ulong appDomain, int count, char* configFile, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetAppDomainData(ulong addr, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetAppDomainList(uint count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] values, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetAppDomainName(ulong addr, uint count, char* name, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetAppDomainStoreData(void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetApplicationBase(ulong appDomain, int count, char* appBase, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetAssemblyData(ulong baseDomainPtr, ulong assembly, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetAssemblyList(ulong appDomain, int count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] values, int* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetAssemblyLocation(ulong assembly, int count, char* location, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetAssemblyModuleList(ulong assembly, uint count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] modules, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetAssemblyName(ulong assembly, uint count, char* name, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
|
||||
public int GetBreakingChangeVersion()
|
||||
{
|
||||
// TODO: Return non-hard-coded version
|
||||
return 4;
|
||||
}
|
||||
|
||||
public unsafe int GetCCWData(ulong ccw, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetCCWInterfaces(ulong ccw, uint count, void* interfaces, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetClrWatsonBuckets(ulong thread, void* pGenericModeBlock) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetCodeHeaderData(ulong ip, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetCodeHeapList(ulong jitManager, uint count, void* codeHeaps, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetDacModuleHandle(void* phModule) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetDomainFromContext(ulong context, ulong* domain) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetDomainLocalModuleData(ulong addr, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetDomainLocalModuleDataFromAppDomain(ulong appDomainAddr, int moduleID, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetDomainLocalModuleDataFromModule(ulong moduleAddr, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetFailedAssemblyData(ulong assembly, uint* pContext, int* pResult) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetFailedAssemblyDisplayName(ulong assembly, uint count, char* name, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetFailedAssemblyList(ulong appDomain, int count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] values, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetFailedAssemblyLocation(ulong assesmbly, uint count, char* location, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetFieldDescData(ulong fieldDesc, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetFrameName(ulong vtable, uint count, char* frameName, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetGCHeapData(void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetGCHeapDetails(ulong heap, void* details) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetGCHeapList(uint count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] heaps, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetGCHeapStaticData(void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetHandleEnum(void** ppHandleEnum) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetHandleEnumForGC(uint gen, void** ppHandleEnum) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetHandleEnumForTypes([In, MarshalUsing(CountElementName = "count")] uint[] types, uint count, void** ppHandleEnum) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetHeapAllocData(uint count, void* data, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetHeapAnalyzeData(ulong addr, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetHeapAnalyzeStaticData(void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetHeapSegmentData(ulong seg, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetHillClimbingLogEntry(ulong addr, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetILForModule(ulong moduleAddr, int rva, ulong* il) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetJitHelperFunctionName(ulong ip, uint count, byte* name, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetJitManagerList(uint count, void* managers, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetJumpThunkTarget(void* ctx, ulong* targetIP, ulong* targetMD) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetMethodDescData(ulong methodDesc, ulong ip, void* data, uint cRevertedRejitVersions, void* rgRevertedRejitData, uint* pcNeededRevertedRejitData) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetMethodDescFromToken(ulong moduleAddr, uint token, ulong* methodDesc) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetMethodDescName(ulong methodDesc, uint count, char* name, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetMethodDescPtrFromFrame(ulong frameAddr, ulong* ppMD) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetMethodDescPtrFromIP(ulong ip, ulong* ppMD) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetMethodDescTransparencyData(ulong methodDesc, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetMethodTableData(ulong mt, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetMethodTableFieldData(ulong mt, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetMethodTableForEEClass(ulong eeClass, ulong* value) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetMethodTableName(ulong mt, uint count, char* mtName, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetMethodTableSlot(ulong mt, uint slot, ulong* value) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetMethodTableTransparencyData(ulong mt, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetModule(ulong addr, void** mod) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetModuleData(ulong moduleAddr, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetNestedExceptionData(ulong exception, ulong* exceptionObject, ulong* nextNestedException) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetObjectClassName(ulong obj, uint count, char* className, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetObjectData(ulong objAddr, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetObjectStringData(ulong obj, uint count, char* stringData, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetOOMData(ulong oomAddr, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetOOMStaticData(void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetPEFileBase(ulong addr, ulong* peBase) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetPEFileName(ulong addr, uint count, char* fileName, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetPrivateBinPaths(ulong appDomain, int count, char* paths, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetRCWData(ulong addr, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetRCWInterfaces(ulong rcw, uint count, void* interfaces, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetRegisterName(int regName, uint count, char* buffer, uint* pNeeded) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetStackLimits(ulong threadPtr, ulong* lower, ulong* upper, ulong* fp) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetStackReferences(int osThreadID, void** ppEnum) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetStressLogAddress(ulong* stressLog) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetSyncBlockCleanupData(ulong addr, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetSyncBlockData(uint number, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetThreadAllocData(ulong thread, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetThreadData(ulong thread, DacpThreadData* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetThreadFromThinlockID(uint thinLockId, ulong* pThread) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetThreadLocalModuleData(ulong thread, uint index, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetThreadpoolData(void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetThreadStoreData(DacpThreadStoreData* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetTLSIndex(uint* pIndex) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetUsefulGlobals(void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int GetWorkRequestData(ulong addrWorkRequest, void* data) => HResults.E_NOTIMPL;
|
||||
public unsafe int TraverseEHInfo(ulong ip, void* pCallback, void* token) => HResults.E_NOTIMPL;
|
||||
public unsafe int TraverseLoaderHeap(ulong loaderHeapAddr, void* pCallback) => HResults.E_NOTIMPL;
|
||||
public unsafe int TraverseModuleMap(int mmt, ulong moduleAddr, void* pCallback, void* token) => HResults.E_NOTIMPL;
|
||||
public unsafe int TraverseRCWCleanupList(ulong cleanupListPtr, void* pCallback, void* token) => HResults.E_NOTIMPL;
|
||||
public unsafe int TraverseVirtCallStubHeap(ulong pAppDomain, int heaptype, void* pCallback) => HResults.E_NOTIMPL;
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.Marshalling;
|
||||
|
||||
namespace Microsoft.Diagnostics.DataContractReader;
|
||||
|
||||
[GeneratedComInterface]
|
||||
[Guid("4eca42d8-7e7b-4c8a-a116-7bfbf6929267")]
|
||||
internal partial interface ISOSDacInterface9
|
||||
{
|
||||
int GetBreakingChangeVersion();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of ISOSDacInterface* interfaces intended to be passed out to consumers
|
||||
/// interacting with the DAC via those COM interfaces.
|
||||
/// </summary>
|
||||
[GeneratedComClass]
|
||||
internal sealed partial class SOSDacImpl : ISOSDacInterface9
|
||||
{
|
||||
private readonly Target _target;
|
||||
|
||||
public SOSDacImpl(Target target)
|
||||
{
|
||||
_target = target;
|
||||
}
|
||||
|
||||
public int GetBreakingChangeVersion()
|
||||
{
|
||||
// TODO: Return non-hard-coded version
|
||||
return 4;
|
||||
}
|
||||
}
|
|
@ -1,11 +1,64 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
|
||||
namespace Microsoft.Diagnostics.DataContractReader;
|
||||
|
||||
internal sealed class Target
|
||||
public struct TargetPointer
|
||||
{
|
||||
public Target(nint _)
|
||||
{
|
||||
}
|
||||
public static TargetPointer Null = new(0);
|
||||
|
||||
public ulong Value;
|
||||
public TargetPointer(ulong value) => Value = value;
|
||||
}
|
||||
|
||||
internal sealed unsafe class Target
|
||||
{
|
||||
private readonly delegate* unmanaged<ulong, byte*, uint, void*, int> _readFromTarget;
|
||||
private readonly void* _readContext;
|
||||
|
||||
private bool _isLittleEndian;
|
||||
private int _pointerSize;
|
||||
|
||||
public Target(ulong _, delegate* unmanaged<ulong, byte*, uint, void*, int> readFromTarget, void* readContext)
|
||||
{
|
||||
_readFromTarget = readFromTarget;
|
||||
_readContext = readContext;
|
||||
|
||||
// TODO: [cdac] Populate from descriptor
|
||||
_isLittleEndian = BitConverter.IsLittleEndian;
|
||||
_pointerSize = IntPtr.Size;
|
||||
}
|
||||
|
||||
public bool TryReadPointer(ulong address, out TargetPointer pointer)
|
||||
{
|
||||
pointer = TargetPointer.Null;
|
||||
|
||||
byte* buffer = stackalloc byte[_pointerSize];
|
||||
ReadOnlySpan<byte> span = new ReadOnlySpan<byte>(buffer, _pointerSize);
|
||||
if (ReadFromTarget(address, buffer, (uint)_pointerSize) < 0)
|
||||
return false;
|
||||
|
||||
if (_pointerSize == sizeof(uint))
|
||||
{
|
||||
pointer = new TargetPointer(
|
||||
_isLittleEndian
|
||||
? BinaryPrimitives.ReadUInt32LittleEndian(span)
|
||||
: BinaryPrimitives.ReadUInt32BigEndian(span));
|
||||
}
|
||||
else if (_pointerSize == sizeof(ulong))
|
||||
{
|
||||
pointer = new TargetPointer(
|
||||
_isLittleEndian
|
||||
? BinaryPrimitives.ReadUInt64LittleEndian(span)
|
||||
: BinaryPrimitives.ReadUInt64BigEndian(span));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private int ReadFromTarget(ulong address, byte* buffer, uint bytesToRead)
|
||||
=> _readFromTarget(address, buffer, bytesToRead, _readContext);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<AssemblyName Condition="'$(TargetsWindows)' != 'true'">lib$(MSBuildProjectName)</AssemblyName>
|
||||
<TargetFramework>$(NetCoreAppToolCurrent)</TargetFramework>
|
||||
<RootNamespace>Microsoft.Diagnostics.DataContractReader</RootNamespace>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<!-- Do not produce a public package. This ships as part of the runtime -->
|
||||
|
@ -9,6 +11,9 @@
|
|||
<InvariantGlobalization>true</InvariantGlobalization>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="$(LibrariesProjectRoot)Common\src\System\HResults.cs" Link="Common\System\HResults.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<InstallRuntimeComponentDestination Include="." />
|
||||
<!-- TODO: [cdac] Output to sharedFramework and add PlatformManifestFileEntry for Microsoft.NETCore.App once ready to include in shipping package -->
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
<Project Sdk="Microsoft.Build.Traversal">
|
||||
<PropertyGroup>
|
||||
<!-- We always want to use release for publishing using NativeAOT -->
|
||||
<NativeLibsPublishConfiguration>Release</NativeLibsPublishConfiguration>
|
||||
<!-- we always want to make shared libs -->
|
||||
<!-- we always want to make shared libs -->
|
||||
<NativeLibKind Condition="'$(NativeLibKind)' == ''">shared</NativeLibKind>
|
||||
|
||||
<!-- When we publish, we want to ensure the SDK does the same thing as though we ran 'dotnet publish' -->
|
||||
|
@ -39,7 +37,7 @@
|
|||
|
||||
<!-- properties to pass down to the subproject builds -->
|
||||
<ItemGroup>
|
||||
<SubprojectProps Include="Configuration" Value="$(NativeLibsPublishConfiguration)" />
|
||||
<SubprojectProps Include="Configuration" Value="$(Configuration)" />
|
||||
<SubprojectProps Include="RuntimeConfiguration" Value="$(RuntimeConfiguration)" />
|
||||
<SubprojectProps Include="LibrariesConfiguration" Value="$(LibrariesConfiguration)" />
|
||||
<SubprojectProps Include="RuntimeIdentifier" Value="$(OutputRID)" />
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue