Skip to content

Commit 8602d9c

Browse files
authored
Merge pull request n4r1b#124 from yjugl/stack-trace-item
Provide access to stack traces of arbitrary size in extended data items.
2 parents bd0d0bb + 16c693c commit 8602d9c

File tree

1 file changed

+63
-4
lines changed

1 file changed

+63
-4
lines changed

src/native/etw_types/extended_data.rs

+63-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,55 @@ use crate::native::{
2020
EVENT_EXTENDED_ITEM_STACK_TRACE64,
2121
};
2222

23+
const OFFSET_OF_ADDRESS_IN_ITEM: usize = offset_of!(EVENT_EXTENDED_ITEM_STACK_TRACE64, Address);
24+
const _: () =
25+
assert!(OFFSET_OF_ADDRESS_IN_ITEM == offset_of!(EVENT_EXTENDED_ITEM_STACK_TRACE32, Address));
26+
27+
/// A fixed-size representation of EVENT_EXTENDED_ITEM_STACK_TRACE32 (if Address is u32)
28+
/// and EVENT_EXTENDED_ITEM_STACK_TRACE64 (if Address is u64)
29+
///
30+
/// See <https://learn.microsoft.com/en-us/windows/win32/api/evntcons/ns-evntcons-event_extended_item_stack_trace32>
31+
/// See <https://learn.microsoft.com/en-us/windows/win32/api/evntcons/ns-evntcons-event_extended_item_stack_trace64>
32+
#[derive(Debug)]
33+
pub struct StackTraceItem<Address>
34+
where
35+
Address: Copy,
36+
{
37+
match_id: u64,
38+
addresses: Box<[Address]>,
39+
}
40+
41+
impl<Address> StackTraceItem<Address>
42+
where
43+
Address: Copy,
44+
{
45+
/// Accessor for the MatchId field
46+
pub fn match_id(&self) -> u64 {
47+
self.match_id
48+
}
49+
50+
/// Accessor for the ANYSIZE_ARRAY Address field
51+
pub fn addresses(&self) -> &[Address] {
52+
self.addresses.as_ref()
53+
}
54+
55+
unsafe fn from_raw(
56+
match_id: u64,
57+
first_address: *const Address,
58+
item_size: usize,
59+
) -> StackTraceItem<Address> {
60+
let array_size_in_bytes = item_size
61+
.checked_sub(OFFSET_OF_ADDRESS_IN_ITEM)
62+
.unwrap_or(0);
63+
let array_size = array_size_in_bytes / core::mem::size_of::<Address>();
64+
let addresses = unsafe { std::slice::from_raw_parts(first_address, array_size) }.into();
65+
StackTraceItem {
66+
match_id,
67+
addresses,
68+
}
69+
}
70+
}
71+
2372
/// A wrapper over [`windows::Win32::System::Diagnostics::Etw::EVENT_HEADER_EXTENDED_DATA_ITEM`]
2473
#[repr(transparent)]
2574
pub struct EventHeaderExtendedDataItem(EVENT_HEADER_EXTENDED_DATA_ITEM);
@@ -39,9 +88,9 @@ pub enum ExtendedDataItem {
3988
TsId(u32),
4089
InstanceInfo(EVENT_EXTENDED_ITEM_INSTANCE),
4190
/// Call stack (if the event is captured on a 32-bit computer)
42-
StackTrace32(EVENT_EXTENDED_ITEM_STACK_TRACE32),
91+
StackTrace32(StackTraceItem<u32>),
4392
/// Call stack (if the event is captured on a 64-bit computer)
44-
StackTrace64(EVENT_EXTENDED_ITEM_STACK_TRACE64),
93+
StackTrace64(StackTraceItem<u64>),
4594
/// TraceLogging event metadata information
4695
TraceLogging(String),
4796
// /// Provider traits data
@@ -96,12 +145,22 @@ impl EventHeaderExtendedDataItem {
96145

97146
EVENT_HEADER_EXT_TYPE_STACK_TRACE32 => {
98147
let data_ptr = data_ptr as *const EVENT_EXTENDED_ITEM_STACK_TRACE32;
99-
ExtendedDataItem::StackTrace32(unsafe { *data_ptr })
148+
ExtendedDataItem::StackTrace32(unsafe {
149+
let match_id = (*data_ptr).MatchId;
150+
let first_address = &(*data_ptr).Address[0] as *const _;
151+
let item_size = self.0.DataSize as usize;
152+
StackTraceItem::from_raw(match_id, first_address, item_size)
153+
})
100154
}
101155

102156
EVENT_HEADER_EXT_TYPE_STACK_TRACE64 => {
103157
let data_ptr = data_ptr as *const EVENT_EXTENDED_ITEM_STACK_TRACE64;
104-
ExtendedDataItem::StackTrace64(unsafe { *data_ptr })
158+
ExtendedDataItem::StackTrace64(unsafe {
159+
let match_id = (*data_ptr).MatchId;
160+
let first_address = &(*data_ptr).Address[0] as *const _;
161+
let item_size = self.0.DataSize as usize;
162+
StackTraceItem::from_raw(match_id, first_address, item_size)
163+
})
105164
}
106165

107166
EVENT_HEADER_EXT_TYPE_PROCESS_START_KEY => {

0 commit comments

Comments
 (0)