#![allow(
non_snake_case,
non_camel_case_types,
non_upper_case_globals,
improper_ctypes_definitions,
clippy::missing_safety_doc
)]
use bitflags::bitflags;
use core::{
ffi::c_void,
mem::{align_of, size_of},
};
use std::{
fmt,
ops::{Deref, DerefMut},
};
use windows::core::GUID;
macro_rules! scalar_newtype {
($name:ident, $inner:ty) => {
#[repr(transparent)]
#[derive(
Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash,
)]
pub struct $name(pub $inner);
};
}
macro_rules! impl_var {
($name:ident, $ty:ty) => {
impl Deref for $name {
type Target = $ty;
fn deref(&self) -> &Self::Target { &self.0 }
}
impl DerefMut for $name {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}
impl From<$ty> for $name {
fn from(value: $ty) -> Self { Self(value) }
}
impl From<$name> for $ty {
fn from(value: $name) -> Self { value.0 }
}
impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl fmt::LowerHex for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::LowerHex::fmt(&self.0, f)
}
}
impl fmt::UpperHex for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::UpperHex::fmt(&self.0, f)
}
}
};
}
pub const IID_ICURSOR_VIEW: GUID =
GUID::from_u128(0xb1d2e6ab_9052_4b72_999e_a88ba868f899);
pub const IID_IREPLAY_ENGINE_VIEW: GUID =
GUID::from_u128(0x4d3420a5_37ef_4114_ae91_63d0378c84a9);
pub const IID_ITRACE_LIST_VIEW: GUID =
GUID::from_u128(0x2dbf3602_669f_490a_962c_749d91c3a1a4);
pub const IID_ICURSOR_INTERNALS: GUID =
GUID::from_u128(0xa1529168_71ab_4bc5_9fe0_184f2520088b);
pub const IID_IENGINE_INTERNALS: GUID =
GUID::from_u128(0x05900c1f_547a_40b2_a66d_4b9639618556);
scalar_newtype!(GuestAddress, u64);
impl GuestAddress {
pub const NULL: Self = Self(0);
pub const MIN: Self = Self(0);
pub const MAX: Self = Self(u64::MAX);
}
impl_var!(GuestAddress, u64);
scalar_newtype!(ProcessorArchitecture, u8);
impl ProcessorArchitecture {
pub const INVALID: Self = Self(0);
pub const X86: Self = Self(1);
pub const X64: Self = Self(2);
pub const ARM32: Self = Self(3);
pub const ARM64: Self = Self(4);
}
scalar_newtype!(SequenceId, u64);
impl SequenceId {
pub const MIN: Self = Self(0);
pub const MAX: Self = Self(u64::MAX - 1);
pub const INVALID: Self = Self(u64::MAX);
}
impl_var!(SequenceId, u64);
scalar_newtype!(RecordClientId, u32);
impl RecordClientId {
pub const MIN: Self = Self(0);
pub const MAX: Self = Self(u32::MAX - 1);
pub const INVALID: Self = Self(u32::MAX);
}
impl_var!(RecordClientId, u32);
scalar_newtype!(ThreadId, u32);
impl ThreadId {
pub const INVALID: Self = Self(0);
pub const MIN: Self = Self(1);
pub const MAX: Self = Self(u32::MAX);
}
impl_var!(ThreadId, u32);
scalar_newtype!(UniqueThreadId, u32);
impl UniqueThreadId {
pub const INVALID: Self = Self(0);
pub const MIN: Self = Self(1);
pub const MAX: Self = Self(u32::MAX);
}
impl_var!(UniqueThreadId, u32);
scalar_newtype!(ActivityId, u32);
impl ActivityId {
pub const NULL: Self = Self(0);
pub const MIN: Self = Self(1);
pub const MAX: Self = Self(u32::MAX);
}
impl_var!(ActivityId, u32);
scalar_newtype!(InstructionCount, u64);
impl InstructionCount {
pub const ZERO: Self = Self(0);
pub const MIN: Self = Self(0);
pub const MAX: Self = Self(u64::MAX - 1);
pub const INVALID: Self = Self(u64::MAX);
}
impl_var!(InstructionCount, u64);
scalar_newtype!(StepCount, u64);
impl StepCount {
pub const ZERO: Self = Self(0);
pub const MIN: Self = Self(0);
pub const MAX: Self = Self(u64::MAX - 1);
pub const INVALID: Self = Self(u64::MAX);
}
impl_var!(StepCount, u64);
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct ConstBufferView {
pub BaseAddress: *const c_void,
pub Size: usize,
}
impl Default for ConstBufferView {
fn default() -> Self {
Self {
BaseAddress: core::ptr::null(),
Size: 0,
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct BufferView {
pub BaseAddress: *mut c_void,
pub Size: usize,
}
impl Default for BufferView {
fn default() -> Self {
Self {
BaseAddress: core::ptr::null_mut(),
Size: 0,
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct TimingInfo {
pub SystemTime: u64,
pub ProcessCreateTime: u64,
pub ProcessUserTime: u64,
pub ProcessKernelTime: u64,
pub SystemUpTime: u64,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct X86CpuInfo {
pub VendorId: [u32; 3],
pub VersionInformation: u32,
pub FeatureInformation: u32,
pub AMDExtendedCpuFeatures: u32,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct OtherCpuInfo {
pub ProcessorFeatures: [u64; 2],
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union SystemInfoCpu {
pub X86CpuInfo: X86CpuInfo,
pub OtherCpuInfo: OtherCpuInfo,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct SystemInfoSystem {
pub ProcessorArchitecture: u16,
pub ProcessorLevel: u16,
pub ProcessorRevision: u16,
pub NumberOfProcessors: u8,
pub ProductType: u8,
pub MajorVersion: u32,
pub MinorVersion: u32,
pub BuildNumber: u32,
pub PlatformId: u32,
pub CSDVersionRva: u32,
pub SuiteMask: u16,
pub Reserved2: u16,
pub Cpu: SystemInfoCpu,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct SystemInfo {
pub MajorVersion: u32,
pub MinorVersion: u32,
pub BuildNumber: u32,
pub ProcessId: u32,
pub Time: TimingInfo,
pub System: SystemInfoSystem,
pub UserName: [u16; 64],
pub SystemName: [u16; 64],
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct RegisterContext {
pub Data: [u64; 2672 / 8],
}
impl Default for RegisterContext {
fn default() -> Self {
Self {
Data: [0; 2672 / 8],
}
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct ExtendedRegisterContext {
pub Data: [u64; 8832 / 8],
}
impl Default for ExtendedRegisterContext {
fn default() -> Self {
Self {
Data: [0; 8832 / 8],
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct M128Bit {
pub Low: u64,
pub High: i64,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct X86FxSaveFormat {
pub ControlWord: u16,
pub StatusWord: u16,
pub TagWord: u16,
pub ErrorOpcode: u16,
pub ErrorOffset: u32,
pub ErrorSelector: u32,
pub DataOffset: u32,
pub DataSelector: u32,
pub MXCsr: u32,
pub Reserved2: u32,
pub RegisterArea: [u8; 128],
pub Reserved3: [u8; 128],
pub Reserved4: [u8; 224],
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct X86FloatingSaveArea {
pub ControlWord: u32,
pub StatusWord: u32,
pub TagWord: u32,
pub ErrorOffset: u32,
pub ErrorSelector: u32,
pub DataOffset: u32,
pub DataSelector: u32,
pub RegisterArea: [u8; 80],
pub Cr0NpxState: u32,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union X86ExtendedRegisterState {
pub ExtendedRegisters: [u8; 512],
pub FxSave: X86FxSaveFormat,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct X86Context {
pub ContextFlags: u32,
pub Dr0: u32,
pub Dr1: u32,
pub Dr2: u32,
pub Dr3: u32,
pub Dr6: u32,
pub Dr7: u32,
pub FloatSave: X86FloatingSaveArea,
pub SegGs: u32,
pub SegFs: u32,
pub SegEs: u32,
pub SegDs: u32,
pub Edi: u32,
pub Esi: u32,
pub Ebx: u32,
pub Edx: u32,
pub Ecx: u32,
pub Eax: u32,
pub Ebp: u32,
pub Eip: u32,
pub SegCs: u32,
pub EFlags: u32,
pub Esp: u32,
pub SegSs: u32,
pub Extended: X86ExtendedRegisterState,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Amd64Context {
pub P1Home: u64,
pub P2Home: u64,
pub P3Home: u64,
pub P4Home: u64,
pub P5Home: u64,
pub P6Home: u64,
pub ContextFlags: u32,
pub MxCsr: u32,
pub SegCs: u16,
pub SegDs: u16,
pub SegEs: u16,
pub SegFs: u16,
pub SegGs: u16,
pub SegSs: u16,
pub EFlags: u32,
pub Dr0: u64,
pub Dr1: u64,
pub Dr2: u64,
pub Dr3: u64,
pub Dr6: u64,
pub Dr7: u64,
pub Rax: u64,
pub Rcx: u64,
pub Rdx: u64,
pub Rbx: u64,
pub Rsp: u64,
pub Rbp: u64,
pub Rsi: u64,
pub Rdi: u64,
pub R8: u64,
pub R9: u64,
pub R10: u64,
pub R11: u64,
pub R12: u64,
pub R13: u64,
pub R14: u64,
pub R15: u64,
pub Rip: u64,
pub FloatingPointState: [u8; 512],
pub VectorRegister: [M128Bit; 26],
pub VectorControl: u64,
pub DebugControl: u64,
pub LastBranchToRip: u64,
pub LastBranchFromRip: u64,
pub LastExceptionToRip: u64,
pub LastExceptionFromRip: u64,
}
impl RegisterContext {
#[inline]
pub unsafe fn as_x86_unchecked(&self) -> &X86Context {
unsafe { &*(self as *const Self).cast::<X86Context>() }
}
#[inline]
pub unsafe fn as_amd64_unchecked(&self) -> &Amd64Context {
unsafe { &*(self as *const Self).cast::<Amd64Context>() }
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Position {
pub Sequence: SequenceId,
pub Steps: StepCount,
}
impl Default for Position {
fn default() -> Self { Self::INVALID }
}
impl Position {
pub const INVALID: Self = Self {
Sequence: SequenceId::INVALID,
Steps: StepCount::ZERO,
};
pub const MIN: Self = Self {
Sequence: SequenceId::MIN,
Steps: StepCount::MIN,
};
pub const MAX: Self = Self {
Sequence: SequenceId::MAX,
Steps: StepCount::MAX,
};
#[inline]
pub const fn new(sequence: u64, steps: u64) -> Self {
Self {
Sequence: SequenceId(sequence),
Steps: StepCount(steps),
}
}
#[inline]
pub const fn is_valid(self) -> bool {
self.Sequence.0 != SequenceId::INVALID.0
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct PositionRange {
pub Min: Position,
pub Max: Position,
}
impl Default for PositionRange {
fn default() -> Self {
Self {
Min: Position::INVALID,
Max: Position::INVALID,
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct Module {
pub pName: *const u16,
pub NameLength: usize,
pub Address: GuestAddress,
pub Size: u64,
pub Checksum: u32,
pub Timestamp: u32,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct ModuleInstance {
pub pModule: *const Module,
pub LoadTime: SequenceId,
pub UnloadTime: SequenceId,
}
scalar_newtype!(DebugModeType, i32);
impl DebugModeType {
pub const NONE: Self = Self(0);
pub const MEDIUM: Self = Self(1);
pub const HIGH: Self = Self(2);
}
scalar_newtype!(RecordingType, u32);
impl RecordingType {
pub const INVALID: Self = Self(0);
pub const FULL: Self = Self(1);
pub const SELECTIVE: Self = Self(2);
pub const CHUNK: Self = Self(3);
}
scalar_newtype!(GapKind, u8);
impl GapKind {
pub const NO_GAP: Self = Self(0);
pub const CONTEXT_SWITCH: Self = Self(1);
pub const UNRECORDED: Self = Self(2);
pub const LARGE: Self = Self(3);
}
bitflags! {
#[derive(Debug, Copy, Clone ,Eq, PartialEq)]
pub struct GapKindMask: u32 {
const NoGap = 1;
const ContextSwitch = 2;
const Unrecorded = 4;
const Large = 8;
const None = 0;
const All = Self::NoGap.bits()
| Self::ContextSwitch.bits()
| Self::Unrecorded.bits()
| Self::Large.bits();
}
}
scalar_newtype!(GapEventType, u8);
impl GapEventType {
pub const SYNTHETIC_SEQUENCE: Self = Self(0);
pub const CODE_CACHE_FLUSH: Self = Self(1);
pub const PRE_ATOMIC_OPERATION: Self = Self(2);
pub const POTENTIAL_ATOMIC_COLLISION: Self = Self(3);
pub const ETW_EVENT: Self = Self(4);
pub const DEBUG_BREAK: Self = Self(5);
pub const FAST_FAIL: Self = Self(6);
pub const KERNEL_CALL: Self = Self(7);
pub const SYNTHETIC_FALLBACK: Self = Self(8);
pub const EXCEPTION_DISPATCH: Self = Self(9);
pub const UNKNOWN_INSTRUCTION: Self = Self(10);
pub const THREAD_SUSPENDED: Self = Self(11);
pub const SLIST_ROLLBACK: Self = Self(12);
pub const SYNC_POINT: Self = Self(13);
pub const PAUSE_EMULATION: Self = Self(14);
pub const STOP_EMULATION: Self = Self(15);
pub const THROTTLED: Self = Self(16);
}
bitflags! {
#[derive(Debug, Copy, Clone ,Eq, PartialEq)]
pub struct GapEventMask: u32 {
const SyntheticSequence = 0x0001;
const CodeCacheFlush = 0x0002;
const PreAtomicOperation = 0x0004;
const PotentialAtomicCollision = 0x0008;
const EtwEvent = 0x0010;
const DebugBreak = 0x0020;
const FastFail = 0x0040;
const KernelCall = 0x0080;
const SyntheticFallback = 0x0100;
const ExceptionDispatch = 0x0200;
const UnknownInstruction = 0x0400;
const ThreadSuspended = 0x0800;
const SListRollback = 0x1000;
const SyncPoint = 0x2000;
const PauseEmulation = 0x4000;
const StopEmulation = 0x8000;
const Throttled = 0x10000;
const None = 0;
const All = Self::SyntheticSequence.bits()
| Self::CodeCacheFlush.bits()
| Self::PreAtomicOperation.bits()
| Self::PotentialAtomicCollision.bits()
| Self::EtwEvent.bits()
| Self::DebugBreak.bits()
| Self::FastFail.bits()
| Self::KernelCall.bits()
| Self::SyntheticFallback.bits()
| Self::ExceptionDispatch.bits()
| Self::UnknownInstruction.bits()
| Self::ThreadSuspended.bits()
| Self::SListRollback.bits()
| Self::SyncPoint.bits()
| Self::PauseEmulation.bits()
| Self::StopEmulation.bits()
| Self::Throttled.bits();
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct GapData {
pub Kind: GapKind,
pub Event: GapEventType,
}
scalar_newtype!(EventType, u8);
impl EventType {
pub const MEMORY_WATCHPOINT: Self = Self(0);
pub const POSITION_WATCHPOINT: Self = Self(1);
pub const EXCEPTION: Self = Self(2);
pub const GAP: Self = Self(3);
pub const THREAD: Self = Self(4);
pub const STEP_COUNT: Self = Self(5);
pub const POSITION: Self = Self(6);
pub const PROCESS: Self = Self(7);
pub const INTERRUPTED: Self = Self(8);
pub const ERROR: Self = Self(9);
pub const COUNT: Self = Self(10);
pub const INVALID: Self = Self(u8::MAX);
}
bitflags! {
#[derive(Debug, Copy, Clone ,Eq, PartialEq)]
pub struct EventMask: u32 {
const MemoryWatchpoint = 0x01;
const PositionWatchpoint = 0x02;
const Exception = 0x04;
const Gap = 0x08;
const Thread = 0x10;
const None = 0;
const All = Self::MemoryWatchpoint.bits()
| Self::PositionWatchpoint.bits()
| Self::Exception.bits()
| Self::Gap.bits()
| Self::Thread.bits();
}
}
scalar_newtype!(DataAccessType, u8);
impl DataAccessType {
pub const READ: Self = Self(0);
pub const WRITE: Self = Self(1);
pub const EXECUTE: Self = Self(2);
pub const CODE_FETCH: Self = Self(3);
pub const OVERWRITE: Self = Self(4);
pub const DATA_MISMATCH: Self = Self(5);
pub const NEW_DATA: Self = Self(6);
pub const REDUNDANT_DATA: Self = Self(7);
}
bitflags! {
#[derive(Debug, Default, Copy, Clone ,Eq, PartialEq)]
pub struct DataAccessMask: u8 {
const Read = 0x01;
const Write = 0x02;
const Execute = 0x04;
const CodeFetch = 0x08;
const Overwrite = 0x10;
const DataMismatch = 0x20;
const NewData = 0x40;
const RedundantData = 0x80;
const None = 0;
const ReadWrite = Self::Read.bits() | Self::Write.bits();
const All = Self::Read.bits()
| Self::Write.bits()
| Self::Execute.bits()
| Self::CodeFetch.bits()
| Self::Overwrite.bits()
| Self::DataMismatch.bits()
| Self::NewData.bits()
| Self::RedundantData.bits();
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct MemoryWatchpointData {
pub Address: GuestAddress,
pub Size: u64,
pub AccessMask: DataAccessMask,
pub ThreadId: UniqueThreadId,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct PositionWatchpointData {
pub Positions: PositionRange,
pub ThreadId: UniqueThreadId,
}
scalar_newtype!(ExceptionType, u8);
impl ExceptionType {
pub const HARDWARE: Self = Self(0);
pub const SOFTWARE: Self = Self(1);
pub const C_PLUS_PLUS: Self = Self(2);
pub const DEBUG_PRINT: Self = Self(3);
}
bitflags! {
#[derive(Debug, Copy, Clone ,Eq, PartialEq)]
pub struct ExceptionMask: u32 {
const Hardware = 1;
const Software = 2;
const CPlusPlus = 4;
const DebugPrint = 8;
const None = 0;
const All = Self::Hardware.bits()
| Self::Software.bits()
| Self::CPlusPlus.bits()
| Self::DebugPrint.bits();
}
}
bitflags! {
#[derive(Debug, Copy, Clone ,Eq, PartialEq)]
pub struct ReplayFlags: u32 {
const ReplayOnlyCurrentThread = 1;
const ReplayAllSegmentsWithoutFiltering = 2;
const ReplaySegmentsSequentially = 4;
const None = 0;
const Default = 0;
const All = Self::ReplayOnlyCurrentThread.bits()
| Self::ReplayAllSegmentsWithoutFiltering.bits()
| Self::ReplaySegmentsSequentially.bits();
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct ThreadInfo {
pub UniqueId: UniqueThreadId,
pub Id: ThreadId,
pub Lifetime: PositionRange,
pub ActiveTime: PositionRange,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct ActiveThreadInfo {
pub pThread: *const ThreadInfo,
pub CurrentPosition: Position,
pub LastValidPosition: Position,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct ExceptionEvent {
pub Position: Position,
pub pThreadInfo: *const ThreadInfo,
pub Type: ExceptionType,
pub Code: u32,
pub Flags: u32,
pub RecordAddress: GuestAddress,
pub ProgramCounter: GuestAddress,
pub ParameterCount: u32,
pub Parameters: [u64; 15],
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct ThreadCreatedEvent {
pub Position: Position,
pub pThreadInfo: *const ThreadInfo,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct ThreadTerminatedEvent {
pub Position: Position,
pub pThreadInfo: *const ThreadInfo,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct ModuleLoadedEvent {
pub Position: Position,
pub pModule: *const Module,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct ModuleUnloadedEvent {
pub Position: Position,
pub pModule: *const Module,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct RecordClient {
pub Id: RecordClientId,
pub ClientGUID: GUID,
pub Lifetime: PositionRange,
pub OpenUserData: ConstBufferView,
pub CloseUserData: ConstBufferView,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct CustomEvent {
pub Position: Position,
pub pThreadInfo: *const ThreadInfo,
pub pRecordClient: *const RecordClient,
pub UserData: ConstBufferView,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct Activity {
pub pRecordClient: *const RecordClient,
pub Id: ActivityId,
pub Lifetime: PositionRange,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct Island {
pub Lifetime: PositionRange,
pub pThreadInfo: *const ThreadInfo,
pub pActivity: *const Activity,
pub UserData: ConstBufferView,
}
scalar_newtype!(IndexStatus, u32);
impl IndexStatus {
pub const INDEX_FILE_LOADED: Self = Self(0);
pub const INDEX_FILE_NOT_PRESENT: Self = Self(1);
pub const INDEX_FILE_UNLOADABLE: Self = Self(2);
}
bitflags! {
#[derive(Debug, Copy, Clone ,Eq, PartialEq)]
pub struct IndexBuildFlags: u32 {
const DeleteExistingUnloadableIndexFile = 1;
const TemporaryIndexFile = 2;
const MakeSelfContained = 4;
const None = 0;
const All = Self::DeleteExistingUnloadableIndexFile.bits()
| Self::TemporaryIndexFile.bits()
| Self::MakeSelfContained.bits();
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct IndexBuildProgressType {
pub KeyframeCount: u32,
pub KeyframesProcessed: u32,
}
pub type IndexBuildProgressCallback = Option<
unsafe extern "system" fn(
pCallerContext: *const c_void,
pProgressData: *const IndexBuildProgressType,
),
>;
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct IndexTreeStats {
pub m_pageSize: u64,
pub m_pageCount: u64,
pub m_innerPageCount: u64,
pub m_innerPageEntryCount: u64,
pub m_innerPageEntryCapacity: u64,
pub m_innerPageEntrySize: u64,
pub m_leafPageCount: u64,
pub m_leafPageEntryCount: u64,
pub m_leafPageEntryCapacity: u64,
pub m_leafPageEntrySize: u64,
pub m_maximumLeafDepth: u64,
pub m_sumOfLeafDepths: u64,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct IndexFileStats {
pub m_globalMemoryIndexStats: IndexTreeStats,
pub m_segmentMemoryIndexStats: IndexTreeStats,
pub m_mapPageCallCount: u64,
pub m_lockPageCallCount: u64,
}
scalar_newtype!(QueryMemoryPolicy, u32);
impl QueryMemoryPolicy {
pub const DEFAULT: Self = Self(0);
pub const THREAD_LOCAL: Self = Self(1);
pub const GLOBALLY_CONSERVATIVE: Self = Self(2);
pub const GLOBALLY_AGGRESSIVE: Self = Self(3);
pub const IN_FRAGMENT_AGGRESSIVE: Self = Self(4);
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct MemoryRange {
pub Address: GuestAddress,
pub Memory: ConstBufferView,
pub Sequence: SequenceId,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct MemoryBuffer {
pub Address: GuestAddress,
pub Memory: ConstBufferView,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct MemoryBufferWithRanges {
pub Address: GuestAddress,
pub Memory: ConstBufferView,
pub RangeCount: usize,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct MemoryWatchpointResult {
pub Address: GuestAddress,
pub Size: u64,
pub AccessType: DataAccessType,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union ReplayResultPayload {
pub MemoryWatchpoint: MemoryWatchpointResult,
pub PositionWatchpoint: Position,
pub GapEvent: GapData,
pub pException: *const ExceptionEvent,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct ReplayResult {
pub StopReason: EventType,
pub StepsExecuted: StepCount,
pub InstructionsExecuted: InstructionCount,
pub Payload: ReplayResultPayload,
}
scalar_newtype!(InternalDataId, u32);
impl InternalDataId {
pub const INVALID: Self = Self(0);
}
#[repr(C)]
pub struct ICursorInternals {
_private: [u8; 0],
}
#[repr(C)]
pub struct IEngineInternals {
_private: [u8; 0],
}
#[repr(C)]
pub struct ErrorReporting {
_private: [u8; 0],
}
#[cfg(target_arch = "x86")]
pub type TtdMethod0<R> = unsafe extern "thiscall" fn(this: *mut c_void) -> R;
#[cfg(target_arch = "x86")]
pub type TtdMethod1<A1, R> =
unsafe extern "thiscall" fn(this: *mut c_void, a1: A1) -> R;
#[cfg(target_arch = "x86")]
pub type TtdMethod2<A1, A2, R> =
unsafe extern "thiscall" fn(this: *mut c_void, a1: A1, a2: A2) -> R;
#[cfg(target_arch = "x86")]
pub type TtdMethod3<A1, A2, A3, R> =
unsafe extern "thiscall" fn(this: *mut c_void, a1: A1, a2: A2, a3: A3) -> R;
#[cfg(target_arch = "x86")]
pub type TtdMethod4<A1, A2, A3, A4, R> = unsafe extern "thiscall" fn(
this: *mut c_void,
a1: A1,
a2: A2,
a3: A3,
a4: A4,
) -> R;
#[cfg(target_arch = "x86")]
pub type TtdMethod5<A1, A2, A3, A4, A5, R> = unsafe extern "thiscall" fn(
this: *mut c_void,
a1: A1,
a2: A2,
a3: A3,
a4: A4,
a5: A5,
) -> R;
#[cfg(target_arch = "x86")]
pub type TtdMethod6<A1, A2, A3, A4, A5, A6, R> =
unsafe extern "thiscall" fn(
this: *mut c_void,
a1: A1,
a2: A2,
a3: A3,
a4: A4,
a5: A5,
a6: A6,
) -> R;
#[cfg(target_arch = "x86")]
pub type TtdFastMethod1<A1, R> =
unsafe extern "fastcall" fn(this: *mut c_void, a1: A1) -> R;
#[cfg(target_arch = "x86_64")]
pub type TtdMethod0<R> = unsafe extern "system" fn(this: *mut c_void) -> R;
#[cfg(target_arch = "x86_64")]
pub type TtdMethod1<A1, R> =
unsafe extern "system" fn(this: *mut c_void, a1: A1) -> R;
#[cfg(target_arch = "x86_64")]
pub type TtdMethod2<A1, A2, R> =
unsafe extern "system" fn(this: *mut c_void, a1: A1, a2: A2) -> R;
#[cfg(target_arch = "x86_64")]
pub type TtdMethod3<A1, A2, A3, R> =
unsafe extern "system" fn(this: *mut c_void, a1: A1, a2: A2, a3: A3) -> R;
#[cfg(target_arch = "x86_64")]
pub type TtdMethod4<A1, A2, A3, A4, R> = unsafe extern "system" fn(
this: *mut c_void,
a1: A1,
a2: A2,
a3: A3,
a4: A4,
) -> R;
#[cfg(target_arch = "x86_64")]
pub type TtdMethod5<A1, A2, A3, A4, A5, R> = unsafe extern "system" fn(
this: *mut c_void,
a1: A1,
a2: A2,
a3: A3,
a4: A4,
a5: A5,
) -> R;
#[cfg(target_arch = "x86_64")]
pub type TtdMethod6<A1, A2, A3, A4, A5, A6, R> = unsafe extern "system" fn(
this: *mut c_void,
a1: A1,
a2: A2,
a3: A3,
a4: A4,
a5: A5,
a6: A6,
)
-> R;
#[cfg(target_arch = "x86_64")]
pub type TtdFastMethod1<A1, R> =
unsafe extern "system" fn(this: *mut c_void, a1: A1) -> R;
#[repr(transparent)]
pub struct IThreadView(pub(crate) *mut c_void);
#[repr(C)]
pub struct IThreadView_Vtbl {
pub GetThreadInfo: TtdMethod0<*const ThreadInfo>,
pub GetTebAddress: TtdMethod0<GuestAddress>,
pub GetPosition: TtdMethod0<*const Position>,
pub GetPreviousPosition: TtdMethod1<*mut Position, ()>,
pub GetProgramCounter: TtdMethod0<GuestAddress>,
pub GetStackPointer: TtdMethod0<GuestAddress>,
pub GetFramePointer: TtdMethod0<GuestAddress>,
pub GetBasicReturnValue: TtdMethod0<u64>,
pub GetCrossPlatformContext: TtdMethod1<*mut RegisterContext, ()>,
pub GetAvxExtendedContext: TtdMethod1<*mut ExtendedRegisterContext, ()>,
pub QueryMemoryRange: TtdMethod2<*mut MemoryRange, GuestAddress, ()>,
#[cfg(target_arch = "x86")]
pub QueryMemoryBuffer:
TtdMethod3<*mut MemoryBuffer, GuestAddress, BufferView, ()>,
#[cfg(target_arch = "x86_64")]
pub QueryMemoryBuffer:
TtdMethod3<*mut MemoryBuffer, GuestAddress, *const BufferView, ()>,
#[cfg(target_arch = "x86")]
pub QueryMemoryBufferWithRanges: TtdMethod5<
*mut MemoryBufferWithRanges,
GuestAddress,
BufferView,
usize,
*mut MemoryRange,
(),
>,
#[cfg(target_arch = "x86_64")]
pub QueryMemoryBufferWithRanges: TtdMethod5<
*mut MemoryBufferWithRanges,
GuestAddress,
*const BufferView,
usize,
*mut MemoryRange,
(),
>,
pub DeletingDestructor: *const c_void,
}
macro_rules! ttd_replay_callback {
($name:ident($($arg:ident: $arg_ty:ty),* $(,)?) -> $ret:ty) => {
#[cfg(target_arch = "x86")]
pub type $name =
Option<unsafe extern "fastcall" fn($($arg: $arg_ty),*) -> $ret>;
#[cfg(target_arch = "x86_64")]
pub type $name =
Option<unsafe extern "system" fn($($arg: $arg_ty),*) -> $ret>;
};
}
ttd_replay_callback!(
MemoryWatchpointCallback(
context: usize,
result: *const MemoryWatchpointResult,
thread: *const c_void,
) -> u8
);
ttd_replay_callback!(
PositionWatchpointCallback(
context: usize,
position: *const Position,
thread: *const c_void,
) -> u8
);
ttd_replay_callback!(
GapEventCallback(
context: usize,
kind: GapKind,
event: GapEventType,
thread: *const c_void,
) -> u8
);
ttd_replay_callback!(ThreadContinuityBreakCallback(context: usize) -> ());
pub type ReplayProgressCallback = Option<
unsafe extern "system" fn(context: usize, position: *const Position),
>;
ttd_replay_callback!(
FallbackCallback(
context: usize,
synthetic: u8,
instruction_address: GuestAddress,
instruction_size: usize,
thread: *const c_void,
) -> ()
);
ttd_replay_callback!(
CallReturnCallback(
context: usize,
guest_instruction_address: GuestAddress,
guest_fall_through_instruction_address: GuestAddress,
thread: *const c_void,
) -> ()
);
ttd_replay_callback!(
IndirectJumpCallback(
context: usize,
target_address: GuestAddress,
thread: *const c_void,
) -> ()
);
ttd_replay_callback!(
RegisterChangedCallback(
context: usize,
reg_id: u8,
old_data: *const c_void,
new_data: *const c_void,
data_size_in_bytes: usize,
thread: *const c_void,
) -> ()
);
#[repr(transparent)]
pub struct ICursorView(pub(crate) *mut c_void);
#[repr(C)]
pub struct ICursorView_Vtbl {
pub QueryMemoryRange:
TtdMethod3<*mut MemoryRange, GuestAddress, QueryMemoryPolicy, ()>,
#[cfg(target_arch = "x86")]
pub QueryMemoryBuffer: TtdMethod4<
*mut MemoryBuffer,
GuestAddress,
BufferView,
QueryMemoryPolicy,
(),
>,
#[cfg(target_arch = "x86_64")]
pub QueryMemoryBuffer: TtdMethod4<
*mut MemoryBuffer,
GuestAddress,
*const BufferView,
QueryMemoryPolicy,
(),
>,
#[cfg(target_arch = "x86")]
pub QueryMemoryBufferWithRanges: TtdMethod6<
*mut MemoryBufferWithRanges,
GuestAddress,
BufferView,
usize,
*mut MemoryRange,
QueryMemoryPolicy,
(),
>,
#[cfg(target_arch = "x86_64")]
pub QueryMemoryBufferWithRanges: TtdMethod6<
*mut MemoryBufferWithRanges,
GuestAddress,
*const BufferView,
usize,
*mut MemoryRange,
QueryMemoryPolicy,
(),
>,
pub SetDefaultMemoryPolicy: TtdMethod1<QueryMemoryPolicy, ()>,
pub GetDefaultMemoryPolicy: TtdMethod0<QueryMemoryPolicy>,
pub UnsafeGetReplayEngine: TtdFastMethod1<*const GUID, *mut c_void>,
pub UnsafeAsInterface: TtdMethod1<*const GUID, *mut c_void>,
pub UnsafeAsInterfaceConst: TtdMethod1<*const GUID, *const c_void>,
pub GetThreadInfo: TtdMethod1<ThreadId, *const ThreadInfo>,
pub GetTebAddress: TtdMethod1<ThreadId, GuestAddress>,
pub GetPosition: TtdMethod1<ThreadId, *const Position>,
pub GetPreviousPosition: TtdMethod1<ThreadId, *const Position>,
pub GetProgramCounter: TtdMethod1<ThreadId, GuestAddress>,
pub GetStackPointer: TtdMethod1<ThreadId, GuestAddress>,
pub GetFramePointer: TtdMethod1<ThreadId, GuestAddress>,
pub GetBasicReturnValue: TtdMethod1<ThreadId, u64>,
pub GetCrossPlatformContext: TtdMethod2<*mut RegisterContext, ThreadId, ()>,
pub GetAvxExtendedContext:
TtdMethod2<*mut ExtendedRegisterContext, ThreadId, ()>,
pub GetModuleCount: TtdMethod0<usize>,
pub GetModuleList: TtdMethod0<*const ModuleInstance>,
pub GetThreadCount: TtdMethod0<usize>,
pub GetThreadList: TtdMethod0<*const ActiveThreadInfo>,
pub SetEventMask: TtdMethod1<EventMask, ()>,
pub GetEventMask: TtdMethod0<EventMask>,
pub SetGapKindMask: TtdMethod1<GapKindMask, ()>,
pub GetGapKindMask: TtdMethod0<GapKindMask>,
pub SetGapEventMask: TtdMethod1<GapEventMask, ()>,
pub GetGapEventMask: TtdMethod0<GapEventMask>,
pub SetExceptionMask: TtdMethod1<ExceptionMask, ()>,
pub GetExceptionMask: TtdMethod0<ExceptionMask>,
pub SetReplayFlags: TtdMethod1<ReplayFlags, ()>,
pub GetReplayFlags: TtdMethod0<ReplayFlags>,
pub AddMemoryWatchpoint: TtdMethod1<*const MemoryWatchpointData, u8>,
pub RemoveMemoryWatchpoint: TtdMethod1<*const MemoryWatchpointData, u8>,
pub AddPositionWatchpoint: TtdMethod1<*const PositionWatchpointData, u8>,
pub RemovePositionWatchpoint: TtdMethod1<*const PositionWatchpointData, u8>,
pub Clear: TtdMethod0<()>,
pub SetPosition: TtdMethod1<*const Position, ()>,
pub SetPositionOnThread: TtdMethod2<UniqueThreadId, *const Position, ()>,
pub SetMemoryWatchpointCallback:
TtdMethod2<MemoryWatchpointCallback, usize, ()>,
pub SetPositionWatchpointCallback:
TtdMethod2<PositionWatchpointCallback, usize, ()>,
pub SetGapEventCallback: TtdMethod2<GapEventCallback, usize, ()>,
pub SetThreadContinuityBreakCallback:
TtdMethod2<ThreadContinuityBreakCallback, usize, ()>,
pub SetReplayProgressCallback:
TtdMethod2<ReplayProgressCallback, usize, ()>,
pub SetFallbackCallback: TtdMethod2<FallbackCallback, usize, ()>,
pub SetCallReturnCallback: TtdMethod2<CallReturnCallback, usize, ()>,
pub SetIndirectJumpCallback: TtdMethod2<IndirectJumpCallback, usize, ()>,
pub SetRegisterChangedCallback:
TtdMethod2<RegisterChangedCallback, usize, ()>,
#[cfg(target_arch = "x86")]
pub ReplayForward: TtdMethod3<*mut ReplayResult, Position, StepCount, ()>,
#[cfg(target_arch = "x86_64")]
pub ReplayForward:
TtdMethod3<*mut ReplayResult, *const Position, StepCount, ()>,
#[cfg(target_arch = "x86")]
pub ReplayBackward: TtdMethod3<*mut ReplayResult, Position, StepCount, ()>,
#[cfg(target_arch = "x86_64")]
pub ReplayBackward:
TtdMethod3<*mut ReplayResult, *const Position, StepCount, ()>,
pub InterruptReplay: TtdMethod0<()>,
pub GetInternals: TtdMethod0<*mut ICursorInternals>,
pub GetInternalsConst: TtdMethod0<*const ICursorInternals>,
pub GetInternalData: TtdMethod3<InternalDataId, *mut c_void, usize, usize>,
pub DeletingDestructor: *const c_void,
}
#[repr(transparent)]
pub struct ICursor(pub(crate) *mut c_void);
impl Drop for ICursor {
fn drop(&mut self) { unsafe { self.Destroy() } }
}
#[repr(C)]
pub struct ICursor_Vtbl {
pub base__: ICursorView_Vtbl,
pub Destroy: TtdMethod0<()>,
}
#[repr(transparent)]
pub struct IReplayEngineView(pub(crate) *mut c_void);
#[repr(C)]
pub struct IReplayEngineView_Vtbl {
pub UnsafeAsInterface: TtdMethod1<*const GUID, *mut c_void>,
pub UnsafeAsInterfaceConst: TtdMethod1<*const GUID, *const c_void>,
pub GetPebAddress: TtdMethod0<GuestAddress>,
pub GetSystemInfo: TtdMethod0<*const SystemInfo>,
pub GetFirstPosition: TtdMethod0<*const Position>,
pub GetLastPosition: TtdMethod0<*const Position>,
pub GetLifetime: TtdMethod0<*const PositionRange>,
pub GetRecordingType: TtdMethod0<RecordingType>,
pub GetThreadInfo: TtdMethod1<UniqueThreadId, *const ThreadInfo>,
pub GetThreadCount: TtdMethod0<usize>,
pub GetThreadList: TtdMethod0<*const ThreadInfo>,
pub GetThreadFirstPositionIndex: TtdMethod0<*const usize>,
pub GetThreadLastPositionIndex: TtdMethod0<*const usize>,
pub GetThreadLifetimeFirstPositionIndex: TtdMethod0<*const usize>,
pub GetThreadLifetimeLastPositionIndex: TtdMethod0<*const usize>,
pub GetThreadCreatedEventCount: TtdMethod0<usize>,
pub GetThreadCreatedEventList: TtdMethod0<*const ThreadCreatedEvent>,
pub GetThreadTerminatedEventCount: TtdMethod0<usize>,
pub GetThreadTerminatedEventList: TtdMethod0<*const ThreadTerminatedEvent>,
pub GetModuleCount: TtdMethod0<usize>,
pub GetModuleList: TtdMethod0<*const Module>,
pub GetModuleInstanceCount: TtdMethod0<usize>,
pub GetModuleInstanceList: TtdMethod0<*const ModuleInstance>,
pub GetModuleInstanceUnloadIndex: TtdMethod0<*const usize>,
pub GetModuleLoadedEventCount: TtdMethod0<usize>,
pub GetModuleLoadedEventList: TtdMethod0<*const ModuleLoadedEvent>,
pub GetModuleUnloadedEventCount: TtdMethod0<usize>,
pub GetModuleUnloadedEventList: TtdMethod0<*const ModuleUnloadedEvent>,
pub GetExceptionEventCount: TtdMethod0<usize>,
pub GetExceptionEventList: TtdMethod0<*const ExceptionEvent>,
pub GetExceptionAtOrAfterPosition:
TtdMethod1<*const Position, *const ExceptionEvent>,
pub GetKeyframeCount: TtdMethod0<usize>,
pub GetKeyframeList: TtdMethod0<*const Position>,
pub GetRecordClientCount: TtdMethod0<usize>,
pub GetRecordClientList: TtdMethod0<*const RecordClient>,
pub GetRecordClient: TtdMethod1<RecordClientId, *const RecordClient>,
pub GetCustomEventCount: TtdMethod0<usize>,
pub GetCustomEventList: TtdMethod0<*const CustomEvent>,
pub GetActivityCount: TtdMethod0<usize>,
pub GetActivityList: TtdMethod0<*const Activity>,
pub GetIslandCount: TtdMethod0<usize>,
pub GetIslandList: TtdMethod0<*const Island>,
pub NewCursor: TtdMethod1<*const GUID, *mut ICursor>,
pub BuildIndex: TtdMethod3<
IndexBuildProgressCallback,
*const c_void,
IndexBuildFlags,
IndexStatus,
>,
pub GetIndexStatus: TtdMethod0<IndexStatus>,
pub GetIndexFileStats: TtdMethod1<*mut IndexFileStats, ()>,
pub RegisterDebugModeAndLogging:
TtdMethod2<DebugModeType, *mut ErrorReporting, ()>,
pub GetInternals: TtdMethod0<*mut IEngineInternals>,
pub GetInternalsConst: TtdMethod0<*const IEngineInternals>,
pub DeletingDestructor: *const c_void,
}
#[repr(transparent)]
pub struct IReplayEngine(pub(crate) *mut c_void);
#[repr(C)]
pub struct IReplayEngine_Vtbl {
pub base__: IReplayEngineView_Vtbl,
pub Destroy: TtdMethod0<()>,
pub Initialize: TtdMethod1<*const u16, u8>,
}
macro_rules! assert_size {
($t:ty, $n:expr) => {
const _: [(); $n] = [(); size_of::<$t>()];
};
}
macro_rules! assert_align {
($t:ty, $n:expr) => {
const _: [(); $n] = [(); align_of::<$t>()];
};
}
assert_size!(GUID, 16);
assert_align!(GUID, 4);
assert_size!(TimingInfo, 40);
assert_size!(SystemInfoSystem, 56);
assert_size!(SystemInfo, 368);
assert_align!(SystemInfo, 8);
assert_size!(RegisterContext, 2672);
assert_align!(RegisterContext, 8);
assert_size!(ExtendedRegisterContext, 8832);
assert_align!(ExtendedRegisterContext, 8);
assert_size!(X86FxSaveFormat, 512);
assert_size!(X86FloatingSaveArea, 112);
assert_size!(X86Context, 716);
assert_align!(X86Context, 4);
assert_size!(Amd64Context, 1232);
assert_size!(Position, 16);
assert_align!(Position, 8);
assert_size!(PositionRange, 32);
assert_size!(ModuleInstance, 24);
assert_size!(MemoryWatchpointData, 24);
assert_size!(PositionWatchpointData, 40);
assert_size!(ThreadInfo, 72);
assert_size!(ActiveThreadInfo, 40);
assert_size!(ThreadCreatedEvent, 24);
assert_size!(ThreadTerminatedEvent, 24);
assert_size!(ModuleLoadedEvent, 24);
assert_size!(ModuleUnloadedEvent, 24);
assert_size!(IndexTreeStats, 96);
assert_size!(IndexFileStats, 208);
assert_size!(MemoryWatchpointResult, 24);
assert_size!(ReplayResultPayload, 24);
assert_size!(ReplayResult, 48);
assert_align!(ReplayResult, 8);
#[cfg(target_arch = "x86_64")]
const _: () = {
assert_size!(ConstBufferView, 16);
assert_size!(BufferView, 16);
assert_size!(Module, 40);
assert_size!(ExceptionEvent, 184);
assert_size!(RecordClient, 88);
assert_size!(CustomEvent, 48);
assert_size!(Activity, 48);
assert_size!(Island, 64);
assert_size!(MemoryRange, 32);
assert_size!(MemoryBuffer, 24);
assert_size!(MemoryBufferWithRanges, 32);
};
#[cfg(target_arch = "x86")]
const _: () = {
assert_size!(ConstBufferView, 8);
assert_size!(BufferView, 8);
assert_size!(Module, 32);
assert_size!(ExceptionEvent, 176);
assert_size!(RecordClient, 72);
assert_size!(CustomEvent, 32);
assert_size!(Activity, 40);
assert_size!(Island, 48);
assert_size!(MemoryRange, 24);
assert_size!(MemoryBuffer, 16);
assert_size!(MemoryBufferWithRanges, 24);
};
assert_size!(IThreadView, size_of::<usize>());
assert_size!(ICursorView, size_of::<usize>());
assert_size!(ICursor, size_of::<usize>());
assert_size!(IReplayEngineView, size_of::<usize>());
assert_size!(IReplayEngine, size_of::<usize>());
assert_size!(IThreadView_Vtbl, 14 * size_of::<usize>());
assert_size!(ICursorView_Vtbl, 55 * size_of::<usize>());
assert_size!(ICursor_Vtbl, 56 * size_of::<usize>());
assert_size!(IReplayEngineView_Vtbl, 50 * size_of::<usize>());
assert_size!(IReplayEngine_Vtbl, 52 * size_of::<usize>());