diff --git a/src/coreclr/inc/xclrdata.idl b/src/coreclr/inc/xclrdata.idl index 943fe9ac678567..b69a6c05bf6f7b 100644 --- a/src/coreclr/inc/xclrdata.idl +++ b/src/coreclr/inc/xclrdata.idl @@ -882,6 +882,38 @@ interface IXCLRDataProcess2 : IXCLRDataProcess HRESULT SetGcNotification([in] GcEvtArgs gcEvtArgs); } +[ + object, + local, + uuid(5c552ab6-fc09-4cb3-8e36-22fa03c798b9) +] +interface IXCLRDataProcess3 : IXCLRDataProcess2 +{ + /* + * tableAddress identifies the target dynamic-function-table header. Records + * are returned in caller-provided storage as contiguous target-native + * RUNTIME_FUNCTION bytes. The callee never allocates output storage, and the + * caller-provided buffer does not require any particular alignment. + * + * bytesNeeded and entries are required outputs that are initialized and + * reported on every valid call. A null buffer with a zero bufferSize queries + * the required size. If the buffer is too small, no data is written, + * bytesNeeded and entries report the required byte and record counts, and + * the method returns S_FALSE. If the buffer is large enough, the complete + * table is written and the method returns S_OK. An empty or unmatched table + * returns S_OK with bytesNeeded and entries both set to zero. + * + * Target memory is an immutable snapshot between IXCLRDataProcess::Flush + * calls, so repeated calls before Flush are idempotent. The caller must call + * Flush after changing the data target. + */ + HRESULT GetFunctionTable([in] CLRDATA_ADDRESS tableAddress, + [in] ULONG32 bufferSize, + [out, size_is(bufferSize)] BYTE* buffer, + [out] ULONG32* bytesNeeded, + [out] ULONG32* entries); +} + typedef enum { CLRDATA_DOMAIN_DEFAULT = 0x00000000, diff --git a/src/coreclr/pal/prebuilt/idl/xclrdata_i.cpp b/src/coreclr/pal/prebuilt/idl/xclrdata_i.cpp index de3f1a537b55aa..5957077fa199ec 100644 --- a/src/coreclr/pal/prebuilt/idl/xclrdata_i.cpp +++ b/src/coreclr/pal/prebuilt/idl/xclrdata_i.cpp @@ -78,6 +78,9 @@ MIDL_DEFINE_GUID(IID, IID_IXCLRDataProcess,0x5c552ab6,0xfc09,0x4cb3,0x8e,0x36,0x MIDL_DEFINE_GUID(IID, IID_IXCLRDataProcess2,0x5c552ab6,0xfc09,0x4cb3,0x8e,0x36,0x22,0xfa,0x03,0xc7,0x98,0xb8); +MIDL_DEFINE_GUID(IID, IID_IXCLRDataProcess3,0x5c552ab6,0xfc09,0x4cb3,0x8e,0x36,0x22,0xfa,0x03,0xc7,0x98,0xb9); + + MIDL_DEFINE_GUID(IID, IID_IXCLRDataAppDomain,0x7CA04601,0xC702,0x4670,0xA6,0x3C,0xFA,0x44,0xF7,0xDA,0x7B,0xD5); @@ -141,4 +144,3 @@ MIDL_DEFINE_GUID(IID, IID_IXCLRDataExceptionNotification5,0xe77a39ea,0x3548,0x44 #endif - diff --git a/src/coreclr/pal/prebuilt/inc/xclrdata.h b/src/coreclr/pal/prebuilt/inc/xclrdata.h index b28463dc86c780..020b8dd8bd923e 100644 --- a/src/coreclr/pal/prebuilt/inc/xclrdata.h +++ b/src/coreclr/pal/prebuilt/inc/xclrdata.h @@ -80,6 +80,13 @@ typedef interface IXCLRDataProcess2 IXCLRDataProcess2; #endif /* __IXCLRDataProcess2_FWD_DEFINED__ */ +#ifndef __IXCLRDataProcess3_FWD_DEFINED__ +#define __IXCLRDataProcess3_FWD_DEFINED__ +typedef interface IXCLRDataProcess3 IXCLRDataProcess3; + +#endif /* __IXCLRDataProcess3_FWD_DEFINED__ */ + + #ifndef __IXCLRDataAppDomain_FWD_DEFINED__ #define __IXCLRDataAppDomain_FWD_DEFINED__ typedef interface IXCLRDataAppDomain IXCLRDataAppDomain; @@ -2892,6 +2899,496 @@ EXTERN_C const IID IID_IXCLRDataProcess2; #endif /* __IXCLRDataProcess2_INTERFACE_DEFINED__ */ +#ifndef __IXCLRDataProcess3_INTERFACE_DEFINED__ +#define __IXCLRDataProcess3_INTERFACE_DEFINED__ + +/* interface IXCLRDataProcess3 */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataProcess3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5c552ab6-fc09-4cb3-8e36-22fa03c798b9") + IXCLRDataProcess3 : public IXCLRDataProcess2 + { + public: + virtual HRESULT STDMETHODCALLTYPE GetFunctionTable( + /* [in] */ CLRDATA_ADDRESS tableAddress, + /* [in] */ ULONG32 bufferSize, + /* [size_is][out] */ BYTE *buffer, + /* [out] */ ULONG32 *bytesNeeded, + /* [out] */ ULONG32 *entries) = 0; + + }; + +#else /* C style interface */ + + typedef struct IXCLRDataProcess3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataProcess3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataProcess3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataProcess3 * This); + + HRESULT ( STDMETHODCALLTYPE *Flush )( + IXCLRDataProcess3 * This); + + HRESULT ( STDMETHODCALLTYPE *StartEnumTasks )( + IXCLRDataProcess3 * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumTask )( + IXCLRDataProcess3 * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTask **task); + + HRESULT ( STDMETHODCALLTYPE *EndEnumTasks )( + IXCLRDataProcess3 * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetTaskByOSThreadID )( + IXCLRDataProcess3 * This, + /* [in] */ ULONG32 osThreadID, + /* [out] */ IXCLRDataTask **task); + + HRESULT ( STDMETHODCALLTYPE *GetTaskByUniqueID )( + IXCLRDataProcess3 * This, + /* [in] */ ULONG64 taskID, + /* [out] */ IXCLRDataTask **task); + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( + IXCLRDataProcess3 * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *IsSameObject )( + IXCLRDataProcess3 * This, + /* [in] */ IXCLRDataProcess *process); + + HRESULT ( STDMETHODCALLTYPE *GetManagedObject )( + IXCLRDataProcess3 * This, + /* [out] */ IXCLRDataValue **value); + + HRESULT ( STDMETHODCALLTYPE *GetDesiredExecutionState )( + IXCLRDataProcess3 * This, + /* [out] */ ULONG32 *state); + + HRESULT ( STDMETHODCALLTYPE *SetDesiredExecutionState )( + IXCLRDataProcess3 * This, + /* [in] */ ULONG32 state); + + HRESULT ( STDMETHODCALLTYPE *GetAddressType )( + IXCLRDataProcess3 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [out] */ CLRDataAddressType *type); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeNameByAddress )( + IXCLRDataProcess3 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ CLRDATA_ADDRESS *displacement); + + HRESULT ( STDMETHODCALLTYPE *StartEnumAppDomains )( + IXCLRDataProcess3 * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumAppDomain )( + IXCLRDataProcess3 * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataAppDomain **appDomain); + + HRESULT ( STDMETHODCALLTYPE *EndEnumAppDomains )( + IXCLRDataProcess3 * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainByUniqueID )( + IXCLRDataProcess3 * This, + /* [in] */ ULONG64 id, + /* [out] */ IXCLRDataAppDomain **appDomain); + + HRESULT ( STDMETHODCALLTYPE *StartEnumAssemblies )( + IXCLRDataProcess3 * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumAssembly )( + IXCLRDataProcess3 * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataAssembly **assembly); + + HRESULT ( STDMETHODCALLTYPE *EndEnumAssemblies )( + IXCLRDataProcess3 * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *StartEnumModules )( + IXCLRDataProcess3 * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumModule )( + IXCLRDataProcess3 * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataModule **mod); + + HRESULT ( STDMETHODCALLTYPE *EndEnumModules )( + IXCLRDataProcess3 * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetModuleByAddress )( + IXCLRDataProcess3 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [out] */ IXCLRDataModule **mod); + + HRESULT ( STDMETHODCALLTYPE *StartEnumMethodInstancesByAddress )( + IXCLRDataProcess3 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumMethodInstanceByAddress )( + IXCLRDataProcess3 * This, + /* [in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodInstance **method); + + HRESULT ( STDMETHODCALLTYPE *EndEnumMethodInstancesByAddress )( + IXCLRDataProcess3 * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetDataByAddress )( + IXCLRDataProcess3 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [in] */ IXCLRDataTask *tlsTask, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ IXCLRDataValue **value, + /* [out] */ CLRDATA_ADDRESS *displacement); + + HRESULT ( STDMETHODCALLTYPE *GetExceptionStateByExceptionRecord )( + IXCLRDataProcess3 * This, + /* [in] */ EXCEPTION_RECORD64 *record, + /* [out] */ IXCLRDataExceptionState **exState); + + HRESULT ( STDMETHODCALLTYPE *TranslateExceptionRecordToNotification )( + IXCLRDataProcess3 * This, + /* [in] */ EXCEPTION_RECORD64 *record, + /* [in] */ IXCLRDataExceptionNotification *notify); + + HRESULT ( STDMETHODCALLTYPE *Request )( + IXCLRDataProcess3 * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *CreateMemoryValue )( + IXCLRDataProcess3 * This, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [in] */ IXCLRDataTask *tlsTask, + /* [in] */ IXCLRDataTypeInstance *type, + /* [in] */ CLRDATA_ADDRESS addr, + /* [out] */ IXCLRDataValue **value); + + HRESULT ( STDMETHODCALLTYPE *SetAllTypeNotifications )( + IXCLRDataProcess3 * This, + IXCLRDataModule *mod, + ULONG32 flags); + + HRESULT ( STDMETHODCALLTYPE *SetAllCodeNotifications )( + IXCLRDataProcess3 * This, + IXCLRDataModule *mod, + ULONG32 flags); + + HRESULT ( STDMETHODCALLTYPE *GetTypeNotifications )( + IXCLRDataProcess3 * This, + /* [in] */ ULONG32 numTokens, + /* [size_is][in] */ IXCLRDataModule *mods[ ], + /* [in] */ IXCLRDataModule *singleMod, + /* [size_is][in] */ mdTypeDef tokens[ ], + /* [size_is][out] */ ULONG32 flags[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetTypeNotifications )( + IXCLRDataProcess3 * This, + /* [in] */ ULONG32 numTokens, + /* [size_is][in] */ IXCLRDataModule *mods[ ], + /* [in] */ IXCLRDataModule *singleMod, + /* [size_is][in] */ mdTypeDef tokens[ ], + /* [size_is][in] */ ULONG32 flags[ ], + /* [in] */ ULONG32 singleFlags); + + HRESULT ( STDMETHODCALLTYPE *GetCodeNotifications )( + IXCLRDataProcess3 * This, + /* [in] */ ULONG32 numTokens, + /* [size_is][in] */ IXCLRDataModule *mods[ ], + /* [in] */ IXCLRDataModule *singleMod, + /* [size_is][in] */ mdMethodDef tokens[ ], + /* [size_is][out] */ ULONG32 flags[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetCodeNotifications )( + IXCLRDataProcess3 * This, + /* [in] */ ULONG32 numTokens, + /* [size_is][in] */ IXCLRDataModule *mods[ ], + /* [in] */ IXCLRDataModule *singleMod, + /* [size_is][in] */ mdMethodDef tokens[ ], + /* [size_is][in] */ ULONG32 flags[ ], + /* [in] */ ULONG32 singleFlags); + + HRESULT ( STDMETHODCALLTYPE *GetOtherNotificationFlags )( + IXCLRDataProcess3 * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *SetOtherNotificationFlags )( + IXCLRDataProcess3 * This, + /* [in] */ ULONG32 flags); + + HRESULT ( STDMETHODCALLTYPE *StartEnumMethodDefinitionsByAddress )( + IXCLRDataProcess3 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumMethodDefinitionByAddress )( + IXCLRDataProcess3 * This, + /* [in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodDefinition **method); + + HRESULT ( STDMETHODCALLTYPE *EndEnumMethodDefinitionsByAddress )( + IXCLRDataProcess3 * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *FollowStub )( + IXCLRDataProcess3 * This, + /* [in] */ ULONG32 inFlags, + /* [in] */ CLRDATA_ADDRESS inAddr, + /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER *inBuffer, + /* [out] */ CLRDATA_ADDRESS *outAddr, + /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER *outBuffer, + /* [out] */ ULONG32 *outFlags); + + HRESULT ( STDMETHODCALLTYPE *FollowStub2 )( + IXCLRDataProcess3 * This, + /* [in] */ IXCLRDataTask *task, + /* [in] */ ULONG32 inFlags, + /* [in] */ CLRDATA_ADDRESS inAddr, + /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER *inBuffer, + /* [out] */ CLRDATA_ADDRESS *outAddr, + /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER *outBuffer, + /* [out] */ ULONG32 *outFlags); + + HRESULT ( STDMETHODCALLTYPE *DumpNativeImage )( + IXCLRDataProcess3 * This, + /* [in] */ CLRDATA_ADDRESS loadedBase, + /* [in] */ LPCWSTR name, + /* [in] */ IXCLRDataDisplay *display, + /* [in] */ IXCLRLibrarySupport *libSupport, + /* [in] */ IXCLRDisassemblySupport *dis); + + HRESULT ( STDMETHODCALLTYPE *GetGcNotification )( + IXCLRDataProcess3 * This, + /* [out][in] */ GcEvtArgs *gcEvtArgs); + + HRESULT ( STDMETHODCALLTYPE *SetGcNotification )( + IXCLRDataProcess3 * This, + /* [in] */ GcEvtArgs gcEvtArgs); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionTable )( + IXCLRDataProcess3 * This, + /* [in] */ CLRDATA_ADDRESS tableAddress, + /* [in] */ ULONG32 bufferSize, + /* [size_is][out] */ BYTE *buffer, + /* [out] */ ULONG32 *bytesNeeded, + /* [out] */ ULONG32 *entries); + END_INTERFACE + } IXCLRDataProcess3Vtbl; + + interface IXCLRDataProcess3 + { + CONST_VTBL struct IXCLRDataProcess3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataProcess3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataProcess3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataProcess3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataProcess3_Flush(This) \ + ( (This)->lpVtbl -> Flush(This) ) + +#define IXCLRDataProcess3_StartEnumTasks(This,handle) \ + ( (This)->lpVtbl -> StartEnumTasks(This,handle) ) + +#define IXCLRDataProcess3_EnumTask(This,handle,task) \ + ( (This)->lpVtbl -> EnumTask(This,handle,task) ) + +#define IXCLRDataProcess3_EndEnumTasks(This,handle) \ + ( (This)->lpVtbl -> EndEnumTasks(This,handle) ) + +#define IXCLRDataProcess3_GetTaskByOSThreadID(This,osThreadID,task) \ + ( (This)->lpVtbl -> GetTaskByOSThreadID(This,osThreadID,task) ) + +#define IXCLRDataProcess3_GetTaskByUniqueID(This,taskID,task) \ + ( (This)->lpVtbl -> GetTaskByUniqueID(This,taskID,task) ) + +#define IXCLRDataProcess3_GetFlags(This,flags) \ + ( (This)->lpVtbl -> GetFlags(This,flags) ) + +#define IXCLRDataProcess3_IsSameObject(This,process) \ + ( (This)->lpVtbl -> IsSameObject(This,process) ) + +#define IXCLRDataProcess3_GetManagedObject(This,value) \ + ( (This)->lpVtbl -> GetManagedObject(This,value) ) + +#define IXCLRDataProcess3_GetDesiredExecutionState(This,state) \ + ( (This)->lpVtbl -> GetDesiredExecutionState(This,state) ) + +#define IXCLRDataProcess3_SetDesiredExecutionState(This,state) \ + ( (This)->lpVtbl -> SetDesiredExecutionState(This,state) ) + +#define IXCLRDataProcess3_GetAddressType(This,address,type) \ + ( (This)->lpVtbl -> GetAddressType(This,address,type) ) + +#define IXCLRDataProcess3_GetRuntimeNameByAddress(This,address,flags,bufLen,nameLen,nameBuf,displacement) \ + ( (This)->lpVtbl -> GetRuntimeNameByAddress(This,address,flags,bufLen,nameLen,nameBuf,displacement) ) + +#define IXCLRDataProcess3_StartEnumAppDomains(This,handle) \ + ( (This)->lpVtbl -> StartEnumAppDomains(This,handle) ) + +#define IXCLRDataProcess3_EnumAppDomain(This,handle,appDomain) \ + ( (This)->lpVtbl -> EnumAppDomain(This,handle,appDomain) ) + +#define IXCLRDataProcess3_EndEnumAppDomains(This,handle) \ + ( (This)->lpVtbl -> EndEnumAppDomains(This,handle) ) + +#define IXCLRDataProcess3_GetAppDomainByUniqueID(This,id,appDomain) \ + ( (This)->lpVtbl -> GetAppDomainByUniqueID(This,id,appDomain) ) + +#define IXCLRDataProcess3_StartEnumAssemblies(This,handle) \ + ( (This)->lpVtbl -> StartEnumAssemblies(This,handle) ) + +#define IXCLRDataProcess3_EnumAssembly(This,handle,assembly) \ + ( (This)->lpVtbl -> EnumAssembly(This,handle,assembly) ) + +#define IXCLRDataProcess3_EndEnumAssemblies(This,handle) \ + ( (This)->lpVtbl -> EndEnumAssemblies(This,handle) ) + +#define IXCLRDataProcess3_StartEnumModules(This,handle) \ + ( (This)->lpVtbl -> StartEnumModules(This,handle) ) + +#define IXCLRDataProcess3_EnumModule(This,handle,mod) \ + ( (This)->lpVtbl -> EnumModule(This,handle,mod) ) + +#define IXCLRDataProcess3_EndEnumModules(This,handle) \ + ( (This)->lpVtbl -> EndEnumModules(This,handle) ) + +#define IXCLRDataProcess3_GetModuleByAddress(This,address,mod) \ + ( (This)->lpVtbl -> GetModuleByAddress(This,address,mod) ) + +#define IXCLRDataProcess3_StartEnumMethodInstancesByAddress(This,address,appDomain,handle) \ + ( (This)->lpVtbl -> StartEnumMethodInstancesByAddress(This,address,appDomain,handle) ) + +#define IXCLRDataProcess3_EnumMethodInstanceByAddress(This,handle,method) \ + ( (This)->lpVtbl -> EnumMethodInstanceByAddress(This,handle,method) ) + +#define IXCLRDataProcess3_EndEnumMethodInstancesByAddress(This,handle) \ + ( (This)->lpVtbl -> EndEnumMethodInstancesByAddress(This,handle) ) + +#define IXCLRDataProcess3_GetDataByAddress(This,address,flags,appDomain,tlsTask,bufLen,nameLen,nameBuf,value,displacement) \ + ( (This)->lpVtbl -> GetDataByAddress(This,address,flags,appDomain,tlsTask,bufLen,nameLen,nameBuf,value,displacement) ) + +#define IXCLRDataProcess3_GetExceptionStateByExceptionRecord(This,record,exState) \ + ( (This)->lpVtbl -> GetExceptionStateByExceptionRecord(This,record,exState) ) + +#define IXCLRDataProcess3_TranslateExceptionRecordToNotification(This,record,notify) \ + ( (This)->lpVtbl -> TranslateExceptionRecordToNotification(This,record,notify) ) + +#define IXCLRDataProcess3_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + +#define IXCLRDataProcess3_CreateMemoryValue(This,appDomain,tlsTask,type,addr,value) \ + ( (This)->lpVtbl -> CreateMemoryValue(This,appDomain,tlsTask,type,addr,value) ) + +#define IXCLRDataProcess3_SetAllTypeNotifications(This,mod,flags) \ + ( (This)->lpVtbl -> SetAllTypeNotifications(This,mod,flags) ) + +#define IXCLRDataProcess3_SetAllCodeNotifications(This,mod,flags) \ + ( (This)->lpVtbl -> SetAllCodeNotifications(This,mod,flags) ) + +#define IXCLRDataProcess3_GetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags) \ + ( (This)->lpVtbl -> GetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags) ) + +#define IXCLRDataProcess3_SetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) \ + ( (This)->lpVtbl -> SetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) ) + +#define IXCLRDataProcess3_GetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags) \ + ( (This)->lpVtbl -> GetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags) ) + +#define IXCLRDataProcess3_SetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) \ + ( (This)->lpVtbl -> SetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) ) + +#define IXCLRDataProcess3_GetOtherNotificationFlags(This,flags) \ + ( (This)->lpVtbl -> GetOtherNotificationFlags(This,flags) ) + +#define IXCLRDataProcess3_SetOtherNotificationFlags(This,flags) \ + ( (This)->lpVtbl -> SetOtherNotificationFlags(This,flags) ) + +#define IXCLRDataProcess3_StartEnumMethodDefinitionsByAddress(This,address,handle) \ + ( (This)->lpVtbl -> StartEnumMethodDefinitionsByAddress(This,address,handle) ) + +#define IXCLRDataProcess3_EnumMethodDefinitionByAddress(This,handle,method) \ + ( (This)->lpVtbl -> EnumMethodDefinitionByAddress(This,handle,method) ) + +#define IXCLRDataProcess3_EndEnumMethodDefinitionsByAddress(This,handle) \ + ( (This)->lpVtbl -> EndEnumMethodDefinitionsByAddress(This,handle) ) + +#define IXCLRDataProcess3_FollowStub(This,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) \ + ( (This)->lpVtbl -> FollowStub(This,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) ) + +#define IXCLRDataProcess3_FollowStub2(This,task,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) \ + ( (This)->lpVtbl -> FollowStub2(This,task,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) ) + +#define IXCLRDataProcess3_DumpNativeImage(This,loadedBase,name,display,libSupport,dis) \ + ( (This)->lpVtbl -> DumpNativeImage(This,loadedBase,name,display,libSupport,dis) ) + + +#define IXCLRDataProcess3_GetGcNotification(This,gcEvtArgs) \ + ( (This)->lpVtbl -> GetGcNotification(This,gcEvtArgs) ) + +#define IXCLRDataProcess3_SetGcNotification(This,gcEvtArgs) \ + ( (This)->lpVtbl -> SetGcNotification(This,gcEvtArgs) ) + +#define IXCLRDataProcess3_GetFunctionTable(This,tableAddress,bufferSize,buffer,bytesNeeded,entries) \ + ( (This)->lpVtbl -> GetFunctionTable(This,tableAddress,bufferSize,buffer,bytesNeeded,entries) ) +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + +#endif /* __IXCLRDataProcess3_INTERFACE_DEFINED__ */ + + /* interface __MIDL_itf_xclrdata_0000_0006 */ /* [local] */ @@ -7906,4 +8403,3 @@ EXTERN_C const IID IID_IXCLRDataExceptionNotification5; #endif - diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/IXCLRData.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/IXCLRData.cs index 8f5203c2209ce5..2b21ec61273e69 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/IXCLRData.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/IXCLRData.cs @@ -366,6 +366,19 @@ public unsafe partial interface IXCLRDataProcess2 : IXCLRDataProcess int SetGcNotification(GcEvtArgs gcEvtArgs); } +[GeneratedComInterface] +[Guid("5c552ab6-fc09-4cb3-8e36-22fa03c798b9")] +public unsafe partial interface IXCLRDataProcess3 : IXCLRDataProcess2 +{ + [PreserveSig] + int GetFunctionTable( + ClrDataAddress tableAddress, + uint bufferSize, + byte* buffer, + uint* bytesNeeded, + uint* entries); +} + [GeneratedComInterface] [Guid("E59D8D22-ADA7-49a2-89B5-A415AFCFC95F")] public unsafe partial interface IXCLRDataStackWalk diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs index 85bd1ad8f10c26..fc563da75a0263 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs @@ -17,8 +17,31 @@ namespace Microsoft.Diagnostics.DataContractReader.Legacy; /// Implementation of IXCLRDataProcess* interfaces intended to be passed out to consumers /// interacting with the DAC via those COM interfaces. /// -public sealed unsafe partial class SOSDacImpl : IXCLRDataProcess, IXCLRDataProcess2 +public sealed unsafe partial class SOSDacImpl : IXCLRDataProcess, IXCLRDataProcess2, IXCLRDataProcess3 { + int IXCLRDataProcess3.GetFunctionTable( + ClrDataAddress tableAddress, + uint bufferSize, + byte* buffer, + uint* bytesNeeded, + uint* entries) + { + if (bytesNeeded is null || entries is null) + { + if (bytesNeeded is not null) + *bytesNeeded = 0; + if (entries is not null) + *entries = 0; + + return HResults.E_POINTER; + } + + *bytesNeeded = 0; + *entries = 0; + + return HResults.E_NOTIMPL; + } + int IXCLRDataProcess.Flush() { _target.Flush(FlushScope.All); diff --git a/src/native/managed/cdac/tests/UnitTests/FunctionTableAccessTests.cs b/src/native/managed/cdac/tests/UnitTests/FunctionTableAccessTests.cs new file mode 100644 index 00000000000000..15cb7323460607 --- /dev/null +++ b/src/native/managed/cdac/tests/UnitTests/FunctionTableAccessTests.cs @@ -0,0 +1,118 @@ +// 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; +using Microsoft.Diagnostics.DataContractReader.Legacy; +using Microsoft.Diagnostics.DataContractReader.TestInfrastructure; +using Xunit; + +namespace Microsoft.Diagnostics.DataContractReader.Tests; + +public unsafe class FunctionTableAccessTests +{ + [Theory] + [ClassData(typeof(MockTarget.StdArch))] + public void QueryInterfaceFromIXCLRDataProcess_ReturnsProcess3(MockTarget.Architecture arch) + { + TestPlaceholderTarget target = new TestPlaceholderTarget.Builder(arch).Build(); + SOSDacImpl impl = new(target, legacyObj: null); + void* process = ComInterfaceMarshaller.ConvertToUnmanaged(impl); + + try + { + Guid iid = typeof(IXCLRDataProcess3).GUID; + int hr = Marshal.QueryInterface((nint)process, in iid, out nint process3); + + Assert.Equal(HResults.S_OK, hr); + Assert.NotEqual(nint.Zero, process3); + + try + { + Guid iidIUnknown = new("00000000-0000-0000-C000-000000000046"); + Assert.Equal(HResults.S_OK, Marshal.QueryInterface((nint)process, in iidIUnknown, out nint identity)); + try + { + foreach (Type interfaceType in new[] { typeof(IXCLRDataProcess2), typeof(IXCLRDataProcess) }) + { + Guid baseIid = interfaceType.GUID; + Assert.Equal(HResults.S_OK, Marshal.QueryInterface(process3, in baseIid, out nint baseInterface)); + try + { + nint baseIdentity = nint.Zero; + try + { + Assert.Equal(HResults.S_OK, Marshal.QueryInterface(baseInterface, in iidIUnknown, out baseIdentity)); + Assert.Equal(identity, baseIdentity); + } + finally + { + if (baseIdentity != nint.Zero) + Marshal.Release(baseIdentity); + } + } + finally + { + Marshal.Release(baseInterface); + } + } + } + finally + { + Marshal.Release(identity); + } + + IXCLRDataProcess3 process3Interface = + ComInterfaceMarshaller.ConvertToManaged((void*)process3)!; + uint bytesNeeded = uint.MaxValue; + uint entries = uint.MaxValue; + + hr = process3Interface.GetFunctionTable( + new ClrDataAddress(0), + 0, + null, + &bytesNeeded, + &entries); + + Assert.Equal(HResults.E_NOTIMPL, hr); + Assert.Equal(0u, bytesNeeded); + Assert.Equal(0u, entries); + + entries = uint.MaxValue; + hr = process3Interface.GetFunctionTable( + new ClrDataAddress(0), + 0, + null, + null, + &entries); + + Assert.Equal(HResults.E_POINTER, hr); + Assert.Equal(0u, entries); + + bytesNeeded = uint.MaxValue; + hr = process3Interface.GetFunctionTable( + new ClrDataAddress(0), + 0, + null, + &bytesNeeded, + null); + + Assert.Equal(HResults.E_POINTER, hr); + Assert.Equal(0u, bytesNeeded); + + Assert.Equal( + HResults.E_POINTER, + process3Interface.GetFunctionTable(new ClrDataAddress(0), 0, null, null, null)); + } + finally + { + Marshal.Release(process3); + } + } + finally + { + ComInterfaceMarshaller.Free(process); + } + } +}