Skip to content

Commit

Permalink
Merge pull request #172 from mstange/etw-reader-at-root
Browse files Browse the repository at this point in the history
Merge etw-reader-at-root to main
  • Loading branch information
mstange authored May 4, 2024
2 parents 9d07c6f + f28c65d commit 2d9568b
Show file tree
Hide file tree
Showing 27 changed files with 1,112 additions and 122 deletions.
25 changes: 24 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
[workspace]
resolver = "2"
default-members = ["samply"]
members = [
"fxprof-processed-profile",
"gecko_profile",
Expand All @@ -11,8 +13,7 @@ members = [
"tools/dump_table",
"tools/query_api"
]
resolver = "2"
default-members = ["samply"]
exclude = ["etw-reader"] # Should not be compiled on non-Windows

# Config for 'cargo dist'
[workspace.metadata.dist]
Expand Down
29 changes: 29 additions & 0 deletions etw-reader/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[package]
name = "etw-reader"
version = "0.1.0"
edition = "2021"
license = "MIT"
repository = "https://github.com/mstange/samply"
documentation = "https://docs.rs/etw-reader"
description = "library for reading ETW etl files"
categories = ["os::windows-apis"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bitflags = "2.4.2"
num-traits = "0.2"
num-derive = "0.4"
once_cell = "1.8.0"
fxhash = "0.2.1"
memoffset = "0.9"

[dependencies.windows]
version = "0.56"
features = ["Win32_System_Diagnostics_Etw",
"Win32_System_Diagnostics_Debug",
"Win32_System_SystemInformation",
"Win32_Security_Authorization",
"Win32_System_Memory",
"Win32_System_Time",
"Win32_Foundation"]
File renamed without changes.
212 changes: 212 additions & 0 deletions etw-reader/examples/dump.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
use std::collections::HashMap;
use std::path::Path;

use etw_reader::parser::{Parser, TryParse};
use etw_reader::schema::SchemaLocator;
use etw_reader::{open_trace, print_property, GUID};
use windows::Win32::System::Diagnostics::Etw::{
self, EtwProviderTraitDecodeGuid, EtwProviderTraitTypeGroup,
};

fn main() {
let mut schema_locator = SchemaLocator::new();
etw_reader::add_custom_schemas(&mut schema_locator);
let pattern = std::env::args().nth(2);
let mut processes = HashMap::new();
open_trace(Path::new(&std::env::args().nth(1).unwrap()), |e| {
//dbg!(e.EventHeader.TimeStamp);

let s = schema_locator.event_schema(e);
if let Ok(s) = s {
if let "MSNT_SystemTrace/Process/Start"
| "MSNT_SystemTrace/Process/DCStart"
| "MSNT_SystemTrace/Process/DCEnd" = s.name()
{
let mut parser = Parser::create(&s);

let image_file_name: String = parser.parse("ImageFileName");
let process_id: u32 = parser.parse("ProcessId");
processes.insert(process_id, image_file_name);
}

if let Some(pattern) = &pattern {
if !s.name().contains(pattern) {
return;
}
}
println!(
"{:?} {} {} {}-{} {} {}",
e.EventHeader.ProviderId,
s.name(),
s.provider_name(),
e.EventHeader.EventDescriptor.Opcode,
e.EventHeader.EventDescriptor.Id,
s.property_count(),
e.EventHeader.TimeStamp
);
println!(
"pid: {} {:?}",
s.process_id(),
processes.get(&s.process_id())
);
if e.EventHeader.ActivityId != GUID::zeroed() {
println!("ActivityId: {:?}", e.EventHeader.ActivityId);
}
if e.ExtendedDataCount > 0 {
let items = unsafe {
std::slice::from_raw_parts(e.ExtendedData, e.ExtendedDataCount as usize)
};
for i in items {
match i.ExtType as u32 {
Etw::EVENT_HEADER_EXT_TYPE_EVENT_SCHEMA_TL => {
println!("extended: SCHEMA_TL");
let data: &[u8] = unsafe {
std::slice::from_raw_parts(
i.DataPtr as *const u8,
i.DataSize as usize,
)
};

// from TraceLoggingProvider.h
let size =
u16::from_ne_bytes(<[u8; 2]>::try_from(&data[0..2]).unwrap());
println!(" size: {}", size);
let mut extension_size = 1;
while data[2 + extension_size] & 0x80 != 0 {
extension_size += 1;
}
println!(" extension: {:?}", &data[2..2 + extension_size]);
let name_start = 2 + extension_size;
let mut name_end = name_start;
while data[name_end] != 0 {
name_end += 1;
}
let name =
String::from_utf8(data[name_start..name_end].to_owned()).unwrap();
println!(" name: {}", name);

let mut field_start = name_end + 1;

while field_start < data.len() {
let field_name_start = field_start;
let mut field_name_end = field_name_start;
while data[field_name_end] != 0 {
field_name_end += 1;
}
let field_name = String::from_utf8(
data[field_name_start..field_name_end].to_owned(),
)
.unwrap();
println!(" field_name: {}", field_name);
let mut field_pos = field_name_end + 1;
let field_in_type = data[field_pos];
dbg!(field_in_type);
field_pos += 1;
if field_in_type & 128 == 128 {
let field_out_type = data[field_pos];
field_pos += 1;
dbg!(field_out_type);
if field_out_type & 128 == 128 {
// field extension
println!(" field extension");
while data[field_pos] & 0x80 != 0 {
field_pos += 1;
}
field_pos += 1;
}
}
let c_count = 32;
let v_count = 64;
let custom = v_count | c_count;
let count_mask = v_count | c_count;
if field_in_type & count_mask == c_count {
// value count
field_pos += 2
}
if field_in_type & count_mask == custom {
let type_info_size = u16::from_ne_bytes(
<[u8; 2]>::try_from(&data[field_pos..field_pos + 2])
.unwrap(),
);
field_pos += 2;
field_pos += type_info_size as usize;
}
field_start = field_pos;
}
}
Etw::EVENT_HEADER_EXT_TYPE_PROV_TRAITS => {
println!("extended: PROV_TRAITS");
let data: &[u8] = unsafe {
std::slice::from_raw_parts(
i.DataPtr as *const u8,
i.DataSize as usize,
)
};
// ProviderMetadata
let size =
u16::from_ne_bytes(<[u8; 2]>::try_from(&data[0..2]).unwrap());
println!(" size: {}", size);
let name_start = 2;
let mut name_end = name_start;
while data[name_end] != 0 {
name_end += 1;
}
let name =
String::from_utf8(data[name_start..name_end].to_owned()).unwrap();
println!(" name: {}", name);
let mut metadata_start = name_end + 1;
// ProviderMetadataChunk
while metadata_start < data.len() {
let metadata_size = u16::from_ne_bytes(
<[u8; 2]>::try_from(&data[metadata_start..metadata_start + 2])
.unwrap(),
);
let metadata_type = data[metadata_start + 2];
println!(" metadata_size: {}", metadata_size);
if metadata_type as i32 == EtwProviderTraitTypeGroup.0 {
println!(" EtwProviderTraitTypeGroup");
// read GUID
let guid = &data[(metadata_start + 3)..];
let guid = GUID::from_values(
u32::from_ne_bytes((&guid[0..4]).try_into().unwrap()),
u16::from_ne_bytes((&guid[4..6]).try_into().unwrap()),
u16::from_ne_bytes((&guid[6..8]).try_into().unwrap()),
[
guid[8], guid[9], guid[10], guid[11], guid[12],
guid[13], guid[14], guid[15],
],
);
println!(" GUID {:?}", guid);
} else if metadata_type as i32 == EtwProviderTraitDecodeGuid.0 {
println!(" EtwProviderTraitDecodeGuid");
} else {
println!(" Unexpected {}", metadata_type);
}
metadata_start += metadata_size as usize;
}
}
_ => {
println!("extended: {:?}", i);
}
}
}
}
let formatted_message = s.event_message();
if let Some(message) = formatted_message {
println!("message: {}", message);
}
let mut parser = Parser::create(&s);
for i in 0..s.property_count() {
let property = s.property(i);
//dbg!(&property);
print_property(&mut parser, &property, true);
}
} else if pattern.is_none() {
println!(
"unknown event {:x?}:{} size: {}",
e.EventHeader.ProviderId, e.EventHeader.EventDescriptor.Opcode, e.UserDataLength
);
}
})
.unwrap();
}
81 changes: 81 additions & 0 deletions etw-reader/examples/event-types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use std::cmp::Reverse;
use std::collections::HashMap;
use std::path::Path;

use etw_reader::schema::SchemaLocator;
use etw_reader::{open_trace, GUID};

fn main() {
let mut schema_locator = SchemaLocator::new();
etw_reader::add_custom_schemas(&mut schema_locator);
let mut event_counts = HashMap::new();
open_trace(Path::new(&std::env::args().nth(1).unwrap()), |e| {
let s = schema_locator.event_schema(e);
if let Ok(s) = s {
let name = format!(
"{} {:?}/{}/{}",
s.name(),
e.EventHeader.ProviderId,
e.EventHeader.EventDescriptor.Id,
e.EventHeader.EventDescriptor.Opcode
);
if let Some(count) = event_counts.get_mut(&name) {
*count += 1;
} else {
event_counts.insert(name, 1);
}
} else {
let provider_name = match e.EventHeader.ProviderId {
GUID {
data1: 0x9B79EE91,
data2: 0xB5FD,
data3: 0x41C0,
data4: [0xA2, 0x43, 0x42, 0x48, 0xE2, 0x66, 0xE9, 0xD0],
} => "SysConfig ",
GUID {
data1: 0xB3E675D7,
data2: 0x2554,
data3: 0x4F18,
data4: [0x83, 0x0B, 0x27, 0x62, 0x73, 0x25, 0x60, 0xDE],
} => "KernelTraceControl ",
GUID {
data1: 0xED54DFF8,
data2: 0xC409,
data3: 0x4CF6,
data4: [0xBF, 0x83, 0x05, 0xE1, 0xE6, 0x1A, 0x09, 0xC4],
} => "WinSat ",
// see https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/umdprovider/nf-umdprovider-umdetwregister
GUID {
data1: 0xa688ee40,
data2: 0xd8d9,
data3: 0x4736,
data4: [0xb6, 0xf9, 0x6b, 0x74, 0x93, 0x5b, 0xa3, 0xb1],
} => "D3DUmdLogging ",
GUID {
data1: 0x3d6fa8d3,
data2: 0xfe05,
data3: 0x11d0,
data4: [0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c],
} => "PageFault_V2 ",
_ => "",
};

let provider = format!(
"{}{:?}/{}-{}/{}",
provider_name,
e.EventHeader.ProviderId,
e.EventHeader.EventDescriptor.Id,
e.EventHeader.EventDescriptor.Version,
e.EventHeader.EventDescriptor.Task
);
*event_counts.entry(provider).or_insert(0) += 1;
}
})
.unwrap();
let mut event_counts: Vec<_> = event_counts.into_iter().collect();
// event_counts.sort_by_key(|x| x.0.clone()); //alphabetical
event_counts.sort_by_key(|x| Reverse(x.1));
for (k, v) in event_counts {
println!("{} {}", k, v);
}
}
Loading

0 comments on commit 2d9568b

Please sign in to comment.