From 306d6b01ad0eb5863d6902b49aedd07710f8caec Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Thu, 21 Feb 2019 20:02:42 +0530 Subject: [PATCH 01/92] first attempt --- src/CMakeLists.txt | 1 + src/LinuxProfiler/CComPtr.h | 81 + src/LinuxProfiler/CExtensionsHost.cpp | 83 + src/LinuxProfiler/CExtensionsHost.h | 57 + src/LinuxProfiler/CMakeLists.txt | 54 + src/LinuxProfiler/ClassFactory.cpp | 66 + src/LinuxProfiler/ClassFactory.h | 19 + src/LinuxProfiler/ImplQueryInterface.cpp | 102 ++ src/LinuxProfiler/ImplQueryInterface.h | 1494 +++++++++++++++++ src/LinuxProfiler/InstrumentationMethod.cpp | 13 + src/LinuxProfiler/InstrumentationMethod.h | 113 ++ .../ProductionBreakpoints_x64.config | 9 + src/LinuxProfiler/dllmain.cpp | 68 + src/LinuxProfiler/linux-profiler.vcxproj | 112 ++ src/LinuxProfiler/profiler_pal.h | 20 + src/LinuxProfiler/refcount.cpp | 248 +++ src/LinuxProfiler/refcount.h | 204 +++ src/LinuxProfiler/stdafx.cpp | 4 + src/LinuxProfiler/stdafx.h | 58 + 19 files changed, 2806 insertions(+) create mode 100644 src/LinuxProfiler/CComPtr.h create mode 100644 src/LinuxProfiler/CExtensionsHost.cpp create mode 100644 src/LinuxProfiler/CExtensionsHost.h create mode 100644 src/LinuxProfiler/CMakeLists.txt create mode 100644 src/LinuxProfiler/ClassFactory.cpp create mode 100644 src/LinuxProfiler/ClassFactory.h create mode 100644 src/LinuxProfiler/ImplQueryInterface.cpp create mode 100644 src/LinuxProfiler/ImplQueryInterface.h create mode 100644 src/LinuxProfiler/InstrumentationMethod.cpp create mode 100644 src/LinuxProfiler/InstrumentationMethod.h create mode 100644 src/LinuxProfiler/ProductionBreakpoints_x64.config create mode 100644 src/LinuxProfiler/dllmain.cpp create mode 100644 src/LinuxProfiler/linux-profiler.vcxproj create mode 100644 src/LinuxProfiler/profiler_pal.h create mode 100644 src/LinuxProfiler/refcount.cpp create mode 100644 src/LinuxProfiler/refcount.h create mode 100644 src/LinuxProfiler/stdafx.cpp create mode 100644 src/LinuxProfiler/stdafx.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f95bc2c0..040c87cf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -342,4 +342,5 @@ add_subdirectory(InstrumentationEngine.Api) add_subdirectory(ExtensionsHostCrossPlat) add_subdirectory(InstrumentationEngine.Lib) add_subdirectory(InstrumentationEngine) +add_subdirectory(LinuxProfiler) diff --git a/src/LinuxProfiler/CComPtr.h b/src/LinuxProfiler/CComPtr.h new file mode 100644 index 00000000..e5a4fa89 --- /dev/null +++ b/src/LinuxProfiler/CComPtr.h @@ -0,0 +1,81 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#pragma once + +template +class CComPtr +{ +private: + TInterface* pointer; +public: + CComPtr(const CComPtr&) = delete; // Copy constructor + CComPtr& operator= (const CComPtr&) = delete; // Copy assignment + CComPtr(CComPtr&&) = delete; // Move constructor + CComPtr& operator= (CComPtr&&) = delete; // Move assignment + + void* operator new(std::size_t) = delete; + void* operator new[](std::size_t) = delete; + + void operator delete(void *ptr) = delete; + void operator delete[](void *ptr) = delete; + + CComPtr() + { + this->pointer = nullptr; + } + + ~CComPtr() + { + if (this->pointer) + { + this->pointer->Release(); + this->pointer = nullptr; + } + } + + operator TInterface*() + { + return this->pointer; + } + + operator TInterface*() const + { + return this->pointer; + } + + TInterface& operator *() + { + return *this->pointer; + } + + TInterface& operator *() const + { + return *this->pointer; + } + + TInterface** operator&() + { + return &this->pointer; + } + + TInterface** operator&() const + { + return &this->pointer; + } + + TInterface* operator->() + { + return this->pointer; + } + + TInterface* operator->() const + { + return this->pointer; + } + + void Release() + { + this->~CComPtr(); + } +}; \ No newline at end of file diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp new file mode 100644 index 00000000..301aa440 --- /dev/null +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -0,0 +1,83 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +// CExtensionsHost.cpp : Implementation of CExtensionHost + +#include "stdafx.h" +#include +#include "CExtensionsHost.h" + +// static +void ExtensionsHostCrossPlat::CExtensionHost::SetLoggingFlags(_In_ IProfilerManagerLogging* pLogger) +{ + WCHAR wszEnvVar[MAX_PATH]; + if (GetEnvironmentVariable(_T("MicrosoftInstrumentationEngine_FileLog"), wszEnvVar, MAX_PATH) > 0) + { + LoggingFlags loggingType = LoggingFlags_None; + if (PAL_wcsstr(wszEnvVar, _T("Errors")) != NULL) + { + loggingType = (LoggingFlags)(loggingType | LoggingFlags_Errors); + } + if (PAL_wcsstr(wszEnvVar, _T("Messages")) != NULL) + { + loggingType = (LoggingFlags)(loggingType | LoggingFlags_Trace); + } + if (PAL_wcsstr(wszEnvVar, _T("Dumps")) != NULL) + { + loggingType = (LoggingFlags)(loggingType | LoggingFlags_InstrumentationResults); + } + if (PAL_wcsstr(wszEnvVar, _T("All")) != NULL) + { + loggingType = (LoggingFlags)(LoggingFlags_Errors | LoggingFlags_Trace | LoggingFlags_InstrumentationResults); + } + + if (loggingType != LoggingFlags_None) + { + //Set to true to enable file level logging + pLogger->SetLoggingFlags(loggingType); + } + } +} + +HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( + _In_ IProfilerManager* pProfilerManager +) +{ + HRESULT hr = S_OK; + usleep(10 * 1000 * 1000); + CComPtr pLogger; + IfFailRet(pProfilerManager->GetLoggingInstance(&pLogger)); + SetLoggingFlags(pLogger); + +#ifdef X86 + WCHAR wszHostPathVariableName[] = _T("MicrosoftInstrumentationEngine_HostPath_32"); +#else + WCHAR wszHostPathVariableName[] = _T("MicrosoftInstrumentationEngine_HostPath_64"); +#endif + + WCHAR wszProfilerPath[MAX_PATH]; + if (!GetEnvironmentVariable(wszHostPathVariableName, wszProfilerPath, MAX_PATH)) + { + return E_UNEXPECTED; + } + + WCHAR* pFileName = PathFindFileName(wszProfilerPath); + if (pFileName == wszProfilerPath) + { + return E_UNEXPECTED; + } + *pFileName = _T('\0'); + +#ifdef X86 + WCHAR wszConfigName[] = _T("ProductionBreakpoints_x86.config"); +#else + WCHAR wszConfigName[] = _T("ProductionBreakpoints_x64.config"); +#endif + + StringCchCatW(wszProfilerPath, MAX_PATH, wszConfigName); + + CComBSTR bstrConfigPath = wszProfilerPath; + IfFailRet(pProfilerManager->SetupProfilingEnvironment(&bstrConfigPath, 1)); + + return S_OK; +} diff --git a/src/LinuxProfiler/CExtensionsHost.h b/src/LinuxProfiler/CExtensionsHost.h new file mode 100644 index 00000000..cf38ab58 --- /dev/null +++ b/src/LinuxProfiler/CExtensionsHost.h @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +// CExtensionsHost.h : Declaration of the CExtensionHost + +#pragma once + +// {CA487940-57D2-10BF-11B2-A3AD5A13CBC0} +const GUID CLSID_ExtensionHost = +{ 0xCA487940, 0x57D2, 0x10BF,{ 0x11, 0xB2, 0xA3, 0xAD, 0x5A, 0x13, 0xCB, 0xC0 } }; + +namespace ExtensionsHostCrossPlat +{ + + // The existing ExtensionsHost had too much non-portable code to port to Linux. + // In order to avoid destabilizing appinsights through a rewrite, this class + // has been created to provide basic instrumentation engine host support for + // production breakpoints. + class ATL_NO_VTABLE CExtensionHost : + public IProfilerManagerHost, + public CModuleRefCount + { + public: + CExtensionHost() + { +#ifdef PLATFORM_UNIX + PAL_Initialize(0, NULL); +#endif + } + + CExtensionHost(const CExtensionHost&) = delete; + + DEFINE_DELEGATED_REFCOUNT_ADDREF(CExtensionHost) + DEFINE_DELEGATED_REFCOUNT_RELEASE(CExtensionHost) + + STDMETHOD(STDMETHODCALLTYPE) QueryInterface(REFIID riid, PVOID* ppvObject) + { + HRESULT hr = E_NOINTERFACE; + + hr = ImplQueryInterface( + static_cast(this), + riid, + ppvObject + ); + + return hr; + } + + // IProfilerManagerHost methods + public: + STDMETHOD(Initialize)(_In_ IProfilerManager* pProfilerManager); + + private: + static void SetLoggingFlags(_In_ IProfilerManagerLogging* pLogger); + }; + +} \ No newline at end of file diff --git a/src/LinuxProfiler/CMakeLists.txt b/src/LinuxProfiler/CMakeLists.txt new file mode 100644 index 00000000..92db01d5 --- /dev/null +++ b/src/LinuxProfiler/CMakeLists.txt @@ -0,0 +1,54 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# + +# Require at least version 2.8.12 of CMake +cmake_minimum_required(VERSION 2.8.12) +project(LinuxProfiler) + +include_directories(. ../InstrumentationEngine.Lib ../InstrumentationEngine) + +build_init(CPP LinuxProfiler) + +set(src_files + ./stdafx.cpp + ./dllmain.cpp + ./CExtensionsHost.cpp + ./refcount.cpp + ./ImplQueryInterface.cpp +) + +add_lib(${PROJECT_NAME} + SHARED + true # use_redefines + false # hide_symbols + ${src_files} + ) + +# Force every object to be included even if it's unused. +SET (CORECLRPAL -Wl,--whole-archive coreclrpal -Wl,--no-whole-archive) +SET (LINUXPAL -Wl,--whole-archive linux_pal -Wl,--no-whole-archive) + +# For some reason linking against musl-libc we need libintl and on glibc we need libdl. +# They have nothing to do with one another, each is just a quirk of the environment. +if(CLR_CMAKE_PLATFORM_ALPINE_LINUX) + target_link_libraries(${PROJECT_NAME} :libintl.so) +else() + # NOTE: Explicitly link to the .so version of libdl.so to make sure we don't somehow accidentally + # start statically linking to these, as these are LGPL components. + target_link_libraries(${PROJECT_NAME} :libdl.so) +endif() + +target_link_libraries(${PROJECT_NAME} + pthread + stdc++ + ${CORECLRPAL} + ${LINUXPAL} + atl + palrt + InstrumentationEngine.Lib + corguids + :libuuid.so + :libunwind-x86_64.so + ) + +add_dependencies(${PROJECT_NAME} linux_pal) \ No newline at end of file diff --git a/src/LinuxProfiler/ClassFactory.cpp b/src/LinuxProfiler/ClassFactory.cpp new file mode 100644 index 00000000..a026b148 --- /dev/null +++ b/src/LinuxProfiler/ClassFactory.cpp @@ -0,0 +1,66 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#include "ClassFactory.h" +#include "InstrumentationMethod.h" + +ClassFactory::ClassFactory() : refCount(0) +{ +} + +ClassFactory::~ClassFactory() +{ +} + +HRESULT STDMETHODCALLTYPE ClassFactory::QueryInterface(REFIID riid, void **ppvObject) +{ + if (riid == IID_IUnknown || riid == IID_IClassFactory) + { + *ppvObject = this; + this->AddRef(); + return S_OK; + } + + *ppvObject = nullptr; + return E_NOINTERFACE; +} + +ULONG STDMETHODCALLTYPE ClassFactory::AddRef() +{ + return std::atomic_fetch_add(&this->refCount, 1) + 1; +} + +ULONG STDMETHODCALLTYPE ClassFactory::Release() +{ + int count = std::atomic_fetch_sub(&this->refCount, 1) - 1; + if (count <= 0) + { + delete this; + } + + return count; +} + +HRESULT STDMETHODCALLTYPE ClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) +{ + if (pUnkOuter != nullptr) + { + *ppvObject = nullptr; + return CLASS_E_NOAGGREGATION; + } + + CInstrumentationMethod* profiler = new CInstrumentationMethod(); + if (profiler == nullptr) + { + return E_FAIL; + } + + return profiler->QueryInterface(riid, ppvObject); + + //return S_OK; +} + +HRESULT STDMETHODCALLTYPE ClassFactory::LockServer(BOOL fLock) +{ + return S_OK; +} \ No newline at end of file diff --git a/src/LinuxProfiler/ClassFactory.h b/src/LinuxProfiler/ClassFactory.h new file mode 100644 index 00000000..b926764c --- /dev/null +++ b/src/LinuxProfiler/ClassFactory.h @@ -0,0 +1,19 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#pragma once +#include "stdafx.h" + +class ClassFactory : public IClassFactory +{ +private: + std::atomic refCount; +public: + ClassFactory(); + virtual ~ClassFactory(); + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) override; + ULONG STDMETHODCALLTYPE AddRef(void) override; + ULONG STDMETHODCALLTYPE Release(void) override; + HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) override; + HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock) override; +}; diff --git a/src/LinuxProfiler/ImplQueryInterface.cpp b/src/LinuxProfiler/ImplQueryInterface.cpp new file mode 100644 index 00000000..eec3a6de --- /dev/null +++ b/src/LinuxProfiler/ImplQueryInterface.cpp @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#include "stdafx.h" +#include "ImplQueryInterface.h" + +namespace ExtensionsHostCrossPlat +{ +namespace InternalImplQueryInterface +{ + +HRESULT MultiInterfaceImp( + _In_count_(dwNumElements) const MULTI_INTERFACE_ELEMENT *qiArray, + DWORD dwNumElements, + REFIID iidReqInterface, + _Deref_out_ PVOID *ppvObject +) +{ + HRESULT hr = S_OK; + //VSASSERT(dwNumElements > 0, L""); + + if (ppvObject != NULL) + { + if (iidReqInterface == IID_IUnknown) + { + *ppvObject = qiArray[0].pUnknown; + } + else + { + PVOID pObject = NULL; + + for (DWORD i = 0; i < dwNumElements; i++) + { + if (*qiArray[i].iidImplInterface == iidReqInterface) + { + pObject = qiArray[i].pUnknown; + } + } + + if (pObject) + { + *ppvObject = pObject; + } + else + { + *ppvObject = NULL; + hr = E_NOINTERFACE; + } + } + } + else + { + hr = E_INVALIDARG; + } + + if (hr == S_OK) + { + //VSASSERT(*ppvObject != NULL, L""); + qiArray[0].pUnknown->AddRef(); + } + + + return hr; +} + +HRESULT SingleInterfaceImp(IUnknown *pThis, REFIID iidImplInterface, REFIID iidReqInterface, _Deref_out_ PVOID *ppvObject) +{ + HRESULT hr = S_OK; + + if (ppvObject != NULL) + { + if (iidReqInterface == iidImplInterface) + { + *ppvObject = pThis; + } + else if (iidReqInterface == IID_IUnknown) + { + *ppvObject = pThis; + } + else + { + *ppvObject = NULL; + hr = E_NOINTERFACE; + } + } + else + { + hr = E_INVALIDARG; + } + + if (hr == S_OK) + { + //VSASSERT(*ppvObject != NULL, L""); + pThis->AddRef(); + } + + return hr; +} + +} +} +; // end namespace InternalImplQueryInterface \ No newline at end of file diff --git a/src/LinuxProfiler/ImplQueryInterface.h b/src/LinuxProfiler/ImplQueryInterface.h new file mode 100644 index 00000000..4ad9bc84 --- /dev/null +++ b/src/LinuxProfiler/ImplQueryInterface.h @@ -0,0 +1,1494 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#pragma once + +namespace ExtensionsHostCrossPlat +{ + #ifndef ARRAYSIZE + #define ARRAYSIZE(a) (sizeof(a)/sizeof((a)[0])) + #endif + + // + // This function maps an IID that identifies a particular module (example: IID_IAmSdmObject) to IUnknown + inline REFIID MapToTrueIID(REFIID riidModIdentifier, REFIID riidRequest) + { + return (riidModIdentifier == riidRequest) ? IID_IUnknown : riidRequest; + } + + + // + // Overloads which accept riidModIdentifier + + template + inline HRESULT ImplQueryInterface(REFIID riidModIdentifier, _In_ INTERFACE_T *pThis, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + return ImplQueryInterface(pThis, MapToTrueIID(riidModIdentifier, riid), ppvObject); + } + + template + inline HRESULT ImplQueryInterface(REFIID riidModIdentifier, _In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + return ImplQueryInterface(pThis1, pThis2, MapToTrueIID(riidModIdentifier, riid), ppvObject); + } + + template + inline HRESULT ImplQueryInterface(REFIID riidModIdentifier, _In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + return ImplQueryInterface(pThis1, pThis2, pThis3, MapToTrueIID(riidModIdentifier, riid), ppvObject); + } + + template + inline HRESULT ImplQueryInterface(REFIID riidModIdentifier, _In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + return ImplQueryInterface(pThis1, pThis2, pThis3, pThis4, MapToTrueIID(riidModIdentifier, riid), ppvObject); + } + + template + inline HRESULT ImplQueryInterface(REFIID riidModIdentifier, _In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + return ImplQueryInterface(pThis1, pThis2, pThis3, pThis4, pThis5, MapToTrueIID(riidModIdentifier, riid), ppvObject); + } + + template + inline HRESULT ImplQueryInterface(REFIID riidModIdentifier, _In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + return ImplQueryInterface(pThis1, pThis2, pThis3, pThis4, pThis5, pThis6, MapToTrueIID(riidModIdentifier, riid), ppvObject); + } + + template + inline HRESULT ImplQueryInterface(REFIID riidModIdentifier, _In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + return ImplQueryInterface(pThis1, pThis2, pThis3, pThis4, pThis5, pThis6, pThis7, MapToTrueIID(riidModIdentifier, riid), ppvObject); + } + + template + inline HRESULT ImplQueryInterface(REFIID riidModIdentifier, _In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + return ImplQueryInterface(pThis1, pThis2, pThis3, pThis4, pThis5, pThis6, pThis7, pThis8, MapToTrueIID(riidModIdentifier, riid), ppvObject); + } + + + + + // + // Functions to implement query interface which take 1-32 interfaces as input + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T *pThis, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk = static_cast(pThis); // Verify that INTERFACE_T is a COM interface + + return InternalImplQueryInterface::SingleInterfaceImp(pUnk, __uuidof(INTERFACE_T), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[2] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[3] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[4] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[5] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[6] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[7] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[8] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[9] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[10] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[11] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[12] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[13] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[14] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[15] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[16] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[17] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[18] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[19] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[20] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[21] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[22] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[23] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[24] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, _In_ INTERFACE_T25 *pThis25, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + IUnknown *pUnk25 = static_cast(pThis25); // Verify that INTERFACE_T25 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[25] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + { pUnk25, &__uuidof(INTERFACE_T25) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, _In_ INTERFACE_T25 *pThis25, _In_ INTERFACE_T26 *pThis26, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + IUnknown *pUnk25 = static_cast(pThis25); // Verify that INTERFACE_T25 is a COM interface + IUnknown *pUnk26 = static_cast(pThis26); // Verify that INTERFACE_T26 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[26] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + { pUnk25, &__uuidof(INTERFACE_T25) }, + { pUnk26, &__uuidof(INTERFACE_T26) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, _In_ INTERFACE_T25 *pThis25, _In_ INTERFACE_T26 *pThis26, _In_ INTERFACE_T27 *pThis27, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + IUnknown *pUnk25 = static_cast(pThis25); // Verify that INTERFACE_T25 is a COM interface + IUnknown *pUnk26 = static_cast(pThis26); // Verify that INTERFACE_T26 is a COM interface + IUnknown *pUnk27 = static_cast(pThis27); // Verify that INTERFACE_T27 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[27] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + { pUnk25, &__uuidof(INTERFACE_T25) }, + { pUnk26, &__uuidof(INTERFACE_T26) }, + { pUnk27, &__uuidof(INTERFACE_T27) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, _In_ INTERFACE_T25 *pThis25, _In_ INTERFACE_T26 *pThis26, _In_ INTERFACE_T27 *pThis27, _In_ INTERFACE_T28 *pThis28, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + IUnknown *pUnk25 = static_cast(pThis25); // Verify that INTERFACE_T25 is a COM interface + IUnknown *pUnk26 = static_cast(pThis26); // Verify that INTERFACE_T26 is a COM interface + IUnknown *pUnk27 = static_cast(pThis27); // Verify that INTERFACE_T27 is a COM interface + IUnknown *pUnk28 = static_cast(pThis28); // Verify that INTERFACE_T28 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[28] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + { pUnk25, &__uuidof(INTERFACE_T25) }, + { pUnk26, &__uuidof(INTERFACE_T26) }, + { pUnk27, &__uuidof(INTERFACE_T27) }, + { pUnk28, &__uuidof(INTERFACE_T28) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, _In_ INTERFACE_T25 *pThis25, _In_ INTERFACE_T26 *pThis26, _In_ INTERFACE_T27 *pThis27, _In_ INTERFACE_T28 *pThis28, _In_ INTERFACE_T29 *pThis29, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + IUnknown *pUnk25 = static_cast(pThis25); // Verify that INTERFACE_T25 is a COM interface + IUnknown *pUnk26 = static_cast(pThis26); // Verify that INTERFACE_T26 is a COM interface + IUnknown *pUnk27 = static_cast(pThis27); // Verify that INTERFACE_T27 is a COM interface + IUnknown *pUnk28 = static_cast(pThis28); // Verify that INTERFACE_T28 is a COM interface + IUnknown *pUnk29 = static_cast(pThis29); // Verify that INTERFACE_T29 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[29] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + { pUnk25, &__uuidof(INTERFACE_T25) }, + { pUnk26, &__uuidof(INTERFACE_T26) }, + { pUnk27, &__uuidof(INTERFACE_T27) }, + { pUnk28, &__uuidof(INTERFACE_T28) }, + { pUnk29, &__uuidof(INTERFACE_T29) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, _In_ INTERFACE_T25 *pThis25, _In_ INTERFACE_T26 *pThis26, _In_ INTERFACE_T27 *pThis27, _In_ INTERFACE_T28 *pThis28, _In_ INTERFACE_T29 *pThis29, _In_ INTERFACE_T30 *pThis30, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + IUnknown *pUnk25 = static_cast(pThis25); // Verify that INTERFACE_T25 is a COM interface + IUnknown *pUnk26 = static_cast(pThis26); // Verify that INTERFACE_T26 is a COM interface + IUnknown *pUnk27 = static_cast(pThis27); // Verify that INTERFACE_T27 is a COM interface + IUnknown *pUnk28 = static_cast(pThis28); // Verify that INTERFACE_T28 is a COM interface + IUnknown *pUnk29 = static_cast(pThis29); // Verify that INTERFACE_T29 is a COM interface + IUnknown *pUnk30 = static_cast(pThis30); // Verify that INTERFACE_T30 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[30] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + { pUnk25, &__uuidof(INTERFACE_T25) }, + { pUnk26, &__uuidof(INTERFACE_T26) }, + { pUnk27, &__uuidof(INTERFACE_T27) }, + { pUnk28, &__uuidof(INTERFACE_T28) }, + { pUnk29, &__uuidof(INTERFACE_T29) }, + { pUnk30, &__uuidof(INTERFACE_T30) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, _In_ INTERFACE_T25 *pThis25, _In_ INTERFACE_T26 *pThis26, _In_ INTERFACE_T27 *pThis27, _In_ INTERFACE_T28 *pThis28, _In_ INTERFACE_T29 *pThis29, _In_ INTERFACE_T30 *pThis30, _In_ INTERFACE_T31 *pThis31, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + IUnknown *pUnk25 = static_cast(pThis25); // Verify that INTERFACE_T25 is a COM interface + IUnknown *pUnk26 = static_cast(pThis26); // Verify that INTERFACE_T26 is a COM interface + IUnknown *pUnk27 = static_cast(pThis27); // Verify that INTERFACE_T27 is a COM interface + IUnknown *pUnk28 = static_cast(pThis28); // Verify that INTERFACE_T28 is a COM interface + IUnknown *pUnk29 = static_cast(pThis29); // Verify that INTERFACE_T29 is a COM interface + IUnknown *pUnk30 = static_cast(pThis30); // Verify that INTERFACE_T30 is a COM interface + IUnknown *pUnk31 = static_cast(pThis31); // Verify that INTERFACE_T31 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[31] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + { pUnk25, &__uuidof(INTERFACE_T25) }, + { pUnk26, &__uuidof(INTERFACE_T26) }, + { pUnk27, &__uuidof(INTERFACE_T27) }, + { pUnk28, &__uuidof(INTERFACE_T28) }, + { pUnk29, &__uuidof(INTERFACE_T29) }, + { pUnk30, &__uuidof(INTERFACE_T30) }, + { pUnk31, &__uuidof(INTERFACE_T31) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, _In_ INTERFACE_T25 *pThis25, _In_ INTERFACE_T26 *pThis26, _In_ INTERFACE_T27 *pThis27, _In_ INTERFACE_T28 *pThis28, _In_ INTERFACE_T29 *pThis29, _In_ INTERFACE_T30 *pThis30, _In_ INTERFACE_T31 *pThis31, _In_ INTERFACE_T32 *pThis32, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + IUnknown *pUnk25 = static_cast(pThis25); // Verify that INTERFACE_T25 is a COM interface + IUnknown *pUnk26 = static_cast(pThis26); // Verify that INTERFACE_T26 is a COM interface + IUnknown *pUnk27 = static_cast(pThis27); // Verify that INTERFACE_T27 is a COM interface + IUnknown *pUnk28 = static_cast(pThis28); // Verify that INTERFACE_T28 is a COM interface + IUnknown *pUnk29 = static_cast(pThis29); // Verify that INTERFACE_T29 is a COM interface + IUnknown *pUnk30 = static_cast(pThis30); // Verify that INTERFACE_T30 is a COM interface + IUnknown *pUnk31 = static_cast(pThis31); // Verify that INTERFACE_T31 is a COM interface + IUnknown *pUnk32 = static_cast(pThis32); // Verify that INTERFACE_T32 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[32] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + { pUnk25, &__uuidof(INTERFACE_T25) }, + { pUnk26, &__uuidof(INTERFACE_T26) }, + { pUnk27, &__uuidof(INTERFACE_T27) }, + { pUnk28, &__uuidof(INTERFACE_T28) }, + { pUnk29, &__uuidof(INTERFACE_T29) }, + { pUnk30, &__uuidof(INTERFACE_T30) }, + { pUnk31, &__uuidof(INTERFACE_T31) }, + { pUnk32, &__uuidof(INTERFACE_T32) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + + + namespace InternalImplQueryInterface + { + struct MULTI_INTERFACE_ELEMENT + { + IUnknown *pUnknown; + const IID *iidImplInterface; + }; + + HRESULT MultiInterfaceImp(_In_count_(dwNumElements) const MULTI_INTERFACE_ELEMENT *qiArray, DWORD dwNumElements, REFIID iidReqInterface, _Deref_out_ PVOID *ppvObject); + HRESULT SingleInterfaceImp(IUnknown *pThis, REFIID iidImplInterface, REFIID iidReqInterface, _Deref_out_ PVOID *ppvObject); + + }; +} \ No newline at end of file diff --git a/src/LinuxProfiler/InstrumentationMethod.cpp b/src/LinuxProfiler/InstrumentationMethod.cpp new file mode 100644 index 00000000..5e99c849 --- /dev/null +++ b/src/LinuxProfiler/InstrumentationMethod.cpp @@ -0,0 +1,13 @@ +//// Copyright (c) Microsoft Corporation. All rights reserved. +//// +// +//#include "InstrumentationMethod.h" +// +//HRESULT CInstrumentationMethod::Initialize(IProfilerManager* pProfilerManager) +//{ +// CComPtr pCorProfilerInfo; +// pProfilerManager->GetCorProfilerInfo((IUnknown**)&pCorProfilerInfo); +// pCorProfilerInfo->SetEventMask(COR_PRF_MONITOR_EXCEPTIONS | COR_PRF_ENABLE_STACK_SNAPSHOT); +// +// return S_OK; +//} \ No newline at end of file diff --git a/src/LinuxProfiler/InstrumentationMethod.h b/src/LinuxProfiler/InstrumentationMethod.h new file mode 100644 index 00000000..e4dd854f --- /dev/null +++ b/src/LinuxProfiler/InstrumentationMethod.h @@ -0,0 +1,113 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#pragma once +#include "stdafx.h" + +class CInstrumentationMethod : public IInstrumentationMethod +{ +private: + std::atomic refCount; + +public: + CInstrumentationMethod() + { + } + + virtual ~CInstrumentationMethod() + { + + } + + virtual HRESULT STDMETHODCALLTYPE Initialize(IProfilerManager* pProfilerManager) + { + CComPtr pCorProfilerInfo; + pProfilerManager->GetCorProfilerInfo((IUnknown**)&pCorProfilerInfo); + pCorProfilerInfo->SetEventMask(COR_PRF_MONITOR_EXCEPTIONS | COR_PRF_ENABLE_STACK_SNAPSHOT); + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE OnAppDomainCreated(IAppDomainInfo *pAppDomainInfo) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnAppDomainShutdown(IAppDomainInfo *pAppDomainInfo) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnAssemblyLoaded(IAssemblyInfo* pAssemblyInfo) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnAssemblyUnloaded(IAssemblyInfo* pAssemblyInfo) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnModuleLoaded(IModuleInfo* pModuleInfo) + { + HRESULT hr = S_OK; + + char16_t* bstrModuleName; + IfFailRet(pModuleInfo->GetModuleName(&bstrModuleName)); + + char16_t* bstrModulePath; + IfFailRet(pModuleInfo->GetFullPath(&bstrModulePath)); + + /*std::wstring path(bstrModulePath, SysStringLen(bstrModulePath)); + wstring pdbFile = path.substr(0, path.find_last_of(L'.')) + L".pdb";*/ + + /*FILE *file; + _wfopen_s(&file, pdbFile.c_str(), L"r"); + + if (file == NULL) + { + return S_OK; + } + else + { + fclose(file); + }*/ + + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE OnModuleUnloaded(IModuleInfo* pModuleInfo) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnShutdown() { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE ShouldInstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit, BOOL* pbInstrument) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE BeforeInstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE InstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnInstrumentationComplete(IMethodInfo* pMethodInfo, BOOL isRejit) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE AllowInlineSite(IMethodInfo* pMethodInfoInlinee, IMethodInfo* pMethodInfoCaller, BOOL* pbAllowInline) { return S_OK; } + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) override + { + if (ppvObject == NULL) + return E_POINTER; + *ppvObject = NULL; + + if (riid == __uuidof(IInstrumentationMethod)) + { + *ppvObject = this; + this->AddRef(); + return S_OK; + } + + *ppvObject = nullptr; + return E_NOINTERFACE; + } + + ULONG STDMETHODCALLTYPE AddRef(void) override + { + return std::atomic_fetch_add(&this->refCount, 1) + 1; + } + + ULONG STDMETHODCALLTYPE Release(void) override + { + int count = std::atomic_fetch_sub(&this->refCount, 1) - 1; + + if (count <= 0) + { + delete this; + } + + return count; + } +}; \ No newline at end of file diff --git a/src/LinuxProfiler/ProductionBreakpoints_x64.config b/src/LinuxProfiler/ProductionBreakpoints_x64.config new file mode 100644 index 00000000..27067b1d --- /dev/null +++ b/src/LinuxProfiler/ProductionBreakpoints_x64.config @@ -0,0 +1,9 @@ + + + Seafood Instrumentation + Dynamically make squids swim + libLinuxProfiler.so + {cf0d821e-299b-5307-a3d8-b283c03916dd} + 50 + + \ No newline at end of file diff --git a/src/LinuxProfiler/dllmain.cpp b/src/LinuxProfiler/dllmain.cpp new file mode 100644 index 00000000..e12dfee7 --- /dev/null +++ b/src/LinuxProfiler/dllmain.cpp @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#include "stdafx.h" +#include "refcount.h" +#include "CExtensionsHost.h" + +namespace ExtensionsHostCrossPlat +{ + + class CLinuxClassFactory : public IClassFactory, public CModuleRefCount + { + private: + + public: + DEFINE_DELEGATED_REFCOUNT_ADDREF(CLinuxClassFactory); + DEFINE_DELEGATED_REFCOUNT_RELEASE(CLinuxClassFactory); + STDMETHOD(STDMETHODCALLTYPE) QueryInterface(REFIID riid, PVOID *ppvObject) + { + HRESULT hr = E_NOINTERFACE; + + hr = ImplQueryInterface( + static_cast(this), + riid, ppvObject + ); + + return hr; + } + + // IClassFactory Methods + public: + STDMETHOD(CreateInstance)( + _In_ IUnknown *pUnkOuter, + _In_ REFIID riid, + _Out_ void **ppvObject + ) + { + HRESULT hr = S_OK; + + CComPtr pExtensionHost; + pExtensionHost.Attach(new CExtensionHost()); + + IfFailRet(pExtensionHost->QueryInterface(riid, ppvObject)); + + return S_OK; + } + + STDMETHOD(LockServer)( + _In_ BOOL fLock + ) + { + return S_OK; + } + }; +} + +extern "C" HRESULT __attribute__((visibility("default"))) DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID FAR* ppv) +{ + CComPtr pClassFactory; + pClassFactory.Attach(new ExtensionsHostCrossPlat::CLinuxClassFactory); + + if (pClassFactory != nullptr) + { + return pClassFactory->QueryInterface(riid, ppv); + } + + return E_NOINTERFACE; +} diff --git a/src/LinuxProfiler/linux-profiler.vcxproj b/src/LinuxProfiler/linux-profiler.vcxproj new file mode 100644 index 00000000..495ea0ed --- /dev/null +++ b/src/LinuxProfiler/linux-profiler.vcxproj @@ -0,0 +1,112 @@ + + + + + Debug + ARM + + + Release + ARM + + + Debug + ARM64 + + + Release + ARM64 + + + Debug + x86 + + + Release + x86 + + + Debug + x64 + + + Release + x64 + + + + {c10693ba-bb9b-4571-9340-defb48bc6428} + Linux + linux_profiler + 15.0 + Linux + 1.0 + Generic + {D51BCBC9-82E9-4017-911E-C93873C4EA2B} + + + + true + + + false + + + true + + + false + + + true + DynamicLibrary + + + false + + + false + + + true + + + + + + + + clang++ + clang++ + clang++ + + + + + + + + + + + + + + + + true + + + + + /home/maban/xplat/CLRInstrumentationEngine/src/unix/inc/atl;/home/maban/xplat/CLRInstrumentationEngine/src/InstrumentationEngine.Api;/home/maban/xplat/CLRInstrumentationEngine/src/unix/inc/winsdk;/home/maban/xplat/CLRInstrumentationEngine/src/unix/inc/empty;/home/maban/xplat/CLRInstrumentationEngine/src/unix/inc;/home/maban/coreclr/src/pal/prebuilt/inc;/home/maban/coreclr/src/pal/inc;/home/maban/coreclr/src/pal/inc/rt;/home/maban/coreclr/src/inc;%(AdditionalIncludeDirectories) + + %(CppAdditionalWarning)%(CppAdditionalWarning) + -W"no-invalid-noreturn" -fPIC -fms-extensions -DBIT64 -DPAL_STDCPP_COMPAT -DPLATFORM_UNIX -std=c++14 %(AdditionalOptions) + TurnOffAllWarnings + /home/maban/xplat/CLRInstrumentationEngine/src/unix/inc/atl/atldef.h;%(ForcedIncludeFiles) + + + + + \ No newline at end of file diff --git a/src/LinuxProfiler/profiler_pal.h b/src/LinuxProfiler/profiler_pal.h new file mode 100644 index 00000000..74e6ee37 --- /dev/null +++ b/src/LinuxProfiler/profiler_pal.h @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#pragma once + +#ifndef WIN32 +#include +#include "pal_mstypes.h" +#include "pal.h" +#include "ntimage.h" +#include "corhdr.h" + +#define CoTaskMemAlloc(cb) malloc(cb) +#define CoTaskMemFree(cb) free(cb) + +#define UINT_PTR_FORMAT "lx" + +#else +#define UINT_PTR_FORMAT "llx" +#endif \ No newline at end of file diff --git a/src/LinuxProfiler/refcount.cpp b/src/LinuxProfiler/refcount.cpp new file mode 100644 index 00000000..3c621b3f --- /dev/null +++ b/src/LinuxProfiler/refcount.cpp @@ -0,0 +1,248 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#include "stdafx.h" + +#include "refcount.h" +#include "intrin.h" + +// TODO: +// Clean this up. It was pulled from Debugger\inc and Debugger\common in order to get leak detection on +// ref counted objects. I didn't just use the compiled lib becase it isn't clear to me where this code +// is eventually going to live and if it turns out to be on a CDM server, the debugger lib won't exist. + +namespace ExtensionsHostCrossPlat +{ +#pragma intrinsic(_InterlockedOr) + +#ifdef _UNICODE +#define TRACE TRACEW +#else +#define TRACE TRACEA +#endif + + +#ifdef DEBUG + bool g_fDisplayTrace = true; + int g_TraceIndent = 0; + + #define TRACEA DisplayTraceA + #define TRACEW DisplayTraceW + + extern bool g_fDisplayTrace; + extern int g_TraceIndent; + + void _cdecl DisplayTraceA(LPCSTR pszFormat, ...); + void _cdecl DisplayTraceW(LPCWSTR pszFormat, ...); + void _cdecl IndentTrace(int indent); + +#else // !DEBUG + +#define TRACEA +#define TRACEW +#define IndentTrace + +#endif + +#ifdef DEBUG + void _cdecl IndentTrace(int indent) + { + g_TraceIndent += indent; + } + + void _cdecl DisplayTraceW(LPCWSTR pszFormat, ...) + { + if (g_fDisplayTrace) + { + WCHAR szTrace[1024]; + + int offset = 0; + + if (g_TraceIndent > 0) + { + offset = min(g_TraceIndent, (int)ARRAYSIZE(szTrace) - 1); + + for (int i = 0; i < offset; i++) + { + szTrace[i] = ' '; + } + } + + va_list marker; + va_start(marker, pszFormat); + _snwprintf_s(szTrace + offset, ARRAYSIZE(szTrace) - offset, _TRUNCATE, pszFormat, marker); + wcscat_s(szTrace, ARRAYSIZE(szTrace), _T("\r\n")); + OutputDebugStringW(szTrace); + } + } +#endif + + // ---------------------------------------------------------------------------- + // CRefRBMap +#ifdef DEBUG + class CRefRBMap : public ATL::CRBMap {}; +#endif + + // ---------------------------------------------------------------------------- + // CRefCount + +#ifdef DEBUG + DWORD CRefCount::g_dwRecorderOptions; //Recording is optional + bool CRefCount::g_fRecordingInitialized = false; + CRefRBMap CRefCount::g_map; + CRITICAL_SECTION CRefCount::g_crst; + + void CRefCount::InitRecorder(DWORD dwOptions) + { + //Add an environment variable hook to disable ref-recording, since this can sometimes be really slow. + if (GetEnvironmentVariable(_T("DisableRefRecording"), nullptr, 0) > 0) + { + dwOptions &= ~EnableRecorder; + } + + g_dwRecorderOptions = dwOptions; + if (g_dwRecorderOptions & EnableRecorder) + { + InitializeCriticalSection(&g_crst); + g_fRecordingInitialized = true; + } + } + + void CRefCount::TerminateRecorder(void) + { + if (g_fRecordingInitialized) + { + //VSASSERT(g_map.IsEmpty(), "Object recorder: Objects when the object recorder was terminated."); + + for (POSITION nextPosition = g_map.GetHeadPosition(); nextPosition != NULL;) + { + CRefRBMap::CPair* pPair = g_map.GetNext(nextPosition); + TRACE(_T("Object \"%s\" (%lxh) was leaked (%lu)."), pPair->m_key->m_pszCRefCountClassName, pPair->m_key, pPair->m_value); + } + + g_map.RemoveAll(); + + DeleteCriticalSection(&g_crst); + g_fRecordingInitialized = false; + } + } + + void CRefCount::RecordCreation(CRefCount* pCRefCount) + { + if (g_fRecordingInitialized) + { + EnterCriticalSection(&g_crst); + + CRefRBMap::CPair* pPair = g_map.Lookup(pCRefCount); + if (pPair) + { + //VSASSERT(false, "Object recorder: Object destroyed without the recorder being notified."); + TRACE(_T("Object \"%s\" (%lxh) destroyed without recorder being notified."), pCRefCount->m_pszCRefCountClassName, pCRefCount); + } + + g_map.SetAt(pCRefCount, 1); + + LeaveCriticalSection(&g_crst); + } + } + + void CRefCount::RecordDestruction(CRefCount* pCRefCount) + { + if (g_fRecordingInitialized) + { + EnterCriticalSection(&g_crst); + + bool fFound = g_map.RemoveKey(pCRefCount); + + //VSASSERT(fFound, "Object recorder: Object created without the recorder being notified."); + + LeaveCriticalSection(&g_crst); + } + } + + void CRefCount::RecordAddRef(CRefCount* pCRefCount) + { + if (g_fRecordingInitialized) + { + EnterCriticalSection(&g_crst); + + BOOL fFound = FALSE; + CRefRBMap::CPair* pPair = g_map.Lookup(pCRefCount); + if (pPair) + { + pPair->m_value++; + fFound = TRUE; + } + + //VSASSERT(fFound, "Object recorder: Object created without the recorder being notified."); + + LeaveCriticalSection(&g_crst); + } + } + + void CRefCount::RecordRelease(CRefCount* pCRefCount) + { + if (g_fRecordingInitialized) + { + EnterCriticalSection(&g_crst); + + BOOL fFound = FALSE; + CRefRBMap::CPair* pPair = g_map.Lookup(pCRefCount); + if (pPair) + { + pPair->m_value--; + + //VSASSERT(pPair->m_value != -1, "Object recorder: Object released too many times."); + + if (pPair->m_value == 0) + { + g_map.RemoveAt(pPair); + } + fFound = TRUE; + } + + //VSASSERT(fFound, "Object recorder: Object created without the recorder being notified."); + + LeaveCriticalSection(&g_crst); + } + } + + void CRefCount::DumpRefCount(void) + { + if (g_fRecordingInitialized) + { + EnterCriticalSection(&g_crst); + + if (!g_map.IsEmpty()) + { + TRACE(_T(">> Begin ref count dump. Leaked objects are also available in the watch window by evaluating g_map. <<")); + + for (POSITION nextPosition = g_map.GetHeadPosition(); nextPosition != NULL;) + { + CRefRBMap::CPair* pPair = g_map.GetNext(nextPosition); + TRACE(_T(">> Object \"%s\" (0x%p) contains ref-count 0x%lu."), pPair->m_key->m_pszCRefCountClassName, pPair->m_key, pPair->m_value); + } + + TRACE(_T(">> End ref count dump <<")); + } + + LeaveCriticalSection(&g_crst); + } + } + +#endif // DEBUG + + // ---------------------------------------------------------------------------- + // CModuleRefCount + + ULONG CModuleRefCount::s_ulcModuleRef = 0; + + // ---------------------------------------------------------------------------- + // module ref count support + + ULONG CModuleRefCount::GetModuleUsage(void) + { + return (ULONG)_InterlockedOr((PLONG)&s_ulcModuleRef, 0); + } + +} \ No newline at end of file diff --git a/src/LinuxProfiler/refcount.h b/src/LinuxProfiler/refcount.h new file mode 100644 index 00000000..e7255ce3 --- /dev/null +++ b/src/LinuxProfiler/refcount.h @@ -0,0 +1,204 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#pragma once + +#ifndef __REFCOUNT_H__ +#define __REFCOUNT_H__ + +namespace ExtensionsHostCrossPlat +{ + // ---------------------------------------------------------------------------- + // CRefCount macros + +#ifdef DEBUG + +#define INITIALIZE_REF_RECORDER(dwOptions) MicrosoftInstrumentationEngine::CRefCount::InitRecorder((dwOptions)) +#define TERMINATE_REF_RECORDER MicrosoftInstrumentationEngine::CRefCount::TerminateRecorder() + +#define DEFINE_REFCOUNT_NAME(cls) m_pszCRefCountClassName = (LPTSTR)_T(#cls) + +#define DUMP_REFCOUNT CRefCount::DumpRefCount() + +#else // !DEBUG + +#define INITIALIZE_REF_RECORDER(fOn) +#define TERMINATE_REF_RECORDER + +#define DEFINE_REFCOUNT_NAME(cls) + +#define DUMP_REFCOUNT + +#endif // DEBUG + + // ---------------------------------------------------------------------------- + // Define generic method delegation from a derived class to a base class. + // + // DEFINE_DELEGATED_METHOD(InprocServerClassFactory, ClassFactory, HRESULT, LockServer, (BOOL bLock), (bLock)); + // defines a delegated method call from InprocServerClassFactory::LockServer() to ClassFactory::LockServer(). + +#define DEFINE_DELEGATED_METHOD(base_cls, result_type, method, derived_paren_args, base_paren_args) \ + result_type STDMETHODCALLTYPE method derived_paren_args \ + { \ + return base_cls::method base_paren_args; \ +} + +#define DEFINE_DELEGATED_REFCOUNT_ADDREF(cls) \ + DEFINE_DELEGATED_METHOD(CRefCount, ULONG, AddRef, (void), ()) +#define DEFINE_DELEGATED_REFCOUNT_RELEASE(cls) \ + DEFINE_DELEGATED_METHOD(CRefCount, ULONG, Release, (void), ()) + +#define DEFINE_DELEGATED_REFCOUNT_ADDREF_DEBUG(cls) STDMETHOD_(ULONG, AddRef)() { ULONG result = CRefCount::AddRef(); VSASSERT(#cls); return result; } +#define DEFINE_DELEGATED_REFCOUNT_RELEASE_DEBUG(cls) STDMETHOD_(ULONG, Release)() { ULONG result = CRefCount::Release(); VSASSERT(#cls); return result; } + + // ---------------------------------------------------------------------------- + // CRefCount + + class CRefCount + { + // ctor/dtor + public: + CRefCount(void) + { + DEFINE_REFCOUNT_NAME(CRefCount); + + m_ulcRef = 1; + +#ifdef DEBUG + + RecordCreation(this); +#endif + + } + virtual ~CRefCount() + { +#ifdef DEBUG + + if (m_ulcRef > 0) + { + RecordDestruction(this); + } +#endif // DEBUG + + } + + // IUnknown methods + public: + STDMETHOD_(ULONG, AddRef)(void) + { + //VSASSERT(m_ulcRef < ULONG_MAX, L""); + + ULONG ulcRef = (ULONG)(InterlockedIncrement((LPLONG)(&m_ulcRef))); + +#ifdef DEBUG + + RecordAddRef(this); +#endif // DEBUG + + // Note: the return from InterlockedIncrement may only match the new value + // in signed-ness and zero-ness, but the return value of AddRef() + // is not guaranteed in any case. + + return ulcRef; + } + STDMETHOD_(ULONG, Release)(void) + { + //VSASSERT(m_ulcRef > 0, L""); + + ULONG ulcRef = (ULONG)(InterlockedDecrement((LPLONG)(&m_ulcRef))); + +#ifdef DEBUG + + RecordRelease(this); +#endif // DEBUG + + if (ulcRef == 0) + { + delete this; + } + + // Note: the return from InterlockedDecrement may only match the new value + // in signed-ness and zero-ness, but the return value of Release() + // is not guaranteed in any case. + + return ulcRef; + } + + // ref count + private: + ULONG m_ulcRef; + +#ifdef DEBUG + + // ------------------------------------------------------------ + // CRefCount recording stuff (for finding leaks) + // ------------------------------------------------------------ + + protected: + LPTSTR m_pszCRefCountClassName; + + private: + static DWORD g_dwRecorderOptions; // Recording is optional. + static bool g_fRecordingInitialized; + static class CRefRBMap g_map; + static CRITICAL_SECTION g_crst; + + static void RecordCreation(CRefCount *pCRefCount); + static void RecordDestruction(CRefCount *pCRefCount); + static void RecordAddRef(CRefCount *pCRefCount); + static void RecordRelease(CRefCount *pCRefCount); + public: + static void DumpRefCount(void); + + public: + enum RecorderOptions + { + EnableRecorder = 0x01, + }; + + static void InitRecorder(DWORD dwOptions); + static void TerminateRecorder(void); + +#endif // DEBUG + }; + + // ---------------------------------------------------------------------------- + // CModuleRefCount + + class CModuleRefCount : public CRefCount + { + // ctor/dtor + public: + CModuleRefCount(void) + { + IncModuleUsage(); + } + ~CModuleRefCount(void) + { + DecModuleUsage(); + } + + // module ref count support + public: + static ULONG IncModuleUsage(void) + { + //VSASSERT(s_ulcModuleRef < ULONG_MAX, L""); + + return (ULONG)InterlockedIncrement((PLONG)(&s_ulcModuleRef)); + } + static ULONG DecModuleUsage(void) + { + // This assert isn't thread-safe but its bug-catching ability is valuable + // enough to risk a few nuisance alerts. + //VSASSERT(s_ulcModuleRef > 0, L""); + ULONG ulcRef = InterlockedDecrement((PLONG)(&s_ulcModuleRef)); + + return ulcRef; + } + static ULONG GetModuleUsage(void); + private: + static ULONG s_ulcModuleRef; + }; +} + +#endif // ! __REFCOUNT_H__ diff --git a/src/LinuxProfiler/stdafx.cpp b/src/LinuxProfiler/stdafx.cpp new file mode 100644 index 00000000..c47d50c5 --- /dev/null +++ b/src/LinuxProfiler/stdafx.cpp @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#include "stdafx.h" diff --git a/src/LinuxProfiler/stdafx.h b/src/LinuxProfiler/stdafx.h new file mode 100644 index 00000000..9d620bad --- /dev/null +++ b/src/LinuxProfiler/stdafx.h @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#pragma once + +#ifdef PLATFORM_UNIX +#include "unix.h" +#include +#endif + +#include "targetver.h" +#ifndef PLATFORM_UNIX +#include +#endif +#include "string.h" +//#include + + +#include // for pfn_REPORTFAULT +#include + + +#include + +#include +#ifndef PLATFORM_UNIX +#include +#include +#include +#endif +#include +//#ifndef PLATFORM_UNIX +#include +//#endif +#include + +using namespace ATL; + +#include +#include +#include +#include "CorHeaders.h" +#include + +#include "Macros.h" + +#include +#include +#include + +#include "CriticalSectionHolder.h" + +using namespace std; + +#include "refcount.h" +#include "ImplQueryInterface.h" +#include "InstrumentationEngine.h" +#include "Logging.h" From 1007a5ae9d1024d51ab4c65f00221094222c041b Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Thu, 21 Feb 2019 20:47:54 +0530 Subject: [PATCH 02/92] Make profiler --- src/LinuxProfiler/CExtensionsHost.cpp | 70 ++------------------------- src/LinuxProfiler/CExtensionsHost.h | 33 ++++++++++--- 2 files changed, 30 insertions(+), 73 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 301aa440..4b1600e5 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -7,77 +7,13 @@ #include #include "CExtensionsHost.h" -// static -void ExtensionsHostCrossPlat::CExtensionHost::SetLoggingFlags(_In_ IProfilerManagerLogging* pLogger) -{ - WCHAR wszEnvVar[MAX_PATH]; - if (GetEnvironmentVariable(_T("MicrosoftInstrumentationEngine_FileLog"), wszEnvVar, MAX_PATH) > 0) - { - LoggingFlags loggingType = LoggingFlags_None; - if (PAL_wcsstr(wszEnvVar, _T("Errors")) != NULL) - { - loggingType = (LoggingFlags)(loggingType | LoggingFlags_Errors); - } - if (PAL_wcsstr(wszEnvVar, _T("Messages")) != NULL) - { - loggingType = (LoggingFlags)(loggingType | LoggingFlags_Trace); - } - if (PAL_wcsstr(wszEnvVar, _T("Dumps")) != NULL) - { - loggingType = (LoggingFlags)(loggingType | LoggingFlags_InstrumentationResults); - } - if (PAL_wcsstr(wszEnvVar, _T("All")) != NULL) - { - loggingType = (LoggingFlags)(LoggingFlags_Errors | LoggingFlags_Trace | LoggingFlags_InstrumentationResults); - } - - if (loggingType != LoggingFlags_None) - { - //Set to true to enable file level logging - pLogger->SetLoggingFlags(loggingType); - } - } -} HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( _In_ IProfilerManager* pProfilerManager ) { - HRESULT hr = S_OK; - usleep(10 * 1000 * 1000); - CComPtr pLogger; - IfFailRet(pProfilerManager->GetLoggingInstance(&pLogger)); - SetLoggingFlags(pLogger); - -#ifdef X86 - WCHAR wszHostPathVariableName[] = _T("MicrosoftInstrumentationEngine_HostPath_32"); -#else - WCHAR wszHostPathVariableName[] = _T("MicrosoftInstrumentationEngine_HostPath_64"); -#endif - - WCHAR wszProfilerPath[MAX_PATH]; - if (!GetEnvironmentVariable(wszHostPathVariableName, wszProfilerPath, MAX_PATH)) - { - return E_UNEXPECTED; - } - - WCHAR* pFileName = PathFindFileName(wszProfilerPath); - if (pFileName == wszProfilerPath) - { - return E_UNEXPECTED; - } - *pFileName = _T('\0'); - -#ifdef X86 - WCHAR wszConfigName[] = _T("ProductionBreakpoints_x86.config"); -#else - WCHAR wszConfigName[] = _T("ProductionBreakpoints_x64.config"); -#endif - - StringCchCatW(wszProfilerPath, MAX_PATH, wszConfigName); - - CComBSTR bstrConfigPath = wszProfilerPath; - IfFailRet(pProfilerManager->SetupProfilingEnvironment(&bstrConfigPath, 1)); - + CComPtr pCorProfilerInfo; + pProfilerManager->GetCorProfilerInfo((IUnknown**)&pCorProfilerInfo); + pCorProfilerInfo->SetEventMask(COR_PRF_MONITOR_EXCEPTIONS | COR_PRF_ENABLE_STACK_SNAPSHOT); return S_OK; } diff --git a/src/LinuxProfiler/CExtensionsHost.h b/src/LinuxProfiler/CExtensionsHost.h index cf38ab58..73fb775f 100644 --- a/src/LinuxProfiler/CExtensionsHost.h +++ b/src/LinuxProfiler/CExtensionsHost.h @@ -4,7 +4,7 @@ // CExtensionsHost.h : Declaration of the CExtensionHost #pragma once - +#include "stdafx.h" // {CA487940-57D2-10BF-11B2-A3AD5A13CBC0} const GUID CLSID_ExtensionHost = { 0xCA487940, 0x57D2, 0x10BF,{ 0x11, 0xB2, 0xA3, 0xAD, 0x5A, 0x13, 0xCB, 0xC0 } }; @@ -17,7 +17,7 @@ namespace ExtensionsHostCrossPlat // has been created to provide basic instrumentation engine host support for // production breakpoints. class ATL_NO_VTABLE CExtensionHost : - public IProfilerManagerHost, + public IInstrumentationMethod, public CModuleRefCount { public: @@ -38,7 +38,7 @@ namespace ExtensionsHostCrossPlat HRESULT hr = E_NOINTERFACE; hr = ImplQueryInterface( - static_cast(this), + static_cast(this), riid, ppvObject ); @@ -48,10 +48,31 @@ namespace ExtensionsHostCrossPlat // IProfilerManagerHost methods public: - STDMETHOD(Initialize)(_In_ IProfilerManager* pProfilerManager); + virtual HRESULT STDMETHODCALLTYPE Initialize(IProfilerManager* pProfilerManager); + + virtual HRESULT STDMETHODCALLTYPE OnAppDomainCreated(IAppDomainInfo *pAppDomainInfo) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnAppDomainShutdown(IAppDomainInfo *pAppDomainInfo) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnAssemblyLoaded(IAssemblyInfo* pAssemblyInfo) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnAssemblyUnloaded(IAssemblyInfo* pAssemblyInfo) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnModuleLoaded(IModuleInfo* pModuleInfo) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnModuleUnloaded(IModuleInfo* pModuleInfo) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnShutdown() { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE ShouldInstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit, BOOL* pbInstrument) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE BeforeInstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE InstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnInstrumentationComplete(IMethodInfo* pMethodInfo, BOOL isRejit) { return S_OK; } - private: - static void SetLoggingFlags(_In_ IProfilerManagerLogging* pLogger); + virtual HRESULT STDMETHODCALLTYPE AllowInlineSite(IMethodInfo* pMethodInfoInlinee, IMethodInfo* pMethodInfoCaller, BOOL* pbAllowInline) { return S_OK; } }; } \ No newline at end of file From 633e0ba17bfd46918b187bd62c6154102264349a Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Thu, 21 Feb 2019 20:53:45 +0530 Subject: [PATCH 03/92] update guid --- src/LinuxProfiler/ProductionBreakpoints_x64.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LinuxProfiler/ProductionBreakpoints_x64.config b/src/LinuxProfiler/ProductionBreakpoints_x64.config index 27067b1d..ea35b775 100644 --- a/src/LinuxProfiler/ProductionBreakpoints_x64.config +++ b/src/LinuxProfiler/ProductionBreakpoints_x64.config @@ -3,7 +3,7 @@ Seafood Instrumentation Dynamically make squids swim libLinuxProfiler.so - {cf0d821e-299b-5307-a3d8-b283c03916dd} + {CA487940-57D2-10BF-11B2-A3AD5A13CBC0} 50 \ No newline at end of file From 590f32c8925cd66202c55c8bb6e171e08c825911 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Fri, 22 Feb 2019 12:17:07 +0530 Subject: [PATCH 04/92] add managed functions/instructions --- src/LinuxProfiler/CExtensionsHost.cpp | 14 ++ src/LinuxProfiler/CExtensionsHost.h | 2 +- src/LinuxProfiler/CMakeLists.txt | 3 + src/LinuxProfiler/ILDisassembler.h | 92 ++++++++++ src/LinuxProfiler/VanguardInstrumentation.cpp | 169 ++++++++++++++++++ src/LinuxProfiler/VanguardInstrumentation.h | 48 +++++ src/LinuxProfiler/block.h | 100 +++++++++++ src/LinuxProfiler/managed_function.cpp | 161 +++++++++++++++++ src/LinuxProfiler/managed_function.h | 140 +++++++++++++++ src/LinuxProfiler/managed_instruction.cpp | 63 +++++++ src/LinuxProfiler/managed_instruction.h | 146 +++++++++++++++ 11 files changed, 937 insertions(+), 1 deletion(-) create mode 100644 src/LinuxProfiler/ILDisassembler.h create mode 100644 src/LinuxProfiler/VanguardInstrumentation.cpp create mode 100644 src/LinuxProfiler/VanguardInstrumentation.h create mode 100644 src/LinuxProfiler/block.h create mode 100644 src/LinuxProfiler/managed_function.cpp create mode 100644 src/LinuxProfiler/managed_function.h create mode 100644 src/LinuxProfiler/managed_instruction.cpp create mode 100644 src/LinuxProfiler/managed_instruction.h diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 4b1600e5..87598fc0 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -17,3 +17,17 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( pCorProfilerInfo->SetEventMask(COR_PRF_MONITOR_EXCEPTIONS | COR_PRF_ENABLE_STACK_SNAPSHOT); return S_OK; } + +HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pModuleInfo) +{ + HRESULT hr = S_OK; + + CComBSTR bstrModuleName; + IfFailRet(pModuleInfo->GetModuleName(&bstrModuleName)); + + CComBSTR bstrModulePath; + IfFailRet(pModuleInfo->GetFullPath(&bstrModulePath)); + + std::wstring path(bstrModulePath, SysStringLen(bstrModulePath)); + wstring pdbFile = path.substr(0, path.find_last_of(L'.')) + L".pdb"; +} diff --git a/src/LinuxProfiler/CExtensionsHost.h b/src/LinuxProfiler/CExtensionsHost.h index 73fb775f..8ae1f80e 100644 --- a/src/LinuxProfiler/CExtensionsHost.h +++ b/src/LinuxProfiler/CExtensionsHost.h @@ -58,7 +58,7 @@ namespace ExtensionsHostCrossPlat virtual HRESULT STDMETHODCALLTYPE OnAssemblyUnloaded(IAssemblyInfo* pAssemblyInfo) { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE OnModuleLoaded(IModuleInfo* pModuleInfo) { return S_OK; } + virtual HRESULT STDMETHODCALLTYPE OnModuleLoaded(IModuleInfo* pModuleInfo); virtual HRESULT STDMETHODCALLTYPE OnModuleUnloaded(IModuleInfo* pModuleInfo) { return S_OK; } diff --git a/src/LinuxProfiler/CMakeLists.txt b/src/LinuxProfiler/CMakeLists.txt index 92db01d5..9639c3b1 100644 --- a/src/LinuxProfiler/CMakeLists.txt +++ b/src/LinuxProfiler/CMakeLists.txt @@ -15,6 +15,9 @@ set(src_files ./CExtensionsHost.cpp ./refcount.cpp ./ImplQueryInterface.cpp + ./VanguardInstrumentation.cpp + ./managed_instruction.cpp + ./managed_function.cpp ) add_lib(${PROJECT_NAME} diff --git a/src/LinuxProfiler/ILDisassembler.h b/src/LinuxProfiler/ILDisassembler.h new file mode 100644 index 00000000..ec456673 --- /dev/null +++ b/src/LinuxProfiler/ILDisassembler.h @@ -0,0 +1,92 @@ +#pragma once + +#include "stdafx.h" +#include "managed_instruction.h" +#include "managed_function.h" +#include "VanguardInstrumentation.h" +#include + +using namespace vanguard::instrumentation::managed; + +struct il_disassembler +{ +public: + il_disassembler(IModuleInfo *pModuleInfo); + + virtual void disassemble_function(); + virtual void initialize_function(IMethodInfo *methodInfo) { _current_method_info = methodInfo; } + virtual size_t get_instructions(/* [out] */ instruction **&instructions); + virtual void cleanup_function(); + virtual bool instrument_function(size_t block_index); + + //virtual bool jit_instrument_function(std::vector& block_index, IMethodInfo* current_method_info, IExceptionSection &exceptions, mdMemberRef runtime_function_token, bool is_assembly_load = false, bool is_coreclr = false); + virtual module_info *get_module_info() { return _module_info; } + +private: + template + target_type lookup(source_type source, std::map &map, target_type default_value) + { + if (source && map.find(source) != map.end()) + { + return map.find(source)->second; + } + + return default_value; + } + + //void fixup_probes(std::map &fixup_map); + + DISCEE::TRMTA get_termination_type(IInstruction *il_inst) + { + ILOrdinalOpcode opcode; + il_inst->GetOpCode(&opcode); + if (opcode < 0) + { + return DISCEE::trmtaUnknown; + } + + switch (opcode) + { + case Cee_Break: + return DISCEE::trmtaTrap; + case Cee_Switch: + return DISCEE::trmtaBraSwitch; + case Cee_Ret: + case Cee_Endfinally: + case Cee_Endfilter: + return DISCEE::trmtaRet; + case Cee_Call: + case Cee_Jmp: + case Cee_Newobj: + return DISCEE::trmtaCall; + case Cee_Calli: + case Cee_Callvirt: + return DISCEE::trmtaCallInd; + case Cee_Br_S: + case Cee_Br: + case Cee_Leave: + case Cee_Leave_S: + return DISCEE::trmtaBra; + case Cee_Throw: + case Cee_Rethrow: + return DISCEE::trmtaBraInd; + } + + if (opcode >= Cee_Brfalse_S && opcode < Cee_Switch) + { + return DISCEE::trmtaBraCc; + } + + // For the rest (NEXT and META), they are fallthrough + return DISCEE::trmtaFallThrough; + } + + bool _use_verifiable_probe; + IMethodInfo *_current_method_info; + std::vector _instructions; + std::vector _il_instructions; + IExceptionSection *_current_exception_section; + module_info *_module_info; + //vanguard::instrumentation::managed::function* _current_function; + size_t _global_block_count; +}; \ No newline at end of file diff --git a/src/LinuxProfiler/VanguardInstrumentation.cpp b/src/LinuxProfiler/VanguardInstrumentation.cpp new file mode 100644 index 00000000..a3cf5f8f --- /dev/null +++ b/src/LinuxProfiler/VanguardInstrumentation.cpp @@ -0,0 +1,169 @@ +#include "stdafx.h" +#include "VanguardInstrumentation.h" +#include "ILDisassembler.h" + +using namespace vanguard::instrumentation::managed; + +bool module_info::contains_instrumented_method(mdToken token) +{ + return _instrumented_functions_list.find(token) != _instrumented_functions_list.end(); +} + +bool module_info::get_method_info(mdToken token, method_info& info) +{ + auto it = _instrumented_functions_list.find(token); + if (it != _instrumented_functions_list.end()) + { + info = it->second; + return true; + } + + return false; +} + + +il_disassembler::il_disassembler(IModuleInfo *pModuleInfo) +{ + _module_info = new module_info(pModuleInfo); +} + +void il_disassembler::disassemble_function() +{ + int index = 0; + map inst_dict; + + IInstructionGraph* instructionsGraph; + HRESULT hr = _current_method_info->GetInstructions(&instructionsGraph); + std::vector _il_instructions; + + if (hr == S_OK) + { + IInstruction* il_inst = NULL; + + HRESULT instructionData = instructionsGraph->GetFirstInstruction(&il_inst); + + DWORD pOffset; + DWORD pSize; + ILOrdinalOpcode pOpCode; + + il_inst->GetOffset(&pOffset); + il_inst->GetInstructionLength(&pSize); + il_inst->GetOpCode(&pOpCode); + + instruction *inst = new instruction((size_t)pOffset, (size_t)pSize, get_termination_type(il_inst), index++, pOpCode); + _il_instructions.push_back(il_inst); + _instructions.push_back(inst); + inst_dict.insert(std::pair(il_inst, inst)); + + while (instructionData == S_OK) + { + IInstruction* nextInstruction = NULL; + instructionData = il_inst->GetNextInstruction(&nextInstruction); + + if (instructionData != S_OK) + { + break; + } + + _il_instructions.push_back(nextInstruction); + + nextInstruction->GetOffset(&pOffset); + nextInstruction->GetInstructionLength(&pSize); + nextInstruction->GetOpCode(&pOpCode); + + inst = new instruction((size_t)pOffset, (size_t)pSize, get_termination_type(il_inst), index++, pOpCode); + _instructions.push_back(inst); + + il_inst = nextInstruction; + inst_dict.insert(std::pair(il_inst, inst)); + } + } + + // Set targets + for (size_t i = 0; i < _il_instructions.size(); i++) + { + BOOL isSwitch, isBranch; + _il_instructions[i]->GetIsSwitch(&isSwitch); + _il_instructions[i]->GetIsBranch(&isBranch); + + if (isSwitch) + { + ISwitchInstruction *il_switch; + _il_instructions[i]->QueryInterface(__uuidof(ISwitchInstruction), (LPVOID*)&il_switch); + + DWORD pBranchCount = 0; + il_switch->GetBranchCount(&pBranchCount); + + _instructions[i]->set_target_count(pBranchCount); + + for (ULONG j = 0; j < pBranchCount; j++) + { + IInstruction *pBranchTarget; + + il_switch->GetBranchTarget(j, &pBranchTarget); + _instructions[i]->get_targets()[j] = lookup(pBranchTarget, inst_dict, (instruction*)nullptr); + } + } + else if (isBranch) + { + IBranchInstruction *il_branch; + _il_instructions[i]->QueryInterface(__uuidof(IBranchInstruction), (LPVOID*)&il_branch); + instruction *target = nullptr; + IInstruction* pBranchTarget; + il_branch->GetBranchTarget(&pBranchTarget); + + if (target = lookup(pBranchTarget, inst_dict, target)) + { + _instructions[i]->set_target_count(1); + _instructions[i]->get_targets()[0] = target; + } + } + } + + /*for (auto clause = _current_exception_section->Clauses().GetFirst(); clause; clause = _current_exception_section->Clauses().GetNext(clause)) + { + _exception_clauses.push_back(exception_clause( + lookup(clause->_tryFirstInstruction, inst_dict, (instruction*)nullptr), + lookup(clause->_handlerFirstInstruction, inst_dict, (instruction*)nullptr), + lookup(clause->_filterFirstInstruction, inst_dict, (instruction*)nullptr))); + }*/ +} + +size_t il_disassembler::get_instructions(vanguard::instrumentation::managed::instruction **&instructions) +{ + instructions = _instructions.data(); + return _instructions.size(); +} + +bool il_disassembler::instrument_function(size_t block_index) +{ + mdToken methodToken; + _current_method_info->GetMethodToken(&methodToken); + method_info info(methodToken); + + /*for (auto block_it = _current_function->get_blocks(); block_it < _current_function->get_blocks() + _current_function->get_block_count(); ++block_it) + { + auto inst = block_it->get_instructions()[0]; + info.add_block_index(inst->get_index()); + } + + info.set_start_index(_global_block_count); + _module_info->add_instrumented_functions(info); + + _global_block_count += _current_function->get_block_count(); +*/ + return true; +} + +void il_disassembler::cleanup_function() +{ + for (auto it = _instructions.begin(); it != _instructions.end(); ++it) + { + delete *it; + } + + _instructions.clear(); + _il_instructions.clear(); + _current_method_info = nullptr; + _current_exception_section = nullptr; +} diff --git a/src/LinuxProfiler/VanguardInstrumentation.h b/src/LinuxProfiler/VanguardInstrumentation.h new file mode 100644 index 00000000..b611f280 --- /dev/null +++ b/src/LinuxProfiler/VanguardInstrumentation.h @@ -0,0 +1,48 @@ +#pragma once + +#include "stdafx.h" +#include "managed_instruction.h" +//#include "managed_function.h" +#include + +struct method_info +{ +public: + method_info() : _token(mdTokenNil), _start_block_index(0) {} + method_info(mdToken token) : _token(token), _start_block_index(0) {} + + ~method_info() { _block_indexes.clear(); } + + mdToken get_method_token() { return _token; } + + void set_start_index(size_t start_block_index) { _start_block_index = start_block_index; } + size_t get_start_index() { return _start_block_index; } + + void add_block_index(size_t block_index) { _block_indexes.push_back(block_index); } + std::vector get_block_indexes() { return _block_indexes; } + +private: + mdToken _token; + std::vector _block_indexes; /* indices where probes are to be added */ + size_t _start_block_index; +}; + +struct module_info +{ +public: + module_info(IModuleInfo* modInfo) : _current_module_info(modInfo) {} + ~module_info() { _instrumented_functions_list.clear(); } + + void add_instrumented_functions(method_info& method_info) { _instrumented_functions_list.insert(std::make_pair(method_info.get_method_token(), method_info)); } + + IModuleInfo *get_module() { return _current_module_info; } + + bool contains_instrumented_method(mdToken token); + bool get_method_info(mdToken token, method_info& method_info); + +private: + std::map _instrumented_functions_list; + IModuleInfo *_current_module_info; +}; + + diff --git a/src/LinuxProfiler/block.h b/src/LinuxProfiler/block.h new file mode 100644 index 00000000..21d2d437 --- /dev/null +++ b/src/LinuxProfiler/block.h @@ -0,0 +1,100 @@ +#pragma once + +#include "stdafx.h" + +namespace vanguard { + namespace instrumentation + { + //! Represents a basic block. + template + struct block + { + typedef instr_type instruction_type; + + //! Constructs a basic block given its starting address. + block(address_type address = 0) : + _address(address), + _size(0), + _is_prolog_block(false), + _instructions(nullptr), + _instruction_count(0), + _is_catch_block(false) + { + } + + //! Move constructor for basic block. + block(block&& other) + { + *this = std::move(other); + } + + //! Destructor + ~block() + { + if (_instructions) delete[] _instructions; + } + + //! Move assignment operator for basic block. + block& operator=(block&& other) + { + _address = other._address; + _size = other._size; + _instructions = other._instructions; + _instruction_count = other._instruction_count; + other._instructions = nullptr; + _is_prolog_block = other._is_prolog_block; + _is_catch_block = other._is_catch_block; + return *this; + } + + //! Gets the starting address of the basic block. + address_type get_address() const { return _address; } + + //! Gets the size of the basic block. + size_t get_size() const { return _size; } + + //! Sets the size of the basic block. + void set_size(size_t size) { _size = size; } + + //! Gets whether or not the block is the prolog block (only applies to x64). + bool is_prolog() const { return _is_prolog_block; } + + // Return true if block is catch handler + bool is_catch_block() const { return _is_catch_block; } + + //! Sets whether or not the block is the prolog block (only applies to x64). + void set_prolog(bool value) { _is_prolog_block = value; } + + // Sets whether or not block is of catch handler type + void set_catch_block(bool value) { _is_catch_block = value; } + + //! Gets the instructions that are part of the basic block. + instruction_type* get_instructions() { return _instructions; } + + //! Gets the instructions that are part of the basic block. + instruction_type* const get_instructions() const { return _instructions; } + + //! Gets instruction count. + size_t get_instruction_count() const { return _instruction_count; } + + //! Sets instruction count. + void set_instruction_count(size_t count) + { + if (_instructions) delete[] _instructions; + _instructions = new instruction_type[_instruction_count = count]; + } + + private: + //! Block does not implement correct copy constructor/operator, make them private. + block(const block&); + const block& operator=(const block&); + + address_type _address; + size_t _size; + instruction_type* _instructions; + size_t _instruction_count; + bool _is_prolog_block; + bool _is_catch_block; + }; + } +} \ No newline at end of file diff --git a/src/LinuxProfiler/managed_function.cpp b/src/LinuxProfiler/managed_function.cpp new file mode 100644 index 00000000..d89c6db8 --- /dev/null +++ b/src/LinuxProfiler/managed_function.cpp @@ -0,0 +1,161 @@ +#include "stdafx.h" +#include "managed_function.h" + +using namespace std; + +namespace vanguard { + namespace instrumentation { + namespace managed + { + //! Constructs a function given the symbol and metadata. + function::function() : + _id(INVALID_ID), + _rva(0), + _address(nullptr), + _token(0), + _type_token(0), + _size(0), + _name(nullptr), + _type_name(nullptr), + _namespace_name(nullptr), + _source_file(nullptr), + _blocks(nullptr), + _block_count(0) + { + } + + //! Disassembles the function and populates the list of blocks; a nop if the function has already been disassembled. + void function::calculate_blocks(il_disassembler& disassembler) + { + // If we've already disassembled or cannot disassemble, do nothing + // In case of Assembly.Load/AssemblyLoadContext.LoadFromStream, we want to instrument, even if there are no symbols + if (_blocks || (!has_symbolic_information() && !_is_assembly_load)) + return; + + instruction* last_inst = nullptr; + instruction** instructions; + size_t count = disassembler.get_instructions(/* [out] */ instructions); + for (auto it = instructions; it < instructions + count; last_inst = *it, it++) + { + //1.The tail prefix instruction must immediately precede a Call, Calli, or Callvirt instruction + //2.The instruction following the call instruction must be a ret. + //so we cannot put a probe after the call instrution as it will make IL invalid, we wait till we pass the ret instruction. + //Bug 167554:Tests pass in regular runs, but fail in coverage run + if ((*it)->get_opcode() == ILOrdinalOpcode::Cee_Tailcall) + { + it++; + while (!(*it)->is_return()) + { + it++; + } + } + else + { + // 1. Mark instructions whose previous instructions are not fallthrough as start of a block + if (!last_inst || !last_inst->is_fall_through()) + { + (*it)->set_starts_block(true); + // For Assembly.Load / AssemblyLoadContext.LoadFromStream, we need to instrument the function start + // i.e., the first block + if (_is_assembly_load) + { + break; + } + } + + // 2. Mark the targets of branches as start of a block + if ((*it)->is_direct_branch() || (*it)->is_indirect_branch()) + { + for (auto target_it = (*it)->get_targets(); target_it < (*it)->get_targets() + (*it)->get_target_count(); ++target_it) + { + (*target_it)->set_starts_block(true); + } + } + } + } + + // Process the instruction map into blocks + process_blocks(disassembler); + } + + void function::process_blocks(il_disassembler& disassembler) + { + // If there we no instructions, it's invalid + instruction** instructions; + size_t inst_count = disassembler.get_instructions(/* [out] */ instructions); + if (inst_count == 0) + { + throw new exception(); + } + + //// First, mark any instructions referenced from the exception causes as starting blocks + //exception_clause* exception_clauses; + //size_t clause_count = 0; // disassembler.get_exception_clauses(/* [out] */ exception_clauses); + //for (auto clause = exception_clauses; clause < exception_clauses + clause_count; clause++) + //{ + // if (clause->get_try_instruction()) + // { + // clause->get_try_instruction()->set_starts_block(true); + // } + // if (clause->get_handler_instruction()) + // { + // clause->get_handler_instruction()->set_starts_block(true); + // } + // if (clause->get_filter_instruction()) + // { + // clause->get_filter_instruction()->set_starts_block(true); + // } + //} + + // Copy the instructions and count the number of blocks + vector blocks; + block_type* current_block = nullptr; + vector current_instructions; + size_t block_size = 0; + for (auto it = instructions; it < instructions + inst_count; ++it) + { + instruction* instr = *it; + + // If we're starting a new block + if (instr->get_starts_block()) + { + if (current_block) + { + size_t blockInstructionCount = current_instructions.size(); + // Set the block size for the block we're finishing + current_block->set_size(block_size); + current_block->set_instruction_count(blockInstructionCount); + for (size_t i = 0; i < blockInstructionCount; i++) + current_block->get_instructions()[i] = current_instructions[i]; + } + + // Insert a new code block. + blocks.push_back(block_type(instr->get_offset())); + current_block = &blocks.back(); + block_size = 0; + current_instructions.clear(); + } + + // Push the instruction into the current block + if (current_block) + { + block_size += instr->get_size(); + current_instructions.push_back(instr); + } + } + + if (current_block) + { + current_block->set_size(block_size); + current_block->set_instruction_count(current_instructions.size()); + for (size_t i = 0; i < current_instructions.size(); i++) + current_block->get_instructions()[i] = current_instructions[i]; + } + + _blocks = new block_type[_block_count = blocks.size()]; + for (size_t i = 0; i < _block_count; i++) + _blocks[i] = std::move(blocks[i]); + } + } + } +} diff --git a/src/LinuxProfiler/managed_function.h b/src/LinuxProfiler/managed_function.h new file mode 100644 index 00000000..bfb0bf0f --- /dev/null +++ b/src/LinuxProfiler/managed_function.h @@ -0,0 +1,140 @@ +#pragma once + +#include "stdafx.h" +#include "block.h" +#include "managed_instruction.h" +#include +#include "ILDisassembler.h" + +struct il_disassembler; + +namespace vanguard { + namespace instrumentation { + namespace managed + { + //! Represents a managed function. + struct function + { + static const DWORD INVALID_ID = 0xFFFFFFFF; + typedef block block_type; + + function(); + + //! Move constructor for function. + function(function&& other) + { + *this = std::move(other); + } + + //! Destructor + ~function() + { + if (_blocks) delete[] _blocks; + } + + //! Move assignment operator for function. + function& operator=(function&& other) + { + _id = other._id; + _rva = other._rva; + _token = other._token; + _type_token = other._type_token; + _address = other._address; + _blocks = other._blocks; + _block_count = other._block_count; + other._blocks = nullptr; + _size = other._size; + _is_assembly_load = other._is_assembly_load; + return *this; + } + + //! Analyze the blocks inside the function. + void calculate_blocks(il_disassembler& disassembler); + + //! Determines if there is enough symbolic information to instrument this function. + bool has_symbolic_information() const + { + return + _id != -1 && + _rva != 0 && + _token != 0 && + _address && + wcslen(_name) > 0 && + wcslen(_source_file) > 0; + } + + //! Gets the function's identifier. + uint32_t get_id() const { return _id; } + + //! Gets the function's RVA. + uint32_t get_rva() const { return _rva; } + + //! Gets the function's metadata token. + uint32_t get_token() const { return _token; } + + //! Gets the function's type's metadata token. + uint32_t get_type_token() const { return _type_token; } + + //! Get tokens of property this method is associated with. Usually there are zero or one such properties + const std::vector& get_property_tokens() const { return _property_tokens; } + + //! Gets the function's address. + _Ret_notnull_ void const* get_address() const { return _address; } + + //! Gets the function's size in bytes. + size_t get_size() const { return _size; } + + //! Sets the function's size in bytes. + void set_size(size_t size) { _size = size; } + + //! Gets the function's name. + const wchar_t* get_name() const { return _name; } + + //! Gets the function's type name. + const wchar_t* get_type_name() const { return _type_name; } + + //! Gets the function's namespace name. + const wchar_t* get_namespace_name() const { return _namespace_name; } + + //! Gets the function's source file. + const wchar_t* get_source_file() const { return _source_file; } + + //! Gets the blocks of the function. + //! Disassemble must be called before this list will be populated. + block_type* const get_blocks() const { return _blocks; } + + //! Gets the block count. + size_t get_block_count() const { return _block_count; } + + static const std::wstring separator; + + protected: + //! Constructs a function given the symbol and metadata. + + const wchar_t* _name; + const wchar_t* _type_name; + const wchar_t* _namespace_name; + const wchar_t* _source_file; + + private: + //! Function does not implement correct copy constructor/operator, make them private. + function(const function&); + const function& operator=(const function&); + + void process_blocks(il_disassembler& disassembler); + + uint32_t _id; + uint32_t _rva; + uint32_t _token; + uint32_t _type_token; + std::vector _property_tokens; + void const* _address; + block_type* _blocks; + size_t _block_count; + size_t _size; + + bool _is_assembly_load; + }; + } + } +} \ No newline at end of file diff --git a/src/LinuxProfiler/managed_instruction.cpp b/src/LinuxProfiler/managed_instruction.cpp new file mode 100644 index 00000000..86b028d1 --- /dev/null +++ b/src/LinuxProfiler/managed_instruction.cpp @@ -0,0 +1,63 @@ +#include "stdafx.h" +#include "managed_instruction.h" + +namespace vanguard { + namespace instrumentation { + namespace managed + { + //! Gets whether or not the instruction's termination type is a direct branch. + bool instruction::is_direct_branch() const + { + return _termination == DISCEE::trmtaBra || is_conditional_branch(); // In IL, all conditional branches are direct + } + + //! Gets whether or not the instruction's termination type is a conditional branch. + bool instruction::is_conditional_branch() const + { + return _termination == DISCEE::trmtaBraCc || is_switch(); // Switches are also conditional + } + + //! Gets whether or not the instruction's termination type is an indirect branch. + bool instruction::is_indirect_branch() const + { + return _termination == DISCEE::trmtaBraInd; + } + + //! Gets whether or not the instruction's termination type is a indirect call. + bool instruction::is_indirect_call() const + { + return _termination == DISCEE::trmtaCallInd; + } + + //! Gets whether or not the instruction's termination type is a direct call. + bool instruction::is_direct_call() const + { + return _termination == DISCEE::trmtaCall; + } + + //! Gets whether or not the instruction's termination type is a return. + bool instruction::is_return() const + { + return _termination == DISCEE::trmtaRet; + } + + //! Gets whether or not the instruction's termination type is falling through to the next instruction. + bool instruction::is_fall_through() const + { + return _termination == DISCEE::trmtaFallThrough; + } + + //! Gets whether or not the instruction's termination type is a trap instruction (break). + bool instruction::is_trap() const + { + return _termination == DISCEE::trmtaTrap; + } + + //! Gets whether or not the instruction's termination type is a switch. + bool instruction::is_switch() const + { + return _termination == DISCEE::trmtaBraSwitch; + } + } + } +} \ No newline at end of file diff --git a/src/LinuxProfiler/managed_instruction.h b/src/LinuxProfiler/managed_instruction.h new file mode 100644 index 00000000..8f16a0d2 --- /dev/null +++ b/src/LinuxProfiler/managed_instruction.h @@ -0,0 +1,146 @@ +#pragma once +#include "stdafx.h" + +namespace DISCEE +{ + enum TRMTA + { + trmtaTrap, + trmtaBraSwitch, + trmtaRet, + trmtaCall, + trmtaCallInd, + trmtaBra, + trmtaBraInd, + trmtaBraCc, + trmtaFallThrough, + trmtaUnknown + }; +}; + +namespace vanguard { + namespace instrumentation { + namespace managed { + + //! Represents environment independent instruction + struct instruction + { + //! Constructor + instruction(size_t offset, size_t instruction_size, DISCEE::TRMTA termination, size_t index, ILOrdinalOpcode opcode) : + _offset(offset), + _instruction_size(instruction_size), + _starts_block(false), + _termination(termination), + _index(index), + _targets(nullptr), + _target_count(0), + _opcode(opcode) + { + } + + //! Move constructor for instruction. + instruction(instruction&& other) + { + *this = std::move(other); + } + + //! Destructor + ~instruction() + { + if (_targets) delete[] _targets; + } + + //! Move assignment operator for instruction. + instruction& operator=(instruction&& other) + { + _termination = other._termination; + _starts_block = other._starts_block; + _index = other._index; + _offset = other._offset; + _instruction_size = other._instruction_size; + _targets = other._targets; + _target_count = other._target_count; + _opcode = other._opcode; + other._targets = nullptr; + + return *this; + } + + //! Gets whether or not this instruction is the start of a basic block. + bool get_starts_block() const { return _starts_block; } + + //! Sets whether or not this instruction is the start of a basic block. + void set_starts_block(bool value) { _starts_block = value; } + + //! Gets whether or not the instruction's termination type is a direct branch. + bool is_direct_branch() const; + + //! Gets whether or not the instruction's termination type is a conditional branch. + bool is_conditional_branch() const; + + //! Gets whether or not the instruction's termination type is an indirect branch. + bool is_indirect_branch() const; + + //! Gets whether or not the instruction's termination type is a indirect call. + bool is_indirect_call() const; + + //! Gets whether or not the instruction's termination type is a direct call. + bool is_direct_call() const; + + //! Gets whether or not the instruction's termination type is a return. + bool is_return() const; + + //! Gets whether or not the instruction's termination type is falling through to the next instruction. + bool is_fall_through() const; + + //! Gets whether or not the instruction's termination type is a trap instruction (break). + bool is_trap() const; + + //! Gets whether or not the instruction's termination type is a switch. + bool is_switch() const; + + //! Gets the index of the instruction (unique in its containing function) + size_t get_index() const { return _index; } + + //! Gets the targets of the instruction. + instruction** get_targets() { return _targets; } + + //! Gets the targets of the instruction. + instruction** const get_targets() const { return _targets; } + + //! Gets the target count. + size_t get_target_count() const { return _target_count; } + + //! Sets the target count. + void set_target_count(size_t count) + { + if (_targets) delete[] _targets; + _targets = new instruction*[_target_count = count]; + } + + //! Gets the instruction's offset relative to the start of the function. + size_t get_offset() const { return _offset; } + + //! Gets the size of the instruction in bytes. + size_t get_size() const { return _instruction_size; } + + ILOrdinalOpcode get_opcode() const { return _opcode; } + + private: + //! Instruction does not implement correct copy constructor/operator, make them private. + instruction(const instruction&); + const instruction& operator=(const instruction&); + + bool _starts_block; + DISCEE::TRMTA _termination; + ILOrdinalOpcode _opcode; + size_t _index; + size_t _offset; + instruction** _targets; + size_t _target_count; + size_t _instruction_size; + + }; + } + } +} \ No newline at end of file From a0d2809849d699dc430159932b3b3e1b1d088538 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Fri, 22 Feb 2019 12:21:11 +0530 Subject: [PATCH 05/92] errors --- src/LinuxProfiler/CExtensionsHost.cpp | 4 ++-- src/LinuxProfiler/VanguardInstrumentation.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 87598fc0..baeb37e9 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -28,6 +28,6 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo CComBSTR bstrModulePath; IfFailRet(pModuleInfo->GetFullPath(&bstrModulePath)); - std::wstring path(bstrModulePath, SysStringLen(bstrModulePath)); - wstring pdbFile = path.substr(0, path.find_last_of(L'.')) + L".pdb"; + /*std::wstring path(bstrModulePath, SysStringLen(bstrModulePath)); + wstring pdbFile = path.substr(0, path.find_last_of(L'.')) + L".pdb";*/ } diff --git a/src/LinuxProfiler/VanguardInstrumentation.cpp b/src/LinuxProfiler/VanguardInstrumentation.cpp index a3cf5f8f..fab09405 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.cpp +++ b/src/LinuxProfiler/VanguardInstrumentation.cpp @@ -112,7 +112,7 @@ void il_disassembler::disassemble_function() IInstruction* pBranchTarget; il_branch->GetBranchTarget(&pBranchTarget); - if (target = lookup(pBranchTarget, inst_dict, target)) + if (target == lookup(pBranchTarget, inst_dict, target)) { _instructions[i]->set_target_count(1); _instructions[i]->get_targets()[0] = target; From 6300fb1b5a7dc5d1b8ed3ba0ae2023c64e3cc58b Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Fri, 22 Feb 2019 12:22:15 +0530 Subject: [PATCH 06/92] minor --- src/LinuxProfiler/CExtensionsHost.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index baeb37e9..cbf658a8 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -30,4 +30,6 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo /*std::wstring path(bstrModulePath, SysStringLen(bstrModulePath)); wstring pdbFile = path.substr(0, path.find_last_of(L'.')) + L".pdb";*/ + + return hr; } From de693fe3943d1aef848fdcb9506edb2d543d1dd9 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Fri, 22 Feb 2019 12:24:20 +0530 Subject: [PATCH 07/92] auto(not supported) --- src/LinuxProfiler/VanguardInstrumentation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/LinuxProfiler/VanguardInstrumentation.cpp b/src/LinuxProfiler/VanguardInstrumentation.cpp index fab09405..87581ecb 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.cpp +++ b/src/LinuxProfiler/VanguardInstrumentation.cpp @@ -129,7 +129,7 @@ void il_disassembler::disassemble_function() }*/ } -size_t il_disassembler::get_instructions(vanguard::instrumentation::managed::instruction **&instructions) +size_t il_disassembler::get_instructions(instruction **&instructions) { instructions = _instructions.data(); return _instructions.size(); @@ -157,7 +157,7 @@ bool il_disassembler::instrument_function(size_t block_index) void il_disassembler::cleanup_function() { - for (auto it = _instructions.begin(); it != _instructions.end(); ++it) + for (instruction* it = _instructions.begin(); it != _instructions.end(); ++it) { delete *it; } From de265c9a8f239fbae4fb08b2e333fa21fcdfbab9 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Fri, 22 Feb 2019 12:27:39 +0530 Subject: [PATCH 08/92] use iterator --- src/LinuxProfiler/VanguardInstrumentation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LinuxProfiler/VanguardInstrumentation.cpp b/src/LinuxProfiler/VanguardInstrumentation.cpp index 87581ecb..1530de8e 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.cpp +++ b/src/LinuxProfiler/VanguardInstrumentation.cpp @@ -157,7 +157,7 @@ bool il_disassembler::instrument_function(size_t block_index) void il_disassembler::cleanup_function() { - for (instruction* it = _instructions.begin(); it != _instructions.end(); ++it) + for (vector::iterator it = _instructions.begin(); it != _instructions.end(); ++it) { delete *it; } From 40a852817f4dddbc17b6c97f0476db0b5fc62011 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Fri, 22 Feb 2019 12:35:26 +0530 Subject: [PATCH 09/92] fix auto debug info generation --- src/CMakeLists.txt | 2 +- src/LinuxProfiler/VanguardInstrumentation.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 040c87cf..2fb1b7e9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,7 +64,7 @@ macro (build_init build_language build_type) add_compile_options(-fdelayed-template-parsing) add_compile_options(-fdiagnostics-show-category=name) add_compile_options(-std=c++14) - add_compile_options(-g) + add_compile_options(-ggdb) add_compile_options(-pthread) add_compile_options(-ferror-limit=1000) endif ("${build_language}" STREQUAL CPP) diff --git a/src/LinuxProfiler/VanguardInstrumentation.cpp b/src/LinuxProfiler/VanguardInstrumentation.cpp index 1530de8e..fab09405 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.cpp +++ b/src/LinuxProfiler/VanguardInstrumentation.cpp @@ -129,7 +129,7 @@ void il_disassembler::disassemble_function() }*/ } -size_t il_disassembler::get_instructions(instruction **&instructions) +size_t il_disassembler::get_instructions(vanguard::instrumentation::managed::instruction **&instructions) { instructions = _instructions.data(); return _instructions.size(); @@ -157,7 +157,7 @@ bool il_disassembler::instrument_function(size_t block_index) void il_disassembler::cleanup_function() { - for (vector::iterator it = _instructions.begin(); it != _instructions.end(); ++it) + for (auto it = _instructions.begin(); it != _instructions.end(); ++it) { delete *it; } From 4f5cec30916a8d92d186f0f3d482d84bd4d348e1 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Fri, 22 Feb 2019 12:37:51 +0530 Subject: [PATCH 10/92] remove -g flag --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2fb1b7e9..3f9fe9b7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,7 +64,7 @@ macro (build_init build_language build_type) add_compile_options(-fdelayed-template-parsing) add_compile_options(-fdiagnostics-show-category=name) add_compile_options(-std=c++14) - add_compile_options(-ggdb) + #add_compile_options(-g) add_compile_options(-pthread) add_compile_options(-ferror-limit=1000) endif ("${build_language}" STREQUAL CPP) From 20c44e1e672c106d3ee55dbcde67987ddda050ec Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Fri, 22 Feb 2019 12:52:45 +0530 Subject: [PATCH 11/92] square 1 --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3f9fe9b7..040c87cf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,7 +64,7 @@ macro (build_init build_language build_type) add_compile_options(-fdelayed-template-parsing) add_compile_options(-fdiagnostics-show-category=name) add_compile_options(-std=c++14) - #add_compile_options(-g) + add_compile_options(-g) add_compile_options(-pthread) add_compile_options(-ferror-limit=1000) endif ("${build_language}" STREQUAL CPP) From 375e10bda45ed3f728b35566fc02a6d88e6e9a0f Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Fri, 22 Feb 2019 13:02:10 +0530 Subject: [PATCH 12/92] clang 3.7 --- src/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/build.sh b/src/build.sh index 361fbaf5..d23c3e79 100644 --- a/src/build.sh +++ b/src/build.sh @@ -391,7 +391,7 @@ __MSBCleanBuildArgs= __CleanBuild=false __VerboseBuild=false __ClangMajorVersion=3 -__ClangMinorVersion=5 +__ClangMinorVersion=7 __NuGetConfigPath="$EnlistmentRoot/src/unix/dependencies/nuget.config" # Package name is used in file system and "dotnet restore" will restore packages using lowercase characters in the filesystem. __CoreCLRPALPackageId="microsoft.visualstudio.debugger.coreclrpal" From 7704ed3dad206f38ce589028cf81e473363c0231 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Fri, 22 Feb 2019 13:40:34 +0530 Subject: [PATCH 13/92] revert --- src/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/build.sh b/src/build.sh index d23c3e79..361fbaf5 100644 --- a/src/build.sh +++ b/src/build.sh @@ -391,7 +391,7 @@ __MSBCleanBuildArgs= __CleanBuild=false __VerboseBuild=false __ClangMajorVersion=3 -__ClangMinorVersion=7 +__ClangMinorVersion=5 __NuGetConfigPath="$EnlistmentRoot/src/unix/dependencies/nuget.config" # Package name is used in file system and "dotnet restore" will restore packages using lowercase characters in the filesystem. __CoreCLRPALPackageId="microsoft.visualstudio.debugger.coreclrpal" From be09f7063975b6061e4d76cdff288ff7b7afded8 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Fri, 22 Feb 2019 14:17:35 +0530 Subject: [PATCH 14/92] fix auto --- src/LinuxProfiler/InstrumentationMethod.cpp | 13 -- src/LinuxProfiler/InstrumentationMethod.h | 113 ------------------ src/LinuxProfiler/VanguardInstrumentation.cpp | 4 +- src/LinuxProfiler/managed_function.cpp | 6 +- 4 files changed, 5 insertions(+), 131 deletions(-) delete mode 100644 src/LinuxProfiler/InstrumentationMethod.cpp delete mode 100644 src/LinuxProfiler/InstrumentationMethod.h diff --git a/src/LinuxProfiler/InstrumentationMethod.cpp b/src/LinuxProfiler/InstrumentationMethod.cpp deleted file mode 100644 index 5e99c849..00000000 --- a/src/LinuxProfiler/InstrumentationMethod.cpp +++ /dev/null @@ -1,13 +0,0 @@ -//// Copyright (c) Microsoft Corporation. All rights reserved. -//// -// -//#include "InstrumentationMethod.h" -// -//HRESULT CInstrumentationMethod::Initialize(IProfilerManager* pProfilerManager) -//{ -// CComPtr pCorProfilerInfo; -// pProfilerManager->GetCorProfilerInfo((IUnknown**)&pCorProfilerInfo); -// pCorProfilerInfo->SetEventMask(COR_PRF_MONITOR_EXCEPTIONS | COR_PRF_ENABLE_STACK_SNAPSHOT); -// -// return S_OK; -//} \ No newline at end of file diff --git a/src/LinuxProfiler/InstrumentationMethod.h b/src/LinuxProfiler/InstrumentationMethod.h deleted file mode 100644 index e4dd854f..00000000 --- a/src/LinuxProfiler/InstrumentationMethod.h +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// - -#pragma once -#include "stdafx.h" - -class CInstrumentationMethod : public IInstrumentationMethod -{ -private: - std::atomic refCount; - -public: - CInstrumentationMethod() - { - } - - virtual ~CInstrumentationMethod() - { - - } - - virtual HRESULT STDMETHODCALLTYPE Initialize(IProfilerManager* pProfilerManager) - { - CComPtr pCorProfilerInfo; - pProfilerManager->GetCorProfilerInfo((IUnknown**)&pCorProfilerInfo); - pCorProfilerInfo->SetEventMask(COR_PRF_MONITOR_EXCEPTIONS | COR_PRF_ENABLE_STACK_SNAPSHOT); - return S_OK; - } - - virtual HRESULT STDMETHODCALLTYPE OnAppDomainCreated(IAppDomainInfo *pAppDomainInfo) { return S_OK; } - - virtual HRESULT STDMETHODCALLTYPE OnAppDomainShutdown(IAppDomainInfo *pAppDomainInfo) { return S_OK; } - - virtual HRESULT STDMETHODCALLTYPE OnAssemblyLoaded(IAssemblyInfo* pAssemblyInfo) { return S_OK; } - - virtual HRESULT STDMETHODCALLTYPE OnAssemblyUnloaded(IAssemblyInfo* pAssemblyInfo) { return S_OK; } - - virtual HRESULT STDMETHODCALLTYPE OnModuleLoaded(IModuleInfo* pModuleInfo) - { - HRESULT hr = S_OK; - - char16_t* bstrModuleName; - IfFailRet(pModuleInfo->GetModuleName(&bstrModuleName)); - - char16_t* bstrModulePath; - IfFailRet(pModuleInfo->GetFullPath(&bstrModulePath)); - - /*std::wstring path(bstrModulePath, SysStringLen(bstrModulePath)); - wstring pdbFile = path.substr(0, path.find_last_of(L'.')) + L".pdb";*/ - - /*FILE *file; - _wfopen_s(&file, pdbFile.c_str(), L"r"); - - if (file == NULL) - { - return S_OK; - } - else - { - fclose(file); - }*/ - - return S_OK; - } - - virtual HRESULT STDMETHODCALLTYPE OnModuleUnloaded(IModuleInfo* pModuleInfo) { return S_OK; } - - virtual HRESULT STDMETHODCALLTYPE OnShutdown() { return S_OK; } - - virtual HRESULT STDMETHODCALLTYPE ShouldInstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit, BOOL* pbInstrument) { return S_OK; } - - virtual HRESULT STDMETHODCALLTYPE BeforeInstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit) { return S_OK; } - - virtual HRESULT STDMETHODCALLTYPE InstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit) { return S_OK; } - - virtual HRESULT STDMETHODCALLTYPE OnInstrumentationComplete(IMethodInfo* pMethodInfo, BOOL isRejit) { return S_OK; } - - virtual HRESULT STDMETHODCALLTYPE AllowInlineSite(IMethodInfo* pMethodInfoInlinee, IMethodInfo* pMethodInfoCaller, BOOL* pbAllowInline) { return S_OK; } - - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) override - { - if (ppvObject == NULL) - return E_POINTER; - *ppvObject = NULL; - - if (riid == __uuidof(IInstrumentationMethod)) - { - *ppvObject = this; - this->AddRef(); - return S_OK; - } - - *ppvObject = nullptr; - return E_NOINTERFACE; - } - - ULONG STDMETHODCALLTYPE AddRef(void) override - { - return std::atomic_fetch_add(&this->refCount, 1) + 1; - } - - ULONG STDMETHODCALLTYPE Release(void) override - { - int count = std::atomic_fetch_sub(&this->refCount, 1) - 1; - - if (count <= 0) - { - delete this; - } - - return count; - } -}; \ No newline at end of file diff --git a/src/LinuxProfiler/VanguardInstrumentation.cpp b/src/LinuxProfiler/VanguardInstrumentation.cpp index fab09405..0fcfab5a 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.cpp +++ b/src/LinuxProfiler/VanguardInstrumentation.cpp @@ -11,7 +11,7 @@ bool module_info::contains_instrumented_method(mdToken token) bool module_info::get_method_info(mdToken token, method_info& info) { - auto it = _instrumented_functions_list.find(token); + map::iterator it = _instrumented_functions_list.find(token); if (it != _instrumented_functions_list.end()) { info = it->second; @@ -157,7 +157,7 @@ bool il_disassembler::instrument_function(size_t block_index) void il_disassembler::cleanup_function() { - for (auto it = _instructions.begin(); it != _instructions.end(); ++it) + for (vector::iterator it = _instructions.begin(); it != _instructions.end(); ++it) { delete *it; } diff --git a/src/LinuxProfiler/managed_function.cpp b/src/LinuxProfiler/managed_function.cpp index d89c6db8..9118d89c 100644 --- a/src/LinuxProfiler/managed_function.cpp +++ b/src/LinuxProfiler/managed_function.cpp @@ -35,7 +35,7 @@ namespace vanguard { instruction* last_inst = nullptr; instruction** instructions; size_t count = disassembler.get_instructions(/* [out] */ instructions); - for (auto it = instructions; it < instructions + count; last_inst = *it, it++) + for (instruction** it = instructions; it < instructions + count; last_inst = *it, it++) { //1.The tail prefix instruction must immediately precede a Call, Calli, or Callvirt instruction //2.The instruction following the call instruction must be a ret. @@ -66,7 +66,7 @@ namespace vanguard { // 2. Mark the targets of branches as start of a block if ((*it)->is_direct_branch() || (*it)->is_indirect_branch()) { - for (auto target_it = (*it)->get_targets(); target_it < (*it)->get_targets() + (*it)->get_target_count(); ++target_it) + for (instruction** target_it = (*it)->get_targets(); target_it < (*it)->get_targets() + (*it)->get_target_count(); ++target_it) { (*target_it)->set_starts_block(true); } @@ -112,7 +112,7 @@ namespace vanguard { block_type* current_block = nullptr; vector current_instructions; size_t block_size = 0; - for (auto it = instructions; it < instructions + inst_count; ++it) + for (instruction** it = instructions; it < instructions + inst_count; ++it) { instruction* instr = *it; From cdf2f2cce0845eb59cecdb49305031e10fce9841 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sun, 24 Feb 2019 20:10:39 +0530 Subject: [PATCH 15/92] please compile --- src/LinuxProfiler/ILDisassembler.h | 2 +- src/LinuxProfiler/VanguardInstrumentation.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/LinuxProfiler/ILDisassembler.h b/src/LinuxProfiler/ILDisassembler.h index ec456673..58995f6b 100644 --- a/src/LinuxProfiler/ILDisassembler.h +++ b/src/LinuxProfiler/ILDisassembler.h @@ -85,7 +85,7 @@ struct il_disassembler IMethodInfo *_current_method_info; std::vector _instructions; std::vector _il_instructions; - IExceptionSection *_current_exception_section; + //IExceptionSection *_current_exception_section; module_info *_module_info; //vanguard::instrumentation::managed::function* _current_function; size_t _global_block_count; diff --git a/src/LinuxProfiler/VanguardInstrumentation.cpp b/src/LinuxProfiler/VanguardInstrumentation.cpp index 0fcfab5a..9fddea2f 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.cpp +++ b/src/LinuxProfiler/VanguardInstrumentation.cpp @@ -165,5 +165,5 @@ void il_disassembler::cleanup_function() _instructions.clear(); _il_instructions.clear(); _current_method_info = nullptr; - _current_exception_section = nullptr; + //_current_exception_section = nullptr; } From c78c6fdd96e1f0677ebcd2f11aa6b650415fdc83 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 2 Mar 2019 12:51:16 +0530 Subject: [PATCH 16/92] separate disassembler --- src/LinuxProfiler/ILDisassembler.cpp | 118 ++++++++++++++ src/LinuxProfiler/ILDisassembler.h | 7 +- src/LinuxProfiler/VanguardInstrumentation.cpp | 150 +----------------- 3 files changed, 120 insertions(+), 155 deletions(-) create mode 100644 src/LinuxProfiler/ILDisassembler.cpp diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp new file mode 100644 index 00000000..1bb2de50 --- /dev/null +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -0,0 +1,118 @@ +#include "stdafx.h" +#include "ILDisassembler.h" + +using namespace vanguard::instrumentation::managed; + + +il_disassembler::il_disassembler(IModuleInfo *pModuleInfo) +{ + _module_info = new module_info(pModuleInfo); +} + +void il_disassembler::disassemble_function() +{ + int index = 0; + map inst_dict; + + IInstructionGraph* instructionsGraph; + HRESULT hr = _current_method_info->GetInstructions(&instructionsGraph); + std::vector _il_instructions; + + if (hr == S_OK) + { + IInstruction* il_inst = NULL; + + HRESULT instructionData = instructionsGraph->GetFirstInstruction(&il_inst); + + DWORD pOffset; + DWORD pSize; + ILOrdinalOpcode pOpCode; + + il_inst->GetOffset(&pOffset); + il_inst->GetInstructionLength(&pSize); + il_inst->GetOpCode(&pOpCode); + + instruction *inst = new instruction((size_t)pOffset, (size_t)pSize, get_termination_type(il_inst), index++, pOpCode); + _il_instructions.push_back(il_inst); + _instructions.push_back(inst); + inst_dict.insert(std::pair(il_inst, inst)); + + while (instructionData == S_OK) + { + IInstruction* nextInstruction = NULL; + instructionData = il_inst->GetNextInstruction(&nextInstruction); + + if (instructionData != S_OK) + { + break; + } + + _il_instructions.push_back(nextInstruction); + + nextInstruction->GetOffset(&pOffset); + nextInstruction->GetInstructionLength(&pSize); + nextInstruction->GetOpCode(&pOpCode); + + inst = new instruction((size_t)pOffset, (size_t)pSize, get_termination_type(il_inst), index++, pOpCode); + _instructions.push_back(inst); + + il_inst = nextInstruction; + inst_dict.insert(std::pair(il_inst, inst)); + } + } + + // Set targets + for (size_t i = 0; i < _il_instructions.size(); i++) + { + BOOL isSwitch, isBranch; + _il_instructions[i]->GetIsSwitch(&isSwitch); + _il_instructions[i]->GetIsBranch(&isBranch); + + if (isSwitch) + { + ISwitchInstruction *il_switch; + _il_instructions[i]->QueryInterface(__uuidof(ISwitchInstruction), (LPVOID*)&il_switch); + + DWORD pBranchCount = 0; + il_switch->GetBranchCount(&pBranchCount); + + _instructions[i]->set_target_count(pBranchCount); + + for (ULONG j = 0; j < pBranchCount; j++) + { + IInstruction *pBranchTarget; + + il_switch->GetBranchTarget(j, &pBranchTarget); + _instructions[i]->get_targets()[j] = lookup(pBranchTarget, inst_dict, (instruction*)nullptr); + } + } + else if (isBranch) + { + IBranchInstruction *il_branch; + _il_instructions[i]->QueryInterface(__uuidof(IBranchInstruction), (LPVOID*)&il_branch); + instruction *target = nullptr; + IInstruction* pBranchTarget; + il_branch->GetBranchTarget(&pBranchTarget); + + if (target == lookup(pBranchTarget, inst_dict, target)) + { + _instructions[i]->set_target_count(1); + _instructions[i]->get_targets()[0] = target; + } + } + } +} + +size_t il_disassembler::get_instructions(vanguard::instrumentation::managed::instruction **&instructions) +{ + instructions = _instructions.data(); + return _instructions.size(); +} + +bool il_disassembler::instrument_function(size_t block_index) +{ + mdToken methodToken; + _current_method_info->GetMethodToken(&methodToken); + method_info info(methodToken); + return true; +} diff --git a/src/LinuxProfiler/ILDisassembler.h b/src/LinuxProfiler/ILDisassembler.h index 58995f6b..f6aac95e 100644 --- a/src/LinuxProfiler/ILDisassembler.h +++ b/src/LinuxProfiler/ILDisassembler.h @@ -16,10 +16,9 @@ struct il_disassembler virtual void disassemble_function(); virtual void initialize_function(IMethodInfo *methodInfo) { _current_method_info = methodInfo; } virtual size_t get_instructions(/* [out] */ instruction **&instructions); - virtual void cleanup_function(); + virtual void cleanup_function() {} virtual bool instrument_function(size_t block_index); - //virtual bool jit_instrument_function(std::vector& block_index, IMethodInfo* current_method_info, IExceptionSection &exceptions, mdMemberRef runtime_function_token, bool is_assembly_load = false, bool is_coreclr = false); virtual module_info *get_module_info() { return _module_info; } private: @@ -34,8 +33,6 @@ struct il_disassembler return default_value; } - //void fixup_probes(std::map &fixup_map); - DISCEE::TRMTA get_termination_type(IInstruction *il_inst) { ILOrdinalOpcode opcode; @@ -85,8 +82,6 @@ struct il_disassembler IMethodInfo *_current_method_info; std::vector _instructions; std::vector _il_instructions; - //IExceptionSection *_current_exception_section; module_info *_module_info; - //vanguard::instrumentation::managed::function* _current_function; size_t _global_block_count; }; \ No newline at end of file diff --git a/src/LinuxProfiler/VanguardInstrumentation.cpp b/src/LinuxProfiler/VanguardInstrumentation.cpp index 9fddea2f..172628f4 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.cpp +++ b/src/LinuxProfiler/VanguardInstrumentation.cpp @@ -1,6 +1,5 @@ #include "stdafx.h" #include "VanguardInstrumentation.h" -#include "ILDisassembler.h" using namespace vanguard::instrumentation::managed; @@ -19,151 +18,4 @@ bool module_info::get_method_info(mdToken token, method_info& info) } return false; -} - - -il_disassembler::il_disassembler(IModuleInfo *pModuleInfo) -{ - _module_info = new module_info(pModuleInfo); -} - -void il_disassembler::disassemble_function() -{ - int index = 0; - map inst_dict; - - IInstructionGraph* instructionsGraph; - HRESULT hr = _current_method_info->GetInstructions(&instructionsGraph); - std::vector _il_instructions; - - if (hr == S_OK) - { - IInstruction* il_inst = NULL; - - HRESULT instructionData = instructionsGraph->GetFirstInstruction(&il_inst); - - DWORD pOffset; - DWORD pSize; - ILOrdinalOpcode pOpCode; - - il_inst->GetOffset(&pOffset); - il_inst->GetInstructionLength(&pSize); - il_inst->GetOpCode(&pOpCode); - - instruction *inst = new instruction((size_t)pOffset, (size_t)pSize, get_termination_type(il_inst), index++, pOpCode); - _il_instructions.push_back(il_inst); - _instructions.push_back(inst); - inst_dict.insert(std::pair(il_inst, inst)); - - while (instructionData == S_OK) - { - IInstruction* nextInstruction = NULL; - instructionData = il_inst->GetNextInstruction(&nextInstruction); - - if (instructionData != S_OK) - { - break; - } - - _il_instructions.push_back(nextInstruction); - - nextInstruction->GetOffset(&pOffset); - nextInstruction->GetInstructionLength(&pSize); - nextInstruction->GetOpCode(&pOpCode); - - inst = new instruction((size_t)pOffset, (size_t)pSize, get_termination_type(il_inst), index++, pOpCode); - _instructions.push_back(inst); - - il_inst = nextInstruction; - inst_dict.insert(std::pair(il_inst, inst)); - } - } - - // Set targets - for (size_t i = 0; i < _il_instructions.size(); i++) - { - BOOL isSwitch, isBranch; - _il_instructions[i]->GetIsSwitch(&isSwitch); - _il_instructions[i]->GetIsBranch(&isBranch); - - if (isSwitch) - { - ISwitchInstruction *il_switch; - _il_instructions[i]->QueryInterface(__uuidof(ISwitchInstruction), (LPVOID*)&il_switch); - - DWORD pBranchCount = 0; - il_switch->GetBranchCount(&pBranchCount); - - _instructions[i]->set_target_count(pBranchCount); - - for (ULONG j = 0; j < pBranchCount; j++) - { - IInstruction *pBranchTarget; - - il_switch->GetBranchTarget(j, &pBranchTarget); - _instructions[i]->get_targets()[j] = lookup(pBranchTarget, inst_dict, (instruction*)nullptr); - } - } - else if (isBranch) - { - IBranchInstruction *il_branch; - _il_instructions[i]->QueryInterface(__uuidof(IBranchInstruction), (LPVOID*)&il_branch); - instruction *target = nullptr; - IInstruction* pBranchTarget; - il_branch->GetBranchTarget(&pBranchTarget); - - if (target == lookup(pBranchTarget, inst_dict, target)) - { - _instructions[i]->set_target_count(1); - _instructions[i]->get_targets()[0] = target; - } - } - } - - /*for (auto clause = _current_exception_section->Clauses().GetFirst(); clause; clause = _current_exception_section->Clauses().GetNext(clause)) - { - _exception_clauses.push_back(exception_clause( - lookup(clause->_tryFirstInstruction, inst_dict, (instruction*)nullptr), - lookup(clause->_handlerFirstInstruction, inst_dict, (instruction*)nullptr), - lookup(clause->_filterFirstInstruction, inst_dict, (instruction*)nullptr))); - }*/ -} - -size_t il_disassembler::get_instructions(vanguard::instrumentation::managed::instruction **&instructions) -{ - instructions = _instructions.data(); - return _instructions.size(); -} - -bool il_disassembler::instrument_function(size_t block_index) -{ - mdToken methodToken; - _current_method_info->GetMethodToken(&methodToken); - method_info info(methodToken); - - /*for (auto block_it = _current_function->get_blocks(); block_it < _current_function->get_blocks() + _current_function->get_block_count(); ++block_it) - { - auto inst = block_it->get_instructions()[0]; - info.add_block_index(inst->get_index()); - } - - info.set_start_index(_global_block_count); - _module_info->add_instrumented_functions(info); - - _global_block_count += _current_function->get_block_count(); -*/ - return true; -} - -void il_disassembler::cleanup_function() -{ - for (vector::iterator it = _instructions.begin(); it != _instructions.end(); ++it) - { - delete *it; - } - - _instructions.clear(); - _il_instructions.clear(); - _current_method_info = nullptr; - //_current_exception_section = nullptr; -} +} \ No newline at end of file From f9e04ff3f7d7e106f79a5507c47be03b15bc1e3b Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 2 Mar 2019 12:55:46 +0530 Subject: [PATCH 17/92] fix --- src/LinuxProfiler/VanguardInstrumentation.cpp | 32 +++++++++---------- src/LinuxProfiler/VanguardInstrumentation.h | 4 +-- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/LinuxProfiler/VanguardInstrumentation.cpp b/src/LinuxProfiler/VanguardInstrumentation.cpp index 172628f4..70c79ef1 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.cpp +++ b/src/LinuxProfiler/VanguardInstrumentation.cpp @@ -3,19 +3,19 @@ using namespace vanguard::instrumentation::managed; -bool module_info::contains_instrumented_method(mdToken token) -{ - return _instrumented_functions_list.find(token) != _instrumented_functions_list.end(); -} - -bool module_info::get_method_info(mdToken token, method_info& info) -{ - map::iterator it = _instrumented_functions_list.find(token); - if (it != _instrumented_functions_list.end()) - { - info = it->second; - return true; - } - - return false; -} \ No newline at end of file +//bool module_info::contains_instrumented_method(mdToken token) +//{ +// return _instrumented_functions_list.find(token) != _instrumented_functions_list.end(); +//} +// +//bool module_info::get_method_info(mdToken token, method_info& info) +//{ +// map::iterator it = _instrumented_functions_list.find(token); +// if (it != _instrumented_functions_list.end()) +// { +// info = it->second; +// return true; +// } +// +// return false; +//} \ No newline at end of file diff --git a/src/LinuxProfiler/VanguardInstrumentation.h b/src/LinuxProfiler/VanguardInstrumentation.h index b611f280..70b1a685 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.h +++ b/src/LinuxProfiler/VanguardInstrumentation.h @@ -37,8 +37,8 @@ struct module_info IModuleInfo *get_module() { return _current_module_info; } - bool contains_instrumented_method(mdToken token); - bool get_method_info(mdToken token, method_info& method_info); + bool contains_instrumented_method(mdToken token) { return false; } + bool get_method_info(mdToken token, method_info& method_info) { return false; } private: std::map _instrumented_functions_list; From 1642579d5ea124e2255ec5294b08887e06753de3 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 2 Mar 2019 12:58:07 +0530 Subject: [PATCH 18/92] narrow --- src/LinuxProfiler/VanguardInstrumentation.cpp | 24 +++++++++---------- src/LinuxProfiler/VanguardInstrumentation.h | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/LinuxProfiler/VanguardInstrumentation.cpp b/src/LinuxProfiler/VanguardInstrumentation.cpp index 70c79ef1..4c3ee22f 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.cpp +++ b/src/LinuxProfiler/VanguardInstrumentation.cpp @@ -7,15 +7,15 @@ using namespace vanguard::instrumentation::managed; //{ // return _instrumented_functions_list.find(token) != _instrumented_functions_list.end(); //} -// -//bool module_info::get_method_info(mdToken token, method_info& info) -//{ -// map::iterator it = _instrumented_functions_list.find(token); -// if (it != _instrumented_functions_list.end()) -// { -// info = it->second; -// return true; -// } -// -// return false; -//} \ No newline at end of file + +bool module_info::get_method_info(mdToken token, method_info& info) +{ + map::iterator it = _instrumented_functions_list.find(token); + if (it != _instrumented_functions_list.end()) + { + info = it->second; + return true; + } + + return false; +} \ No newline at end of file diff --git a/src/LinuxProfiler/VanguardInstrumentation.h b/src/LinuxProfiler/VanguardInstrumentation.h index 70b1a685..6c446513 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.h +++ b/src/LinuxProfiler/VanguardInstrumentation.h @@ -38,7 +38,7 @@ struct module_info IModuleInfo *get_module() { return _current_module_info; } bool contains_instrumented_method(mdToken token) { return false; } - bool get_method_info(mdToken token, method_info& method_info) { return false; } + bool get_method_info(mdToken token, method_info& method_info); private: std::map _instrumented_functions_list; From 7b5ec14732b88468957d5e819babf214b2fdd84b Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 2 Mar 2019 13:00:05 +0530 Subject: [PATCH 19/92] fix --- src/LinuxProfiler/VanguardInstrumentation.cpp | 28 +++++++++---------- src/LinuxProfiler/VanguardInstrumentation.h | 4 +-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/LinuxProfiler/VanguardInstrumentation.cpp b/src/LinuxProfiler/VanguardInstrumentation.cpp index 4c3ee22f..627c0064 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.cpp +++ b/src/LinuxProfiler/VanguardInstrumentation.cpp @@ -3,19 +3,19 @@ using namespace vanguard::instrumentation::managed; -//bool module_info::contains_instrumented_method(mdToken token) -//{ -// return _instrumented_functions_list.find(token) != _instrumented_functions_list.end(); -//} - -bool module_info::get_method_info(mdToken token, method_info& info) +bool module_info::contains_instrumented_method(mdToken token) { - map::iterator it = _instrumented_functions_list.find(token); - if (it != _instrumented_functions_list.end()) - { - info = it->second; - return true; - } + return _instrumented_functions_list.find(token) != _instrumented_functions_list.end(); +} - return false; -} \ No newline at end of file +//bool module_info::get_method_info(mdToken token, method_info& info) +//{ +// map::iterator it = _instrumented_functions_list.find(token); +// if (it != _instrumented_functions_list.end()) +// { +// info = it->second; +// return true; +// } +// +// return false; +//} \ No newline at end of file diff --git a/src/LinuxProfiler/VanguardInstrumentation.h b/src/LinuxProfiler/VanguardInstrumentation.h index 6c446513..4179ddf8 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.h +++ b/src/LinuxProfiler/VanguardInstrumentation.h @@ -37,8 +37,8 @@ struct module_info IModuleInfo *get_module() { return _current_module_info; } - bool contains_instrumented_method(mdToken token) { return false; } - bool get_method_info(mdToken token, method_info& method_info); + bool contains_instrumented_method(mdToken token); + bool get_method_info(mdToken token, method_info& method_info) { return false; } private: std::map _instrumented_functions_list; From 15f40a982c3392e7e006162d77fe4d212a73ab82 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 2 Mar 2019 13:03:31 +0530 Subject: [PATCH 20/92] move map to header --- src/LinuxProfiler/VanguardInstrumentation.cpp | 10 +++++----- src/LinuxProfiler/VanguardInstrumentation.h | 17 +++++++++++++++-- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/LinuxProfiler/VanguardInstrumentation.cpp b/src/LinuxProfiler/VanguardInstrumentation.cpp index 627c0064..70c79ef1 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.cpp +++ b/src/LinuxProfiler/VanguardInstrumentation.cpp @@ -3,11 +3,11 @@ using namespace vanguard::instrumentation::managed; -bool module_info::contains_instrumented_method(mdToken token) -{ - return _instrumented_functions_list.find(token) != _instrumented_functions_list.end(); -} - +//bool module_info::contains_instrumented_method(mdToken token) +//{ +// return _instrumented_functions_list.find(token) != _instrumented_functions_list.end(); +//} +// //bool module_info::get_method_info(mdToken token, method_info& info) //{ // map::iterator it = _instrumented_functions_list.find(token); diff --git a/src/LinuxProfiler/VanguardInstrumentation.h b/src/LinuxProfiler/VanguardInstrumentation.h index 4179ddf8..6b3e4827 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.h +++ b/src/LinuxProfiler/VanguardInstrumentation.h @@ -37,8 +37,21 @@ struct module_info IModuleInfo *get_module() { return _current_module_info; } - bool contains_instrumented_method(mdToken token); - bool get_method_info(mdToken token, method_info& method_info) { return false; } + bool contains_instrumented_method(mdToken token) + { + return _instrumented_functions_list.find(token) != _instrumented_functions_list.end(); + } + bool get_method_info(mdToken token, method_info& method_info) + { + map::iterator it = _instrumented_functions_list.find(token); + if (it != _instrumented_functions_list.end()) + { + info = it->second; + return true; + } + + return false; + } private: std::map _instrumented_functions_list; From 4ae13933a76053c3fabb1e138e65a840311b9b54 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 2 Mar 2019 13:05:59 +0530 Subject: [PATCH 21/92] error --- src/LinuxProfiler/VanguardInstrumentation.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/LinuxProfiler/VanguardInstrumentation.h b/src/LinuxProfiler/VanguardInstrumentation.h index 6b3e4827..43fc7581 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.h +++ b/src/LinuxProfiler/VanguardInstrumentation.h @@ -41,7 +41,8 @@ struct module_info { return _instrumented_functions_list.find(token) != _instrumented_functions_list.end(); } - bool get_method_info(mdToken token, method_info& method_info) + + bool get_method_info(mdToken token, method_info& info) { map::iterator it = _instrumented_functions_list.find(token); if (it != _instrumented_functions_list.end()) From 8c02537f15525029f37790ca779267828d5443dc Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 2 Mar 2019 13:07:59 +0530 Subject: [PATCH 22/92] compile disassembler --- src/LinuxProfiler/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/LinuxProfiler/CMakeLists.txt b/src/LinuxProfiler/CMakeLists.txt index 9639c3b1..1bf8c4f2 100644 --- a/src/LinuxProfiler/CMakeLists.txt +++ b/src/LinuxProfiler/CMakeLists.txt @@ -18,6 +18,7 @@ set(src_files ./VanguardInstrumentation.cpp ./managed_instruction.cpp ./managed_function.cpp + ./ILDisassembler.cpp ) add_lib(${PROJECT_NAME} From ab6dadd31a1d88ffc0bdbf2937e5c435e9e06756 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 2 Mar 2019 18:28:28 +0530 Subject: [PATCH 23/92] unordered_map --- src/LinuxProfiler/ILDisassembler.cpp | 2 +- src/LinuxProfiler/ILDisassembler.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp index 1bb2de50..d2e8f7bd 100644 --- a/src/LinuxProfiler/ILDisassembler.cpp +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -12,7 +12,7 @@ il_disassembler::il_disassembler(IModuleInfo *pModuleInfo) void il_disassembler::disassemble_function() { int index = 0; - map inst_dict; + unordered_map inst_dict; IInstructionGraph* instructionsGraph; HRESULT hr = _current_method_info->GetInstructions(&instructionsGraph); diff --git a/src/LinuxProfiler/ILDisassembler.h b/src/LinuxProfiler/ILDisassembler.h index f6aac95e..c631ab53 100644 --- a/src/LinuxProfiler/ILDisassembler.h +++ b/src/LinuxProfiler/ILDisassembler.h @@ -4,7 +4,7 @@ #include "managed_instruction.h" #include "managed_function.h" #include "VanguardInstrumentation.h" -#include +#include using namespace vanguard::instrumentation::managed; @@ -23,7 +23,7 @@ struct il_disassembler private: template - target_type lookup(source_type source, std::map &map, target_type default_value) + target_type lookup(source_type source, std::unordered_map &map, target_type default_value) { if (source && map.find(source) != map.end()) { From f3795754f8f9c811749fd429d87b11a5e0e7973a Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 2 Mar 2019 18:33:48 +0530 Subject: [PATCH 24/92] remove map --- src/ExtensionsHostCrossPlat/CExtensionsHost.cpp | 4 ++-- src/LinuxProfiler/ILDisassembler.cpp | 12 ++++++------ src/LinuxProfiler/ILDisassembler.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ExtensionsHostCrossPlat/CExtensionsHost.cpp b/src/ExtensionsHostCrossPlat/CExtensionsHost.cpp index 8f9e2ff3..301aa440 100644 --- a/src/ExtensionsHostCrossPlat/CExtensionsHost.cpp +++ b/src/ExtensionsHostCrossPlat/CExtensionsHost.cpp @@ -4,7 +4,7 @@ // CExtensionsHost.cpp : Implementation of CExtensionHost #include "stdafx.h" - +#include #include "CExtensionsHost.h" // static @@ -44,7 +44,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( ) { HRESULT hr = S_OK; - + usleep(10 * 1000 * 1000); CComPtr pLogger; IfFailRet(pProfilerManager->GetLoggingInstance(&pLogger)); SetLoggingFlags(pLogger); diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp index d2e8f7bd..62eb3d47 100644 --- a/src/LinuxProfiler/ILDisassembler.cpp +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -12,7 +12,7 @@ il_disassembler::il_disassembler(IModuleInfo *pModuleInfo) void il_disassembler::disassemble_function() { int index = 0; - unordered_map inst_dict; + //unordered_map inst_dict; IInstructionGraph* instructionsGraph; HRESULT hr = _current_method_info->GetInstructions(&instructionsGraph); @@ -35,7 +35,7 @@ void il_disassembler::disassemble_function() instruction *inst = new instruction((size_t)pOffset, (size_t)pSize, get_termination_type(il_inst), index++, pOpCode); _il_instructions.push_back(il_inst); _instructions.push_back(inst); - inst_dict.insert(std::pair(il_inst, inst)); + //inst_dict.insert(std::pair(il_inst, inst)); while (instructionData == S_OK) { @@ -57,7 +57,7 @@ void il_disassembler::disassemble_function() _instructions.push_back(inst); il_inst = nextInstruction; - inst_dict.insert(std::pair(il_inst, inst)); + //inst_dict.insert(std::pair(il_inst, inst)); } } @@ -83,7 +83,7 @@ void il_disassembler::disassemble_function() IInstruction *pBranchTarget; il_switch->GetBranchTarget(j, &pBranchTarget); - _instructions[i]->get_targets()[j] = lookup(pBranchTarget, inst_dict, (instruction*)nullptr); + //_instructions[i]->get_targets()[j] = lookup(pBranchTarget, inst_dict, (instruction*)nullptr); } } else if (isBranch) @@ -94,11 +94,11 @@ void il_disassembler::disassemble_function() IInstruction* pBranchTarget; il_branch->GetBranchTarget(&pBranchTarget); - if (target == lookup(pBranchTarget, inst_dict, target)) + /*if (target == lookup(pBranchTarget, inst_dict, target)) { _instructions[i]->set_target_count(1); _instructions[i]->get_targets()[0] = target; - } + }*/ } } } diff --git a/src/LinuxProfiler/ILDisassembler.h b/src/LinuxProfiler/ILDisassembler.h index c631ab53..1e222ece 100644 --- a/src/LinuxProfiler/ILDisassembler.h +++ b/src/LinuxProfiler/ILDisassembler.h @@ -4,9 +4,9 @@ #include "managed_instruction.h" #include "managed_function.h" #include "VanguardInstrumentation.h" -#include using namespace vanguard::instrumentation::managed; +using namespace ATL; struct il_disassembler { From 4d3347c7fc499fa97cbc3efbd59aa44edf44351e Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 2 Mar 2019 18:56:04 +0530 Subject: [PATCH 25/92] remove map --- src/LinuxProfiler/CMakeLists.txt | 6 ++-- src/LinuxProfiler/VanguardInstrumentation.cpp | 32 +++++++++--------- src/LinuxProfiler/VanguardInstrumentation.h | 33 +++++-------------- 3 files changed, 28 insertions(+), 43 deletions(-) diff --git a/src/LinuxProfiler/CMakeLists.txt b/src/LinuxProfiler/CMakeLists.txt index 1bf8c4f2..ee058387 100644 --- a/src/LinuxProfiler/CMakeLists.txt +++ b/src/LinuxProfiler/CMakeLists.txt @@ -5,7 +5,9 @@ cmake_minimum_required(VERSION 2.8.12) project(LinuxProfiler) -include_directories(. ../InstrumentationEngine.Lib ../InstrumentationEngine) +find_package(LibXml2 REQUIRED) + +include_directories(. ../InstrumentationEngine.Lib ${LIBXML2_INCLUDE_DIR}) build_init(CPP LinuxProfiler) @@ -18,7 +20,7 @@ set(src_files ./VanguardInstrumentation.cpp ./managed_instruction.cpp ./managed_function.cpp - ./ILDisassembler.cpp + #./ILDisassembler.cpp ) add_lib(${PROJECT_NAME} diff --git a/src/LinuxProfiler/VanguardInstrumentation.cpp b/src/LinuxProfiler/VanguardInstrumentation.cpp index 70c79ef1..7c96dbca 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.cpp +++ b/src/LinuxProfiler/VanguardInstrumentation.cpp @@ -1,21 +1,19 @@ #include "stdafx.h" #include "VanguardInstrumentation.h" -using namespace vanguard::instrumentation::managed; +bool module_info::contains_instrumented_method(mdToken token) +{ + return _instrumented_functions_list.find(token) != _instrumented_functions_list.end(); +} -//bool module_info::contains_instrumented_method(mdToken token) -//{ -// return _instrumented_functions_list.find(token) != _instrumented_functions_list.end(); -//} -// -//bool module_info::get_method_info(mdToken token, method_info& info) -//{ -// map::iterator it = _instrumented_functions_list.find(token); -// if (it != _instrumented_functions_list.end()) -// { -// info = it->second; -// return true; -// } -// -// return false; -//} \ No newline at end of file +bool module_info::get_method_info(mdToken token, method_info& info) +{ + unordered_map::iterator it = _instrumented_functions_list.find(token); + if (it != _instrumented_functions_list.end()) + { + info = it->second; + return true; + } + + return false; +} \ No newline at end of file diff --git a/src/LinuxProfiler/VanguardInstrumentation.h b/src/LinuxProfiler/VanguardInstrumentation.h index 43fc7581..8d7bd8c0 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.h +++ b/src/LinuxProfiler/VanguardInstrumentation.h @@ -1,9 +1,8 @@ #pragma once -#include "stdafx.h" -#include "managed_instruction.h" -//#include "managed_function.h" -#include +//#include "stdafx.h" + +using namespace ATL; struct method_info { @@ -19,11 +18,11 @@ struct method_info size_t get_start_index() { return _start_block_index; } void add_block_index(size_t block_index) { _block_indexes.push_back(block_index); } - std::vector get_block_indexes() { return _block_indexes; } + vector get_block_indexes() { return _block_indexes; } private: mdToken _token; - std::vector _block_indexes; /* indices where probes are to be added */ + vector _block_indexes; /* indices where probes are to be added */ size_t _start_block_index; }; @@ -33,29 +32,15 @@ struct module_info module_info(IModuleInfo* modInfo) : _current_module_info(modInfo) {} ~module_info() { _instrumented_functions_list.clear(); } - void add_instrumented_functions(method_info& method_info) { _instrumented_functions_list.insert(std::make_pair(method_info.get_method_token(), method_info)); } + void add_instrumented_functions(method_info& method_info) { _instrumented_functions_list.insert(make_pair(method_info.get_method_token(), method_info)); } IModuleInfo *get_module() { return _current_module_info; } - bool contains_instrumented_method(mdToken token) - { - return _instrumented_functions_list.find(token) != _instrumented_functions_list.end(); - } - - bool get_method_info(mdToken token, method_info& info) - { - map::iterator it = _instrumented_functions_list.find(token); - if (it != _instrumented_functions_list.end()) - { - info = it->second; - return true; - } - - return false; - } + bool contains_instrumented_method(mdToken token); + bool get_method_info(mdToken token, method_info& info); private: - std::map _instrumented_functions_list; + unordered_map _instrumented_functions_list; IModuleInfo *_current_module_info; }; From f1c60e251d6a928ff093f98f12f607b0b1e02a54 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 2 Mar 2019 18:58:13 +0530 Subject: [PATCH 26/92] include directory --- src/LinuxProfiler/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CMakeLists.txt b/src/LinuxProfiler/CMakeLists.txt index ee058387..5dbde8e2 100644 --- a/src/LinuxProfiler/CMakeLists.txt +++ b/src/LinuxProfiler/CMakeLists.txt @@ -7,7 +7,7 @@ project(LinuxProfiler) find_package(LibXml2 REQUIRED) -include_directories(. ../InstrumentationEngine.Lib ${LIBXML2_INCLUDE_DIR}) +include_directories(. ../InstrumentationEngine.Lib ../InstrumentationEngine ${LIBXML2_INCLUDE_DIR}) build_init(CPP LinuxProfiler) From 48bfb07a37e71466c8e3e713edd3eccf373aa41a Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 2 Mar 2019 19:02:52 +0530 Subject: [PATCH 27/92] build dis-assem --- src/LinuxProfiler/CMakeLists.txt | 2 +- src/LinuxProfiler/ILDisassembler.cpp | 15 ++++++--------- src/LinuxProfiler/ILDisassembler.h | 7 +++---- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/LinuxProfiler/CMakeLists.txt b/src/LinuxProfiler/CMakeLists.txt index 5dbde8e2..7132483b 100644 --- a/src/LinuxProfiler/CMakeLists.txt +++ b/src/LinuxProfiler/CMakeLists.txt @@ -20,7 +20,7 @@ set(src_files ./VanguardInstrumentation.cpp ./managed_instruction.cpp ./managed_function.cpp - #./ILDisassembler.cpp + ./ILDisassembler.cpp ) add_lib(${PROJECT_NAME} diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp index 62eb3d47..6cb0cd5b 100644 --- a/src/LinuxProfiler/ILDisassembler.cpp +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -1,9 +1,6 @@ #include "stdafx.h" #include "ILDisassembler.h" -using namespace vanguard::instrumentation::managed; - - il_disassembler::il_disassembler(IModuleInfo *pModuleInfo) { _module_info = new module_info(pModuleInfo); @@ -12,7 +9,7 @@ il_disassembler::il_disassembler(IModuleInfo *pModuleInfo) void il_disassembler::disassemble_function() { int index = 0; - //unordered_map inst_dict; + unordered_map inst_dict; IInstructionGraph* instructionsGraph; HRESULT hr = _current_method_info->GetInstructions(&instructionsGraph); @@ -35,7 +32,7 @@ void il_disassembler::disassemble_function() instruction *inst = new instruction((size_t)pOffset, (size_t)pSize, get_termination_type(il_inst), index++, pOpCode); _il_instructions.push_back(il_inst); _instructions.push_back(inst); - //inst_dict.insert(std::pair(il_inst, inst)); + inst_dict.insert(std::pair(il_inst, inst)); while (instructionData == S_OK) { @@ -57,7 +54,7 @@ void il_disassembler::disassemble_function() _instructions.push_back(inst); il_inst = nextInstruction; - //inst_dict.insert(std::pair(il_inst, inst)); + inst_dict.insert(std::pair(il_inst, inst)); } } @@ -83,7 +80,7 @@ void il_disassembler::disassemble_function() IInstruction *pBranchTarget; il_switch->GetBranchTarget(j, &pBranchTarget); - //_instructions[i]->get_targets()[j] = lookup(pBranchTarget, inst_dict, (instruction*)nullptr); + _instructions[i]->get_targets()[j] = lookup(pBranchTarget, inst_dict, (instruction*)nullptr); } } else if (isBranch) @@ -94,11 +91,11 @@ void il_disassembler::disassemble_function() IInstruction* pBranchTarget; il_branch->GetBranchTarget(&pBranchTarget); - /*if (target == lookup(pBranchTarget, inst_dict, target)) + if (target == lookup(pBranchTarget, inst_dict, target)) { _instructions[i]->set_target_count(1); _instructions[i]->get_targets()[0] = target; - }*/ + } } } } diff --git a/src/LinuxProfiler/ILDisassembler.h b/src/LinuxProfiler/ILDisassembler.h index 1e222ece..7a807fff 100644 --- a/src/LinuxProfiler/ILDisassembler.h +++ b/src/LinuxProfiler/ILDisassembler.h @@ -1,6 +1,5 @@ #pragma once -#include "stdafx.h" #include "managed_instruction.h" #include "managed_function.h" #include "VanguardInstrumentation.h" @@ -23,11 +22,11 @@ struct il_disassembler private: template - target_type lookup(source_type source, std::unordered_map &map, target_type default_value) + target_type lookup(source_type source, std::unordered_map &input_map, target_type default_value) { - if (source && map.find(source) != map.end()) + if (source && input_map.find(source) != input_map.end()) { - return map.find(source)->second; + return input_map.find(source)->second; } return default_value; From d528156756a0f0c92e8fa2f75e4341b2bdc78ec1 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Tue, 12 Mar 2019 21:46:28 +0530 Subject: [PATCH 28/92] load lib --- src/LinuxProfiler/CExtensionsHost.cpp | 8 ++++++-- src/LinuxProfiler/CExtensionsHost.h | 5 +++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index cbf658a8..790ae61a 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -28,8 +28,12 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo CComBSTR bstrModulePath; IfFailRet(pModuleInfo->GetFullPath(&bstrModulePath)); - /*std::wstring path(bstrModulePath, SysStringLen(bstrModulePath)); - wstring pdbFile = path.substr(0, path.find_last_of(L'.')) + L".pdb";*/ + std::wstring path(bstrModulePath, SysStringLen(bstrModulePath)); + wstring pdbFile = path.substr(0, path.find_last_of(L'.')) + L".pdb"; + + m_hmod = ::LoadLibrary("/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); + + typedef int(*ReadPdb)(wstring path); return hr; } diff --git a/src/LinuxProfiler/CExtensionsHost.h b/src/LinuxProfiler/CExtensionsHost.h index 8ae1f80e..b89e31dc 100644 --- a/src/LinuxProfiler/CExtensionsHost.h +++ b/src/LinuxProfiler/CExtensionsHost.h @@ -73,6 +73,11 @@ namespace ExtensionsHostCrossPlat virtual HRESULT STDMETHODCALLTYPE OnInstrumentationComplete(IMethodInfo* pMethodInfo, BOOL isRejit) { return S_OK; } virtual HRESULT STDMETHODCALLTYPE AllowInlineSite(IMethodInfo* pMethodInfoInlinee, IMethodInfo* pMethodInfoCaller, BOOL* pbAllowInline) { return S_OK; } + + private: + + HMODULE m_hmod = NULL; + }; } \ No newline at end of file From 930c771cea1f347fc0d7e172458945e1a598907b Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Tue, 12 Mar 2019 21:49:37 +0530 Subject: [PATCH 29/92] bstr to wstring --- src/LinuxProfiler/CExtensionsHost.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 790ae61a..4a9afff9 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -28,10 +28,14 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo CComBSTR bstrModulePath; IfFailRet(pModuleInfo->GetFullPath(&bstrModulePath)); - std::wstring path(bstrModulePath, SysStringLen(bstrModulePath)); + WCHAR wszModuleFullPath[MAX_PATH]; + memset(wszModuleFullPath, 0, MAX_PATH); + wcscpy_s(wszModuleFullPath, MAX_PATH, bstrModulePath); + + std::wstring path(wszModuleFullPath); wstring pdbFile = path.substr(0, path.find_last_of(L'.')) + L".pdb"; - m_hmod = ::LoadLibrary("/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); + //m_hmod = ::LoadLibrary("/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); typedef int(*ReadPdb)(wstring path); From abd5429bf709701c7c1b856eb49a04b3903f5317 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Tue, 12 Mar 2019 21:51:28 +0530 Subject: [PATCH 30/92] zz --- src/LinuxProfiler/CExtensionsHost.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 4a9afff9..8246ca31 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -32,9 +32,6 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo memset(wszModuleFullPath, 0, MAX_PATH); wcscpy_s(wszModuleFullPath, MAX_PATH, bstrModulePath); - std::wstring path(wszModuleFullPath); - wstring pdbFile = path.substr(0, path.find_last_of(L'.')) + L".pdb"; - //m_hmod = ::LoadLibrary("/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); typedef int(*ReadPdb)(wstring path); From d6e7b6a5ba3c52e13344ba70b0c62f8d8ee1c2ea Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Tue, 12 Mar 2019 21:53:21 +0530 Subject: [PATCH 31/92] load lib --- src/LinuxProfiler/CExtensionsHost.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 8246ca31..f16494da 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -30,9 +30,9 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo WCHAR wszModuleFullPath[MAX_PATH]; memset(wszModuleFullPath, 0, MAX_PATH); - wcscpy_s(wszModuleFullPath, MAX_PATH, bstrModulePath); + wcscpy_s(wszModuleFullPath, MAX_PATH, "/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); - //m_hmod = ::LoadLibrary("/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); + m_hmod = ::LoadLibrary(wszModuleFullPath); typedef int(*ReadPdb)(wstring path); From e17923f47260bb4eca0113a85730246ac7ccf1de Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Tue, 12 Mar 2019 22:06:57 +0530 Subject: [PATCH 32/92] zzz --- src/LinuxProfiler/CExtensionsHost.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index f16494da..88857f4b 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -28,9 +28,11 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo CComBSTR bstrModulePath; IfFailRet(pModuleInfo->GetFullPath(&bstrModulePath)); + wstring pdbReader = L"/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"; + WCHAR wszModuleFullPath[MAX_PATH]; memset(wszModuleFullPath, 0, MAX_PATH); - wcscpy_s(wszModuleFullPath, MAX_PATH, "/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); + wcscpy_s(wszModuleFullPath, MAX_PATH, pdbReader.c_str()); m_hmod = ::LoadLibrary(wszModuleFullPath); From ca107ebf5945121d05237a2860a72b81a3bf7c2b Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 12:22:49 +0530 Subject: [PATCH 33/92] tstring --- src/LinuxProfiler/CExtensionsHost.cpp | 11 ++++------- src/LinuxProfiler/stdafx.h | 1 + src/LinuxProfiler/tstring.h | 15 +++++++++++++++ 3 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 src/LinuxProfiler/tstring.h diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 88857f4b..725ef9c0 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -28,15 +28,12 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo CComBSTR bstrModulePath; IfFailRet(pModuleInfo->GetFullPath(&bstrModulePath)); - wstring pdbReader = L"/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"; + tstringstream pathBuilder; + pathBuilder <<_T(L"/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); - WCHAR wszModuleFullPath[MAX_PATH]; - memset(wszModuleFullPath, 0, MAX_PATH); - wcscpy_s(wszModuleFullPath, MAX_PATH, pdbReader.c_str()); - - m_hmod = ::LoadLibrary(wszModuleFullPath); + m_hmod = ::LoadLibrary(pathBuilder.c_str().c_str()); - typedef int(*ReadPdb)(wstring path); + //typedef int(*ReadPdb)(wstring path); return hr; } diff --git a/src/LinuxProfiler/stdafx.h b/src/LinuxProfiler/stdafx.h index 9d620bad..07a62485 100644 --- a/src/LinuxProfiler/stdafx.h +++ b/src/LinuxProfiler/stdafx.h @@ -56,3 +56,4 @@ using namespace std; #include "ImplQueryInterface.h" #include "InstrumentationEngine.h" #include "Logging.h" +#include "tstring.h" diff --git a/src/LinuxProfiler/tstring.h b/src/LinuxProfiler/tstring.h new file mode 100644 index 00000000..7af1c646 --- /dev/null +++ b/src/LinuxProfiler/tstring.h @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#pragma once + +#include + +#ifdef PLATFORM_UNIX +typedef std::basic_string, std::allocator> tstring; +typedef std::basic_stringstream tstringstream; +#else +typedef std::wstring tstring; +typedef std::wstringstream tstringstream; +#endif +typedef std::basic_ofstream > tofstream; \ No newline at end of file From 0a351a4fa4473c7df9263e1486fbb27d6a622478 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 12:30:05 +0530 Subject: [PATCH 34/92] fix --- src/LinuxProfiler/CExtensionsHost.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 725ef9c0..689c3eb7 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -29,9 +29,9 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo IfFailRet(pModuleInfo->GetFullPath(&bstrModulePath)); tstringstream pathBuilder; - pathBuilder <<_T(L"/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); + pathBuilder <<_T("/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); - m_hmod = ::LoadLibrary(pathBuilder.c_str().c_str()); + m_hmod = ::LoadLibrary(pathBuilder.str().c_str()); //typedef int(*ReadPdb)(wstring path); From bac5f87595736681cf8879a4f86e268a88732367 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 12:33:24 +0530 Subject: [PATCH 35/92] load method --- src/LinuxProfiler/CExtensionsHost.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 689c3eb7..40229753 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -33,7 +33,25 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo m_hmod = ::LoadLibrary(pathBuilder.str().c_str()); - //typedef int(*ReadPdb)(wstring path); + if (m_hmod == NULL) + { + auto error = ::GetLastError(); + // Failed to load the module. + return HRESULT_FROM_WIN32(error); + } + + typedef int(*ReadPdb)(wstring path); + + ReadPdb pfnReadPdb = (ReadPdb)GetProcAddress(m_hmod, "ReadPdb"); + if (!pfnDllGetClassObject) + { + auto error = ::GetLastError(); + FreeLibrary(m_hmod); + return HRESULT_FROM_WIN32(error); + } + + //int methodCount = pfnReadPdb(); + return hr; } From 216e49af157986b628168b677bc79a9b6c4ccb90 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 12:34:19 +0530 Subject: [PATCH 36/92] nit --- src/LinuxProfiler/CExtensionsHost.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 40229753..c6d2fea8 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -43,7 +43,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo typedef int(*ReadPdb)(wstring path); ReadPdb pfnReadPdb = (ReadPdb)GetProcAddress(m_hmod, "ReadPdb"); - if (!pfnDllGetClassObject) + if (!pfnReadPdb) { auto error = ::GetLastError(); FreeLibrary(m_hmod); From 31a5704fc08d4da5e6fb777b2cf8a592e88ea9c2 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 12:45:50 +0530 Subject: [PATCH 37/92] correct function def --- src/LinuxProfiler/CExtensionsHost.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index c6d2fea8..d3b56147 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -40,7 +40,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo return HRESULT_FROM_WIN32(error); } - typedef int(*ReadPdb)(wstring path); + typedef int(*ReadPdb)(const char* path); ReadPdb pfnReadPdb = (ReadPdb)GetProcAddress(m_hmod, "ReadPdb"); if (!pfnReadPdb) @@ -52,6 +52,5 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo //int methodCount = pfnReadPdb(); - return hr; } From 30674c660e656f469ec08aa427f758d766e012ad Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 12:50:44 +0530 Subject: [PATCH 38/92] get method --- src/LinuxProfiler/CExtensionsHost.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index d3b56147..3817e836 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -40,7 +40,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo return HRESULT_FROM_WIN32(error); } - typedef int(*ReadPdb)(const char* path); + typedef int(ReadPdb)(const char* path); ReadPdb pfnReadPdb = (ReadPdb)GetProcAddress(m_hmod, "ReadPdb"); if (!pfnReadPdb) From 79c0f761dc61fc85fb60bc58a73edfec66ced350 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 12:53:05 +0530 Subject: [PATCH 39/92] stdcall --- src/LinuxProfiler/CExtensionsHost.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 3817e836..fe7a65b5 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -40,7 +40,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo return HRESULT_FROM_WIN32(error); } - typedef int(ReadPdb)(const char* path); + typedef int(__stdcall* ReadPdb)(const char* path); ReadPdb pfnReadPdb = (ReadPdb)GetProcAddress(m_hmod, "ReadPdb"); if (!pfnReadPdb) From c46048c33e40810e29aab901af131bb961bcbb91 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 13:17:00 +0530 Subject: [PATCH 40/92] method name --- src/LinuxProfiler/CExtensionsHost.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index fe7a65b5..efd808d0 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -40,9 +40,9 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo return HRESULT_FROM_WIN32(error); } - typedef int(__stdcall* ReadPdb)(const char* path); + typedef int(__stdcall* ReadPDB)(const char* path); - ReadPdb pfnReadPdb = (ReadPdb)GetProcAddress(m_hmod, "ReadPdb"); + ReadPDB pfnReadPdb = (ReadPDB)GetProcAddress(m_hmod, "ReadPdb"); if (!pfnReadPdb) { auto error = ::GetLastError(); From f41973709177a4a4a1de08be13c4341dba3432ba Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 13:18:44 +0530 Subject: [PATCH 41/92] zz --- src/LinuxProfiler/CExtensionsHost.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index efd808d0..8014c94a 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -42,7 +42,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo typedef int(__stdcall* ReadPDB)(const char* path); - ReadPDB pfnReadPdb = (ReadPDB)GetProcAddress(m_hmod, "ReadPdb"); + ReadPDB pfnReadPdb = (ReadPDB)GetProcAddress(m_hmod, "ReadPDB"); if (!pfnReadPdb) { auto error = ::GetLastError(); From c9c73d83ceae43f265fc1bd972a19dafc684a6db Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 14:03:00 +0530 Subject: [PATCH 42/92] load pdb --- src/LinuxProfiler/CExtensionsHost.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 8014c94a..4de7c16d 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -28,10 +28,19 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo CComBSTR bstrModulePath; IfFailRet(pModuleInfo->GetFullPath(&bstrModulePath)); + tstringstream dllPath; + dllPath << (LPWSTR)bstrModulePath; + + tstring pdbPath = dllPath.str(); + pdbPath = pdbPath.substr(0, path.find_last_of(L'.')) + L".pdb"; + tstringstream pathBuilder; pathBuilder <<_T("/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); - m_hmod = ::LoadLibrary(pathBuilder.str().c_str()); + if (m_hmod == NULL) + { + m_hmod = ::LoadLibrary(pathBuilder.str().c_str()); + } if (m_hmod == NULL) { From fde4e3a85012843e569807ae05c7429bd7bde73f Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 14:04:11 +0530 Subject: [PATCH 43/92] zzz --- src/LinuxProfiler/CExtensionsHost.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 4de7c16d..ce1cfb14 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -32,7 +32,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo dllPath << (LPWSTR)bstrModulePath; tstring pdbPath = dllPath.str(); - pdbPath = pdbPath.substr(0, path.find_last_of(L'.')) + L".pdb"; + pdbPath = pdbPath.substr(0, pdbPath.find_last_of(L'.')) + L".pdb"; tstringstream pathBuilder; pathBuilder <<_T("/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); From 5c02e370829ffdbce3a35b109d3491994f1bfb5e Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 14:06:38 +0530 Subject: [PATCH 44/92] zzzz --- src/LinuxProfiler/CExtensionsHost.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index ce1cfb14..07962c10 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -32,7 +32,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo dllPath << (LPWSTR)bstrModulePath; tstring pdbPath = dllPath.str(); - pdbPath = pdbPath.substr(0, pdbPath.find_last_of(L'.')) + L".pdb"; + pdbPath = pdbPath.substr(0, pdbPath.find_last_of(_T('.'))) + _T(".pdb"); tstringstream pathBuilder; pathBuilder <<_T("/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); From 4e02353edcc9768c5c59d34b89fd91b857cf9e91 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 14:13:25 +0530 Subject: [PATCH 45/92] check if pdb exists --- src/LinuxProfiler/CExtensionsHost.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 07962c10..de692771 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -34,6 +34,18 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo tstring pdbPath = dllPath.str(); pdbPath = pdbPath.substr(0, pdbPath.find_last_of(_T('.'))) + _T(".pdb"); + FILE * pFile; + pFile = fopen(pdbPath.c_str(), "r"); + + if (pFile == NULL) + { + return S_OK; + } + else + { + fclose(pFile); + } + tstringstream pathBuilder; pathBuilder <<_T("/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); From 0ad9baf2b7e2e72414c95d713214f0481d1c9ff8 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 14:14:50 +0530 Subject: [PATCH 46/92] read --- src/LinuxProfiler/CExtensionsHost.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index de692771..72f0abbb 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -34,7 +34,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo tstring pdbPath = dllPath.str(); pdbPath = pdbPath.substr(0, pdbPath.find_last_of(_T('.'))) + _T(".pdb"); - FILE * pFile; + /*FILE * pFile; pFile = fopen(pdbPath.c_str(), "r"); if (pFile == NULL) @@ -44,7 +44,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo else { fclose(pFile); - } + }*/ tstringstream pathBuilder; pathBuilder <<_T("/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); @@ -71,7 +71,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo return HRESULT_FROM_WIN32(error); } - //int methodCount = pfnReadPdb(); + int methodCount = pfnReadPdb(pdbPath.c_str()); return hr; } From 2d24c365152cba9699450179fb01a315368cace9 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 14:16:22 +0530 Subject: [PATCH 47/92] zzzz --- src/LinuxProfiler/CExtensionsHost.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 72f0abbb..39c413d0 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -71,7 +71,8 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo return HRESULT_FROM_WIN32(error); } - int methodCount = pfnReadPdb(pdbPath.c_str()); + string filePathChar(pdbPath.begin(), pdbPath.end()); + int methodCount = pfnReadPdb(filePathChar.c_str()); return hr; } From 5fad3afcd275e735235c41497dc323d46513744f Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 15:15:17 +0530 Subject: [PATCH 48/92] check file exists --- src/LinuxProfiler/CExtensionsHost.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 39c413d0..1bf7442f 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -34,8 +34,9 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo tstring pdbPath = dllPath.str(); pdbPath = pdbPath.substr(0, pdbPath.find_last_of(_T('.'))) + _T(".pdb"); - /*FILE * pFile; - pFile = fopen(pdbPath.c_str(), "r"); + string filePathChar(pdbPath.begin(), pdbPath.end()); + FILE * pFile; + pFile = fopen(filePathChar.c_str(), "r"); if (pFile == NULL) { @@ -44,7 +45,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo else { fclose(pFile); - }*/ + } tstringstream pathBuilder; pathBuilder <<_T("/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); @@ -71,7 +72,6 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo return HRESULT_FROM_WIN32(error); } - string filePathChar(pdbPath.begin(), pdbPath.end()); int methodCount = pfnReadPdb(filePathChar.c_str()); return hr; From a20bc65e76d630c5755f6b51fd58a3f35f3e52a7 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 15:22:18 +0530 Subject: [PATCH 49/92] zzzz --- src/LinuxProfiler/CExtensionsHost.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 1bf7442f..68cff2d2 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -35,7 +35,8 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo pdbPath = pdbPath.substr(0, pdbPath.find_last_of(_T('.'))) + _T(".pdb"); string filePathChar(pdbPath.begin(), pdbPath.end()); - FILE * pFile; + + /*FILE * pFile; pFile = fopen(filePathChar.c_str(), "r"); if (pFile == NULL) @@ -45,7 +46,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo else { fclose(pFile); - } + }*/ tstringstream pathBuilder; pathBuilder <<_T("/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); From c0ba3a151187771dfdf1ea3c8e16b6bf97599f15 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 15:34:35 +0530 Subject: [PATCH 50/92] compute blocks --- src/LinuxProfiler/CExtensionsHost.cpp | 38 +++++++++++++++++++++++++++ src/LinuxProfiler/CExtensionsHost.h | 4 +++ src/LinuxProfiler/managed_function.h | 2 +- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 68cff2d2..e7d10238 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -75,5 +75,43 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo int methodCount = pfnReadPdb(filePathChar.c_str()); + const mdMethodDef baseToken = 0x06 << 24; + mdMethodDef methodDef = 1; + HRESULT methodInfoResult = S_OK; + vector methodInfoCollection; + + il_disassembler disassembler(pModuleInfo); + + while (methodCount) + { + IMethodInfo* methodInfo = NULL; + CComBSTR bstrMethodName; + + methodInfoResult = pModuleInfo->GetMethodInfoByToken(baseToken | methodDef, &methodInfo); + methodInfoCollection.push_back(methodInfo); + methodDef++; + methodCount--; + methodInfo->GetFullName(&bstrMethodName); + printf("Method Name: %S \n ", bstrMethodName); + disassembler.initialize_function(methodInfo); + disassembler.disassemble_function(); + + struct function_releaser + { + function_releaser(il_disassembler& d) : + _disassembler(d) + { + } + + ~function_releaser() { _disassembler.cleanup_function(); } + + private: + il_disassembler& _disassembler; + } releaser(disassembler); + + vanguard::instrumentation::managed::function* func = new vanguard::instrumentation::managed::function(); + func->calculate_blocks(disassembler); + } + return hr; } diff --git a/src/LinuxProfiler/CExtensionsHost.h b/src/LinuxProfiler/CExtensionsHost.h index b89e31dc..711b2b6c 100644 --- a/src/LinuxProfiler/CExtensionsHost.h +++ b/src/LinuxProfiler/CExtensionsHost.h @@ -5,6 +5,10 @@ #pragma once #include "stdafx.h" +#include "ILDisassembler.h" +#include "managed_function.h" + + // {CA487940-57D2-10BF-11B2-A3AD5A13CBC0} const GUID CLSID_ExtensionHost = { 0xCA487940, 0x57D2, 0x10BF,{ 0x11, 0xB2, 0xA3, 0xAD, 0x5A, 0x13, 0xCB, 0xC0 } }; diff --git a/src/LinuxProfiler/managed_function.h b/src/LinuxProfiler/managed_function.h index bfb0bf0f..bda16d9e 100644 --- a/src/LinuxProfiler/managed_function.h +++ b/src/LinuxProfiler/managed_function.h @@ -18,7 +18,7 @@ namespace vanguard { static const DWORD INVALID_ID = 0xFFFFFFFF; typedef block block_type; - function(); + function() {} //! Move constructor for function. function(function&& other) From 306c45bc62ef94f47bc9e075d77dae6f27172b69 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 15:35:40 +0530 Subject: [PATCH 51/92] nit --- src/LinuxProfiler/managed_function.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LinuxProfiler/managed_function.h b/src/LinuxProfiler/managed_function.h index bda16d9e..bfb0bf0f 100644 --- a/src/LinuxProfiler/managed_function.h +++ b/src/LinuxProfiler/managed_function.h @@ -18,7 +18,7 @@ namespace vanguard { static const DWORD INVALID_ID = 0xFFFFFFFF; typedef block block_type; - function() {} + function(); //! Move constructor for function. function(function&& other) From a95147b2708db36075b49e24d6a6163a23148acb Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 17:10:49 +0530 Subject: [PATCH 52/92] print wchar --- src/LinuxProfiler/CExtensionsHost.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index e7d10238..3858ecd5 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -73,7 +73,8 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo return HRESULT_FROM_WIN32(error); } - int methodCount = pfnReadPdb(filePathChar.c_str()); + int methodCount = 0; + methodCount = pfnReadPdb(filePathChar.c_str()); const mdMethodDef baseToken = 0x06 << 24; mdMethodDef methodDef = 1; @@ -92,7 +93,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo methodDef++; methodCount--; methodInfo->GetFullName(&bstrMethodName); - printf("Method Name: %S \n ", bstrMethodName); + printf("Method Name: %ls \n ", bstrMethodName); disassembler.initialize_function(methodInfo); disassembler.disassemble_function(); From 5d822c96e0b81a58efd96ea66acbc36f3af8239a Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 13 Mar 2019 17:13:03 +0530 Subject: [PATCH 53/92] zzz --- src/LinuxProfiler/CExtensionsHost.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 3858ecd5..1cb8f548 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -93,7 +93,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo methodDef++; methodCount--; methodInfo->GetFullName(&bstrMethodName); - printf("Method Name: %ls \n ", bstrMethodName); + //printf("Method Name: %ls \n ", bstrMethodName); disassembler.initialize_function(methodInfo); disassembler.disassemble_function(); From fb602816ce2f64cdf3553b0250a670d623acc87d Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 20 Mar 2019 17:43:33 +0530 Subject: [PATCH 54/92] fixes --- src/LinuxProfiler/CExtensionsHost.cpp | 2 ++ src/LinuxProfiler/ILDisassembler.cpp | 17 +++++++++++++++-- src/LinuxProfiler/ILDisassembler.h | 2 +- src/LinuxProfiler/managed_function.cpp | 4 ++-- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 1cb8f548..48622f4c 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -12,6 +12,8 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( _In_ IProfilerManager* pProfilerManager ) { + printf("Loaded Custom Profiler"); + usleep(5*1000); CComPtr pCorProfilerInfo; pProfilerManager->GetCorProfilerInfo((IUnknown**)&pCorProfilerInfo); pCorProfilerInfo->SetEventMask(COR_PRF_MONITOR_EXCEPTIONS | COR_PRF_ENABLE_STACK_SNAPSHOT); diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp index 6cb0cd5b..51f3ef4a 100644 --- a/src/LinuxProfiler/ILDisassembler.cpp +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -50,7 +50,7 @@ void il_disassembler::disassemble_function() nextInstruction->GetInstructionLength(&pSize); nextInstruction->GetOpCode(&pOpCode); - inst = new instruction((size_t)pOffset, (size_t)pSize, get_termination_type(il_inst), index++, pOpCode); + inst = new instruction((size_t)pOffset, (size_t)pSize, get_termination_type(nextInstruction), index++, pOpCode); _instructions.push_back(inst); il_inst = nextInstruction; @@ -90,8 +90,9 @@ void il_disassembler::disassemble_function() instruction *target = nullptr; IInstruction* pBranchTarget; il_branch->GetBranchTarget(&pBranchTarget); + target = lookup(pBranchTarget, inst_dict, target); - if (target == lookup(pBranchTarget, inst_dict, target)) + if (target) { _instructions[i]->set_target_count(1); _instructions[i]->get_targets()[0] = target; @@ -106,6 +107,18 @@ size_t il_disassembler::get_instructions(vanguard::instrumentation::managed::ins return _instructions.size(); } +void il_disassembler::cleanup_function() +{ + for (vector::iterator it = _instructions.begin(); it != _instructions.end(); ++it) + { + delete *it; + } + + _instructions.clear(); + _il_instructions.clear(); + _current_method_info = nullptr; +} + bool il_disassembler::instrument_function(size_t block_index) { mdToken methodToken; diff --git a/src/LinuxProfiler/ILDisassembler.h b/src/LinuxProfiler/ILDisassembler.h index 7a807fff..e441d872 100644 --- a/src/LinuxProfiler/ILDisassembler.h +++ b/src/LinuxProfiler/ILDisassembler.h @@ -15,7 +15,7 @@ struct il_disassembler virtual void disassemble_function(); virtual void initialize_function(IMethodInfo *methodInfo) { _current_method_info = methodInfo; } virtual size_t get_instructions(/* [out] */ instruction **&instructions); - virtual void cleanup_function() {} + virtual void cleanup_function(); virtual bool instrument_function(size_t block_index); virtual module_info *get_module_info() { return _module_info; } diff --git a/src/LinuxProfiler/managed_function.cpp b/src/LinuxProfiler/managed_function.cpp index 9118d89c..f1075439 100644 --- a/src/LinuxProfiler/managed_function.cpp +++ b/src/LinuxProfiler/managed_function.cpp @@ -29,8 +29,8 @@ namespace vanguard { { // If we've already disassembled or cannot disassemble, do nothing // In case of Assembly.Load/AssemblyLoadContext.LoadFromStream, we want to instrument, even if there are no symbols - if (_blocks || (!has_symbolic_information() && !_is_assembly_load)) - return; + // if (_blocks || (!has_symbolic_information() && !_is_assembly_load)) + // return; instruction* last_inst = nullptr; instruction** instructions; From 1aae300253be5c32dbb2b213873ebb4c1d6631f2 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 20 Mar 2019 18:13:44 +0530 Subject: [PATCH 55/92] namespace --- src/LinuxProfiler/CExtensionsHost.cpp | 7 +- src/LinuxProfiler/CExtensionsHost.h | 5 - src/LinuxProfiler/ILDisassembler.cpp | 234 +++++++++++++------------- src/LinuxProfiler/ILDisassembler.h | 143 ++++++++-------- 4 files changed, 198 insertions(+), 191 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 48622f4c..cf5d5507 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -1,12 +1,8 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// - -// CExtensionsHost.cpp : Implementation of CExtensionHost - #include "stdafx.h" #include #include "CExtensionsHost.h" +using namespace vanguard::instrumentation::managed; HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( _In_ IProfilerManager* pProfilerManager @@ -95,6 +91,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo methodDef++; methodCount--; methodInfo->GetFullName(&bstrMethodName); + //printf("Method Name: %ls \n ", bstrMethodName); disassembler.initialize_function(methodInfo); disassembler.disassemble_function(); diff --git a/src/LinuxProfiler/CExtensionsHost.h b/src/LinuxProfiler/CExtensionsHost.h index 711b2b6c..6e87ba72 100644 --- a/src/LinuxProfiler/CExtensionsHost.h +++ b/src/LinuxProfiler/CExtensionsHost.h @@ -1,8 +1,3 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// - -// CExtensionsHost.h : Declaration of the CExtensionHost - #pragma once #include "stdafx.h" #include "ILDisassembler.h" diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp index 51f3ef4a..675eb8c2 100644 --- a/src/LinuxProfiler/ILDisassembler.cpp +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -1,128 +1,136 @@ #include "stdafx.h" #include "ILDisassembler.h" -il_disassembler::il_disassembler(IModuleInfo *pModuleInfo) -{ - _module_info = new module_info(pModuleInfo); -} - -void il_disassembler::disassemble_function() -{ - int index = 0; - unordered_map inst_dict; - - IInstructionGraph* instructionsGraph; - HRESULT hr = _current_method_info->GetInstructions(&instructionsGraph); - std::vector _il_instructions; - - if (hr == S_OK) - { - IInstruction* il_inst = NULL; - - HRESULT instructionData = instructionsGraph->GetFirstInstruction(&il_inst); - - DWORD pOffset; - DWORD pSize; - ILOrdinalOpcode pOpCode; - - il_inst->GetOffset(&pOffset); - il_inst->GetInstructionLength(&pSize); - il_inst->GetOpCode(&pOpCode); - - instruction *inst = new instruction((size_t)pOffset, (size_t)pSize, get_termination_type(il_inst), index++, pOpCode); - _il_instructions.push_back(il_inst); - _instructions.push_back(inst); - inst_dict.insert(std::pair(il_inst, inst)); - - while (instructionData == S_OK) +namespace vanguard { + namespace instrumentation { + namespace managed { - IInstruction* nextInstruction = NULL; - instructionData = il_inst->GetNextInstruction(&nextInstruction); - - if (instructionData != S_OK) + il_disassembler::il_disassembler(IModuleInfo *pModuleInfo) { - break; + _module_info = new module_info(pModuleInfo); } - _il_instructions.push_back(nextInstruction); - - nextInstruction->GetOffset(&pOffset); - nextInstruction->GetInstructionLength(&pSize); - nextInstruction->GetOpCode(&pOpCode); - - inst = new instruction((size_t)pOffset, (size_t)pSize, get_termination_type(nextInstruction), index++, pOpCode); - _instructions.push_back(inst); - - il_inst = nextInstruction; - inst_dict.insert(std::pair(il_inst, inst)); - } - } - - // Set targets - for (size_t i = 0; i < _il_instructions.size(); i++) - { - BOOL isSwitch, isBranch; - _il_instructions[i]->GetIsSwitch(&isSwitch); - _il_instructions[i]->GetIsBranch(&isBranch); - - if (isSwitch) - { - ISwitchInstruction *il_switch; - _il_instructions[i]->QueryInterface(__uuidof(ISwitchInstruction), (LPVOID*)&il_switch); - - DWORD pBranchCount = 0; - il_switch->GetBranchCount(&pBranchCount); - - _instructions[i]->set_target_count(pBranchCount); + void il_disassembler::disassemble_function() + { + int index = 0; + unordered_map inst_dict; + + IInstructionGraph* instructionsGraph; + HRESULT hr = _current_method_info->GetInstructions(&instructionsGraph); + std::vector _il_instructions; + + if (hr == S_OK) + { + IInstruction* il_inst = NULL; + + HRESULT instructionData = instructionsGraph->GetFirstInstruction(&il_inst); + + DWORD pOffset; + DWORD pSize; + ILOrdinalOpcode pOpCode; + + il_inst->GetOffset(&pOffset); + il_inst->GetInstructionLength(&pSize); + il_inst->GetOpCode(&pOpCode); + + instruction *inst = new instruction((size_t)pOffset, (size_t)pSize, get_termination_type(il_inst), index++, pOpCode); + _il_instructions.push_back(il_inst); + _instructions.push_back(inst); + inst_dict.insert(std::pair(il_inst, inst)); + + while (instructionData == S_OK) + { + IInstruction* nextInstruction = NULL; + instructionData = il_inst->GetNextInstruction(&nextInstruction); + + if (instructionData != S_OK) + { + break; + } + + _il_instructions.push_back(nextInstruction); + + nextInstruction->GetOffset(&pOffset); + nextInstruction->GetInstructionLength(&pSize); + nextInstruction->GetOpCode(&pOpCode); + + inst = new instruction((size_t)pOffset, (size_t)pSize, get_termination_type(nextInstruction), index++, pOpCode); + _instructions.push_back(inst); + + il_inst = nextInstruction; + inst_dict.insert(std::pair(il_inst, inst)); + } + } + + // Set targets + for (size_t i = 0; i < _il_instructions.size(); i++) + { + BOOL isSwitch, isBranch; + _il_instructions[i]->GetIsSwitch(&isSwitch); + _il_instructions[i]->GetIsBranch(&isBranch); + + if (isSwitch) + { + ISwitchInstruction *il_switch; + _il_instructions[i]->QueryInterface(__uuidof(ISwitchInstruction), (LPVOID*)&il_switch); + + DWORD pBranchCount = 0; + il_switch->GetBranchCount(&pBranchCount); + + _instructions[i]->set_target_count(pBranchCount); + + for (ULONG j = 0; j < pBranchCount; j++) + { + IInstruction *pBranchTarget; + + il_switch->GetBranchTarget(j, &pBranchTarget); + _instructions[i]->get_targets()[j] = lookup(pBranchTarget, inst_dict, (instruction*)nullptr); + } + } + else if (isBranch) + { + IBranchInstruction *il_branch; + _il_instructions[i]->QueryInterface(__uuidof(IBranchInstruction), (LPVOID*)&il_branch); + instruction *target = nullptr; + IInstruction* pBranchTarget; + il_branch->GetBranchTarget(&pBranchTarget); + target = lookup(pBranchTarget, inst_dict, target); + + if (target) + { + _instructions[i]->set_target_count(1); + _instructions[i]->get_targets()[0] = target; + } + } + } + } - for (ULONG j = 0; j < pBranchCount; j++) + size_t il_disassembler::get_instructions(vanguard::instrumentation::managed::instruction **&instructions) { - IInstruction *pBranchTarget; + instructions = _instructions.data(); + return _instructions.size(); + } - il_switch->GetBranchTarget(j, &pBranchTarget); - _instructions[i]->get_targets()[j] = lookup(pBranchTarget, inst_dict, (instruction*)nullptr); + void il_disassembler::cleanup_function() + { + for (vector::iterator it = _instructions.begin(); it != _instructions.end(); ++it) + { + delete *it; + } + + _instructions.clear(); + _il_instructions.clear(); + _current_method_info = nullptr; } - } - else if (isBranch) - { - IBranchInstruction *il_branch; - _il_instructions[i]->QueryInterface(__uuidof(IBranchInstruction), (LPVOID*)&il_branch); - instruction *target = nullptr; - IInstruction* pBranchTarget; - il_branch->GetBranchTarget(&pBranchTarget); - target = lookup(pBranchTarget, inst_dict, target); - - if (target) + + bool il_disassembler::instrument_function(size_t block_index) { - _instructions[i]->set_target_count(1); - _instructions[i]->get_targets()[0] = target; + mdToken methodToken; + _current_method_info->GetMethodToken(&methodToken); + method_info info(methodToken); + return true; } + } } -} - -size_t il_disassembler::get_instructions(vanguard::instrumentation::managed::instruction **&instructions) -{ - instructions = _instructions.data(); - return _instructions.size(); -} - -void il_disassembler::cleanup_function() -{ - for (vector::iterator it = _instructions.begin(); it != _instructions.end(); ++it) - { - delete *it; - } - - _instructions.clear(); - _il_instructions.clear(); - _current_method_info = nullptr; -} - -bool il_disassembler::instrument_function(size_t block_index) -{ - mdToken methodToken; - _current_method_info->GetMethodToken(&methodToken); - method_info info(methodToken); - return true; -} +} \ No newline at end of file diff --git a/src/LinuxProfiler/ILDisassembler.h b/src/LinuxProfiler/ILDisassembler.h index e441d872..64ca373c 100644 --- a/src/LinuxProfiler/ILDisassembler.h +++ b/src/LinuxProfiler/ILDisassembler.h @@ -4,83 +4,90 @@ #include "managed_function.h" #include "VanguardInstrumentation.h" -using namespace vanguard::instrumentation::managed; using namespace ATL; -struct il_disassembler -{ -public: - il_disassembler(IModuleInfo *pModuleInfo); +namespace vanguard { + namespace instrumentation { + namespace managed + { + struct il_disassembler + { + public: + il_disassembler(IModuleInfo *pModuleInfo); - virtual void disassemble_function(); - virtual void initialize_function(IMethodInfo *methodInfo) { _current_method_info = methodInfo; } - virtual size_t get_instructions(/* [out] */ instruction **&instructions); - virtual void cleanup_function(); - virtual bool instrument_function(size_t block_index); + virtual void disassemble_function(); + virtual void initialize_function(IMethodInfo *methodInfo) { _current_method_info = methodInfo; } + virtual size_t get_instructions(/* [out] */ instruction **&instructions); + virtual void cleanup_function(); + virtual bool instrument_function(size_t block_index); - virtual module_info *get_module_info() { return _module_info; } + virtual module_info *get_module_info() { return _module_info; } -private: - template - target_type lookup(source_type source, std::unordered_map &input_map, target_type default_value) - { - if (source && input_map.find(source) != input_map.end()) - { - return input_map.find(source)->second; - } + private: + template + target_type lookup(source_type source, std::unordered_map &input_map, target_type default_value) + { + if (source && input_map.find(source) != input_map.end()) + { + return input_map.find(source)->second; + } - return default_value; - } + return default_value; + } - DISCEE::TRMTA get_termination_type(IInstruction *il_inst) - { - ILOrdinalOpcode opcode; - il_inst->GetOpCode(&opcode); - if (opcode < 0) - { - return DISCEE::trmtaUnknown; - } + DISCEE::TRMTA get_termination_type(IInstruction *il_inst) + { + ILOrdinalOpcode opcode; + il_inst->GetOpCode(&opcode); + if (opcode < 0) + { + return DISCEE::trmtaUnknown; + } - switch (opcode) - { - case Cee_Break: - return DISCEE::trmtaTrap; - case Cee_Switch: - return DISCEE::trmtaBraSwitch; - case Cee_Ret: - case Cee_Endfinally: - case Cee_Endfilter: - return DISCEE::trmtaRet; - case Cee_Call: - case Cee_Jmp: - case Cee_Newobj: - return DISCEE::trmtaCall; - case Cee_Calli: - case Cee_Callvirt: - return DISCEE::trmtaCallInd; - case Cee_Br_S: - case Cee_Br: - case Cee_Leave: - case Cee_Leave_S: - return DISCEE::trmtaBra; - case Cee_Throw: - case Cee_Rethrow: - return DISCEE::trmtaBraInd; - } + switch (opcode) + { + case Cee_Break: + return DISCEE::trmtaTrap; + case Cee_Switch: + return DISCEE::trmtaBraSwitch; + case Cee_Ret: + case Cee_Endfinally: + case Cee_Endfilter: + return DISCEE::trmtaRet; + case Cee_Call: + case Cee_Jmp: + case Cee_Newobj: + return DISCEE::trmtaCall; + case Cee_Calli: + case Cee_Callvirt: + return DISCEE::trmtaCallInd; + case Cee_Br_S: + case Cee_Br: + case Cee_Leave: + case Cee_Leave_S: + return DISCEE::trmtaBra; + case Cee_Throw: + case Cee_Rethrow: + return DISCEE::trmtaBraInd; + } - if (opcode >= Cee_Brfalse_S && opcode < Cee_Switch) - { - return DISCEE::trmtaBraCc; - } + if (opcode >= Cee_Brfalse_S && opcode < Cee_Switch) + { + return DISCEE::trmtaBraCc; + } + + // For the rest (NEXT and META), they are fallthrough + return DISCEE::trmtaFallThrough; + } - // For the rest (NEXT and META), they are fallthrough - return DISCEE::trmtaFallThrough; + bool _use_verifiable_probe; + IMethodInfo *_current_method_info; + std::vector _instructions; + std::vector _il_instructions; + module_info *_module_info; + size_t _global_block_count; + }; + } } +} - bool _use_verifiable_probe; - IMethodInfo *_current_method_info; - std::vector _instructions; - std::vector _il_instructions; - module_info *_module_info; - size_t _global_block_count; -}; \ No newline at end of file From c6fdb204de59737c1be8cb7d42c4d376ec496837 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 20 Mar 2019 18:16:31 +0530 Subject: [PATCH 56/92] fix --- src/LinuxProfiler/CExtensionsHost.h | 1 + src/LinuxProfiler/managed_function.h | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.h b/src/LinuxProfiler/CExtensionsHost.h index 6e87ba72..e64dc440 100644 --- a/src/LinuxProfiler/CExtensionsHost.h +++ b/src/LinuxProfiler/CExtensionsHost.h @@ -3,6 +3,7 @@ #include "ILDisassembler.h" #include "managed_function.h" +using namespace vanguard::instrumentation::managed; // {CA487940-57D2-10BF-11B2-A3AD5A13CBC0} const GUID CLSID_ExtensionHost = diff --git a/src/LinuxProfiler/managed_function.h b/src/LinuxProfiler/managed_function.h index bfb0bf0f..f1bbfb35 100644 --- a/src/LinuxProfiler/managed_function.h +++ b/src/LinuxProfiler/managed_function.h @@ -6,8 +6,6 @@ #include #include "ILDisassembler.h" -struct il_disassembler; - namespace vanguard { namespace instrumentation { namespace managed From 36b481237051679cd1c91c102f20127ce1fdc588 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 20 Mar 2019 18:20:05 +0530 Subject: [PATCH 57/92] fix2 --- src/LinuxProfiler/managed_function.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/LinuxProfiler/managed_function.h b/src/LinuxProfiler/managed_function.h index f1bbfb35..91f230af 100644 --- a/src/LinuxProfiler/managed_function.h +++ b/src/LinuxProfiler/managed_function.h @@ -4,12 +4,13 @@ #include "block.h" #include "managed_instruction.h" #include -#include "ILDisassembler.h" namespace vanguard { namespace instrumentation { namespace managed { + struct il_disassembler; + //! Represents a managed function. struct function { From 8d4ff0ef435a2b37e2d2fe32ac07418be22f2af6 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 20 Mar 2019 18:22:46 +0530 Subject: [PATCH 58/92] fix --- src/LinuxProfiler/managed_function.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/LinuxProfiler/managed_function.cpp b/src/LinuxProfiler/managed_function.cpp index f1075439..9dce8b7c 100644 --- a/src/LinuxProfiler/managed_function.cpp +++ b/src/LinuxProfiler/managed_function.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "managed_function.h" +#include "ILDisassembler.h" using namespace std; From 53c272700aa292f87505a93646ab5d090f906c90 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 20 Mar 2019 18:27:38 +0530 Subject: [PATCH 59/92] ref --- src/LinuxProfiler/ILDisassembler.cpp | 2 ++ src/LinuxProfiler/ILDisassembler.h | 1 + 2 files changed, 3 insertions(+) diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp index 675eb8c2..36651a97 100644 --- a/src/LinuxProfiler/ILDisassembler.cpp +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -8,6 +8,7 @@ namespace vanguard { il_disassembler::il_disassembler(IModuleInfo *pModuleInfo) { _module_info = new module_info(pModuleInfo); + _current_function = nullptr; } void il_disassembler::disassemble_function() @@ -121,6 +122,7 @@ namespace vanguard { _instructions.clear(); _il_instructions.clear(); _current_method_info = nullptr; + _current_function = nullptr; } bool il_disassembler::instrument_function(size_t block_index) diff --git a/src/LinuxProfiler/ILDisassembler.h b/src/LinuxProfiler/ILDisassembler.h index 64ca373c..74a8acc1 100644 --- a/src/LinuxProfiler/ILDisassembler.h +++ b/src/LinuxProfiler/ILDisassembler.h @@ -86,6 +86,7 @@ namespace vanguard { std::vector _il_instructions; module_info *_module_info; size_t _global_block_count; + vanguard::instrumentation::managed::function* _current_function; }; } } From fd3ff571279b7e174f28004b62ea2602c5db231a Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 20 Mar 2019 18:35:16 +0530 Subject: [PATCH 60/92] fix --- src/LinuxProfiler/CExtensionsHost.cpp | 4 ++-- src/LinuxProfiler/ILDisassembler.h | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index cf5d5507..c2e37622 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -93,7 +93,8 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo methodInfo->GetFullName(&bstrMethodName); //printf("Method Name: %ls \n ", bstrMethodName); - disassembler.initialize_function(methodInfo); + vanguard::instrumentation::managed::function* func = new vanguard::instrumentation::managed::function(); + disassembler.initialize_function(methodInfo, func); disassembler.disassemble_function(); struct function_releaser @@ -109,7 +110,6 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo il_disassembler& _disassembler; } releaser(disassembler); - vanguard::instrumentation::managed::function* func = new vanguard::instrumentation::managed::function(); func->calculate_blocks(disassembler); } diff --git a/src/LinuxProfiler/ILDisassembler.h b/src/LinuxProfiler/ILDisassembler.h index 74a8acc1..c345996f 100644 --- a/src/LinuxProfiler/ILDisassembler.h +++ b/src/LinuxProfiler/ILDisassembler.h @@ -16,7 +16,11 @@ namespace vanguard { il_disassembler(IModuleInfo *pModuleInfo); virtual void disassemble_function(); - virtual void initialize_function(IMethodInfo *methodInfo) { _current_method_info = methodInfo; } + virtual void initialize_function(IMethodInfo *methodInfo, function* current_function) + { + _current_method_info = methodInfo; + _current_function = current_exception; + } virtual size_t get_instructions(/* [out] */ instruction **&instructions); virtual void cleanup_function(); virtual bool instrument_function(size_t block_index); From 07a67cf57a91111dd34463bfeb18d5ccd9f41e5a Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Wed, 20 Mar 2019 18:37:07 +0530 Subject: [PATCH 61/92] zzz --- src/LinuxProfiler/ILDisassembler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LinuxProfiler/ILDisassembler.h b/src/LinuxProfiler/ILDisassembler.h index c345996f..ebcddcb7 100644 --- a/src/LinuxProfiler/ILDisassembler.h +++ b/src/LinuxProfiler/ILDisassembler.h @@ -19,7 +19,7 @@ namespace vanguard { virtual void initialize_function(IMethodInfo *methodInfo, function* current_function) { _current_method_info = methodInfo; - _current_function = current_exception; + _current_function = current_function; } virtual size_t get_instructions(/* [out] */ instruction **&instructions); virtual void cleanup_function(); From c810914338782dacd981f27b7bd3b88b260a666e Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 23 Mar 2019 12:21:38 +0530 Subject: [PATCH 62/92] instrument --- src/LinuxProfiler/CExtensionsHost.cpp | 1 + src/LinuxProfiler/ILDisassembler.cpp | 19 +++++++++++++++---- src/LinuxProfiler/ILDisassembler.h | 2 +- src/LinuxProfiler/stdafx.h | 6 ++++++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index c2e37622..62cdb2a6 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -111,6 +111,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo } releaser(disassembler); func->calculate_blocks(disassembler); + disassembler.instrument_function(); } return hr; diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp index 36651a97..2936ad0a 100644 --- a/src/LinuxProfiler/ILDisassembler.cpp +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -125,11 +125,22 @@ namespace vanguard { _current_function = nullptr; } - bool il_disassembler::instrument_function(size_t block_index) + HRESULT il_disassembler::instrument_function(/* size_t block_index */) { - mdToken methodToken; - _current_method_info->GetMethodToken(&methodToken); - method_info info(methodToken); + CComPtr sptrInstructionFactory; + IfFailRet(_current_method_info->GetInstructionFactory(&sptrInstructionFactory)); + + for (vanguard::instrumentation::managed::function::block_type* block_it = _current_function->get_blocks(); block_it < _current_function->get_blocks() + _current_function->get_block_count(); ++block_it) + { + instruction* inst = block_it->get_instructions()[0]; + IInstruction* sptrCurrent = _il_instructions[inst->get_index()]; + + CComPtr sptrReturn; + + IfFailRet(sptrInstructionFactory->CreateInstruction(Cee_Ret, &sptrReturn)); + IfFailRet(sptrInstructionGraph->InsertAfter(sptrCurrent, sptrReturn)); + sptrCurrent = sptrReturn; + } return true; } diff --git a/src/LinuxProfiler/ILDisassembler.h b/src/LinuxProfiler/ILDisassembler.h index ebcddcb7..89342bf5 100644 --- a/src/LinuxProfiler/ILDisassembler.h +++ b/src/LinuxProfiler/ILDisassembler.h @@ -23,7 +23,7 @@ namespace vanguard { } virtual size_t get_instructions(/* [out] */ instruction **&instructions); virtual void cleanup_function(); - virtual bool instrument_function(size_t block_index); + virtual HRESULT instrument_function(/* size_t block_index */); virtual module_info *get_module_info() { return _module_info; } diff --git a/src/LinuxProfiler/stdafx.h b/src/LinuxProfiler/stdafx.h index 07a62485..2451b4b8 100644 --- a/src/LinuxProfiler/stdafx.h +++ b/src/LinuxProfiler/stdafx.h @@ -55,5 +55,11 @@ using namespace std; #include "refcount.h" #include "ImplQueryInterface.h" #include "InstrumentationEngine.h" + +#ifndef IfFailRet +#define IfFailRet(EXPR) \ +do { if (FAILED(hr = (EXPR))) { ATLASSERT(!L"IfFailRet(" L#EXPR L") failed"); return hr; } } while (false) +#endif + #include "Logging.h" #include "tstring.h" From f2020a6376ece128da4812d8e9ed56148b9d6f26 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 23 Mar 2019 12:27:14 +0530 Subject: [PATCH 63/92] fix --- src/LinuxProfiler/ILDisassembler.cpp | 18 +++++++++++++----- src/LinuxProfiler/stdafx.h | 5 ----- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp index 2936ad0a..a7b6d75f 100644 --- a/src/LinuxProfiler/ILDisassembler.cpp +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -128,7 +128,12 @@ namespace vanguard { HRESULT il_disassembler::instrument_function(/* size_t block_index */) { CComPtr sptrInstructionFactory; - IfFailRet(_current_method_info->GetInstructionFactory(&sptrInstructionFactory)); + HRESULT hr = _current_method_info->GetInstructionFactory(&sptrInstructionFactory); + + if (hr != S_OK) + { + return hr; + } for (vanguard::instrumentation::managed::function::block_type* block_it = _current_function->get_blocks(); block_it < _current_function->get_blocks() + _current_function->get_block_count(); ++block_it) { @@ -137,13 +142,16 @@ namespace vanguard { CComPtr sptrReturn; - IfFailRet(sptrInstructionFactory->CreateInstruction(Cee_Ret, &sptrReturn)); - IfFailRet(sptrInstructionGraph->InsertAfter(sptrCurrent, sptrReturn)); + hr = sptrInstructionFactory->CreateInstruction(Cee_Ret, &sptrReturn); + hr = sptrInstructionGraph->InsertAfter(sptrCurrent, sptrReturn); + if (hr != S_OK) + { + return hr; + } sptrCurrent = sptrReturn; } - return true; + return hr; } - } } } \ No newline at end of file diff --git a/src/LinuxProfiler/stdafx.h b/src/LinuxProfiler/stdafx.h index 2451b4b8..4b074f7c 100644 --- a/src/LinuxProfiler/stdafx.h +++ b/src/LinuxProfiler/stdafx.h @@ -56,10 +56,5 @@ using namespace std; #include "ImplQueryInterface.h" #include "InstrumentationEngine.h" -#ifndef IfFailRet -#define IfFailRet(EXPR) \ -do { if (FAILED(hr = (EXPR))) { ATLASSERT(!L"IfFailRet(" L#EXPR L") failed"); return hr; } } while (false) -#endif - #include "Logging.h" #include "tstring.h" From d80fdfea272a87405978a2c5cb426df78f4a3965 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 23 Mar 2019 12:35:30 +0530 Subject: [PATCH 64/92] fix --- src/LinuxProfiler/ILDisassembler.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp index a7b6d75f..be2708d5 100644 --- a/src/LinuxProfiler/ILDisassembler.cpp +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -135,6 +135,14 @@ namespace vanguard { return hr; } + CComPtr sptrInstructionGraph; + hr = _current_method_info->GetInstructions(&sptrInstructionGraph); + + if (hr != S_OK) + { + return hr; + } + for (vanguard::instrumentation::managed::function::block_type* block_it = _current_function->get_blocks(); block_it < _current_function->get_blocks() + _current_function->get_block_count(); ++block_it) { instruction* inst = block_it->get_instructions()[0]; @@ -148,7 +156,6 @@ namespace vanguard { { return hr; } - sptrCurrent = sptrReturn; } return hr; } From c8224cc5c3fd0101623aacc8ca3db5bb3572cbb2 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 23 Mar 2019 12:49:39 +0530 Subject: [PATCH 65/92] fix --- src/LinuxProfiler/ILDisassembler.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp index be2708d5..ec291f8d 100644 --- a/src/LinuxProfiler/ILDisassembler.cpp +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -18,8 +18,7 @@ namespace vanguard { IInstructionGraph* instructionsGraph; HRESULT hr = _current_method_info->GetInstructions(&instructionsGraph); - std::vector _il_instructions; - + if (hr == S_OK) { IInstruction* il_inst = NULL; From aba5b05b759bbf63ada9263e11504454a3c0cf12 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 23 Mar 2019 17:14:20 +0530 Subject: [PATCH 66/92] headers --- src/LinuxProfiler/ILDisassembler.cpp | 5 +---- src/LinuxProfiler/stdafx.h | 11 +++++++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp index ec291f8d..7fcffbab 100644 --- a/src/LinuxProfiler/ILDisassembler.cpp +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -129,10 +129,7 @@ namespace vanguard { CComPtr sptrInstructionFactory; HRESULT hr = _current_method_info->GetInstructionFactory(&sptrInstructionFactory); - if (hr != S_OK) - { - return hr; - } + IfFailRet(hr); CComPtr sptrInstructionGraph; hr = _current_method_info->GetInstructions(&sptrInstructionGraph); diff --git a/src/LinuxProfiler/stdafx.h b/src/LinuxProfiler/stdafx.h index 4b074f7c..108e3187 100644 --- a/src/LinuxProfiler/stdafx.h +++ b/src/LinuxProfiler/stdafx.h @@ -24,8 +24,6 @@ #include #ifndef PLATFORM_UNIX -#include -#include #include #endif #include @@ -33,6 +31,10 @@ #include //#endif #include +#include +#include +#include +#include using namespace ATL; @@ -56,5 +58,10 @@ using namespace std; #include "ImplQueryInterface.h" #include "InstrumentationEngine.h" +#ifndef IfFailRet +#define IfFailRet(EXPR) \ +do { if (FAILED(hr = (EXPR))) { ATLASSERT(!L"IfFailRet(" L#EXPR L") failed"); return hr; } } while (false) +#endif + #include "Logging.h" #include "tstring.h" From 15dbd384feb88c841ea6f8eafd619c3be8e14f73 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 23 Mar 2019 17:15:46 +0530 Subject: [PATCH 67/92] zzz --- src/LinuxProfiler/stdafx.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/LinuxProfiler/stdafx.h b/src/LinuxProfiler/stdafx.h index 108e3187..2451b4b8 100644 --- a/src/LinuxProfiler/stdafx.h +++ b/src/LinuxProfiler/stdafx.h @@ -24,6 +24,8 @@ #include #ifndef PLATFORM_UNIX +#include +#include #include #endif #include @@ -31,10 +33,6 @@ #include //#endif #include -#include -#include -#include -#include using namespace ATL; From a4fb7dd4b04bb66ea53aa57daa19babd804e9cbc Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 23 Mar 2019 17:17:22 +0530 Subject: [PATCH 68/92] zzz --- src/LinuxProfiler/ILDisassembler.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp index 7fcffbab..780ef13a 100644 --- a/src/LinuxProfiler/ILDisassembler.cpp +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -127,10 +127,9 @@ namespace vanguard { HRESULT il_disassembler::instrument_function(/* size_t block_index */) { CComPtr sptrInstructionFactory; - HRESULT hr = _current_method_info->GetInstructionFactory(&sptrInstructionFactory); - - IfFailRet(hr); + IfFailRet(_current_method_info->GetInstructionFactory(&sptrInstructionFactory)); + HRESULT hr = S_OK; CComPtr sptrInstructionGraph; hr = _current_method_info->GetInstructions(&sptrInstructionGraph); From c7c0d90bffa5d38fbbc15ee10e5c12dcfed2e3d7 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 23 Mar 2019 17:18:59 +0530 Subject: [PATCH 69/92] zzz --- src/LinuxProfiler/ILDisassembler.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp index 780ef13a..e639620f 100644 --- a/src/LinuxProfiler/ILDisassembler.cpp +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -127,16 +127,12 @@ namespace vanguard { HRESULT il_disassembler::instrument_function(/* size_t block_index */) { CComPtr sptrInstructionFactory; - IfFailRet(_current_method_info->GetInstructionFactory(&sptrInstructionFactory)); + HRESULT hr = IfFailRet(_current_method_info->GetInstructionFactory(&sptrInstructionFactory)); + IfFailRet(hr); - HRESULT hr = S_OK; CComPtr sptrInstructionGraph; hr = _current_method_info->GetInstructions(&sptrInstructionGraph); - - if (hr != S_OK) - { - return hr; - } + IfFailRet(hr); for (vanguard::instrumentation::managed::function::block_type* block_it = _current_function->get_blocks(); block_it < _current_function->get_blocks() + _current_function->get_block_count(); ++block_it) { @@ -147,10 +143,7 @@ namespace vanguard { hr = sptrInstructionFactory->CreateInstruction(Cee_Ret, &sptrReturn); hr = sptrInstructionGraph->InsertAfter(sptrCurrent, sptrReturn); - if (hr != S_OK) - { - return hr; - } + IfFailRet(hr); } return hr; } From f30a4927a86068c2af8b089f9177aa72cde4746c Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 23 Mar 2019 17:25:50 +0530 Subject: [PATCH 70/92] on method instr --- src/LinuxProfiler/CExtensionsHost.cpp | 49 ++++++++++++++++++++------- src/LinuxProfiler/CExtensionsHost.h | 2 +- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 62cdb2a6..c7c1e610 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -16,6 +16,43 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( return S_OK; } +HRESULT ExtensionsHostCrossPlat::InstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit) +{ + BYTE pSignature[256] = {}; + DWORD cbSignature = 0; + pMethodInfo->GetCorSignature(_countof(pSignature), pSignature, &cbSignature); + + if (cbSignature < 2) + return S_FALSE; + USHORT argsCount = pSignature[1]; + + CComPtr sptrInstructionFactory; + IfFailRet(pMethodInfo->GetInstructionFactory(&sptrInstructionFactory)); + + CComPtr sptrInstructionGraph; + IfFailRet(pMethodInfo->GetInstructions(&sptrInstructionGraph)); + sptrInstructionGraph->RemoveAll(); + + CComPtr sptrCurrent; + IfFailRet(sptrInstructionGraph->GetFirstInstruction(&sptrCurrent)); + + for (USHORT i = 0; i < argsCount; i++) + { + CComPtr sptrLoadArg; + + IfFailRet(sptrInstructionFactory->CreateLoadArgInstruction(i, &sptrLoadArg)); + IfFailRet(sptrInstructionGraph->InsertAfter(sptrCurrent, sptrLoadArg)); + + sptrCurrent = sptrLoadArg; + } + + CComPtr sptrReturn; + + IfFailRet(sptrInstructionFactory->CreateInstruction(Cee_Ret, &sptrReturn)); + IfFailRet(sptrInstructionGraph->InsertAfter(sptrCurrent, sptrReturn)); + sptrCurrent = sptrReturn; +} + HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pModuleInfo) { HRESULT hr = S_OK; @@ -34,18 +71,6 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo string filePathChar(pdbPath.begin(), pdbPath.end()); - /*FILE * pFile; - pFile = fopen(filePathChar.c_str(), "r"); - - if (pFile == NULL) - { - return S_OK; - } - else - { - fclose(pFile); - }*/ - tstringstream pathBuilder; pathBuilder <<_T("/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); diff --git a/src/LinuxProfiler/CExtensionsHost.h b/src/LinuxProfiler/CExtensionsHost.h index e64dc440..387fe1af 100644 --- a/src/LinuxProfiler/CExtensionsHost.h +++ b/src/LinuxProfiler/CExtensionsHost.h @@ -68,7 +68,7 @@ namespace ExtensionsHostCrossPlat virtual HRESULT STDMETHODCALLTYPE BeforeInstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit) { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE InstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit) { return S_OK; } + virtual HRESULT STDMETHODCALLTYPE InstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit); virtual HRESULT STDMETHODCALLTYPE OnInstrumentationComplete(IMethodInfo* pMethodInfo, BOOL isRejit) { return S_OK; } From d4300d774deb6b51557f1f42c140dd32b7910aef Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 23 Mar 2019 17:28:17 +0530 Subject: [PATCH 71/92] minor --- src/LinuxProfiler/CExtensionsHost.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index c7c1e610..9a38c699 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -27,29 +27,40 @@ HRESULT ExtensionsHostCrossPlat::InstrumentMethod(_In_ IMethodInfo* pMethodInfo, USHORT argsCount = pSignature[1]; CComPtr sptrInstructionFactory; - IfFailRet(pMethodInfo->GetInstructionFactory(&sptrInstructionFactory)); + HRESULT hr = (pMethodInfo->GetInstructionFactory(&sptrInstructionFactory)); + IfFailRet(hr); CComPtr sptrInstructionGraph; - IfFailRet(pMethodInfo->GetInstructions(&sptrInstructionGraph)); + hr = (pMethodInfo->GetInstructions(&sptrInstructionGraph)); + IfFailRet(hr); + sptrInstructionGraph->RemoveAll(); CComPtr sptrCurrent; - IfFailRet(sptrInstructionGraph->GetFirstInstruction(&sptrCurrent)); + hr = (sptrInstructionGraph->GetFirstInstruction(&sptrCurrent)); + IfFailRet(hr); for (USHORT i = 0; i < argsCount; i++) { CComPtr sptrLoadArg; - IfFailRet(sptrInstructionFactory->CreateLoadArgInstruction(i, &sptrLoadArg)); - IfFailRet(sptrInstructionGraph->InsertAfter(sptrCurrent, sptrLoadArg)); + hr = (sptrInstructionFactory->CreateLoadArgInstruction(i, &sptrLoadArg)); + IfFailRet(hr); + + hr = (sptrInstructionGraph->InsertAfter(sptrCurrent, sptrLoadArg)); + IfFailRet(hr); sptrCurrent = sptrLoadArg; } CComPtr sptrReturn; - IfFailRet(sptrInstructionFactory->CreateInstruction(Cee_Ret, &sptrReturn)); - IfFailRet(sptrInstructionGraph->InsertAfter(sptrCurrent, sptrReturn)); + hr = (sptrInstructionFactory->CreateInstruction(Cee_Ret, &sptrReturn)); + IfFailRet(hr); + + hr = (sptrInstructionGraph->InsertAfter(sptrCurrent, sptrReturn)); + IfFailRet(hr); + sptrCurrent = sptrReturn; } From 106203037ee4060b7d3716d8b62612c5e6d2c880 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 23 Mar 2019 17:41:34 +0530 Subject: [PATCH 72/92] instrumnet --- src/LinuxProfiler/CExtensionsHost.cpp | 38 +++++++++++++++++++++++++++ src/LinuxProfiler/ILDisassembler.cpp | 2 +- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 9a38c699..e538e037 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -4,6 +4,8 @@ using namespace vanguard::instrumentation::managed; +vector globalMethodCol; + HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( _In_ IProfilerManager* pProfilerManager ) @@ -18,6 +20,31 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( HRESULT ExtensionsHostCrossPlat::InstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit) { + CComBSTR bstrMethodName; + pMethodInfo->GetFullName(&bstrMethodName); + + tstringstream methodName; + methodName << (LPWSTR)bstrMethodName; + + tstring methodNameWStr = methodName.str(); + string methodNameStr(methodNameWStr.begin(), methodNameWStr.end()); + + bool instrument = false; + + for (size_t a = 0; a < globalMethodCol.size(); a++) + { + if (methodNameStr.compare(globalMethodCol[i]) == 0) + { + instrument = true; + break; + } + } + + if (!instrument) + { + return S_OK; + } + BYTE pSignature[256] = {}; DWORD cbSignature = 0; pMethodInfo->GetCorSignature(_countof(pSignature), pSignature, &cbSignature); @@ -147,6 +174,17 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo } releaser(disassembler); func->calculate_blocks(disassembler); + + if (func->get_block_count() > 0) + { + tstringstream methodName; + methodName << (LPWSTR)bstrMethodName; + + tstring methodNameWStr = methodName.str(); + string methodNameStr(methodNameWStr.begin(), methodNameWStr.end()); + globalMethodCol.push_back(methodNameWStr); + } + disassembler.instrument_function(); } diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp index e639620f..9efb9d49 100644 --- a/src/LinuxProfiler/ILDisassembler.cpp +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -127,7 +127,7 @@ namespace vanguard { HRESULT il_disassembler::instrument_function(/* size_t block_index */) { CComPtr sptrInstructionFactory; - HRESULT hr = IfFailRet(_current_method_info->GetInstructionFactory(&sptrInstructionFactory)); + HRESULT hr = _current_method_info->GetInstructionFactory(&sptrInstructionFactory); IfFailRet(hr); CComPtr sptrInstructionGraph; From bf344e0690de158fe96d8309e456f434751004fb Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 23 Mar 2019 17:45:05 +0530 Subject: [PATCH 73/92] fixx --- src/LinuxProfiler/CExtensionsHost.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index e538e037..f3d9dbed 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -4,7 +4,7 @@ using namespace vanguard::instrumentation::managed; -vector globalMethodCol; +static vector globalMethodCol; HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( _In_ IProfilerManager* pProfilerManager @@ -18,7 +18,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( return S_OK; } -HRESULT ExtensionsHostCrossPlat::InstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit) +HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit) { CComBSTR bstrMethodName; pMethodInfo->GetFullName(&bstrMethodName); @@ -31,7 +31,7 @@ HRESULT ExtensionsHostCrossPlat::InstrumentMethod(_In_ IMethodInfo* pMethodInfo, bool instrument = false; - for (size_t a = 0; a < globalMethodCol.size(); a++) + for (size_t i = 0; i < globalMethodCol.size(); i++) { if (methodNameStr.compare(globalMethodCol[i]) == 0) { @@ -182,7 +182,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo tstring methodNameWStr = methodName.str(); string methodNameStr(methodNameWStr.begin(), methodNameWStr.end()); - globalMethodCol.push_back(methodNameWStr); + globalMethodCol.push_back(methodNameStr); } disassembler.instrument_function(); From 8f851cfaa4097b13d1d7751bc687a6a0aa085bf3 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 23 Mar 2019 17:46:27 +0530 Subject: [PATCH 74/92] minor --- src/LinuxProfiler/CExtensionsHost.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index f3d9dbed..9e426dae 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -89,6 +89,8 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodIn IfFailRet(hr); sptrCurrent = sptrReturn; + + return hr; } HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pModuleInfo) From 887946cf4ff1d0f0b854a107eb8495a0bc8f0e66 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 23 Mar 2019 17:52:11 +0530 Subject: [PATCH 75/92] fix --- src/LinuxProfiler/CExtensionsHost.cpp | 6 ++++++ src/LinuxProfiler/CExtensionsHost.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 9e426dae..9962646e 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -93,6 +93,12 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodIn return hr; } +HRESULT ExtensionsHostCrossPlat::CExtensionHost::ShouldInstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit, _Out_ BOOL* pbInstrument) +{ + *pbInstrument = TRUE; + return S_OK; +} + HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pModuleInfo) { HRESULT hr = S_OK; diff --git a/src/LinuxProfiler/CExtensionsHost.h b/src/LinuxProfiler/CExtensionsHost.h index 387fe1af..ec0d7d9e 100644 --- a/src/LinuxProfiler/CExtensionsHost.h +++ b/src/LinuxProfiler/CExtensionsHost.h @@ -64,7 +64,7 @@ namespace ExtensionsHostCrossPlat virtual HRESULT STDMETHODCALLTYPE OnShutdown() { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE ShouldInstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit, BOOL* pbInstrument) { return S_OK; } + virtual HRESULT STDMETHODCALLTYPE ShouldInstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit, BOOL* pbInstrument); virtual HRESULT STDMETHODCALLTYPE BeforeInstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit) { return S_OK; } From 8a071c24d13e2db925047fdb2af07f00fb303ce5 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sat, 23 Mar 2019 17:59:23 +0530 Subject: [PATCH 76/92] zzz --- src/LinuxProfiler/CExtensionsHost.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 9962646e..7368d686 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -193,7 +193,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo globalMethodCol.push_back(methodNameStr); } - disassembler.instrument_function(); + //disassembler.instrument_function(); } return hr; From 1696e373fcedd37e4674aff4ac3566c6e73338ff Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Fri, 29 Mar 2019 18:00:00 +0530 Subject: [PATCH 77/92] fix --- src/LinuxProfiler/CExtensionsHost.cpp | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 7368d686..8ad741f7 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -61,13 +61,13 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodIn hr = (pMethodInfo->GetInstructions(&sptrInstructionGraph)); IfFailRet(hr); - sptrInstructionGraph->RemoveAll(); + //sptrInstructionGraph->RemoveAll(); CComPtr sptrCurrent; hr = (sptrInstructionGraph->GetFirstInstruction(&sptrCurrent)); IfFailRet(hr); - for (USHORT i = 0; i < argsCount; i++) + /*for (USHORT i = 0; i < argsCount; i++) { CComPtr sptrLoadArg; @@ -78,7 +78,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodIn IfFailRet(hr); sptrCurrent = sptrLoadArg; - } + }*/ CComPtr sptrReturn; @@ -95,7 +95,25 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodIn HRESULT ExtensionsHostCrossPlat::CExtensionHost::ShouldInstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit, _Out_ BOOL* pbInstrument) { - *pbInstrument = TRUE; + CComBSTR bstrMethodName; + pMethodInfo->GetFullName(&bstrMethodName); + + tstringstream methodName; + methodName << (LPWSTR)bstrMethodName; + + tstring methodNameWStr = methodName.str(); + string methodNameStr(methodNameWStr.begin(), methodNameWStr.end()); + + + for (size_t i = 0; i < globalMethodCol.size(); i++) + { + if (methodNameStr.compare(globalMethodCol[i]) == 0) + { + *pbInstrument = TRUE; + break; + } + } + return S_OK; } From 2205029df7db38c4d2dba5006f1bb8446fc7a6d8 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sun, 31 Mar 2019 18:43:48 +0530 Subject: [PATCH 78/92] instr --- src/LinuxProfiler/CExtensionsHost.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 8ad741f7..80be3a6f 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -80,7 +80,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodIn sptrCurrent = sptrLoadArg; }*/ - CComPtr sptrReturn; + /*CComPtr sptrReturn; hr = (sptrInstructionFactory->CreateInstruction(Cee_Ret, &sptrReturn)); IfFailRet(hr); @@ -88,7 +88,28 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodIn hr = (sptrInstructionGraph->InsertAfter(sptrCurrent, sptrReturn)); IfFailRet(hr); - sptrCurrent = sptrReturn; + sptrCurrent = sptrReturn;*/ + + vector<__int64> vec(1); + auto data = vec.data(); + + CComPtr operandInstr; + hr = (sptrInstructionFactory->CreateIntOperandInstruction(Cee_Ldc_I8, 0ULL, &operandInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBeforeAndRetargetOffsets(sptrCurrent, operandInstr)); + IfFailRet(hr); + + CComPtr pushInstr; + hr = (sptrInstructionFactory->CreateInstruction(Cee_Ldc_I4_1, &pushInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBefore(sptrCurrent, pushInstr)); + IfFailRet(hr); + + CComPtr commitInstr; + hr = (sptrInstructionFactory->CreateInstruction(Cee_Stind_I1, &commitInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBefore(sptrCurrent, commitInstr)); + IfFailRet(hr); return hr; } From 28272af7e46f354c91eb9bd51bb2cdd5defa5a22 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sun, 31 Mar 2019 18:50:39 +0530 Subject: [PATCH 79/92] fix --- src/LinuxProfiler/CExtensionsHost.cpp | 5 +++++ src/LinuxProfiler/CExtensionsHost.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 80be3a6f..54e0eead 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -114,6 +114,11 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodIn return hr; } +HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnShutdown() +{ + return S_OK; +} + HRESULT ExtensionsHostCrossPlat::CExtensionHost::ShouldInstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit, _Out_ BOOL* pbInstrument) { CComBSTR bstrMethodName; diff --git a/src/LinuxProfiler/CExtensionsHost.h b/src/LinuxProfiler/CExtensionsHost.h index ec0d7d9e..8a64b9a6 100644 --- a/src/LinuxProfiler/CExtensionsHost.h +++ b/src/LinuxProfiler/CExtensionsHost.h @@ -62,7 +62,7 @@ namespace ExtensionsHostCrossPlat virtual HRESULT STDMETHODCALLTYPE OnModuleUnloaded(IModuleInfo* pModuleInfo) { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE OnShutdown() { return S_OK; } + virtual HRESULT STDMETHODCALLTYPE OnShutdown(); virtual HRESULT STDMETHODCALLTYPE ShouldInstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit, BOOL* pbInstrument); From 0618259324f3235049fc8665289533145491827e Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sun, 31 Mar 2019 18:55:24 +0530 Subject: [PATCH 80/92] fix --- src/LinuxProfiler/CExtensionsHost.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 54e0eead..f23032d9 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include #include "CExtensionsHost.h" +#include using namespace vanguard::instrumentation::managed; @@ -90,7 +91,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodIn sptrCurrent = sptrReturn;*/ - vector<__int64> vec(1); + vector vec(1); auto data = vec.data(); CComPtr operandInstr; From 5824e72d1c1e45e7349ef9a71ccc81b7036c065c Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sun, 31 Mar 2019 18:59:54 +0530 Subject: [PATCH 81/92] global data --- src/LinuxProfiler/CExtensionsHost.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index f23032d9..4f437fa4 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -6,6 +6,7 @@ using namespace vanguard::instrumentation::managed; static vector globalMethodCol; +static vector vec(1); HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( _In_ IProfilerManager* pProfilerManager From 6c2b2f9cd6ea3c4332e2ad0d16326e79ba86ff63 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Sun, 31 Mar 2019 19:01:45 +0530 Subject: [PATCH 82/92] imp --- src/LinuxProfiler/CExtensionsHost.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 4f437fa4..eb3dc4a7 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -92,7 +92,6 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodIn sptrCurrent = sptrReturn;*/ - vector vec(1); auto data = vec.data(); CComPtr operandInstr; From d790bef0c877e7074c59d989393a47bde7ed17a3 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Mon, 1 Apr 2019 12:07:09 +0530 Subject: [PATCH 83/92] fix --- src/LinuxProfiler/CExtensionsHost.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index eb3dc4a7..9a91b11c 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -6,7 +6,6 @@ using namespace vanguard::instrumentation::managed; static vector globalMethodCol; -static vector vec(1); HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( _In_ IProfilerManager* pProfilerManager @@ -92,10 +91,11 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodIn sptrCurrent = sptrReturn;*/ - auto data = vec.data(); + vector<__int64> vec(1); + auto data = reinterpret_cast<__int64>(std::addressof(vec[0])); CComPtr operandInstr; - hr = (sptrInstructionFactory->CreateIntOperandInstruction(Cee_Ldc_I8, 0ULL, &operandInstr)); + hr = (sptrInstructionFactory->CreateLongOperandInstruction(Cee_Ldc_I8, data, &operandInstr)); IfFailRet(hr); hr = (sptrInstructionGraph->InsertBeforeAndRetargetOffsets(sptrCurrent, operandInstr)); IfFailRet(hr); From 482a09cac568e2485c40e75c133b92fea3104ced Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Mon, 1 Apr 2019 17:55:13 +0530 Subject: [PATCH 84/92] instr module level --- src/LinuxProfiler/CExtensionsHost.cpp | 89 ++++++++++++------- src/LinuxProfiler/CExtensionsHost.h | 1 + src/LinuxProfiler/ILDisassembler.cpp | 24 ++--- src/LinuxProfiler/VanguardInstrumentation.cpp | 10 +++ src/LinuxProfiler/VanguardInstrumentation.h | 7 ++ src/LinuxProfiler/managed_function.cpp | 6 -- src/LinuxProfiler/managed_function.h | 3 + 7 files changed, 88 insertions(+), 52 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 9a91b11c..9fb35966 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -1,7 +1,6 @@ #include "stdafx.h" #include #include "CExtensionsHost.h" -#include using namespace vanguard::instrumentation::managed; @@ -11,7 +10,6 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( _In_ IProfilerManager* pProfilerManager ) { - printf("Loaded Custom Profiler"); usleep(5*1000); CComPtr pCorProfilerInfo; pProfilerManager->GetCorProfilerInfo((IUnknown**)&pCorProfilerInfo); @@ -21,7 +19,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit) { - CComBSTR bstrMethodName; + /*CComBSTR bstrMethodName; pMethodInfo->GetFullName(&bstrMethodName); tstringstream methodName; @@ -52,44 +50,49 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodIn if (cbSignature < 2) return S_FALSE; - USHORT argsCount = pSignature[1]; + USHORT argsCount = pSignature[1];*/ - CComPtr sptrInstructionFactory; - HRESULT hr = (pMethodInfo->GetInstructionFactory(&sptrInstructionFactory)); - IfFailRet(hr); - - CComPtr sptrInstructionGraph; - hr = (pMethodInfo->GetInstructions(&sptrInstructionGraph)); - IfFailRet(hr); + CComPtr pModuleInfo; + pMethodInfo->GetModuleInfo(&pModuleInfo); - //sptrInstructionGraph->RemoveAll(); + ModuleID modId; + pModuleInfo->GetModuleID(&modId); - CComPtr sptrCurrent; - hr = (sptrInstructionGraph->GetFirstInstruction(&sptrCurrent)); - IfFailRet(hr); + module_info *instrumented_module = NULL; - /*for (USHORT i = 0; i < argsCount; i++) + unordered_map::iterator it = _instrumented_modules.find(modId); + if (it != _instrumented_modules.end()) { - CComPtr sptrLoadArg; - - hr = (sptrInstructionFactory->CreateLoadArgInstruction(i, &sptrLoadArg)); - IfFailRet(hr); + mdToken token; + pMethodInfo->GetMethodToken(&token); + instrumented_module = it->second; + } - hr = (sptrInstructionGraph->InsertAfter(sptrCurrent, sptrLoadArg)); - IfFailRet(hr); + mdMethodDef token; + pMethodInfo->GetMethodToken(&token); - sptrCurrent = sptrLoadArg; - }*/ + method_info info; + bool result = instrumented_module->get_method_info(token, info); - /*CComPtr sptrReturn; + if (result) + { + il_disassembler disassembler(pModuleInfo); + auto block_indices = info.get_block_indexes(); + auto start_index = info.get_start_index(); + void const *coverage_buffer = instrumented_module->get_coverage_buffer(); + } - hr = (sptrInstructionFactory->CreateInstruction(Cee_Ret, &sptrReturn)); + CComPtr sptrInstructionFactory; + HRESULT hr = (pMethodInfo->GetInstructionFactory(&sptrInstructionFactory)); IfFailRet(hr); - hr = (sptrInstructionGraph->InsertAfter(sptrCurrent, sptrReturn)); + CComPtr sptrInstructionGraph; + hr = (pMethodInfo->GetInstructions(&sptrInstructionGraph)); IfFailRet(hr); - sptrCurrent = sptrReturn;*/ + CComPtr sptrCurrent; + hr = (sptrInstructionGraph->GetFirstInstruction(&sptrCurrent)); + IfFailRet(hr); vector<__int64> vec(1); auto data = reinterpret_cast<__int64>(std::addressof(vec[0])); @@ -122,7 +125,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnShutdown() HRESULT ExtensionsHostCrossPlat::CExtensionHost::ShouldInstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit, _Out_ BOOL* pbInstrument) { - CComBSTR bstrMethodName; + /*CComBSTR bstrMethodName; pMethodInfo->GetFullName(&bstrMethodName); tstringstream methodName; @@ -139,6 +142,21 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::ShouldInstrumentMethod(_In_ IMe *pbInstrument = TRUE; break; } + }*/ + + CComPtr pModuleInfo; + pMethodInfo->GetModuleInfo(&pModuleInfo); + + ModuleID modId; + pModuleInfo->GetModuleID(&modId); + + unordered_map::iterator it = _instrumented_modules.find(modId); + if (it != _instrumented_modules.end()) + { + mdToken token; + pMethodInfo->GetMethodToken(&token); + module_info *info = it->second; + *pbInstrument = info->contains_instrumented_method(token); } return S_OK; @@ -210,6 +228,8 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo //printf("Method Name: %ls \n ", bstrMethodName); vanguard::instrumentation::managed::function* func = new vanguard::instrumentation::managed::function(); + func->set_token(token); + disassembler.initialize_function(methodInfo, func); disassembler.disassemble_function(); @@ -236,10 +256,17 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo tstring methodNameWStr = methodName.str(); string methodNameStr(methodNameWStr.begin(), methodNameWStr.end()); globalMethodCol.push_back(methodNameStr); + disassembler.instrument_function(); } - - //disassembler.instrument_function(); } + ModuleID modId; + pModuleInfo->GetModuleID(&modId); + + module_info* info = disassembler.get_module_info(); + info->set_block_count(disassembler.get_global_block_count()); + + _instrumented_modules.insert(make_pair(modId, info)); + return hr; } diff --git a/src/LinuxProfiler/CExtensionsHost.h b/src/LinuxProfiler/CExtensionsHost.h index 8a64b9a6..e82fbc3a 100644 --- a/src/LinuxProfiler/CExtensionsHost.h +++ b/src/LinuxProfiler/CExtensionsHost.h @@ -77,6 +77,7 @@ namespace ExtensionsHostCrossPlat private: HMODULE m_hmod = NULL; + unordered_map_instrumented_modules; }; diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp index 9efb9d49..85743fe3 100644 --- a/src/LinuxProfiler/ILDisassembler.cpp +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -126,26 +126,20 @@ namespace vanguard { HRESULT il_disassembler::instrument_function(/* size_t block_index */) { - CComPtr sptrInstructionFactory; - HRESULT hr = _current_method_info->GetInstructionFactory(&sptrInstructionFactory); - IfFailRet(hr); - - CComPtr sptrInstructionGraph; - hr = _current_method_info->GetInstructions(&sptrInstructionGraph); - IfFailRet(hr); - + method_info info(_current_function->get_token()); for (vanguard::instrumentation::managed::function::block_type* block_it = _current_function->get_blocks(); block_it < _current_function->get_blocks() + _current_function->get_block_count(); ++block_it) { instruction* inst = block_it->get_instructions()[0]; - IInstruction* sptrCurrent = _il_instructions[inst->get_index()]; - - CComPtr sptrReturn; - hr = sptrInstructionFactory->CreateInstruction(Cee_Ret, &sptrReturn); - hr = sptrInstructionGraph->InsertAfter(sptrCurrent, sptrReturn); - IfFailRet(hr); + info.add_block_index(inst->get_index()); } - return hr; + + info.set_start_index(_global_block_count); + _module_info->add_instrumented_functions(info); + + _global_block_count += _current_function->get_block_count(); + + return S_OK; } } } diff --git a/src/LinuxProfiler/VanguardInstrumentation.cpp b/src/LinuxProfiler/VanguardInstrumentation.cpp index 7c96dbca..95391f75 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.cpp +++ b/src/LinuxProfiler/VanguardInstrumentation.cpp @@ -16,4 +16,14 @@ bool module_info::get_method_info(mdToken token, method_info& info) } return false; +} + +void module_info::set_block_count(size_t block_count) +{ + _block_count = block_count; + for (size_t i = 0; i < block_count; ++i) + { + _coverage_buffer.push_back(0); + } + } \ No newline at end of file diff --git a/src/LinuxProfiler/VanguardInstrumentation.h b/src/LinuxProfiler/VanguardInstrumentation.h index 8d7bd8c0..258a36eb 100644 --- a/src/LinuxProfiler/VanguardInstrumentation.h +++ b/src/LinuxProfiler/VanguardInstrumentation.h @@ -39,9 +39,16 @@ struct module_info bool contains_instrumented_method(mdToken token); bool get_method_info(mdToken token, method_info& info); + size_t get_block_count() { return _block_count; } + void set_block_count(size_t block_count); + + void const* get_coverage_buffer() { return (std::addressof(_coverage_buffer[0])); } + private: unordered_map _instrumented_functions_list; IModuleInfo *_current_module_info; + size_t _block_count; + vector<__int64> _coverage_buffer; /* address to buffer where probes mark their value */ }; diff --git a/src/LinuxProfiler/managed_function.cpp b/src/LinuxProfiler/managed_function.cpp index 9dce8b7c..d9a4a0bf 100644 --- a/src/LinuxProfiler/managed_function.cpp +++ b/src/LinuxProfiler/managed_function.cpp @@ -56,12 +56,6 @@ namespace vanguard { if (!last_inst || !last_inst->is_fall_through()) { (*it)->set_starts_block(true); - // For Assembly.Load / AssemblyLoadContext.LoadFromStream, we need to instrument the function start - // i.e., the first block - if (_is_assembly_load) - { - break; - } } // 2. Mark the targets of branches as start of a block diff --git a/src/LinuxProfiler/managed_function.h b/src/LinuxProfiler/managed_function.h index 91f230af..b0243678 100644 --- a/src/LinuxProfiler/managed_function.h +++ b/src/LinuxProfiler/managed_function.h @@ -71,6 +71,9 @@ namespace vanguard { //! Gets the function's metadata token. uint32_t get_token() const { return _token; } + //! Sets the function's metadata token. + void set_token(uint32_t token) { _token = token; } + //! Gets the function's type's metadata token. uint32_t get_type_token() const { return _type_token; } From c04f868768e7d4b562a457737ec413d5271a8777 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Mon, 1 Apr 2019 17:57:48 +0530 Subject: [PATCH 85/92] errors --- src/LinuxProfiler/CExtensionsHost.cpp | 3 ++- src/LinuxProfiler/ILDisassembler.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 9fb35966..406df292 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -220,7 +220,8 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pMo IMethodInfo* methodInfo = NULL; CComBSTR bstrMethodName; - methodInfoResult = pModuleInfo->GetMethodInfoByToken(baseToken | methodDef, &methodInfo); + mdMethodDef token = baseToken | methodDef; + methodInfoResult = pModuleInfo->GetMethodInfoByToken(token, &methodInfo); methodInfoCollection.push_back(methodInfo); methodDef++; methodCount--; diff --git a/src/LinuxProfiler/ILDisassembler.h b/src/LinuxProfiler/ILDisassembler.h index 89342bf5..2c0db568 100644 --- a/src/LinuxProfiler/ILDisassembler.h +++ b/src/LinuxProfiler/ILDisassembler.h @@ -27,6 +27,8 @@ namespace vanguard { virtual module_info *get_module_info() { return _module_info; } + size_t get_global_block_count() { return _global_block_count; } + private: template target_type lookup(source_type source, std::unordered_map &input_map, target_type default_value) From 7e2827f6d81f0a2637e8832dddf9a0c879fe7359 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Mon, 1 Apr 2019 18:07:54 +0530 Subject: [PATCH 86/92] fixes --- src/LinuxProfiler/CExtensionsHost.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 406df292..e40762e8 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -19,7 +19,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit) { - /*CComBSTR bstrMethodName; + CComBSTR bstrMethodName; pMethodInfo->GetFullName(&bstrMethodName); tstringstream methodName; @@ -50,7 +50,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodIn if (cbSignature < 2) return S_FALSE; - USHORT argsCount = pSignature[1];*/ + USHORT argsCount = pSignature[1]; CComPtr pModuleInfo; pMethodInfo->GetModuleInfo(&pModuleInfo); @@ -125,7 +125,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnShutdown() HRESULT ExtensionsHostCrossPlat::CExtensionHost::ShouldInstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit, _Out_ BOOL* pbInstrument) { - /*CComBSTR bstrMethodName; + CComBSTR bstrMethodName; pMethodInfo->GetFullName(&bstrMethodName); tstringstream methodName; @@ -142,7 +142,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::ShouldInstrumentMethod(_In_ IMe *pbInstrument = TRUE; break; } - }*/ + } CComPtr pModuleInfo; pMethodInfo->GetModuleInfo(&pModuleInfo); From 979b624fc6a1b6e2439d12f43dcbee12f6c41afa Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Mon, 1 Apr 2019 18:15:03 +0530 Subject: [PATCH 87/92] idiot --- src/LinuxProfiler/ILDisassembler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp index 85743fe3..0047fc40 100644 --- a/src/LinuxProfiler/ILDisassembler.cpp +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -5,7 +5,7 @@ namespace vanguard { namespace instrumentation { namespace managed { - il_disassembler::il_disassembler(IModuleInfo *pModuleInfo) + il_disassembler::il_disassembler(IModuleInfo *pModuleInfo) : _global_block_count(0) { _module_info = new module_info(pModuleInfo); _current_function = nullptr; From 3070c817d7b01b41eebf197c70dab1a93b929958 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Mon, 1 Apr 2019 18:31:27 +0530 Subject: [PATCH 88/92] remove --- src/LinuxProfiler/CExtensionsHost.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index e40762e8..406df292 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -19,7 +19,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit) { - CComBSTR bstrMethodName; + /*CComBSTR bstrMethodName; pMethodInfo->GetFullName(&bstrMethodName); tstringstream methodName; @@ -50,7 +50,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodIn if (cbSignature < 2) return S_FALSE; - USHORT argsCount = pSignature[1]; + USHORT argsCount = pSignature[1];*/ CComPtr pModuleInfo; pMethodInfo->GetModuleInfo(&pModuleInfo); @@ -125,7 +125,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnShutdown() HRESULT ExtensionsHostCrossPlat::CExtensionHost::ShouldInstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit, _Out_ BOOL* pbInstrument) { - CComBSTR bstrMethodName; + /*CComBSTR bstrMethodName; pMethodInfo->GetFullName(&bstrMethodName); tstringstream methodName; @@ -142,7 +142,7 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::ShouldInstrumentMethod(_In_ IMe *pbInstrument = TRUE; break; } - } + }*/ CComPtr pModuleInfo; pMethodInfo->GetModuleInfo(&pModuleInfo); From cfd1995a3e809bd00ee46844d8ff1c17cc7c80cf Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Tue, 2 Apr 2019 14:15:16 +0530 Subject: [PATCH 89/92] instr --- src/LinuxProfiler/CExtensionsHost.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 406df292..26015c8d 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -94,11 +94,11 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodIn hr = (sptrInstructionGraph->GetFirstInstruction(&sptrCurrent)); IfFailRet(hr); - vector<__int64> vec(1); - auto data = reinterpret_cast<__int64>(std::addressof(vec[0])); + auto index = reinterpret_cast<__int64>(coverage_buffer); + index = index + info.get_start_index(); CComPtr operandInstr; - hr = (sptrInstructionFactory->CreateLongOperandInstruction(Cee_Ldc_I8, data, &operandInstr)); + hr = (sptrInstructionFactory->CreateLongOperandInstruction(Cee_Ldc_I8, index, &operandInstr)); IfFailRet(hr); hr = (sptrInstructionGraph->InsertBeforeAndRetargetOffsets(sptrCurrent, operandInstr)); IfFailRet(hr); From fae3edfdfafdea82f07c30d51371be79b36175b8 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Tue, 2 Apr 2019 14:16:46 +0530 Subject: [PATCH 90/92] fix --- src/LinuxProfiler/CExtensionsHost.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp index 26015c8d..8def3172 100644 --- a/src/LinuxProfiler/CExtensionsHost.cpp +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -74,14 +74,15 @@ HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodIn method_info info; bool result = instrumented_module->get_method_info(token, info); - if (result) + if (!result) { - il_disassembler disassembler(pModuleInfo); - auto block_indices = info.get_block_indexes(); - auto start_index = info.get_start_index(); - void const *coverage_buffer = instrumented_module->get_coverage_buffer(); + return S_OK; } + auto block_indices = info.get_block_indexes(); + auto start_index = info.get_start_index(); + void const *coverage_buffer = instrumented_module->get_coverage_buffer(); + CComPtr sptrInstructionFactory; HRESULT hr = (pMethodInfo->GetInstructionFactory(&sptrInstructionFactory)); IfFailRet(hr); From e1a856eb40c1e6fec9e64a9d2e93583ea07f6e6a Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Fri, 5 Apr 2019 20:41:37 +0530 Subject: [PATCH 91/92] copy this --- .../InstrumentationMethod.cpp | 667 ++++++++++++++++++ 1 file changed, 667 insertions(+) create mode 100644 SeafoodInstrumentation/InstrumentationMethod.cpp diff --git a/SeafoodInstrumentation/InstrumentationMethod.cpp b/SeafoodInstrumentation/InstrumentationMethod.cpp new file mode 100644 index 00000000..aea42eb5 --- /dev/null +++ b/SeafoodInstrumentation/InstrumentationMethod.cpp @@ -0,0 +1,667 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#include "stdafx.h" +#include "InstrumentationMethod.h" +#include +#include "ProfilerManagerHost.h" +#include "Util.h" +#include "ILDisassembler.h" + +using namespace vanguard::instrumentation::managed; + +static vector globalMethodCol; + +HRESULT CInstrumentationMethod::Initialize(_In_ IProfilerManager* pProfilerManager) +{ + m_pProfilerManager = pProfilerManager; + + CHandle hConfigThread; + hConfigThread.Attach(CreateThread(NULL, 0, InstrumentationMethodThreadProc, this, 0, NULL)); + + DWORD retVal = WaitForSingleObject(hConfigThread, 15000); + + if (m_bExceptionTrackingEnabled) + { + CComPtr pCorProfilerInfo; + pProfilerManager->GetCorProfilerInfo((IUnknown**)&pCorProfilerInfo); + pCorProfilerInfo->SetEventMask(COR_PRF_MONITOR_EXCEPTIONS | COR_PRF_ENABLE_STACK_SNAPSHOT); + + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + } + + return S_OK; +} + +// The CLR doesn't initialize com before calling the profiler, and the profiler manager cannot do so itself +// as that would screw up the com state for the application's thread. Spin up a new thread to allow the instrumentation +// method to co create a free threaded version of msxml on a thread that it owns to avoid this. +DWORD WINAPI CInstrumentationMethod::InstrumentationMethodThreadProc( + _In_ LPVOID lpParameter +) +{ + CoInitialize(NULL); + + CInstrumentationMethod* pThis = (CInstrumentationMethod*)lpParameter; + CoUninitialize(); + + return S_OK; +} + +HRESULT CInstrumentationMethod::OnAppDomainCreated( + _In_ IAppDomainInfo *pAppDomainInfo) +{ + return S_OK; +} + +HRESULT CInstrumentationMethod::OnAppDomainShutdown( + _In_ IAppDomainInfo *pAppDomainInfo) +{ + return S_OK; +} + +HRESULT CInstrumentationMethod::OnAssemblyLoaded(_In_ IAssemblyInfo* pAssemblyInfo) +{ + return S_OK; +} + +HRESULT CInstrumentationMethod::OnAssemblyUnloaded(_In_ IAssemblyInfo* pAssemblyInfo) +{ + return S_OK; +} + +HRESULT CInstrumentationMethod::OnModuleLoaded(_In_ IModuleInfo* pModuleInfo) +{ + HRESULT hr = S_OK; + + CComBSTR bstrModuleName; + IfFailRet(pModuleInfo->GetModuleName(&bstrModuleName)); + + CComBSTR bstrModulePath; + IfFailRet(pModuleInfo->GetFullPath(&bstrModulePath)); + + std::wstring path(bstrModulePath, SysStringLen(bstrModulePath)); + wstring pdbFile = path.substr(0, path.find_last_of(L'.')) + L".pdb"; + + FILE *file; + _wfopen_s(&file, pdbFile.c_str(), L"r"); + + if (file == NULL) + { + return S_OK; + } + else + { + fclose(file); + } + + if (m_hmod == NULL) + { + m_hmod = ::LoadLibrary(L"E:/xplat/CLRInstrumentationEngine/x64/Debug/BJSBReader.dll"); + } + + if (m_hmod != NULL) + { + ReadPdb pfnReadPdb = (ReadPdb)GetProcAddress(m_hmod, "ReadPdb"); + if (!pfnReadPdb) + { + auto error = ::GetLastError(); + FreeLibrary(m_hmod); + return HRESULT_FROM_WIN32(error); + } + + int methodCount = pfnReadPdb(pdbFile); + + const mdMethodDef baseToken = 0x06 << 24; + mdMethodDef methodDef = 1; + HRESULT methodInfoResult = S_OK; + vector methodInfoCollection; + + il_disassembler disassembler(pModuleInfo); + + while (methodCount) + { + IMethodInfo* methodInfo = NULL; + CComBSTR bstrMethodName; + + mdMethodDef token = baseToken | methodDef; + methodInfoResult = pModuleInfo->GetMethodInfoByToken(token, &methodInfo); + methodInfoCollection.push_back(methodInfo); + methodDef++; + methodCount--; + methodInfo->GetFullName(&bstrMethodName); + printf("Method Name: %S \n ", bstrMethodName); + + vanguard::instrumentation::managed::function* func = new vanguard::instrumentation::managed::function(); + func->set_token(token); + + disassembler.initialize_function(methodInfo, func); + disassembler.disassemble_function(); + + struct function_releaser + { + function_releaser(il_disassembler& d) : + _disassembler(d) + { + } + + ~function_releaser() { _disassembler.cleanup_function(); } + + private: + il_disassembler& _disassembler; + } releaser(disassembler); + + func->calculate_blocks(disassembler); + + if (func->get_block_count() > 0) + { + std::wstring methodNameStr(bstrMethodName, SysStringLen(bstrMethodName)); + globalMethodCol.push_back(methodNameStr); + + disassembler.instrument_function(); + } + } + + ModuleID modId; + pModuleInfo->GetModuleID(&modId); + + module_info* info = disassembler.get_module_info(); + info->set_block_count(disassembler.get_global_block_count()); + + _instrumented_modules.insert(make_pair(modId, info)); + + /*for each (IMethodInfo* methodInfo in methodInfoCollection) + { + IInstructionGraph* instructionsGraph; + HRESULT hr = methodInfo->GetInstructions(&instructionsGraph); + + if (hr == S_OK) + { + std::vector _il_instructions; + IInstruction* instruction = NULL; + + HRESULT instructionData = instructionsGraph->GetFirstInstruction(&instruction); + _il_instructions.push_back(instruction); + + while (instructionData == S_OK) + { + IInstruction* nextInstruction = NULL; + instructionData = instruction->GetNextInstruction(&nextInstruction); + + _il_instructions.push_back(nextInstruction); + instruction = nextInstruction; + } + } + }*/ + } + + return S_OK; +} + +HRESULT CInstrumentationMethod::OnModuleUnloaded(_In_ IModuleInfo* pModuleInfo) +{ + return S_OK; +} + +HRESULT CInstrumentationMethod::OnShutdown() +{ + if (m_bExceptionTrackingEnabled) + { + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + } + return S_OK; +} + +HRESULT CInstrumentationMethod::ShouldInstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit, _Out_ BOOL* pbInstrument) +{ + /*CComBSTR bstrMethodName; + pMethodInfo->GetFullName(&bstrMethodName); + + std::wstring methodNameStr(bstrMethodName, SysStringLen(bstrMethodName)); + + for (size_t i = 0; i < globalMethodCol.size(); i++) + { + if (methodNameStr.compare(globalMethodCol[i]) == 0) + { + *pbInstrument = TRUE; + break; + } + }*/ + + CComPtr pModuleInfo; + pMethodInfo->GetModuleInfo(&pModuleInfo); + + ModuleID modId; + pModuleInfo->GetModuleID(&modId); + + unordered_map::iterator it = _instrumented_modules.find(modId); + if (it != _instrumented_modules.end()) + { + mdToken token; + pMethodInfo->GetMethodToken(&token); + module_info *info = it->second; + *pbInstrument = info->contains_instrumented_method(token); + } + + return S_OK; +} + +HRESULT CInstrumentationMethod::InstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit) +{ + /* CComBSTR bstrMethodName; + pMethodInfo->GetFullName(&bstrMethodName); + + std::wstring methodNameStr(bstrMethodName, SysStringLen(bstrMethodName)); + + bool instrument = false; + + for (size_t i = 0; i < globalMethodCol.size(); i++) + { + if (methodNameStr.compare(globalMethodCol[i]) == 0) + { + instrument = true; + break; + } + } + + if (!instrument) + { + return S_OK; + } + + BYTE pSignature[256] = {}; + DWORD cbSignature = 0; + pMethodInfo->GetCorSignature(_countof(pSignature), pSignature, &cbSignature); + + if (cbSignature < 2) + return S_FALSE; + USHORT argsCount = pSignature[1];*/ + + CComPtr pModuleInfo; + pMethodInfo->GetModuleInfo(&pModuleInfo); + + ModuleID modId; + pModuleInfo->GetModuleID(&modId); + + module_info *instrumented_module = NULL; + + unordered_map::iterator it = _instrumented_modules.find(modId); + if (it != _instrumented_modules.end()) + { + mdToken token; + pMethodInfo->GetMethodToken(&token); + instrumented_module = it->second; + } + + mdMethodDef token; + pMethodInfo->GetMethodToken(&token); + + method_info info; + bool result = instrumented_module->get_method_info(token, info); + + if (!result) + { + return S_OK; + } + + auto block_indices = info.get_block_indexes(); + auto start_index = info.get_start_index(); + void const *coverage_buffer = instrumented_module->get_coverage_buffer(); + + auto index = reinterpret_cast<__int64>(coverage_buffer); + index = index + info.get_start_index(); + + CComPtr sptrInstructionGraph; + HRESULT hr = (pMethodInfo->GetInstructions(&sptrInstructionGraph)); + IfFailRet(hr); + + std::vector il_instructions; + CComPtr il_inst; + + hr = sptrInstructionGraph->GetFirstInstruction(&il_inst); + il_instructions.push_back(il_inst); + + while (hr == S_OK) + { + CComPtr nextInstruction; + hr = il_inst->GetNextInstruction(&nextInstruction); + + if (hr != S_OK) + { + break; + } + + il_instructions.push_back(nextInstruction); + il_inst = nextInstruction; + } + + CComPtr sptrInstructionFactory; + hr = (pMethodInfo->GetInstructionFactory(&sptrInstructionFactory)); + IfFailRet(hr); + + for (auto loc = block_indices.begin(); loc < block_indices.end(); ++loc) + { + CComPtr il_inst = il_instructions[*loc]; + + CComPtr operandInstr; + hr = (sptrInstructionFactory->CreateLongOperandInstruction(Cee_Ldc_I8, index, &operandInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBeforeAndRetargetOffsets(il_inst, operandInstr)); + IfFailRet(hr); + + CComPtr pushInstr; + hr = (sptrInstructionFactory->CreateInstruction(Cee_Ldc_I4_1, &pushInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBefore(il_inst, pushInstr)); + IfFailRet(hr); + + CComPtr commitInstr; + hr = (sptrInstructionFactory->CreateInstruction(Cee_Stind_I1, &commitInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBefore(il_inst, commitInstr)); + IfFailRet(hr); + + ++index; + } + + + /*CComPtr sptrCurrent; + hr = (sptrInstructionGraph->GetFirstInstruction(&sptrCurrent)); + IfFailRet(hr); + + CComPtr operandInstr; + hr = (sptrInstructionFactory->CreateLongOperandInstruction(Cee_Ldc_I8, index, &operandInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBeforeAndRetargetOffsets(sptrCurrent, operandInstr)); + IfFailRet(hr); + + CComPtr pushInstr; + hr = (sptrInstructionFactory->CreateInstruction(Cee_Ldc_I4_1, &pushInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBefore(sptrCurrent, pushInstr)); + IfFailRet(hr); + + CComPtr commitInstr; + hr = (sptrInstructionFactory->CreateInstruction(Cee_Stind_I1, &commitInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBefore(sptrCurrent, commitInstr)); + IfFailRet(hr);*/ + + return hr; +} + +HRESULT CInstrumentationMethod::AllowInlineSite(_In_ IMethodInfo* pMethodInfoInlinee, _In_ IMethodInfo* pMethodInfoCaller, _Out_ BOOL* pbAllowInline) +{ + *pbAllowInline = FALSE; + return S_OK; +} + + +HRESULT CInstrumentationMethod::ExceptionCatcherEnter( + _In_ IMethodInfo* pMethodInfo, + _In_ UINT_PTR objectId +) +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + CComBSTR bstrFullName; + pMethodInfo->GetFullName(&bstrFullName); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("")); + pProfilerManagerHost->LogDumpMessage(bstrFullName); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionCatcherLeave() +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionSearchCatcherFound( + _In_ IMethodInfo* pMethodInfo +) +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + CComBSTR bstrFullName; + pMethodInfo->GetFullName(&bstrFullName); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("")); + pProfilerManagerHost->LogDumpMessage(bstrFullName); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionSearchFilterEnter( + _In_ IMethodInfo* pMethodInfo +) +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + CComBSTR bstrFullName; + pMethodInfo->GetFullName(&bstrFullName); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("")); + pProfilerManagerHost->LogDumpMessage(bstrFullName); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionSearchFilterLeave() +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionSearchFunctionEnter( + _In_ IMethodInfo* pMethodInfo +) +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + CComBSTR bstrFullName; + pMethodInfo->GetFullName(&bstrFullName); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("")); + pProfilerManagerHost->LogDumpMessage(bstrFullName); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionSearchFunctionLeave() +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionThrown( + _In_ UINT_PTR thrownObjectId +) +{ + HRESULT hr = S_OK; + + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + CComPtr pCorProfilerInfo; + IfFailRet(m_pProfilerManager->GetCorProfilerInfo((IUnknown**)&pCorProfilerInfo)); + + CComPtr pCorProfilerInfo2; + pCorProfilerInfo->QueryInterface(__uuidof(ICorProfilerInfo2), (void**)&pCorProfilerInfo2); + + IfFailRet(pCorProfilerInfo2->DoStackSnapshot( + NULL, + StackSnapshotCallbackExceptionThrown, + COR_PRF_SNAPSHOT_DEFAULT, + this, + nullptr, + 0)); + + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +// static +HRESULT CInstrumentationMethod::StackSnapshotCallbackExceptionThrown( + _In_ FunctionID funcId, + _In_ UINT_PTR ip, + _In_ COR_PRF_FRAME_INFO frameInfo, + _In_ ULONG32 contextSize, + _In_reads_(contextSize) BYTE context[], + _In_ void *clientData +) +{ + HRESULT hr = S_OK; + CInstrumentationMethod* pThis = (CInstrumentationMethod*)clientData; + + IfFailRet(pThis->HandleStackSnapshotCallbackExceptionThrown( + funcId, + ip, + frameInfo, + contextSize, + context + )); + + return S_OK; +} + +HRESULT CInstrumentationMethod::HandleStackSnapshotCallbackExceptionThrown( + _In_ FunctionID funcId, + _In_ UINT_PTR ip, + _In_ COR_PRF_FRAME_INFO frameInfo, + _In_ ULONG32 contextSize, + _In_reads_(contextSize) BYTE context[] +) +{ + HRESULT hr = S_OK; + + if (funcId == 0) + { + // Can't do anything if there is no function id + return S_OK; + } + + CComPtr pAppDomainCollection; + IfFailRet(m_pProfilerManager->GetAppDomainCollection(&pAppDomainCollection)); + + CComPtr pMethodInfo; + IfFailRet(pAppDomainCollection->GetMethodInfoById(funcId, &pMethodInfo)); + + CComBSTR bstrMethodName; + IfFailRet(pMethodInfo->GetName(&bstrMethodName)); + + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("")); + pProfilerManagerHost->LogDumpMessage(bstrMethodName); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + + // verify other code paths that don't contribute to actual baseline + // This is just to get coverage on althernative code paths to obtain method infos + CComPtr pModuleInfo; + IfFailRet(pMethodInfo->GetModuleInfo(&pModuleInfo)); + mdToken methodToken; + IfFailRet(pMethodInfo->GetMethodToken(&methodToken)); + + CComPtr pMethodInfo2; + IfFailRet(pModuleInfo->GetMethodInfoByToken(methodToken, &pMethodInfo2)); + + CComBSTR bstrMethodName2; + IfFailRet(pMethodInfo2->GetName(&bstrMethodName2)); + + if (bstrMethodName != bstrMethodName2) + { + pProfilerManagerHost->LogDumpMessage(_T("pModuleInfo->GetMethodInfoByToken did not return same method as pAppDomainCollection->GetMethodInfoById")); + return S_OK; + } + + CComPtr pInstructionGraph; + IfFailRet(pMethodInfo2->GetInstructions(&pInstructionGraph)); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionUnwindFinallyEnter( + _In_ IMethodInfo* pMethodInfo +) +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + CComBSTR bstrFullName; + pMethodInfo->GetFullName(&bstrFullName); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("")); + pProfilerManagerHost->LogDumpMessage(bstrFullName); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionUnwindFinallyLeave() +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionUnwindFunctionEnter( + _In_ IMethodInfo* pMethodInfo +) +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + CComBSTR bstrFullName; + pMethodInfo->GetFullName(&bstrFullName); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("")); + pProfilerManagerHost->LogDumpMessage(bstrFullName); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionUnwindFunctionLeave() +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} From a1dcb8928a9af42c8c1327dc7a3a8816ba39f318 Mon Sep 17 00:00:00 2001 From: Jakub Chocholowicz Date: Sat, 18 Apr 2020 01:38:20 +0200 Subject: [PATCH 92/92] CHanges --- src/CMakeLists.txt | 16 +++----- src/LinuxProfiler/stdafx.h | 77 +++++++++++++++++++++++++++++--------- 2 files changed, 64 insertions(+), 29 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e82392da..ce42164f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -118,14 +118,10 @@ macro (build_init build_language build_type) # add_definitions(-D_DEBUG) TODO: Enable this endif () - if(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64) - message("Detected Linux x86_64") - add_definitions(-DLINUX64) - add_definitions(-D_M_AMD64) - add_definitions(-DTARGET_AMD64) - else (CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64) - message(FATAL_ERROR "error: Detected non x86_64 target processor. Not supported!") - endif(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64) + message("Detected Linux x86_64") + add_definitions(-DLINUX64) + add_definitions(-D_M_AMD64) + add_definitions(-DTARGET_AMD64) # Ignored warnings # TODO: Reenable these @@ -242,9 +238,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL Linux) endif(CMAKE_SYSTEM_NAME STREQUAL Linux) # Set flag to indicate if this will be a 64bit Linux build -if(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64) - set(IS_64BIT_BUILD 1) -endif (CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64) +set(IS_64BIT_BUILD 1) # Ensure that on MacOS, dylibs are referenced as '@rpath/example.dylib' instead of just 'example.dylib'. Otherwise they # will not be found unless the working directory == vsdbg directory. diff --git a/src/LinuxProfiler/stdafx.h b/src/LinuxProfiler/stdafx.h index 2451b4b8..c9f934d6 100644 --- a/src/LinuxProfiler/stdafx.h +++ b/src/LinuxProfiler/stdafx.h @@ -1,21 +1,26 @@ // Copyright (c) Microsoft Corporation. All rights reserved. -// +// Licensed under the MIT License. + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// #pragma once #ifdef PLATFORM_UNIX #include "unix.h" #include +#include +#include #endif #include "targetver.h" -#ifndef PLATFORM_UNIX -#include -#endif -#include "string.h" -//#include +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include +#include "string.h" #include // for pfn_REPORTFAULT #include @@ -39,27 +44,63 @@ using namespace ATL; #include #include #include -#include "CorHeaders.h" #include -#include "Macros.h" +#ifndef PLATFORM_UNIX +#include +#include +#else +#include +#include +#endif + + +#ifdef PLATFORM_UNIX +#include +#endif + +#ifdef PLATFORM_UNIX +// pal.h defines these, but they aren't picked up for our build because std_c++ compatibility is defined +// in CMakeFile.txt +#define PAL_wcsnlen_s(a, b) (a != nullptr) ? PAL_wcsnlen(a, b) : 0 +#define wcsstr PAL_wcsstr +#define wcslen PAL_wcslen +#define wcsnlen_s PAL_wcsnlen_s +#endif +#include #include #include #include -#include "CriticalSectionHolder.h" +#ifdef PLATFORM_UNIX +// pal.h defines these, but they aren't picked up for our build because std_c++ compatibility is defined +// in CMakeFile.txt +#define fclose PAL_fclose +#define fflush PAL_fflush +#define fprintf PAL_fprintf +#define fwprintf PAL_fwprintf +#endif -using namespace std; +#include +#include +#include +#ifdef PLATFORM_UNIX +#include +#endif -#include "refcount.h" +#include "Logging.h" #include "ImplQueryInterface.h" -#include "InstrumentationEngine.h" +#include "refcount.h" +#include "SharedArray.h" -#ifndef IfFailRet -#define IfFailRet(EXPR) \ -do { if (FAILED(hr = (EXPR))) { ATLASSERT(!L"IfFailRet(" L#EXPR L") failed"); return hr; } } while (false) -#endif +#include "../Common.Lib/tstring.h" +#include "../Common.Lib/Macros.h" +#include "../Common.Lib/CriticalSectionHolder.h" +#include "../Common.Lib/InitOnce.h" +#include "../Common.Lib/Singleton.h" -#include "Logging.h" -#include "tstring.h" +#include "../Common.Lib/banned.h" + +using namespace std; +using namespace MicrosoftInstrumentationEngine; \ No newline at end of file