Skip to main content

stracers_core/
memory.rs

1use nix::unistd::Pid;
2use std::io;
3
4use crate::platform;
5
6/// Read a null-terminated string from the tracee's address space.
7/// Reads word-by-word via ptrace, stops at null byte or `max_len`.
8pub fn read_string(pid: Pid, addr: u64, max_len: usize) -> io::Result<String> {
9    if addr == 0 {
10        return Ok("NULL".to_string());
11    }
12
13    let mut result = Vec::with_capacity(128);
14    let mut offset = 0u64;
15
16    while result.len() < max_len {
17        let word = match platform::read_word(pid, addr + offset) {
18            Ok(w) => w,
19            Err(_) => return Ok(format!("{:#x}", addr)),
20        };
21        let bytes = word.to_ne_bytes();
22
23        for &b in &bytes {
24            if b == 0 {
25                return Ok(String::from_utf8_lossy(&result).into_owned());
26            }
27            result.push(b);
28            if result.len() >= max_len {
29                return Ok(format!("{}...", String::from_utf8_lossy(&result)));
30            }
31        }
32        offset += size_of::<i64>() as u64;
33    }
34    Ok(String::from_utf8_lossy(&result).into_owned())
35}
36
37/// Read a fixed number of bytes from the tracee's address space.
38pub fn read_bytes(pid: Pid, addr: u64, len: usize) -> io::Result<Vec<u8>> {
39    if addr == 0 || len == 0 {
40        return Ok(Vec::new());
41    }
42
43    let mut result = Vec::with_capacity(len);
44    let mut offset = 0u64;
45
46    while result.len() < len {
47        let word = platform::read_word(pid, addr + offset)?;
48        let bytes = word.to_ne_bytes();
49        for &b in &bytes {
50            if result.len() >= len {
51                break;
52            }
53            result.push(b);
54        }
55        offset += size_of::<i64>() as u64;
56    }
57    result.truncate(len);
58    Ok(result)
59}