Skip to content

Instantly share code, notes, and snippets.

@303248153
Last active December 25, 2017 03:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 303248153/ee9870d70a39f97b487f504ecee40360 to your computer and use it in GitHub Desktop.
Save 303248153/ee9870d70a39f97b487f504ecee40360 to your computer and use it in GitHub Desktop.
The code is a piece of shit invokes the worst api microsoft ever made but should just work, requires mingw and win above vista
// https://github.com/packetzero/etwrealtime/blob/master/etwrealtime/packet_trace.cpp
// https://mollyrocket.com/casey/stream_0029.html
// https://docs.microsoft.com/en-us/dotnet/framework/performance/clr-etw-providers
#define WINNT
#include <windows.h>
#include <evntrace.h>
#include <evntprov.h>
#include <iostream>
#include <array>
#define PROCESS_TRACE_MODE_REAL_TIME 0x00000100
#define PROCESS_TRACE_MODE_RAW_TIMESTAMP 0x00001000
#define PROCESS_TRACE_MODE_EVENT_RECORD 0x10000000
typedef struct _EVENT_HEADER_EXTENDED_DATA_ITEM {
USHORT Reserved1; // Reserved for internal use
USHORT ExtType; // Extended info type
struct {
USHORT Linkage : 1; // Indicates additional extended
// data item
USHORT Reserved2 : 15;
};
USHORT DataSize; // Size of extended info data
ULONGLONG DataPtr; // Pointer to extended info data
} EVENT_HEADER_EXTENDED_DATA_ITEM, *PEVENT_HEADER_EXTENDED_DATA_ITEM;
typedef struct _EVENT_HEADER {
USHORT Size; // Event Size
USHORT HeaderType; // Header Type
USHORT Flags; // Flags
USHORT EventProperty; // User given event property
ULONG ThreadId; // Thread Id
ULONG ProcessId; // Process Id
LARGE_INTEGER TimeStamp; // Event Timestamp
GUID ProviderId; // Provider Id
EVENT_DESCRIPTOR EventDescriptor; // Event Descriptor
union {
struct {
ULONG KernelTime; // Kernel Mode CPU ticks
ULONG UserTime; // User mode CPU ticks
} DUMMYSTRUCTNAME;
ULONG64 ProcessorTime; // Processor Clock
// for private session events
} DUMMYUNIONNAME;
GUID ActivityId; // Activity Id
} EVENT_HEADER, *PEVENT_HEADER;
typedef struct _EVENT_RECORD {
EVENT_HEADER EventHeader; // Event header
ETW_BUFFER_CONTEXT BufferContext; // Buffer context
USHORT ExtendedDataCount; // Number of extended
// data items
USHORT UserDataLength; // User data length
PEVENT_HEADER_EXTENDED_DATA_ITEM // Pointer to an array of
ExtendedData; // extended data items
PVOID UserData; // Pointer to user data
PVOID UserContext; // Context from OpenTrace
} EVENT_RECORD, *PEVENT_RECORD;
namespace {
static const GUID ClrRuntimeProvider = {
0xe13c0d23, 0xccbc, 0x4e12, { 0x93, 0x1b, 0xd9, 0xcc, 0x2e, 0xee, 0x27, 0xe4 }
};
static const GUID ClrRundownProvider = {
0xa669021c, 0xc450, 0x4609, { 0xa0, 0x35, 0x5a, 0xf5, 0x9a, 0xf4, 0xdf, 0x18 }
};
static const GUID myGuid =
{ 0x10101010, 0x2345, 0xabcd, { 0xAA, 0x22, 0x71, 0x00, 0x00, 0x00, 0x08, 0xFF } };
std::string mySessionName = "aaaaaaa";
DWORD dwEnableFlags = 0;
struct EventTraceProperties {
EVENT_TRACE_PROPERTIES props;
char sessionNameBuffer[1024];
};
// https://stackoverflow.com/questions/29242/off-the-shelf-c-hex-dump-code
void hexdump(const void *ptr, int buflen) {
unsigned char *buf = (unsigned char*)ptr;
int i, j;
for (i=0; i<buflen; i+=16) {
printf("%06x: ", i);
for (j=0; j<16; j++)
if (i+j < buflen)
printf("%02x ", buf[i+j]);
else
printf(" ");
printf(" ");
for (j=0; j<16; j++)
if (i+j < buflen)
printf("%c", isprint(buf[i+j]) ? buf[i+j] : '.');
printf("\n");
}
}
static VOID WINAPI StaticRecordEventCallback(PEVENT_RECORD pEvent)
{
std::cout << "StaticRecordEventCallback" << std::endl;
auto &header = pEvent->EventHeader;
UCHAR processorNumber = pEvent->BufferContext.ProcessorNumber;
int64_t cycleTime = header.TimeStamp.QuadPart;
std::string userdata((char*)pEvent->UserData, pEvent->UserDataLength);
std::cout << "ProcessorNumber: " << +processorNumber << std::endl;
std::cout << "ProcessID: " << header.ProcessId << std::endl;
std::cout << "ThreadID: " << header.ThreadId << std::endl;
std::cout << "CycleTime: " << cycleTime << std::endl;
std::cout << "EventDescriptor.Id " << header.EventDescriptor.Id << std::endl;
std::cout << "EventDescriptor.Keyword 0x" << std::hex << header.EventDescriptor.Keyword << std::dec << std::endl;
std::cout << "UserDataLength: " << userdata.size() << std::endl;
if (userdata.size() < 256)
hexdump(userdata.c_str(), userdata.size());
std::cout << std::endl;
}
static BOOL WINAPI StaticBufferEventCallback(PEVENT_TRACE_LOGFILE buf)
{
std::cout << "StaticBufferEventCallback" << std::endl << std::endl;
return TRUE;
}
}
int main() {
EventTraceProperties prop = {};
prop.props.Wnode.BufferSize = sizeof(prop);
prop.props.Wnode.Guid = myGuid;
prop.props.Wnode.ClientContext = 1;
prop.props.Wnode.Flags = WNODE_FLAG_TRACED_GUID;
prop.props.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
prop.props.LogFileNameOffset = 0;
prop.props.LoggerNameOffset = offsetof(EventTraceProperties, sessionNameBuffer);
prop.props.FlushTimer = 1;
prop.props.EnableFlags = dwEnableFlags;
memcpy(prop.sessionNameBuffer ,mySessionName.c_str(), mySessionName.size() + 1);
::ControlTrace(0, mySessionName.c_str(), &prop.props, EVENT_TRACE_CONTROL_STOP);
TRACEHANDLE handle;
ULONG status = ::StartTrace(&handle, mySessionName.c_str(), &prop.props);
std::cout << "StartTrace: " << status << std::endl;
if (ERROR_ALREADY_EXISTS == status) {
std::cout << "already exists" << std::endl;
} else if (status != ERROR_SUCCESS) {
std::cout << "error" << std::endl;
} else {
status = ::EnableTrace(true, 0xffffffff, TRACE_LEVEL_VERBOSE, &ClrRuntimeProvider, handle);
std::cout << "EnableTrace: " << status << std::endl;
}
EVENT_TRACE_LOGFILE trace = { };
trace.LoggerName = (char*)mySessionName.c_str();
trace.EventRecordCallback = (PEVENT_RECORD_CALLBACK)(StaticRecordEventCallback);
trace.BufferCallback = (PEVENT_TRACE_BUFFER_CALLBACK)(StaticBufferEventCallback);
trace.ProcessTraceMode = PROCESS_TRACE_MODE_EVENT_RECORD | PROCESS_TRACE_MODE_REAL_TIME;
TRACEHANDLE sessionHandle = ::OpenTrace(&trace);
if (sessionHandle == INVALID_PROCESSTRACE_HANDLE) {
std::cout << "OpenTrace error" << std::endl;
return -1;
}
ULONG processStatus = ::ProcessTrace(&sessionHandle, 1, nullptr, nullptr);
::ControlTrace(0, mySessionName.c_str(), &prop.props, EVENT_TRACE_CONTROL_STOP);
::CloseTrace(handle);
::CloseTrace(sessionHandle);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment