Skip to content

Commit

Permalink
Provide access to stack traces of arbitrary size in extended data items.
Browse files Browse the repository at this point in the history
The current StackTrace32(_) and StackTrace64(_) definitions yield a value of the inner item type exposed by the windows crate. This type is autogenerated from the C definition, which uses an ANYSIZE_ARRAY (a constant defined as 1). As a side effect, a value of the autogenerated Rust type can only contain a single address from the captured call stack.

* Define a custom type usable as StackTraceItem<u32> and StackTraceItem<u64> to represent captured call stacks of arbitrary size.

* Make StackTrace32(_) and StackTrace64(_) yield values of this new custom type.
  • Loading branch information
yjugl committed Mar 6, 2024
1 parent bd0d0bb commit 16c693c
Showing 1 changed file with 63 additions and 4 deletions.
67 changes: 63 additions & 4 deletions src/native/etw_types/extended_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,55 @@ use crate::native::{
EVENT_EXTENDED_ITEM_STACK_TRACE64,
};

const OFFSET_OF_ADDRESS_IN_ITEM: usize = offset_of!(EVENT_EXTENDED_ITEM_STACK_TRACE64, Address);
const _: () =
assert!(OFFSET_OF_ADDRESS_IN_ITEM == offset_of!(EVENT_EXTENDED_ITEM_STACK_TRACE32, Address));

/// A fixed-size representation of EVENT_EXTENDED_ITEM_STACK_TRACE32 (if Address is u32)
/// and EVENT_EXTENDED_ITEM_STACK_TRACE64 (if Address is u64)
///
/// See <https://learn.microsoft.com/en-us/windows/win32/api/evntcons/ns-evntcons-event_extended_item_stack_trace32>
/// See <https://learn.microsoft.com/en-us/windows/win32/api/evntcons/ns-evntcons-event_extended_item_stack_trace64>
#[derive(Debug)]
pub struct StackTraceItem<Address>
where
Address: Copy,
{
match_id: u64,
addresses: Box<[Address]>,
}

impl<Address> StackTraceItem<Address>
where
Address: Copy,
{
/// Accessor for the MatchId field
pub fn match_id(&self) -> u64 {
self.match_id
}

/// Accessor for the ANYSIZE_ARRAY Address field
pub fn addresses(&self) -> &[Address] {
self.addresses.as_ref()
}

unsafe fn from_raw(
match_id: u64,
first_address: *const Address,
item_size: usize,
) -> StackTraceItem<Address> {
let array_size_in_bytes = item_size
.checked_sub(OFFSET_OF_ADDRESS_IN_ITEM)
.unwrap_or(0);
let array_size = array_size_in_bytes / core::mem::size_of::<Address>();
let addresses = unsafe { std::slice::from_raw_parts(first_address, array_size) }.into();
StackTraceItem {
match_id,
addresses,
}
}
}

/// A wrapper over [`windows::Win32::System::Diagnostics::Etw::EVENT_HEADER_EXTENDED_DATA_ITEM`]
#[repr(transparent)]
pub struct EventHeaderExtendedDataItem(EVENT_HEADER_EXTENDED_DATA_ITEM);
Expand All @@ -39,9 +88,9 @@ pub enum ExtendedDataItem {
TsId(u32),
InstanceInfo(EVENT_EXTENDED_ITEM_INSTANCE),
/// Call stack (if the event is captured on a 32-bit computer)
StackTrace32(EVENT_EXTENDED_ITEM_STACK_TRACE32),
StackTrace32(StackTraceItem<u32>),
/// Call stack (if the event is captured on a 64-bit computer)
StackTrace64(EVENT_EXTENDED_ITEM_STACK_TRACE64),
StackTrace64(StackTraceItem<u64>),
/// TraceLogging event metadata information
TraceLogging(String),
// /// Provider traits data
Expand Down Expand Up @@ -96,12 +145,22 @@ impl EventHeaderExtendedDataItem {

EVENT_HEADER_EXT_TYPE_STACK_TRACE32 => {
let data_ptr = data_ptr as *const EVENT_EXTENDED_ITEM_STACK_TRACE32;
ExtendedDataItem::StackTrace32(unsafe { *data_ptr })
ExtendedDataItem::StackTrace32(unsafe {
let match_id = (*data_ptr).MatchId;
let first_address = &(*data_ptr).Address[0] as *const _;
let item_size = self.0.DataSize as usize;
StackTraceItem::from_raw(match_id, first_address, item_size)
})
}

EVENT_HEADER_EXT_TYPE_STACK_TRACE64 => {
let data_ptr = data_ptr as *const EVENT_EXTENDED_ITEM_STACK_TRACE64;
ExtendedDataItem::StackTrace64(unsafe { *data_ptr })
ExtendedDataItem::StackTrace64(unsafe {
let match_id = (*data_ptr).MatchId;
let first_address = &(*data_ptr).Address[0] as *const _;
let item_size = self.0.DataSize as usize;
StackTraceItem::from_raw(match_id, first_address, item_size)
})
}

EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY => {
Expand Down

0 comments on commit 16c693c

Please sign in to comment.