windows - 如何关联 ETW 跟踪中的 RPC 调用?

标签 windows ipc etw msrpc

我记录了一个应用程序在 Windows 上执行本地 RPC 调用的痕迹。我在启用了 Microsoft-Windows-RPC 提供程序的情况下使用了 xperf。打开trace后,才发现要把client和server的调用关联起来并没有那么简单。用一个例子来解释问题会更容易。

客户端发送的其中一个 RpcClientCall 事件如下所示:

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
    <System>
        <Provider Name="Microsoft-Windows-RPC" Guid="{6ad52b32-d609-4be9-ae07-ce8dae937e39}" />
        <EventID>5</EventID>
        <Version>1</Version>
        <Level>4</Level>
        <Task>1</Task>
        <Opcode>1</Opcode>
        <Keywords>0x4000000000000000</Keywords>
        <TimeCreated SystemTime="2017-01-02T18:21:54.825009200+0059" />
        <Correlation ActivityID="{f9ace53a-28fe-4129-ac24-8d04ea0a79a9}" />
        <Execution ProcessID="10688" ThreadID="5384" ProcessorID="7" KernelTime="30" UserTime="15" />
        <Channel>Microsoft-Windows-RPC/Debug</Channel>
        <Computer />
    </System>
    <EventData>
        <Data Name="InterfaceUuid">{e60c73e6-88f9-11cf-9af1-0020af6e72f4}</Data>
        <Data Name="ProcNum">0x8</Data>
        <Data Name="Protocol">       3</Data>
        <Data Name="NetworkAddress">NULL</Data>
        <Data Name="Endpoint">epmapper</Data>
        <Data Name="Options">NULL</Data>
        <Data Name="AuthenticationLevel">       6</Data>
        <Data Name="AuthenticationService">      20</Data>
        <Data Name="ImpersonationLevel">       3</Data>
    </EventData>
    <RenderingInfo Culture="en-US">
        <Level>Information </Level>
        <Opcode>Start </Opcode>
        <Task>RpcClientCall</Task>
        <Message>Client RPC call started.   InterfaceUuid:  {e60c73e6-88f9-11cf-9af1-0020af6e72f4}  OpNum:  0x8     Protocol:   LRPC    NetworkAddress  NULL    Endpoint    epmapper    Binding Options     NULL    Authentication Level    7   Authentication Service  8 Impersonation Level   9 </Message>
        <Channel>Debug </Channel>
        <Provider>Microsoft-Windows-RPC </Provider>
    </RenderingInfo>
</Event>

然后是一些Debug事件(具有相同的ActivityID),比如这个:

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
    <System>
        <Provider Name="Microsoft-Windows-RPC" Guid="{6ad52b32-d609-4be9-ae07-ce8dae937e39}" />
        <EventID>4</EventID>
        <Version>1</Version>
        <Level>5</Level>
        <Task>3</Task>
        <Opcode>0</Opcode>
        <Keywords>0x4000000000000000</Keywords>
        <TimeCreated SystemTime="2017-01-02T18:21:54.825028400+0059" />
        <Correlation ActivityID="{f9ace53a-28fe-4129-ac24-8d04ea0a79a9}" />
        <Execution ProcessID="10688" ThreadID="5384" ProcessorID="7" KernelTime="30" UserTime="15" />
        <Channel>Microsoft-Windows-RPC/Debug</Channel>
        <Computer />
    </System>
    <EventData>
        <Data Name="Subject">76</Data>
        <Data Name="Verb">75</Data>
        <Data Name="SubjectPointer">0x24F9A52CAF0</Data>
        <Data Name="ObjectPointer">0x180</Data>
        <Data Name="DataPointer">0x22000130</Data>
    </EventData>
    <RenderingInfo Culture="en-US">
        <Level>Verbose </Level>
        <Task>Debug</Task>
        <Message>RPC Log Event. 
    Subject:    ALPC    Verb:   PKT_OUT     SubjectPointer:     0x24F9A52CAF0   ObjectPointer:  0x180   Data:   0x22000130 </Message>
        <Channel>Debug </Channel>
        <Provider>Microsoft-Windows-RPC </Provider>
    </RenderingInfo>
