use crate::constants::*;
use bitflags::bitflags;
bitflags! {
pub struct SampleFormat: u64 {
const IP = PERF_SAMPLE_IP;
const TID = PERF_SAMPLE_TID;
const TIME = PERF_SAMPLE_TIME;
const ADDR = PERF_SAMPLE_ADDR;
const READ = PERF_SAMPLE_READ;
const CALLCHAIN = PERF_SAMPLE_CALLCHAIN;
const ID = PERF_SAMPLE_ID;
const CPU = PERF_SAMPLE_CPU;
const PERIOD = PERF_SAMPLE_PERIOD;
const STREAM_ID = PERF_SAMPLE_STREAM_ID;
const RAW = PERF_SAMPLE_RAW;
const BRANCH_STACK = PERF_SAMPLE_BRANCH_STACK;
const REGS_USER = PERF_SAMPLE_REGS_USER;
const STACK_USER = PERF_SAMPLE_STACK_USER;
const WEIGHT = PERF_SAMPLE_WEIGHT;
const DATA_SRC = PERF_SAMPLE_DATA_SRC;
const IDENTIFIER = PERF_SAMPLE_IDENTIFIER;
const TRANSACTION = PERF_SAMPLE_TRANSACTION;
const REGS_INTR = PERF_SAMPLE_REGS_INTR;
const PHYS_ADDR = PERF_SAMPLE_PHYS_ADDR;
const AUX = PERF_SAMPLE_AUX;
const CGROUP = PERF_SAMPLE_CGROUP;
const DATA_PAGE_SIZE = PERF_SAMPLE_DATA_PAGE_SIZE;
const CODE_PAGE_SIZE = PERF_SAMPLE_CODE_PAGE_SIZE;
const WEIGHT_STRUCT = PERF_SAMPLE_WEIGHT_STRUCT;
}
pub struct BranchSampleFormat: u64 {
const USER = PERF_SAMPLE_BRANCH_USER;
const KERNEL = PERF_SAMPLE_BRANCH_KERNEL;
const HV = PERF_SAMPLE_BRANCH_HV;
const ANY = PERF_SAMPLE_BRANCH_ANY;
const ANY_CALL = PERF_SAMPLE_BRANCH_ANY_CALL;
const ANY_RETURN = PERF_SAMPLE_BRANCH_ANY_RETURN;
const IND_CALL = PERF_SAMPLE_BRANCH_IND_CALL;
const ABORT_TX = PERF_SAMPLE_BRANCH_ABORT_TX;
const IN_TX = PERF_SAMPLE_BRANCH_IN_TX;
const NO_TX = PERF_SAMPLE_BRANCH_NO_TX;
const COND = PERF_SAMPLE_BRANCH_COND;
const CALL_STACK = PERF_SAMPLE_BRANCH_CALL_STACK;
const IND_JUMP = PERF_SAMPLE_BRANCH_IND_JUMP;
const CALL = PERF_SAMPLE_BRANCH_CALL;
const NO_FLAGS = PERF_SAMPLE_BRANCH_NO_FLAGS;
const NO_CYCLES = PERF_SAMPLE_BRANCH_NO_CYCLES;
const TYPE_SAVE = PERF_SAMPLE_BRANCH_TYPE_SAVE;
const HW_INDEX = PERF_SAMPLE_BRANCH_HW_INDEX;
}
pub struct AttrFlags: u64 {
const DISABLED = ATTR_FLAG_BIT_DISABLED;
const INHERIT = ATTR_FLAG_BIT_INHERIT;
const PINNED = ATTR_FLAG_BIT_PINNED;
const EXCLUSIVE = ATTR_FLAG_BIT_EXCLUSIVE;
const EXCLUDE_USER = ATTR_FLAG_BIT_EXCLUDE_USER;
const EXCLUDE_KERNEL = ATTR_FLAG_BIT_EXCLUDE_KERNEL;
const EXCLUDE_HV = ATTR_FLAG_BIT_EXCLUDE_HV;
const EXCLUDE_IDLE = ATTR_FLAG_BIT_EXCLUDE_IDLE;
const MMAP = ATTR_FLAG_BIT_MMAP;
const COMM = ATTR_FLAG_BIT_COMM;
const FREQ = ATTR_FLAG_BIT_FREQ;
const INHERIT_STAT = ATTR_FLAG_BIT_INHERIT_STAT;
const ENABLE_ON_EXEC = ATTR_FLAG_BIT_ENABLE_ON_EXEC;
const TASK = ATTR_FLAG_BIT_TASK;
const WATERMARK = ATTR_FLAG_BIT_WATERMARK;
const PRECISE_IP_BIT_15 = 1 << 15;
const PRECISE_IP_BIT_16 = 1 << 16;
const PRECISE_IP_BITMASK = ATTR_FLAG_BITMASK_PRECISE_IP;
const MMAP_DATA = ATTR_FLAG_BIT_MMAP_DATA;
const SAMPLE_ID_ALL = ATTR_FLAG_BIT_SAMPLE_ID_ALL;
const EXCLUDE_HOST = ATTR_FLAG_BIT_EXCLUDE_HOST;
const EXCLUDE_GUEST = ATTR_FLAG_BIT_EXCLUDE_GUEST;
const EXCLUDE_CALLCHAIN_KERNEL = ATTR_FLAG_BIT_EXCLUDE_CALLCHAIN_KERNEL;
const EXCLUDE_CALLCHAIN_USER = ATTR_FLAG_BIT_EXCLUDE_CALLCHAIN_USER;
const MMAP2 = ATTR_FLAG_BIT_MMAP2;
const COMM_EXEC = ATTR_FLAG_BIT_COMM_EXEC;
const USE_CLOCKID = ATTR_FLAG_BIT_USE_CLOCKID;
const CONTEXT_SWITCH = ATTR_FLAG_BIT_CONTEXT_SWITCH;
const WRITE_BACKWARD = ATTR_FLAG_BIT_WRITE_BACKWARD;
const NAMESPACES = ATTR_FLAG_BIT_NAMESPACES;
const KSYMBOL = ATTR_FLAG_BIT_KSYMBOL;
const BPF_EVENT = ATTR_FLAG_BIT_BPF_EVENT;
const AUX_OUTPUT = ATTR_FLAG_BIT_AUX_OUTPUT;
const CGROUP = ATTR_FLAG_BIT_CGROUP;
const TEXT_POKE = ATTR_FLAG_BIT_TEXT_POKE;
const BUILD_ID = ATTR_FLAG_BIT_BUILD_ID;
const INHERIT_THREAD = ATTR_FLAG_BIT_INHERIT_THREAD;
const REMOVE_ON_EXEC = ATTR_FLAG_BIT_REMOVE_ON_EXEC;
const SIGTRAP = ATTR_FLAG_BIT_SIGTRAP;
}
pub struct HwBreakpointType: u32 {
const EMPTY = 0;
const R = 1;
const W = 2;
const RW = Self::R.bits | Self::W.bits;
const X = 4;
const INVALID = Self::RW.bits | Self::X.bits;
}
pub struct ReadFormat: u64 {
const TOTAL_TIME_ENABLED = PERF_FORMAT_TOTAL_TIME_ENABLED;
const TOTAL_TIME_RUNNING = PERF_FORMAT_TOTAL_TIME_RUNNING;
const ID = PERF_FORMAT_ID;
const GROUP = PERF_FORMAT_GROUP;
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum IpSkidConstraint {
ArbitrarySkid,
ConstantSkid,
ZeroSkid,
ZeroSkidOrRandomization,
}
impl AttrFlags {
pub fn ip_skid_constraint(&self) -> IpSkidConstraint {
match (self.bits & Self::PRECISE_IP_BITMASK.bits) >> 15 {
0 => IpSkidConstraint::ArbitrarySkid,
1 => IpSkidConstraint::ConstantSkid,
2 => IpSkidConstraint::ZeroSkid,
3 => IpSkidConstraint::ZeroSkidOrRandomization,
_ => unreachable!(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub enum ClockId {
Realtime,
Monotonic,
ProcessCputimeId,
ThreadCputimeId,
MonotonicRaw,
RealtimeCoarse,
MonotonicCoarse,
Boottime,
RealtimeAlarm,
BoottimeAlarm,
}
impl ClockId {
pub fn from_u32(clockid: u32) -> Option<Self> {
Some(match clockid {
0 => Self::Realtime,
1 => Self::Monotonic,
2 => Self::ProcessCputimeId,
3 => Self::ThreadCputimeId,
4 => Self::MonotonicRaw,
5 => Self::RealtimeCoarse,
6 => Self::MonotonicCoarse,
7 => Self::Boottime,
8 => Self::RealtimeAlarm,
9 => Self::BoottimeAlarm,
_ => return None,
})
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RecordType(pub u32);
impl RecordType {
pub const MMAP: Self = Self(PERF_RECORD_MMAP);
pub const LOST: Self = Self(PERF_RECORD_LOST);
pub const COMM: Self = Self(PERF_RECORD_COMM);
pub const EXIT: Self = Self(PERF_RECORD_EXIT);
pub const THROTTLE: Self = Self(PERF_RECORD_THROTTLE);
pub const UNTHROTTLE: Self = Self(PERF_RECORD_UNTHROTTLE);
pub const FORK: Self = Self(PERF_RECORD_FORK);
pub const READ: Self = Self(PERF_RECORD_READ);
pub const SAMPLE: Self = Self(PERF_RECORD_SAMPLE);
pub const MMAP2: Self = Self(PERF_RECORD_MMAP2);
pub const AUX: Self = Self(PERF_RECORD_AUX);
pub const ITRACE_START: Self = Self(PERF_RECORD_ITRACE_START);
pub const LOST_SAMPLES: Self = Self(PERF_RECORD_LOST_SAMPLES);
pub const SWITCH: Self = Self(PERF_RECORD_SWITCH);
pub const SWITCH_CPU_WIDE: Self = Self(PERF_RECORD_SWITCH_CPU_WIDE);
pub const NAMESPACES: Self = Self(PERF_RECORD_NAMESPACES);
pub const KSYMBOL: Self = Self(PERF_RECORD_KSYMBOL);
pub const BPF_EVENT: Self = Self(PERF_RECORD_BPF_EVENT);
pub const CGROUP: Self = Self(PERF_RECORD_CGROUP);
pub const TEXT_POKE: Self = Self(PERF_RECORD_TEXT_POKE);
pub const AUX_OUTPUT_HW_ID: Self = Self(PERF_RECORD_AUX_OUTPUT_HW_ID);
pub fn is_builtin_type(&self) -> bool {
self.0 < PERF_RECORD_USER_TYPE_START
}
pub fn is_user_type(&self) -> bool {
self.0 >= PERF_RECORD_USER_TYPE_START
}
}
impl std::fmt::Debug for RecordType {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
let s = match *self {
Self::MMAP => "MMAP",
Self::LOST => "LOST",
Self::COMM => "COMM",
Self::EXIT => "EXIT",
Self::THROTTLE => "THROTTLE",
Self::UNTHROTTLE => "UNTHROTTLE",
Self::FORK => "FORK",
Self::READ => "READ",
Self::SAMPLE => "SAMPLE",
Self::MMAP2 => "MMAP2",
Self::AUX => "AUX",
Self::ITRACE_START => "ITRACE_START",
Self::LOST_SAMPLES => "LOST_SAMPLES",
Self::SWITCH => "SWITCH",
Self::SWITCH_CPU_WIDE => "SWITCH_CPU_WIDE",
Self::NAMESPACES => "NAMESPACES",
Self::KSYMBOL => "KSYMBOL",
Self::BPF_EVENT => "BPF_EVENT",
Self::CGROUP => "CGROUP",
Self::TEXT_POKE => "TEXT_POKE",
Self::AUX_OUTPUT_HW_ID => "AUX_OUTPUT_HW_ID",
other if self.is_builtin_type() => {
return fmt.write_fmt(format_args!("Unknown built-in: {}", other.0));
}
other => {
return fmt.write_fmt(format_args!("User type: {}", other.0));
}
};
fmt.write_str(s)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum CpuMode {
Unknown,
Kernel,
User,
Hypervisor,
GuestKernel,
GuestUser,
}
impl CpuMode {
pub fn from_misc(misc: u16) -> Self {
match misc & PERF_RECORD_MISC_CPUMODE_MASK {
PERF_RECORD_MISC_CPUMODE_UNKNOWN => Self::Unknown,
PERF_RECORD_MISC_KERNEL => Self::Kernel,
PERF_RECORD_MISC_USER => Self::User,
PERF_RECORD_MISC_HYPERVISOR => Self::Hypervisor,
PERF_RECORD_MISC_GUEST_KERNEL => Self::GuestKernel,
PERF_RECORD_MISC_GUEST_USER => Self::GuestUser,
_ => Self::Unknown,
}
}
}