if (bDumpMDTable)
{
- table.ReInit(4, POINTERSIZE_HEX, AlignRight);
+ table.ReInit(5, POINTERSIZE_HEX, AlignRight);
table.SetColAlignment(3, AlignLeft);
table.SetColWidth(2, 6);
Print("--------------------------------------\n");
Print("MethodDesc Table\n");
- table.WriteRow("Entry", "MethodDesc", "JIT", "Name");
+ table.WriteRow("Entry", "MethodDesc", "JIT", "Slot", "Name");
- for (DWORD n = 0; n < vMethTable.wNumMethods; n++)
+ ISOSMethodEnum *pMethodEnumerator;
+ if (SUCCEEDED(g_sos15->GetMethodTableSlotEnumerator(dwStartAddr, &pMethodEnumerator)))
{
- JITTypes jitType;
- DWORD_PTR methodDesc=0;
- DWORD_PTR gcinfoAddr;
-
- CLRDATA_ADDRESS entry;
- if (g_sos->GetMethodTableSlot(dwStartAddr, n, &entry) != S_OK)
+ SOSMethodData entry;
+ unsigned int fetched;
+ while (SUCCEEDED(pMethodEnumerator->Next(1, &entry, &fetched)) && fetched != 0)
{
- PrintLn("<error getting slot ", Decimal(n), ">");
- continue;
- }
+ JITTypes jitType = TYPE_UNKNOWN;
+ DWORD_PTR methodDesc = (DWORD_PTR)entry.MethodDesc;
+ DWORD_PTR methodDescFromIP2MD = 0;
+ DWORD_PTR gcinfoAddr = 0;
+
+ if (entry.Entrypoint != 0)
+ {
+ IP2MethodDesc((DWORD_PTR)entry.Entrypoint, methodDescFromIP2MD, jitType, gcinfoAddr);
+ if ((methodDescFromIP2MD != methodDesc) && methodDesc != 0)
+ {
+ ExtOut("MethodDesc from IP2MD does not match MethodDesc from enumerator\n");
+ }
+ }
- IP2MethodDesc((DWORD_PTR)entry, methodDesc, jitType, gcinfoAddr);
- table.WriteColumn(0, entry);
- table.WriteColumn(1, MethodDescPtr(methodDesc));
+ table.WriteColumn(0, entry.Entrypoint);
+ table.WriteColumn(1, MethodDescPtr(methodDesc));
- if (jitType == TYPE_UNKNOWN && methodDesc != (TADDR)0)
- {
- // We can get a more accurate jitType from NativeCodeAddr of the methoddesc,
- // because the methodtable entry hasn't always been patched.
- DacpMethodDescData tmpMethodDescData;
- if (tmpMethodDescData.Request(g_sos, TO_CDADDR(methodDesc)) == S_OK)
+ if (jitType == TYPE_UNKNOWN && methodDesc != (TADDR)0)
{
- DacpCodeHeaderData codeHeaderData;
- if (codeHeaderData.Request(g_sos,tmpMethodDescData.NativeCodeAddr) == S_OK)
+ // We can get a more accurate jitType from NativeCodeAddr of the methoddesc,
+ // because the methodtable entry hasn't always been patched.
+ DacpMethodDescData tmpMethodDescData;
+ if (tmpMethodDescData.Request(g_sos, TO_CDADDR(methodDesc)) == S_OK)
{
- jitType = (JITTypes) codeHeaderData.JITType;
+ DacpCodeHeaderData codeHeaderData;
+ if (codeHeaderData.Request(g_sos,tmpMethodDescData.NativeCodeAddr) == S_OK)
+ {
+ jitType = (JITTypes) codeHeaderData.JITType;
+ }
}
}
- }
- const char *pszJitType = "NONE";
- if (jitType == TYPE_JIT)
- pszJitType = "JIT";
- else if (jitType == TYPE_PJIT)
- pszJitType = "PreJIT";
- else
- {
- DacpMethodDescData MethodDescData;
- if (MethodDescData.Request(g_sos, TO_CDADDR(methodDesc)) == S_OK)
+ const char *pszJitType = "NONE";
+ if (jitType == TYPE_JIT)
+ pszJitType = "JIT";
+ else if (jitType == TYPE_PJIT)
+ pszJitType = "PreJIT";
+ else
{
- // Is it an fcall?
- ULONG64 baseAddress = g_pRuntime->GetModuleAddress();
- ULONG64 size = g_pRuntime->GetModuleSize();
- if ((TO_TADDR(MethodDescData.NativeCodeAddr) >= TO_TADDR(baseAddress)) &&
- ((TO_TADDR(MethodDescData.NativeCodeAddr) < TO_TADDR(baseAddress + size))))
+ DacpMethodDescData MethodDescData;
+ if (MethodDescData.Request(g_sos, TO_CDADDR(methodDesc)) == S_OK)
{
- pszJitType = "FCALL";
+ // Is it an fcall?
+ ULONG64 baseAddress = g_pRuntime->GetModuleAddress();
+ ULONG64 size = g_pRuntime->GetModuleSize();
+ if ((TO_TADDR(MethodDescData.NativeCodeAddr) >= TO_TADDR(baseAddress)) &&
+ ((TO_TADDR(MethodDescData.NativeCodeAddr) < TO_TADDR(baseAddress + size))))
+ {
+ pszJitType = "FCALL";
+ }
}
}
- }
- table.WriteColumn(2, pszJitType);
+ table.WriteColumn(2, pszJitType);
+ table.WriteColumn(3, entry.Slot);
- NameForMD_s(methodDesc,g_mdName,mdNameLen);
- table.WriteColumn(3, g_mdName);
+ if (methodDesc != 0)
+ NameForMD_s(methodDesc,g_mdName,mdNameLen);
+ else
+ {
+ DacpModuleData moduleData;
+ if(moduleData.Request(g_sos, entry.DefiningModule)==S_OK)
+ {
+ NameForToken_s(&moduleData, entry.Token, g_mdName, mdNameLen, true);
+ }
+ else
+ {
+ _snwprintf_s(g_mdName, mdNameLen, _TRUNCATE, W("Unknown Module!%08x"), entry.Token);
+ }
+ }
+ table.WriteColumn(4, g_mdName);
+ }
}
}
return Status;
IXCLRDataProcess *g_clrData = NULL;
ISOSDacInterface *g_sos = NULL;
+ISOSDacInterface15 *g_sos15 = NULL;
#ifndef IfFailRet
#define IfFailRet(EXPR) do { Status = (EXPR); if(FAILED(Status)) { return (Status); } } while (0)
Output::ResetIndent();
}
+class SOSDacInterface15Simulator : public ISOSDacInterface15
+{
+ class SOSMethodEnum : public ISOSMethodEnum
+ {
+ CLRDATA_ADDRESS pMT;
+ unsigned int index;
+ unsigned int slotCount;
+ ULONG refCount;
+ public:
+ SOSMethodEnum(CLRDATA_ADDRESS mt) : pMT(mt), refCount(1)
+ {
+ }
+
+ virtual ~SOSMethodEnum() {}
+
+ virtual HRESULT STDMETHODCALLTYPE Reset()
+ {
+ index = 0;
+ DacpMethodTableData vMethTable;
+ HRESULT hr = vMethTable.Request(g_sos, pMT);
+ if (FAILED(hr))
+ return hr;
+
+ slotCount = vMethTable.wNumMethods;
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetCount(unsigned int *pc)
+ {
+ *pc = slotCount;
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE Skip(unsigned int skipCount)
+ {
+ index += skipCount;
+ return S_OK;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE Next(
+ /* [in] */ unsigned int count,
+ /* [length_is][size_is][out] */ SOSMethodData methods[ ],
+ /* [out] */ unsigned int *pFetched)
+ {
+ if (!pFetched)
+ return E_POINTER;
+
+ if (!methods)
+ return E_POINTER;
+
+ unsigned int i = 0;
+ while (i < count && index < slotCount)
+ {
+ SOSMethodData methodData = { 0 };
+
+ JITTypes jitType;
+ DWORD_PTR methodDesc=0;
+ DWORD_PTR gcinfoAddr;
+
+ CLRDATA_ADDRESS entry;
+ methodData.Slot = index;
+ HRESULT hr = g_sos->GetMethodTableSlot(pMT, index++, &entry);
+ if (hr != S_OK)
+ {
+ PrintLn("<error getting slot ", Decimal(index - 1), ">");
+ continue;
+ }
+
+ IP2MethodDesc((DWORD_PTR)entry, methodDesc, jitType, gcinfoAddr);
+
+ methodData.MethodDesc = methodDesc;
+ methodData.Entrypoint = entry;
+
+ methods[i++] = methodData;
+ }
+
+ *pFetched = i;
+ return i < count ? S_FALSE : S_OK;
+ }
+
+ STDMETHOD_(ULONG, AddRef)() { return ++refCount; }
+ STDMETHOD_(ULONG, Release)()
+ {
+ --refCount;
+ if (refCount == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return refCount;
+ }
+
+ STDMETHOD(QueryInterface)(
+ THIS_
+ ___in REFIID InterfaceId,
+ ___out PVOID* Interface
+ )
+ {
+ if (InterfaceId == IID_IUnknown ||
+ InterfaceId == IID_ISOSMethodEnum)
+ {
+ *Interface = (ISOSMethodEnum*)this;
+ AddRef();
+ return S_OK;
+ }
+ *Interface = NULL;
+ return E_NOINTERFACE;
+ }
+ };
+
+public:
+ STDMETHOD_(ULONG, AddRef)() { return 1; };
+ STDMETHOD_(ULONG, Release)() { return 1; };
+ STDMETHOD(QueryInterface)(
+ THIS_
+ ___in REFIID InterfaceId,
+ ___out PVOID* Interface
+ )
+ {
+ if (InterfaceId == IID_IUnknown ||
+ InterfaceId == IID_ISOSDacInterface15)
+ {
+ *Interface = (ISOSDacInterface15*)this;
+ return S_OK;
+ }
+ *Interface = NULL;
+ return E_NOINTERFACE;
+ }
+
+ virtual HRESULT STDMETHODCALLTYPE GetMethodTableSlotEnumerator(
+ CLRDATA_ADDRESS mt,
+ ISOSMethodEnum **enumerator)
+ {
+ SOSMethodEnum *simulator = new(std::nothrow) SOSMethodEnum(mt);
+ *enumerator = simulator;
+ if (simulator == NULL)
+ {
+ return E_OUTOFMEMORY;
+ }
+ HRESULT hr = simulator->Reset();
+ if (FAILED(hr))
+ {
+ simulator->Release();
+ }
+ return hr;
+ }
+} SOSDacInterface15Simulator_Instance;
+
//---------------------------------------------------------------------------------------
//
// Loads private DAC interface, and points g_clrData to it.
g_sos = NULL;
return hr;
}
+
+ // Always have an instance of the MethodTable enumerator
+ hr = g_clrData->QueryInterface(__uuidof(ISOSDacInterface15), (void**)&g_sos15);
+ if (FAILED(hr))
+ {
+ g_sos15 = &SOSDacInterface15Simulator_Instance;
+ }
return S_OK;
}
#include "sospriv.h"
extern IXCLRDataProcess *g_clrData;
extern ISOSDacInterface *g_sos;
+extern ISOSDacInterface15 *g_sos15;
#include "dacprivate.h"
HRESULT GetThreadStaticBaseAddress(CLRDATA_ADDRESS methodTable, CLRDATA_ADDRESS thread, CLRDATA_ADDRESS *nonGCStaticsAddress, CLRDATA_ADDRESS *GCStaticsAddress);
HRESULT GetMethodTableInitializationFlags(CLRDATA_ADDRESS methodTable, MethodTableInitializationFlags *initializationStatus);
}
+
+cpp_quote("#ifndef _SOS_MethodData")
+cpp_quote("#define _SOS_MethodData")
+
+typedef struct _SOSMethodData
+{
+ // At least one of MethodDesc, Entrypoint, or Token/DefiningMethodTable/DefiningModule is guaranteed to be set.
+ // Multiple of them may be set as well
+ CLRDATA_ADDRESS MethodDesc;
+
+ CLRDATA_ADDRESS Entrypoint;
+
+ CLRDATA_ADDRESS DefininingMethodTable; // Useful for when the method is inherited from a parent type which is instantiated
+ CLRDATA_ADDRESS DefiningModule;
+ unsigned int Token;
+
+ // Slot data, a given MethodDesc may be present in multiple slots for a single MethodTable
+ unsigned int Slot; // Will be set to 0xFFFFFFFF for EnC added methods
+} SOSMethodData;
+
+cpp_quote("#endif //_SOS_MethodData")
+
+[
+ object,
+ local,
+ uuid(3c0fe725-c324-4a4f-8100-d399588a662e)
+]
+interface ISOSMethodEnum : ISOSEnum
+{
+ HRESULT Next([in] unsigned int count,
+ [out, size_is(count), length_is(*pNeeded)] SOSMethodData handles[],
+ [out] unsigned int *pNeeded);
+}
+
+[
+ object,
+ local,
+ uuid(7ed81261-52a9-4a23-a358-c3313dea30a8)
+]
+interface ISOSDacInterface15 : IUnknown
+{
+ HRESULT GetMethodTableSlotEnumerator(CLRDATA_ADDRESS mt, ISOSMethodEnum **enumerator);
+}
MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface14,0x9aa22aca,0x6dc6,0x4a0c,0xb4,0xe0,0x70,0xd2,0x41,0x6b,0x98,0x37);
+
+MIDL_DEFINE_GUID(IID, IID_ISOSMethodEnum,0x3c0fe725,0xc324,0x4a4f,0x81,0x00,0xd3,0x99,0x58,0x8a,0x66,0x2e);
+
+
+MIDL_DEFINE_GUID(IID, IID_ISOSDacInterface15,0x7ed81261,0x52a9,0x4a23,0xa3,0x58,0xc3,0x31,0x3d,0xea,0x30,0xa8);
+
#undef MIDL_DEFINE_GUID
#ifdef __cplusplus
#define ISOSDacInterface13_TraverseLoaderHeap(This,loaderHeapAddr,kind,pCallback) \
( (This)->lpVtbl -> TraverseLoaderHeap(This,loaderHeapAddr,kind,pCallback) )
+#define ISOSDacInterface13_GetDomainLoaderAllocator(This,domainAddress,pLoaderAllocator) \
+ ( (This)->lpVtbl -> GetDomainLoaderAllocator(This,domainAddress,pLoaderAllocator) )
+
+#define ISOSDacInterface13_GetLoaderAllocatorHeapNames(This,count,ppNames,pNeeded) \
+ ( (This)->lpVtbl -> GetLoaderAllocatorHeapNames(This,count,ppNames,pNeeded) )
+
+#define ISOSDacInterface13_GetLoaderAllocatorHeaps(This,loaderAllocator,count,pLoaderHeaps,pKinds,pNeeded) \
+ ( (This)->lpVtbl -> GetLoaderAllocatorHeaps(This,loaderAllocator,count,pLoaderHeaps,pKinds,pNeeded) )
+
+#define ISOSDacInterface13_GetHandleTableMemoryRegions(This,ppEnum) \
+ ( (This)->lpVtbl -> GetHandleTableMemoryRegions(This,ppEnum) )
+
+#define ISOSDacInterface13_GetGCBookkeepingMemoryRegions(This,ppEnum) \
+ ( (This)->lpVtbl -> GetGCBookkeepingMemoryRegions(This,ppEnum) )
+
+#define ISOSDacInterface13_GetGCFreeRegions(This,ppEnum) \
+ ( (This)->lpVtbl -> GetGCFreeRegions(This,ppEnum) )
+
+#define ISOSDacInterface13_LockedFlush(This) \
+ ( (This)->lpVtbl -> LockedFlush(This) )
+
#endif /* COBJMACROS */
#endif /* __ISOSDacInterface14_INTERFACE_DEFINED__ */
+/* interface __MIDL_itf_sospriv_0000_0019 */
+/* [local] */
+
+#ifndef _SOS_MethodData
+#define _SOS_MethodData
+typedef struct _SOSMethodData
+ {
+ CLRDATA_ADDRESS MethodDesc;
+ CLRDATA_ADDRESS Entrypoint;
+ CLRDATA_ADDRESS DefininingMethodTable;
+ CLRDATA_ADDRESS DefiningModule;
+ unsigned int Token;
+ unsigned int Slot;
+ } SOSMethodData;
+
+#endif //_SOS_MethodData
+
+
+extern RPC_IF_HANDLE __MIDL_itf_sospriv_0000_0019_v0_0_c_ifspec;
+extern RPC_IF_HANDLE __MIDL_itf_sospriv_0000_0019_v0_0_s_ifspec;
+
+#ifndef __ISOSMethodEnum_INTERFACE_DEFINED__
+#define __ISOSMethodEnum_INTERFACE_DEFINED__
+
+/* interface ISOSMethodEnum */
+/* [uuid][local][object] */
+
+
+EXTERN_C const IID IID_ISOSMethodEnum;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("3c0fe725-c324-4a4f-8100-d399588a662e")
+ ISOSMethodEnum : public ISOSEnum
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE Next(
+ /* [in] */ unsigned int count,
+ /* [length_is][size_is][out] */ SOSMethodData handles[ ],
+ /* [out] */ unsigned int *pNeeded) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ISOSMethodEnumVtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ISOSMethodEnum * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ISOSMethodEnum * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ISOSMethodEnum * This);
+
+ HRESULT ( STDMETHODCALLTYPE *Skip )(
+ ISOSMethodEnum * This,
+ /* [in] */ unsigned int count);
+
+ HRESULT ( STDMETHODCALLTYPE *Reset )(
+ ISOSMethodEnum * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetCount )(
+ ISOSMethodEnum * This,
+ /* [out] */ unsigned int *pCount);
+
+ HRESULT ( STDMETHODCALLTYPE *Next )(
+ ISOSMethodEnum * This,
+ /* [in] */ unsigned int count,
+ /* [length_is][size_is][out] */ SOSMethodData handles[ ],
+ /* [out] */ unsigned int *pNeeded);
+
+ END_INTERFACE
+ } ISOSMethodEnumVtbl;
+
+ interface ISOSMethodEnum
+ {
+ CONST_VTBL struct ISOSMethodEnumVtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ISOSMethodEnum_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ISOSMethodEnum_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ISOSMethodEnum_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ISOSMethodEnum_Skip(This,count) \
+ ( (This)->lpVtbl -> Skip(This,count) )
+
+#define ISOSMethodEnum_Reset(This) \
+ ( (This)->lpVtbl -> Reset(This) )
+
+#define ISOSMethodEnum_GetCount(This,pCount) \
+ ( (This)->lpVtbl -> GetCount(This,pCount) )
+
+
+#define ISOSMethodEnum_Next(This,count,handles,pNeeded) \
+ ( (This)->lpVtbl -> Next(This,count,handles,pNeeded) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ISOSMethodEnum_INTERFACE_DEFINED__ */
+
+
+#ifndef __ISOSDacInterface15_INTERFACE_DEFINED__
+#define __ISOSDacInterface15_INTERFACE_DEFINED__
+
+/* interface ISOSDacInterface15 */
+/* [uuid][local][object] */
+
+
+EXTERN_C const IID IID_ISOSDacInterface15;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+
+ MIDL_INTERFACE("7ed81261-52a9-4a23-a358-c3313dea30a8")
+ ISOSDacInterface15 : public IUnknown
+ {
+ public:
+ virtual HRESULT STDMETHODCALLTYPE GetMethodTableSlotEnumerator(
+ CLRDATA_ADDRESS mt,
+ ISOSMethodEnum **enumerator) = 0;
+
+ };
+
+
+#else /* C style interface */
+
+ typedef struct ISOSDacInterface15Vtbl
+ {
+ BEGIN_INTERFACE
+
+ HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
+ ISOSDacInterface15 * This,
+ /* [in] */ REFIID riid,
+ /* [annotation][iid_is][out] */
+ _COM_Outptr_ void **ppvObject);
+
+ ULONG ( STDMETHODCALLTYPE *AddRef )(
+ ISOSDacInterface15 * This);
+
+ ULONG ( STDMETHODCALLTYPE *Release )(
+ ISOSDacInterface15 * This);
+
+ HRESULT ( STDMETHODCALLTYPE *GetMethodTableSlotEnumerator )(
+ ISOSDacInterface15 * This,
+ CLRDATA_ADDRESS mt,
+ ISOSMethodEnum **enumerator);
+
+ END_INTERFACE
+ } ISOSDacInterface15Vtbl;
+
+ interface ISOSDacInterface15
+ {
+ CONST_VTBL struct ISOSDacInterface15Vtbl *lpVtbl;
+ };
+
+
+
+#ifdef COBJMACROS
+
+
+#define ISOSDacInterface15_QueryInterface(This,riid,ppvObject) \
+ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) )
+
+#define ISOSDacInterface15_AddRef(This) \
+ ( (This)->lpVtbl -> AddRef(This) )
+
+#define ISOSDacInterface15_Release(This) \
+ ( (This)->lpVtbl -> Release(This) )
+
+
+#define ISOSDacInterface15_GetMethodTableSlotEnumerator(This,mt,enumerator) \
+ ( (This)->lpVtbl -> GetMethodTableSlotEnumerator(This,mt,enumerator) )
+
+#endif /* COBJMACROS */
+
+
+#endif /* C style interface */
+
+
+
+
+#endif /* __ISOSDacInterface15_INTERFACE_DEFINED__ */
+
+
/* Additional Prototypes for ALL interfaces */
/* end of Additional Prototypes */