Iptr -- Idiomatic Intel-PT decoder

⚓ Rust    📅 2026-02-10    👤 surdeus    👁️ 6      

surdeus

Intel PT is a hardware mechanism provided by Intel to trace process behavior in basic-block level. This feature is available since Intel 5th generation processors. Linux has made it very convenient to use Intel PT to record process traces:

sudo perf record -e intel_pt//u ls

To decode Intel PT traces, we developed the iptr project. This project contains several crates, providing functionalities from low-level packet interactions to AFL++-bitmap-compatible trace analyzers. Moreover, this project is aimed to provide idiomatic Rust APIs, and the usage is straightforward for Rust users:

use iptr_decoder::{DecoderContext, DecodeOptions, HandlePacket};

struct MyPtHandler;

impl HandlePacket for MyPtHandler {
    // We don't produce high-level errors for simplicity
    type Error = std::convert::Infallible;

    // Required method, will be invoked at the begining of decoding
    fn at_decode_begin(&mut self) -> Result<(), Self::Error> {
        Ok(())
    }

    // One of the provided methods, will be invoked when a short
    // TNT packet is encountered. The actual byte is `packet_byte`, and
    // `highest_bit` refers to the index of highest bit that represents
    // a Taken/Not-Taken bit.
    fn on_short_tnt_packet(
        &mut self,
        context: &DecoderContext,
        packet_byte: std::num::NonZero<u8>,
        highest_bit: u32,
    ) -> Result<(), Self::Error> {
        println!("Short TNT packet get! Byte is {packet_byte:x}");
        Ok(())
    }
}

// Use the defined `MyPtHandler` to decode Intel PT traces
fn handle_pt_trace(pt: &[u8]) {
    let mut packet_handler = MyPtHandler;
    iptr_decoder::decode(pt, DecodeOptions::default(), &mut packet_handler).unwrap();
}

Intel PT trace is also an important approach for dynamic vulnerability discovery, where it is used for fuzzing to record basic block transitions to update edge bitmaps. The iptr-edge-analyzer crate provides an easy-to-use interface for constructing AFL++-compatible bitmaps:

use iptr_decoder::DecodeOptions;
use iptr_edge_analyzer::{
    EdgeAnalyzer,
    control_flow_handler::fuzz_bitmap::FuzzBitmapControlFlowHandler,
    memory_reader::perf_mmap::PerfMmapBasedMemoryReader,
};

fn process_intel_pt(intel_pt: &[u8], fuzzing_bitmap: &mut [u8], memory_reader: PerfMmapBasedMemoryReader) {
    let control_flow_handler = FuzzBitmapControlFlowHandler::new(fuzzing_bitmap, None);
    let mut edge_analyzer = EdgeAnalyzer::new(control_flow_handler, memory_reader);
    iptr_decoder::decode(intel_pt, DecodeOptions::default(), &mut edge_analyzer).unwrap();
    // At this moment, `fuzzing_bitmap` is updated in an AFL++-compatible manner
}

iptr-edge-analyzer has comparable performance with libxdc, the state-of-the-art Intel PT decoder written in C.

Any suggestions are welcome, and feel free to use this project :slight_smile:

1 post - 1 participant

Read full topic

🏷️ Rust_feed