stracers-core 0.1.0

Library for tracing system calls and signals
Documentation
use nix::unistd::Pid;
use std::io;

use crate::platform;

/// Read a null-terminated string from the tracee's address space.
/// Reads word-by-word via ptrace, stops at null byte or `max_len`.
pub fn read_string(pid: Pid, addr: u64, max_len: usize) -> io::Result<String> {
    if addr == 0 {
        return Ok("NULL".to_string());
    }

    let mut result = Vec::with_capacity(128);
    let mut offset = 0u64;

    while result.len() < max_len {
        let word = match platform::read_word(pid, addr + offset) {
            Ok(w) => w,
            Err(_) => return Ok(format!("{:#x}", addr)),
        };
        let bytes = word.to_ne_bytes();

        for &b in &bytes {
            if b == 0 {
                return Ok(String::from_utf8_lossy(&result).into_owned());
            }
            result.push(b);
            if result.len() >= max_len {
                return Ok(format!("{}...", String::from_utf8_lossy(&result)));
            }
        }
        offset += size_of::<i64>() as u64;
    }
    Ok(String::from_utf8_lossy(&result).into_owned())
}

/// Read a fixed number of bytes from the tracee's address space.
pub fn read_bytes(pid: Pid, addr: u64, len: usize) -> io::Result<Vec<u8>> {
    if addr == 0 || len == 0 {
        return Ok(Vec::new());
    }

    let mut result = Vec::with_capacity(len);
    let mut offset = 0u64;

    while result.len() < len {
        let word = platform::read_word(pid, addr + offset)?;
        let bytes = word.to_ne_bytes();
        for &b in &bytes {
            if result.len() >= len {
                break;
            }
            result.push(b);
        }
        offset += size_of::<i64>() as u64;
    }
    result.truncate(len);
    Ok(result)
}