在 Linux 平台上为 .NET 构建一个简单的探查器。我正在使用微软提供的平台自适应层来获取分析 api(corprof.h) 的头文件以及相关的宏和依赖项。在 Visual Studio 中使用 MSBUILD,在 ubuntu WSL 中使用带有 stdlibc++ 库的 clang++ 编译器来编译 .so 文件。 CLR 中的 ICorProfilerInfo-> SetEventMask 在这里失败。
这是我的 DLLMain.cpp - 将 .so 加载到运行时
#include "Logger.h"
#include "OS.h"
#include "CoreProfilerFactory.h"
#include "CoreProfiler.h
extern "C" BOOL __stdcall DllMain(HINSTANCE hInstDll, DWORD reason, PVOID) {
switch (reason) {
case DLL_PROCESS_ATTACH:
Logger::Info("Profiler DLL loaded into PID %d", OS::GetPid());
break;
case DLL_PROCESS_DETACH:
Logger::Info("Profiler DLL unloaded from PID %d", OS::GetPid());
Logger::Shutdown();
break;
}
return TRUE;
}
class __declspec(uuid("805A308B-061C-47F3-9B30-F785C3186E81")) CoreProfiler;
extern "C" HRESULT __stdcall DllGetClassObject(REFCLSID rclsid, REFIID riid, void** ppv) {
Logger::Debug(__FUNCTION__);
const GUID CLSID_CorProfiler = { 0x805a308b,
0x061c,
0x47f3,
{0x9b,0x30,0xf7,0x85,0xc3,0x18,0x6e,0x81} };
if (rclsid == CLSID_CorProfiler) {
static CoreProfilerFactory factory;
Logger::Info("Returning CoreProfilerFactory to CLR!");
return factory.QueryInterface(riid, ppv);
}
Logger::Error("GUID of Profiler not matching!");
return CLASS_E_CLASSNOTAVAILABLE;
}
extern "C" HRESULT __stdcall DllCanUnloadNow() {
Logger::Debug("DllCanUnloadNow() is invoked!");
return S_OK;
}
这是我继承自 IClassFactory 的 CoreProfilerFactory.cpp
#include "CoreProfilerFactory.h"
#include "Logger.h"
#include "CoreProfiler.h"
#include <new>
const IID IID_IUnknown = { 0x00000000,
0x0000,
0x0000,
{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
const IID IID_IClassFactory = {
0x00000001,
0x0000,
0x0000,
{0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
HRESULT __stdcall CoreProfilerFactory::QueryInterface(REFIID riid, void** ppvObject) {
if (ppvObject == nullptr) {
Logger::Error("ppvObject pointer is null");
return E_POINTER;
}
if (riid == IID_IUnknown ||riid == IID_IClassFactory){
*ppvObject = static_cast<IClassFactory*>(this);
this->AddRef();
Logger::Info("Returning Instance of IClassFactory in the ppvObject pointer");
return S_OK;
}
Logger::Error("GUID not matching!");
return E_NOINTERFACE;
}
ULONG __stdcall CoreProfilerFactory::AddRef(void) {
ULONG refcount = _refcount.fetch_add(1) + 1;
return S_OK;
}
ULONG __stdcall CoreProfilerFactory::Release(void) {\
ULONG refcount = _refcount.fetch_add(1) - 1;
if (refcount == 0) {
delete this;
}
return S_OK;
}
HRESULT __stdcall CoreProfilerFactory::CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppvObject) {
auto profiler = new (std::nothrow) CoreProfiler;
if (profiler == nullptr) {
return E_OUTOFMEMORY;
}
auto hr = profiler->QueryInterface(riid, ppvObject);
if (FAILED(hr)) {
delete profiler;
}
return hr;
}
这是我继承自 ICorProfilerCallback3 的 CoreProfiler.cpp
_info 是一个 CComptr
CoreProfiler* CoreProfiler::_this = nullptr;
CoreProfiler::CoreProfiler() {
_this = this;
}
CoreProfiler::~CoreProfiler() {
_this = nullptr;
}
HRESULT __stdcall CoreProfiler::QueryInterface(REFIID riid, void** ppvObject) {
if (ppvObject == nullptr) {
return E_POINTER;
}
if (riid == __uuidof(IUnknown) ||
riid == __uuidof(ICorProfilerCallback) ||
riid == __uuidof(ICorProfilerCallback2) ||
riid == __uuidof(ICorProfilerCallback3)){
*ppvObject = this;
this->AddRef();
Logger::Debug("CorProfiler::QueryInterface");
return S_OK;
}
return E_NOINTERFACE;
}
ULONG __stdcall CoreProfiler::AddRef(void) {
return _refCount.fetch_add(1) + 1;
}
ULONG __stdcall CoreProfiler::Release(void) {
auto count = _refCount.fetch_sub(1) -1;
if (count == 0) {
delete this;
}
return count;
}
const IID IID_ICorProfilerInfo3 = {0xb555ed4f,
0x452a,
0x4e54,
{0x8b,0x39,0xb5,0x36,0x0b,0xad,0x32,0xa0} };
const IID IID_ICorProfilerInfo = { 0x28b5557d,
0x3f3f,
0x48b4,
{0x90,0xb2,0x5f,0x9e,0xea,0x2f,0x6c,0x48} };
HRESULT CoreProfiler::Initialize(IUnknown* pICorProfilerInfoUnk) {
if (pICorProfilerInfoUnk == nullptr) {
Logger::Error("pICorProfilerInfoUnk is a nullptr");
return E_FAIL;
}
Logger::Debug(__FUNCTION__);
HRESULT ok = pICorProfilerInfoUnk->QueryInterface(IID_ICorProfilerInfo3, (void**)&_info);
if(!SUCCEEDED(ok)) {
return E_NOINTERFACE;
}
std::cout << "Queried Interface";
std::cout << "assert _info";
assert(_info);
_info->SetEventMask(
COR_PRF_MONITOR_MODULE_LOADS |
COR_PRF_MONITOR_ASSEMBLY_LOADS |
COR_PRF_MONITOR_GC |
COR_PRF_MONITOR_CLASS_LOADS |
COR_PRF_MONITOR_THREADS |
COR_PRF_MONITOR_EXCEPTIONS |
COR_PRF_MONITOR_JIT_COMPILATION |
COR_PRF_MONITOR_OBJECT_ALLOCATED |
COR_PRF_ENABLE_OBJECT_ALLOCATED);
std::cout << "SET EVENTMASK";
return S_OK;
}
HRESULT CoreProfiler::Shutdown() {
Logger::Info("Profiler shutdown (PID=%d)", OS::GetPid());
_info.Release();
//delete _info;
return S_OK;
}
“查询接口”是在出现段错误(核心转储)之前在控制台上打印的最后一件事。 这是为什么?
编辑:好的。所以我发现访问 CComPtr