93 lines
2.8 KiB
Rust
93 lines
2.8 KiB
Rust
use libipt::enc_dec_builder::EncoderDecoderBuilder;
|
|
use libipt::packet::{Packet, PacketDecoder};
|
|
use memmap2::Mmap;
|
|
use std::error::Error;
|
|
use std::fs::File;
|
|
use std::path::Path;
|
|
use std::time::Duration;
|
|
|
|
#[derive(Debug)]
|
|
pub struct AnalyzeData {
|
|
pub packets: u64,
|
|
pub cycles: u64,
|
|
pub time: Duration,
|
|
pub time_main: Duration,
|
|
pub time_disabled: Duration,
|
|
}
|
|
|
|
#[derive(Debug, Eq, PartialEq)]
|
|
enum Scope {
|
|
Disabled,
|
|
Main,
|
|
PreRun,
|
|
PostRun,
|
|
}
|
|
|
|
pub fn analyze_dump(path: impl AsRef<Path>) -> Result<AnalyzeData, Box<dyn Error>> {
|
|
let trace_file = File::open(path)?;
|
|
let mmap = unsafe { Mmap::map(&trace_file)? };
|
|
|
|
let builder = EncoderDecoderBuilder::<PacketDecoder<()>>::new();
|
|
// I hope this is safe if the buffer is never written to
|
|
let builder = unsafe { builder.buffer_from_raw(mmap.as_ptr() as *mut _, mmap.len()) };
|
|
|
|
let mut decoder = builder.build()?;
|
|
// Required before it can be used
|
|
decoder.sync_forward()?;
|
|
|
|
let mut segments = vec![(Scope::PreRun, 0u64)];
|
|
let mut total = 0u64;
|
|
|
|
for packet in decoder {
|
|
total += 1;
|
|
match packet {
|
|
Ok(Packet::Cyc(cyc)) => {
|
|
segments.last_mut().unwrap().1 += cyc.value();
|
|
}
|
|
Ok(Packet::TipPge(_)) => {
|
|
segments.push((Scope::Main, 0));
|
|
}
|
|
Ok(Packet::TipPgd(_)) => {
|
|
segments.push((Scope::Disabled, 0));
|
|
}
|
|
Ok(Packet::Ptw(ptwrite)) => {
|
|
if ptwrite.payload() == 42 {
|
|
// Main enter
|
|
segments.push((Scope::Main, 0));
|
|
} else if ptwrite.payload() == 43 {
|
|
// Main exit
|
|
segments.push((Scope::PostRun, 0));
|
|
} else {
|
|
println!("GOT PTWRITE!!!!!: {ptwrite:?}");
|
|
}
|
|
}
|
|
Ok(_) => {}
|
|
Err(error) => println!("Got error: {error:?}"),
|
|
}
|
|
}
|
|
// dbg!(&segments);
|
|
let cycles_total = segments.iter().map(|(_, cycles)| cycles).sum();
|
|
let total_seconds = cycles_total as f64 / 2_700_000_000.0;
|
|
|
|
let main_duration = duration_in_mode(&segments, Scope::Main);
|
|
let disabled_duration = duration_in_mode(&segments, Scope::Disabled);
|
|
|
|
Ok(AnalyzeData {
|
|
packets: total,
|
|
cycles: cycles_total,
|
|
time: Duration::from_secs_f64(total_seconds),
|
|
time_main: main_duration,
|
|
time_disabled: disabled_duration
|
|
})
|
|
}
|
|
|
|
fn duration_in_mode(segments: &[(Scope, u64)], scope: Scope) -> Duration {
|
|
let total_cycles = segments
|
|
.into_iter()
|
|
.filter(|(it, _)| *it == scope)
|
|
.map(|(_, cycles)| *cycles)
|
|
.sum::<u64>();
|
|
let total_seconds = total_cycles as f64 / 2_700_000_000.0;
|
|
Duration::from_secs_f64(total_seconds)
|
|
}
|