microsoft / krabsetw

KrabsETW provides a modern C++ wrapper and a .NET wrapper around the low-level ETW trace consumption functions.
Other
588 stars 147 forks source link

Reading PMC data #142

Closed pr8x closed 3 years ago

pr8x commented 3 years ago

Hey, I was wondering if somebody could give me a hint on how to read PMC data. Is krabs::kernel::profile_provider the right provider? How do I set intervals etc? How do I make sense of the schema data?

This is what I have so far:

void main() {

    krabs::kernel_trace trace(L"My magic trace");
    krabs::kernel::profile_provider provider;

    //SE_SYSTEM_PROFILE_PRIVILEGE
    SetPrivilege(11);

    provider.add_on_event_callback([](const EVENT_RECORD& record, const krabs::trace_context& trace_context) {
        krabs::schema schema(record, trace_context.schema_locator);

        std::cout << schema.event_name() << std::endl;
    });

    trace.enable(provider);
    trace.start();
}
jdu2600 commented 3 years ago

This seems to be the official documentation - https://docs.microsoft.com/en-us/windows/win32/etw/perfinfo You should be able to find the field names and types here.

Based off that it looks like krabs also has three other performance counter convenience providers - dpc_provider, interrupt_provider and system_call_provider. Depending on which specific events, you might need to use those instead. Though, the documentation implies that EVENT_TRACE_FLAG_DPC must be set - so it's possible that the convenience providers don't work correctly.

Alternatively you could create a single performance counter provider with all EnableFlags set -

krabs::kernel_provider perfinfo_provider(EVENT_TRACE_FLAG_DPC|EVENT_TRACE_FLAG_INTERRUPT|EVENT_TRACE_FLAG_PROFILE|EVENT_TRACE_FLAG_SYSTEMCALL, krabs::guids::perf_info);

The official documentation seems to be missing definitions for some events, but I maintain a list here - https://github.com/jdu2600/Windows10EtwEvents/blob/master/mof/Windows_Kernel_Trace.tsv#L459

pr8x commented 3 years ago

I am looking for more specific counters like RetiredInstructions and BranchPrediction failures etc. Turns out the documentation for PerfInfo is actually incomplete. There's actually an opcode 47 event called PMCCounterProf that contains the actual PMC data. Enabling this is anything but trivial though and it requires going through a lot of undocumented Microsoft APIs. I cobbled something together and it seems to work so far: https://gist.github.com/pr8x/3ec386865b1d613366faf23bd7b17221

I don't think this will work out-of-the-Box with this library.

jdu2600 commented 3 years ago

I suspected that event 47 was going to the be interesting one. :-)

If that needs to be enabled by a Groupmask rather than EnableFlags then the krabs way to do this is - krabs::kernel_provider pmc_profile_provider(krabs::guids::perf_info, PERF_PMC_PROFILE);

Geoff Chappell's work is always very helpful when working with undocumented APIs. :-)

jdu2600 commented 3 years ago

Did you look at the version of ntwmi.h from the Windows 10 1511 SDK that Geoff mentions?

If you don't want to download the entire SDK, then there are multiple copies on github. e.g. https://github.com/tpn/winsdk-10/blob/master/Include/10.0.10240.0/um/minwin/ntwmi.h

pr8x commented 3 years ago

@jdu2600 I still need to manually call TraceSetInformation(0, TraceProfileSourceConfigInfo, ...) right? Or is there a krabs equivalent?

jdu2600 commented 3 years ago

No. krabs can help with the generic ETW plumbing, but it doesn't currently wrap those calls.

perfview's TraceEvent C# library seems to though. See https://github.com/microsoft/perfview/blob/master/src/TraceEvent/TraceEventSession.cs#L2836

pr8x commented 3 years ago

Yeah, PerfView is great, that's actually where I got most of my input for the gist I wrote. Unfortunately I don't have much usage for a C# library right now.

pr8x commented 3 years ago

I guess we can close this for now. Passing a group mask to provider and doing some additional setup should do the trick.