</Event>

稍后我可能会发现RpcServerCall事件,它可能代表服务器的响应:

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
    <System>
        <Provider Name="Microsoft-Windows-RPC" Guid="{6ad52b32-d609-4be9-ae07-ce8dae937e39}" />
        <EventID>6</EventID>
        <Version>1</Version>
        <Level>4</Level>
        <Task>2</Task>
        <Opcode>1</Opcode>
        <Keywords>0x4000000000000000</Keywords>
        <TimeCreated SystemTime="2017-01-02T18:21:56.786737300+0059" />
        <Correlation ActivityID="{11bb1d8d-336f-44e3-b853-b903f4fd2651}" />
        <Execution ProcessID="652" ThreadID="15348" ProcessorID="4" KernelTime="90" UserTime="195" />
        <Channel>Microsoft-Windows-RPC/Debug</Channel>
        <Computer />
    </System>
    <EventData>
        <Data Name="InterfaceUuid">{e60c73e6-88f9-11cf-9af1-0020af6e72f4}</Data>
        <Data Name="ProcNum">0x8</Data>
        <Data Name="Protocol">       3</Data>
        <Data Name="NetworkAddress">NULL</Data>
        <Data Name="Endpoint">epmapper</Data>
        <Data Name="Options">NULL</Data>
        <Data Name="AuthenticationLevel">       6</Data>
        <Data Name="AuthenticationService">      20</Data>
        <Data Name="ImpersonationLevel">       0</Data>
    </EventData>
    <RenderingInfo Culture="en-US">
        <Level>Information </Level>
        <Opcode>Start </Opcode>
        <Task>RpcServerCall</Task>
        <Message>Server RPC call started.   InterfaceUuid:  {e60c73e6-88f9-11cf-9af1-0020af6e72f4}  OpNum:  0x4     Protocol:   LRPC    Endpoint    epmapper    Authentication Level    7   Authentication Service  8 </Message>
        <Channel>Debug </Channel>
        <Provider>Microsoft-Windows-RPC </Provider>
    </RenderingInfo>
</Event>

此事件之后又是一些Debug 事件(具有相同的 ActivityID):

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
    <System>
        <Provider Name="Microsoft-Windows-RPC" Guid="{6ad52b32-d609-4be9-ae07-ce8dae937e39}" />
        <EventID>4</EventID>
        <Version>1</Version>
        <Level>5</Level>
        <Task>3</Task>
        <Opcode>0</Opcode>
        <Keywords>0x4000000000000000</Keywords>
        <TimeCreated SystemTime="2017-01-02T18:21:56.786747500+0059" />
        <Correlation ActivityID="{11bb1d8d-336f-44e3-b853-b903f4fd2651}" />
        <Execution ProcessID="652" ThreadID="15348" ProcessorID="4" KernelTime="90" UserTime="195" />
        <Channel>Microsoft-Windows-RPC/Debug</Channel>
        <Computer />
    </System>
    <EventData>
        <Data Name="Subject">105</Data>
        <Data Name="Verb">43</Data>
        <Data Name="SubjectPointer">0x15B5283A110</Data>
        <Data Name="ObjectPointer">0x0</Data>
        <Data Name="DataPointer">0x1</Data>
    </EventData>
    <RenderingInfo Culture="en-US">
        <Level>Verbose </Level>
        <Task>Debug</Task>
        <Message>RPC Log Event. 
    Subject:    IF      Verb:   INC     SubjectPointer:     0x15B5283A110   ObjectPointer:  0x0     Data:   0x1 </Message>
        <Channel>Debug </Channel>
        <Provider>Microsoft-Windows-RPC </Provider>
    </RenderingInfo>
</Event>

