为什么 ICorProfilerCallback::Initialize( IUnknown*) 的实现返回成功而 SETEVENTMASK 失败(段错误)?

问题描述 投票:0回答:0

在 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_info 中除了 _info->SetEventMask() 和 _info->ForeGC() 之外的函数时,我得到了分段错误。也许 pICorProfilerInfoUnk->QueryInterface 返回的 _info 不是 ICorProfilerInfo3 的?我必须找出答案。

.net-core clang cross-platform windows-subsystem-for-linux clr-profiling-api
© www.soinside.com 2019 - 2024. All rights reserved.