2

ネイティブ プラグインを使用するアプリケーションがあります。これらのプラグインには独自のバイナリ形式があります。各プラグインは、DLL をプロセスの空間にマッピングするのと同様の方法を使用して、実行時にロードされます。つまり、各プラグインには独自の, のようなImageBaseセクションがあり、従来の DLL と同じ方法で処理されます。唯一の違いは、プラグインのバイナリ形式 (ファイルではない) と、プラグインをプロセス空間にマップするローダー コードです。.text.dataPE

このコマンドラインでトレースを実行すると、ETW が発生することがわかりました。

xperf -on latency -stackwalk profile -buffersize 1024 -minbuffers 300 -start tracea1 -on Microsoft-Windows-Win32k:::'stack' 

トレース キャプチャ中にプロセス環境を再構築するために使用できるイベントを発行します。つまり、「プロセスの追加」、「プロセスへのスレッドの追加」、「プロセスへの DLL モジュールの追加」などのイベントを発行し、そのようなツールxperfviewがシステム内のプロセスの状態の仮想環境を構築し、情報を構築できるようにします。現在のプロセスツリーのように。これらのイベントは、たとえば、トレース前またはトレース中に読み込まれる各 DLL に関する情報を提供するImageLoadイベントです。

もちろん、私のプラグインではこれらのImageLoadイベントは生成されません。これは、技術的には DLL ではないためです (つまり、機能は同じですが、DLL と同じ機能によって読み込まれるわけではありません)。これが、 のようなツールがxperfviewプロセス空間での存在を認識しない理由です。

私がやりたいことは、プラグイン ローダー コードに独自の EventWrite を記述し、ImageLoad必要な情報を含むこれらのイベントを発行してxperfview、 および同様のツールがプラグインを通常の DLL として解釈できるようにすることです。ImageBaseProcessIdImageSizeなどの必要な情報を入力します。

MSNT_SystemTraceこれを行うには、イベントの所有者であるイベント プロバイダーを登録しImageLoad、次のような構造でイベントを構築する必要があることを理解しています。

    <Data Name="ImageBase">0x7FEFDBD0000</Data>
    <Data Name="ImageSize">0x12D000</Data>
    <Data Name="ProcessId">     548</Data>
    ...
    <Data Name="Reserved0">       0</Data>
    <Data Name="DefaultBase">0x7FEFDBD0000</Data>

そしてイベントを発行します。

問題は、このプロバイダーが既に存在するため、論理的なERROR_ACCESS_DENIED別の を登録しようとしたときに得られることです。MSNT_SystemTrace

しかし、それは私が質問をすることを余儀なくさせます.私がやろうとしていることはETWでサポートされていますか?

4

1 に答える 1

3

私は解決策を見つけたと思います。

既存のプロバイダーを介してリアルタイムでイベントを発行する方法はわかりませんが、Windows 8 は ETL トレース ログを変更できるインターフェイスを公開しているためProviderId、イベントの を別の値に変更することができます。問題のインターフェイスはITraceRelogger. 次のガイドが必要です。

EXTERN_GUID(CLSID_TraceRelogger, 0x7b40792d, 0x05ff, 0x44c4, 0x90, 0x58, 0xf4, 0x40, 0xc7, 0x1f, 0x17, 0xd4);
DEFINE_GUID(IID_ITraceRelogger, 0xF754AD43, 0x3BCC, 0x4286, 0x80, 0x09,0x9C, 0x5D, 0xA2, 0x14, 0xE8, 0x4E); // {F754AD43-3BCC-4286-8009-9C5DA214E84E}
DEFINE_GUID(IID_ITraceEventCallback, 0x3ED25501, 0x593F, 0x43E9, 0x8F, 0x38,0x3A, 0xB4, 0x6F, 0x5A, 0x4A, 0x52); // {3ED25501-593F-43E9-8F38-3AB46F5A4A52}

およびrelogger.hWindows 8 SDK からのファイル ( c:\Program Files (x86)\Windows Kits\8.0\Include\um\relogger.h)。いくつかの外部シンボルを参照しているため、オリジナルrelogger.hは何らかの形で壊れているようですが、それを補足する LIB ファイルがないようです。私はあなたがこれを解決することができると確信しています!

これを使用するには、次の方法でインスタンスを作成するだけです。

ITraceRelogger *relog = NULL;
hres = CoCreateInstance(CLSID_TraceRelogger, 0, CLSCTX_INPROC_SERVER, IID_ITraceRelogger2, (LPVOID *)& relog);

input.etlあなたとoutput.etlファイルを追加します。

#include <windows.h>
#include <cguid.h>
#include <atlbase.h>
#include <comdef.h>
...
CComBSTR input = "input.etl";
CComBSTR output = "output.etl";
...
hres = relog->AddLogfileTraceStream(input, NULL, & trace);
...
hres = relog->SetOutputFilename(output);

次に、イベントの変更を処理するコールバックを登録する必要があります。イベント コールバックの実装例は、この回答の最後に記載されています。現在の ITraceRelogger で使用する方法のコードは次のとおりです。

EventCallback *ec = new EventCallback();
hres = relog->RegisterCallback(ec);
...
hres = relog->ProcessTrace();

警告:ProcessTrace()コールバックを登録していない場合、エラーが返されます。

動作するコールバックの例を次に示します。

class EventCallback: public ITraceEventCallback {
private:
    DWORD ref_count;
    DWORD64 evno;

public:
    EventCallback() {
        ref_count = 0;
        evno = 0;
    }

    STDMETHODIMP QueryInterface(const IID& iid, void **obj) {
        if(iid == IID_IUnknown) {
            *obj = dynamic_cast<IUnknown *>(this);
        } else if(iid == IID_ITraceEventCallback) {
            *obj = dynamic_cast<ITraceEventCallback *>(this);
        } else {
            *obj = NULL;
            return E_NOINTERFACE;
        }

        return S_OK;
    }

    STDMETHODIMP_ (ULONG) AddRef(void) {
        return InterlockedIncrement(& ref_count);
    }

    STDMETHODIMP_ (ULONG) Release() {
        ULONG ucount = InterlockedDecrement(& ref_count);
        if(ucount == 0) {
            delete this;
        }

        return ucount;
    }

    HRESULT STDMETHODCALLTYPE OnBeginProcessTrace(ITraceEvent *HeaderEvent, ITraceRelogger *Relogger)   {
        return S_OK;
    }

    HRESULT STDMETHODCALLTYPE OnEvent(ITraceEvent *Event, ITraceRelogger *Relogger) {
        // Your main method.
        evno++;
        Relogger->Inject(Event);
    }


    HRESULT STDMETHODCALLTYPE OnFinalizeProcessTrace(ITraceRelogger *Relogger) {
        return S_OK;
    }
};

Relogger->InjectEventcurrentを出力ファイルにコピーします。MSDN を使用ITraceReloggerして、目的のイベント プロパティを変更できるメソッドを確認できます。私が気になった方法はSetProviderId().

また、Windows 7 で利用できる MSDN の状態も覚えておいてITraceReloggerください。それは私が経験したことではありません。Windows 7 ではこのクラスをインスタンス化できないため、MSDN はこの件に関して間違った情報を持っている可能性があります。

于 2013-11-26T11:09:36.897 に答える