调用完成后,我可以在客户端和服务器上看到 win:stop 事件,但这些事件只有一个字段:StatusActivityID 设置为与 win:start 事件相同的值,示例:

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
    <System>
        <Provider Name="Microsoft-Windows-RPC" Guid="{6ad52b32-d609-4be9-ae07-ce8dae937e39}" />
        <EventID>8</EventID>
        <Version>1</Version>
        <Level>4</Level>
        <Task>2</Task>
        <Opcode>2</Opcode>
        <Keywords>0x4000000000000000</Keywords>
        <TimeCreated SystemTime="2017-01-02T18:21:56.786835000+0059" />
        <Correlation ActivityID="{11bb1d8d-336f-44e3-b853-b903f4fd2651}" />
        <Execution ProcessID="652" ThreadID="15348" ProcessorID="4" KernelTime="90" UserTime="195" />
        <Channel>Microsoft-Windows-RPC/Debug</Channel>
        <Computer />
    </System>
    <EventData>
        <Data Name="Status">0x0</Data>
    </EventData>
    <RenderingInfo Culture="en-US">
        <Level>Information </Level>
        <Opcode>Stop </Opcode>
        <Task>RpcServerCall</Task>
        <Message>Server RPC call was completed.     Status:     0x0 </Message>
        <Channel>Debug </Channel>
        <Provider>Microsoft-Windows-RPC </Provider>
    </RenderingInfo>
</Event>

问题

最后,我的问题是:我如何才能 100% 确定给定的 RpcServerCall 是对我初始 RpcClientCall 的响应?我猜想通过 InterfaceUuid 进行匹配,ProcNumProtocolEndpoint 是不够的,因为可能同时有多个调用给定端点。我希望也许这些 Debug 事件可以在这里提供帮助。也许我应该使用另一个 ETW 提供程序?或者可能有启用 RelativeActivityId 的设置?

最佳答案

您可以通过启用 Microsoft-Windows-RPC 和按 Activity Id 分组来关联事件,这对于每个 RPC 调用都是唯一的。然后,您只需关联每个事件 ID 的开始/停止事件,您可以在客户端进程的上下文中拥有持续时间,以关联任何 RPC 调用的持续时间。

对于每个 Acitivity,可以记录许多调试事件,但只有一个启动/停止元组。这应该可以解决问题。

enter image description here

要关联 RPC 客户端和服务器调用,您首先需要通过查看具有相同事件 GUID 的启动/停止事件来找到相应的 RPC 客户端和服务器调用。对于带有 RpcServer 调用的给定 RpcClient,您可以使用字段 5(端点)按它们分组。至少我发现,如果给定的端点仅同步提供调用服务,那么它看起来像是一个可靠的指标。接口(interface)也可能有效,但由于可能有多个 COM 服务器同时运行且具有相同的接口(interface) GUID,因此它不是一个可靠的指标。我认为它不会比给定数据好多少。为什么您如此热衷于 RPC 服务器部分?通常,您只会查看很长的客户端时间,这无论如何都足以触发更深入的分析。您是否在 RPC 基础架构中寻找问题?

enter image description here

关于windows - 如何关联 ETW 跟踪中的 RPC 调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41504738/

相关文章:

c++ - C++ 和 Python 之间的简单 IPC(跨平台)

子进程执行 fork 调用之前写的语句

c++ - 驱动程序中的 ETW 跟踪——过程后

c# - System.Diagnostics.Tracing.EventSource 与 System.Diagnostics.Trace

c# - 当我在 ServiceFabric 群集上使用 EventFlow 监听 ETW 事件时出现“系统资源不足”

windows - AMD64 页面条目基地址字段如何将 52 位地址编码为 40 位?

windows - PL/SQL Developer 不显示 "ő"字符

c++ - 使用代码注入(inject)在远程进程中执行函数

windows - OEMToCharW 返回错误字符

c - mingw64 系统 ("command") 与 shell 中的 "command"不同