diff options
author | Mike McLaughlin <mikem@microsoft.com> | 2018-03-19 18:26:59 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-19 18:26:59 -0700 |
commit | 66758f48163b90700f0551fd9df4f15bcd1a8a45 (patch) | |
tree | 96f7b342909b7392c2843a0195245b6b94b660b6 | |
parent | 96e83a82e2b7cad75ab363739326cb39c25c5f33 (diff) | |
download | coreclr-66758f48163b90700f0551fd9df4f15bcd1a8a45.tar.gz coreclr-66758f48163b90700f0551fd9df4f15bcd1a8a45.tar.bz2 coreclr-66758f48163b90700f0551fd9df4f15bcd1a8a45.zip |
Add new ICLRDebuggingLibraryProvider2 interface for OpenVirtualProces that works on Linux (#16978)
Add new ICLRDebuggingLibraryProvider2 interface for OpenVirtualProcess that works on Linux.
The old ICLRDebuggingLibraryProvider::ProviderLibrary returns module handles that can't
be properly supported on Linux.
ICLRDebuggerLibraryProvider2 returns the module path string instead of a handle. Works on
both Windows and Linux. If ICLRDebuggerLibraryProvider2 is QI'ed, OpenVirtualProcess will
NOT fall back to ICLRDebuggerLibraryProvider if ProviderLibrary2 fails.
HRESULT ProvideLibrary2(
[in] const WCHAR* pwszFileName,
[in] DWORD dwTimestamp,
[in] DWORD dwSizeOfImage,
[out] LPWSTR* ppResolvedModulePath);
ppResolvedModulePath - Where *ppResolvedModulePath is a null terminated path to the module dll. On Windows it should be allocated
with CoTaskMemAlloc. On Unix it should be allocated with malloc. Failure leave it untouched.
-rw-r--r-- | src/debug/shim/debugshim.cpp | 214 | ||||
-rw-r--r-- | src/dlls/dbgshim/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/inc/metahost.idl | 49 | ||||
-rw-r--r-- | src/pal/prebuilt/inc/metahost.h | 118 |
4 files changed, 292 insertions, 90 deletions
diff --git a/src/debug/shim/debugshim.cpp b/src/debug/shim/debugshim.cpp index 08f1ec58a1..b4e709adcf 100644 --- a/src/debug/shim/debugshim.cpp +++ b/src/debug/shim/debugshim.cpp @@ -90,116 +90,170 @@ STDMETHODIMP CLRDebuggingImpl::OpenVirtualProcess( CLR_DEBUGGING_VERSION version; BOOL versionSupportedByCaller = FALSE; - + // argument checking + if( (ppProcess != NULL || pFlags != NULL) && pLibraryProvider == NULL) + { + hr = E_POINTER; // the library provider must be specified if either + // ppProcess or pFlags is non-NULL + } + else if( (ppProcess != NULL || pFlags != NULL) && pMaxDebuggerSupportedVersion == NULL) + { + hr = E_POINTER; // the max supported version must be specified if either + // ppProcess or pFlags is non-NULL + } + else if(pVersion != NULL && pVersion->wStructVersion != 0) + { + hr = CORDBG_E_UNSUPPORTED_VERSION_STRUCT; + } + else if(FAILED(pDataTarget->QueryInterface(__uuidof(ICorDebugDataTarget), (void**) &pDt))) + { + hr = CORDBG_E_MISSING_DATA_TARGET_INTERFACE; + } - // argument checking - if( (ppProcess != NULL || pFlags != NULL) && pLibraryProvider == NULL) - { - hr = E_POINTER; // the library provider must be specified if either - // ppProcess or pFlags is non-NULL - } - else if( (ppProcess != NULL || pFlags != NULL) && pMaxDebuggerSupportedVersion == NULL) - { - hr = E_POINTER; // the max supported version must be specified if either - // ppProcess or pFlags is non-NULL - } - else if(pVersion != NULL && pVersion->wStructVersion != 0) - { - hr = CORDBG_E_UNSUPPORTED_VERSION_STRUCT; - } - else if(FAILED(pDataTarget->QueryInterface(__uuidof(ICorDebugDataTarget), (void**) &pDt))) - { - hr = CORDBG_E_MISSING_DATA_TARGET_INTERFACE; - } + if(SUCCEEDED(hr)) + { + // get CLR version + // The expectation is that new versions of the CLR will continue to use the same GUID + // (unless there's a reason to hide them from older shims), but debuggers will tell us the + // CLR version they're designed for and mscordbi.dll can decide whether or not to accept it. + version.wStructVersion = 0; + hr = GetCLRInfo(pDt, + moduleBaseAddress, + &version, + &dbiTimestamp, + &dbiSizeOfImage, + dbiName, + MAX_PATH_FNAME, + &dacTimestamp, + &dacSizeOfImage, + dacName, + MAX_PATH_FNAME); + } - if(SUCCEEDED(hr)) + // If we need to fetch either the process info or the flags info then we need to find + // mscordbi and DAC and do the version specific OVP work + if(SUCCEEDED(hr) && (ppProcess != NULL || pFlags != NULL)) + { + ICLRDebuggingLibraryProvider2* pLibraryProvider2; + if (SUCCEEDED(pLibraryProvider->QueryInterface(__uuidof(ICLRDebuggingLibraryProvider2), (void**)&pLibraryProvider2))) { - // get CLR version - // The expectation is that new versions of the CLR will continue to use the same GUID - // (unless there's a reason to hide them from older shims), but debuggers will tell us the - // CLR version they're designed for and mscordbi.dll can decide whether or not to accept it. - version.wStructVersion = 0; - hr = GetCLRInfo(pDt, - moduleBaseAddress, - &version, - &dbiTimestamp, - &dbiSizeOfImage, - dbiName, - MAX_PATH_FNAME, - &dacTimestamp, - &dacSizeOfImage, - dacName, - MAX_PATH_FNAME); - } + LPWSTR pDbiModulePath; + if (FAILED(pLibraryProvider2->ProvideLibrary2(dbiName, dbiTimestamp, dbiSizeOfImage, &pDbiModulePath)) || + pDbiModulePath == NULL) + { + hr = CORDBG_E_LIBRARY_PROVIDER_ERROR; + } - // If we need to fetch either the process info or the flags info then we need to find - // mscordbi and DAC and do the version specific OVP work - if(SUCCEEDED(hr) && (ppProcess != NULL || pFlags != NULL)) - { + if (SUCCEEDED(hr)) + { + hDbi = LoadLibraryW(pDbiModulePath); + if (hDbi == NULL) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } +#ifdef FEATURE_PAL + free(pDbiModulePath); +#else + CoTaskMemFree(pDbiModulePath); +#endif + } + + if (SUCCEEDED(hr)) + { + // Adjust the timestamp and size of image if this DAC is a known buggy version and needs to be retargeted + RetargetDacIfNeeded(&dacTimestamp, &dacSizeOfImage); + + // ask library provider for dac + LPWSTR pDacModulePath; + if (FAILED(pLibraryProvider2->ProvideLibrary2(dacName, dacTimestamp, dacSizeOfImage, &pDacModulePath)) || + pDacModulePath == NULL) + { + hr = CORDBG_E_LIBRARY_PROVIDER_ERROR; + } + + if (SUCCEEDED(hr)) + { + hDac = LoadLibraryW(pDacModulePath); + if (hDac == NULL) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + } +#ifdef FEATURE_PAL + free(pDacModulePath); +#else + CoTaskMemFree(pDacModulePath); +#endif + } + } + + pLibraryProvider2->Release(); + } + else { // ask library provider for dbi - if(FAILED(pLibraryProvider->ProvideLibrary(dbiName, dbiTimestamp, dbiSizeOfImage, &hDbi)) || + if (FAILED(pLibraryProvider->ProvideLibrary(dbiName, dbiTimestamp, dbiSizeOfImage, &hDbi)) || hDbi == NULL) { hr = CORDBG_E_LIBRARY_PROVIDER_ERROR; } - if(SUCCEEDED(hr)) + if (SUCCEEDED(hr)) { // Adjust the timestamp and size of image if this DAC is a known buggy version and needs to be retargeted RetargetDacIfNeeded(&dacTimestamp, &dacSizeOfImage); // ask library provider for dac - if(FAILED(pLibraryProvider->ProvideLibrary(dacName, dacTimestamp, dacSizeOfImage, &hDac)) || + if (FAILED(pLibraryProvider->ProvideLibrary(dacName, dacTimestamp, dacSizeOfImage, &hDac)) || hDac == NULL) { hr = CORDBG_E_LIBRARY_PROVIDER_ERROR; } } + } - if(SUCCEEDED(hr)) + if(SUCCEEDED(hr)) + { + // get access to OVP and call it + OpenVirtualProcessImplFnPtr ovpFn = (OpenVirtualProcessImplFnPtr) GetProcAddress(hDbi, "OpenVirtualProcessImpl"); + if(ovpFn == NULL) { - // get access to OVP and call it - OpenVirtualProcessImplFnPtr ovpFn = (OpenVirtualProcessImplFnPtr) GetProcAddress(hDbi, "OpenVirtualProcessImpl"); - if(ovpFn == NULL) + // Fallback to CLR v4 Beta1 path, but skip some of the checking we'd normally do (maxSupportedVersion, etc.) + OpenVirtualProcess2FnPtr ovp2Fn = (OpenVirtualProcess2FnPtr) GetProcAddress(hDbi, "OpenVirtualProcess2"); + if (ovp2Fn == NULL) { - // Fallback to CLR v4 Beta1 path, but skip some of the checking we'd normally do (maxSupportedVersion, etc.) - OpenVirtualProcess2FnPtr ovp2Fn = (OpenVirtualProcess2FnPtr) GetProcAddress(hDbi, "OpenVirtualProcess2"); - if (ovp2Fn == NULL) - { - hr = CORDBG_E_LIBRARY_PROVIDER_ERROR; - } - else - { - hr = ovp2Fn(moduleBaseAddress, pDataTarget, hDac, riidProcess, ppProcess, pFlags); - } + hr = CORDBG_E_LIBRARY_PROVIDER_ERROR; } else { - // Have a CLR v4 Beta2+ DBI, call it and let it do the version check - hr = ovpFn(moduleBaseAddress, pDataTarget, hDac, pMaxDebuggerSupportedVersion, riidProcess, ppProcess, pFlags); - if(FAILED(hr)) - { - _ASSERTE(ppProcess == NULL || *ppProcess == NULL); - _ASSERTE(pFlags == NULL || *pFlags == 0); - } + hr = ovp2Fn(moduleBaseAddress, pDataTarget, hDac, riidProcess, ppProcess, pFlags); + } + } + else + { + // Have a CLR v4 Beta2+ DBI, call it and let it do the version check + hr = ovpFn(moduleBaseAddress, pDataTarget, hDac, pMaxDebuggerSupportedVersion, riidProcess, ppProcess, pFlags); + if(FAILED(hr)) + { + _ASSERTE(ppProcess == NULL || *ppProcess == NULL); + _ASSERTE(pFlags == NULL || *pFlags == 0); } } } - - //version is still valid in some failure cases - if(pVersion != NULL && - (SUCCEEDED(hr) || - (hr == CORDBG_E_UNSUPPORTED_DEBUGGING_MODEL) || - (hr == CORDBG_E_UNSUPPORTED_FORWARD_COMPAT))) - { - memcpy(pVersion, &version, sizeof(CLR_DEBUGGING_VERSION)); - } + } - // free the data target we QI'ed earlier - if(pDt != NULL) - { - pDt->Release(); - } + //version is still valid in some failure cases + if(pVersion != NULL && + (SUCCEEDED(hr) || + (hr == CORDBG_E_UNSUPPORTED_DEBUGGING_MODEL) || + (hr == CORDBG_E_UNSUPPORTED_FORWARD_COMPAT))) + { + memcpy(pVersion, &version, sizeof(CLR_DEBUGGING_VERSION)); + } + + // free the data target we QI'ed earlier + if(pDt != NULL) + { + pDt->Release(); + } return hr; } diff --git a/src/dlls/dbgshim/CMakeLists.txt b/src/dlls/dbgshim/CMakeLists.txt index 4e72ee219a..7e6ae61de1 100644 --- a/src/dlls/dbgshim/CMakeLists.txt +++ b/src/dlls/dbgshim/CMakeLists.txt @@ -66,6 +66,7 @@ if(WIN32) uuid.lib user32.lib advapi32.lib + ole32.lib oleaut32.lib WtsApi32.lib version.lib diff --git a/src/inc/metahost.idl b/src/inc/metahost.idl index ac889e2594..2bc7f1a3c9 100644 --- a/src/inc/metahost.idl +++ b/src/inc/metahost.idl @@ -93,6 +93,9 @@ cpp_quote("EXTERN_GUID(IID_ICLRProfiling, 0xb349abe3, 0xb56f, 0x4689, 0xbf, 0xcd // IID ICLRDebuggingLibraryProvider interface : uuid{3151C08D-4D09-4f9b-8838-2880BF18FE51} cpp_quote("EXTERN_GUID(IID_ICLRDebuggingLibraryProvider, 0x3151c08d, 0x4d09, 0x4f9b, 0x88, 0x38, 0x28, 0x80, 0xbf, 0x18, 0xfe, 0x51);") +// IID ICLRDebuggingLibraryProvider2 interface : uuid{E04E2FF1-DCFD-45D5-BCD1-16FFF2FAF7BA} +cpp_quote("EXTERN_GUID(IID_ICLRDebuggingLibraryProvider2, 0xE04E2FF1, 0xDCFD, 0x45D5, 0xBC, 0xD1, 0x16, 0xFF, 0xF2, 0xFA, 0xF7, 0xBA);") + typedef HRESULT(__stdcall * CLRCreateInstanceFnPtr)( REFCLSID clsid, REFIID riid, @@ -402,7 +405,7 @@ CLR_DEBUGGING_PROCESS_FLAGS; interface ICLRDebuggingLibraryProvider : IUnknown { /********************************************************************************** - ** The goal of this method is to allow the debugger to provide a handle to a ** + ** The goal of this method is to allow the debugger to provide a handle to a ** ** module which is needed for debugging. The debugger may use any available means** ** to locate and/or procure the module. See the security note below for important** ** information about implementing this method securely. ** @@ -429,6 +432,50 @@ interface ICLRDebuggingLibraryProvider : IUnknown [out] HMODULE* phModule); } + /************************************************************************************** + ** ICLRDebuggingLibraryProvider2 ** + ** Implemented by API user ** + ** This interface allows the debugger to provide module paths which are needed for ** + ** debugging a particular CLR such as mscordbi and mscordacwks. ** + **************************************************************************************/ +[ + uuid(E04E2FF1-DCFD-45D5-BCD1-16FFF2FAF7BA), + version(1.0), + helpstring("CLR debugging LibraryProvider callback interface"), + local +] +interface ICLRDebuggingLibraryProvider2 : IUnknown +{ + /********************************************************************************** + ** The goal of this method is to allow the debugger to provide a module path ** + ** which is needed for debugging. The debugger may use any available means to ** + ** locate and/or procure the module. See the security note below for important ** + ** information about implementing this method securely. ** + ** Arguments: ** + ** pwzFileName - The name of the module being requested ** + ** dwTimeStamp - The date time stamp stored in the COFF file header of PE files ** + ** dwSizeOfImage - The SizeOfImage field stored in the COFF optional file header ** + ** of PE files ** + ** ppResolvedModulePath - Where *ppResolvedModulePath is a null terminated ** + ** path to the module dll. On Windows it should be ** + ** allocated with CoTaskMemAlloc. On Unix it should be ** + ** allocated with malloc. Failure leave it untouched. See ** + ** security note below! ** + ** ** + ** Return value - S_OK if the module was provided, or any other convenient ** + ** error HRESULT if the module could not be provided ** + ** ** + ** !!!!!!!!!!!!!! ** + ** SECURITY NOTE: Anything the caller would not be willing to execute itself, it ** + ** should not provide to the this API call ** + ***********************************************************************************/ + HRESULT ProvideLibrary2( + [in] const WCHAR* pwszFileName, + [in] DWORD dwTimestamp, + [in] DWORD dwSizeOfImage, + [out] LPWSTR* ppResolvedModulePath); +} + /************************************************************************************** ** ICLRDebugging ** ** Activated using mscoree!CLRCreateInstance. ** diff --git a/src/pal/prebuilt/inc/metahost.h b/src/pal/prebuilt/inc/metahost.h index 0714e42157..a8638683bc 100644 --- a/src/pal/prebuilt/inc/metahost.h +++ b/src/pal/prebuilt/inc/metahost.h @@ -1,13 +1,19 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - /* this ALWAYS GENERATED file contains the definitions for the interfaces */ - /* File created by MIDL compiler version 8.00.0603 */ + /* File created by MIDL compiler version 8.01.0622 */ +/* at Mon Jan 18 19:14:07 2038 + */ +/* Compiler settings for C:/ssd/coreclr/src/inc/metahost.idl: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ /* @@MIDL_FILE_HEADING( ) */ #pragma warning( disable: 4049 ) /* more than 64k source lines */ @@ -23,7 +29,7 @@ #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of <rpcndr.h> -#endif // __RPCNDR_H_VERSION__ +#endif /* __RPCNDR_H_VERSION__ */ #ifndef COM_NO_WINDOWS_H #include "windows.h" @@ -67,6 +73,13 @@ typedef interface ICLRDebuggingLibraryProvider ICLRDebuggingLibraryProvider; #endif /* __ICLRDebuggingLibraryProvider_FWD_DEFINED__ */ +#ifndef __ICLRDebuggingLibraryProvider2_FWD_DEFINED__ +#define __ICLRDebuggingLibraryProvider2_FWD_DEFINED__ +typedef interface ICLRDebuggingLibraryProvider2 ICLRDebuggingLibraryProvider2; + +#endif /* __ICLRDebuggingLibraryProvider2_FWD_DEFINED__ */ + + #ifndef __ICLRDebugging_FWD_DEFINED__ #define __ICLRDebugging_FWD_DEFINED__ typedef interface ICLRDebugging ICLRDebugging; @@ -183,6 +196,7 @@ EXTERN_GUID(CLSID_CLRDebuggingLegacy, 0xDF8395B5, 0xA4BA, 0x450b, 0xA7, 0x7C, 0x EXTERN_GUID(CLSID_CLRProfiling, 0xbd097ed8, 0x733e, 0x43fe, 0x8e, 0xd7, 0xa9, 0x5f, 0xf9, 0xa8, 0x44, 0x8c); EXTERN_GUID(IID_ICLRProfiling, 0xb349abe3, 0xb56f, 0x4689, 0xbf, 0xcd, 0x76, 0xbf, 0x39, 0xd8, 0x88, 0xea); EXTERN_GUID(IID_ICLRDebuggingLibraryProvider, 0x3151c08d, 0x4d09, 0x4f9b, 0x88, 0x38, 0x28, 0x80, 0xbf, 0x18, 0xfe, 0x51); +EXTERN_GUID(IID_ICLRDebuggingLibraryProvider2, 0xE04E2FF1, 0xDCFD, 0x45D5, 0xBC, 0xD1, 0x16, 0xFF, 0xF2, 0xFA, 0xF7, 0xBA); typedef HRESULT ( __stdcall *CLRCreateInstanceFnPtr )( REFCLSID clsid, REFIID riid, @@ -693,6 +707,92 @@ EXTERN_C const IID IID_ICLRDebuggingLibraryProvider; #endif /* __ICLRDebuggingLibraryProvider_INTERFACE_DEFINED__ */ +#ifndef __ICLRDebuggingLibraryProvider2_INTERFACE_DEFINED__ +#define __ICLRDebuggingLibraryProvider2_INTERFACE_DEFINED__ + +/* interface ICLRDebuggingLibraryProvider2 */ +/* [object][local][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRDebuggingLibraryProvider2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("E04E2FF1-DCFD-45D5-BCD1-16FFF2FAF7BA") + ICLRDebuggingLibraryProvider2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE ProvideLibrary2( + /* [in] */ const WCHAR *pwszFileName, + /* [in] */ DWORD dwTimestamp, + /* [in] */ DWORD dwSizeOfImage, + /* [out] */ LPWSTR *ppResolvedModulePath) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRDebuggingLibraryProvider2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRDebuggingLibraryProvider2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRDebuggingLibraryProvider2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRDebuggingLibraryProvider2 * This); + + HRESULT ( STDMETHODCALLTYPE *ProvideLibrary2 )( + ICLRDebuggingLibraryProvider2 * This, + /* [in] */ const WCHAR *pwszFileName, + /* [in] */ DWORD dwTimestamp, + /* [in] */ DWORD dwSizeOfImage, + /* [out] */ LPWSTR *ppResolvedModulePath); + + END_INTERFACE + } ICLRDebuggingLibraryProvider2Vtbl; + + interface ICLRDebuggingLibraryProvider2 + { + CONST_VTBL struct ICLRDebuggingLibraryProvider2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRDebuggingLibraryProvider2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRDebuggingLibraryProvider2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRDebuggingLibraryProvider2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRDebuggingLibraryProvider2_ProvideLibrary2(This,pwszFileName,dwTimestamp,dwSizeOfImage,ppResolvedModulePath) \ + ( (This)->lpVtbl -> ProvideLibrary2(This,pwszFileName,dwTimestamp,dwSizeOfImage,ppResolvedModulePath) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRDebuggingLibraryProvider2_INTERFACE_DEFINED__ */ + + #ifndef __ICLRDebugging_INTERFACE_DEFINED__ #define __ICLRDebugging_INTERFACE_DEFINED__ @@ -1745,14 +1845,14 @@ EXTERN_C const IID IID_ICLRStrongName3; EXTERN_C const IID LIBID_CLRMetaHost; #endif /* __CLRMetaHost_LIBRARY_DEFINED__ */ -/* interface __MIDL_itf_metahost_0000_0010 */ +/* interface __MIDL_itf_metahost_0000_0011 */ /* [local] */ #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0010_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0010_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0011_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0011_v0_0_s_ifspec; /* Additional Prototypes for ALL interfaces */ |