Skip to main content

wazabin_binary/
blob.rs

1use crate::Arch;
2
3use crate::BinaryFormat;
4
5/// A generic binary blob: raw bytes loaded at a fixed virtual address.
6///
7/// This is the simplest possible [`BinaryFormat`] — it holds an arbitrary byte
8/// slice together with its load address and has no symbol information.  Tests
9/// and other code that already work with raw bytes can use this instead of
10/// passing `(address, bytes)` tuples directly, enabling them to go through the
11/// same `BinaryFormat`-based pipeline as real ELF binaries.
12#[derive(Clone)]
13pub struct Blob {
14    pub load_address: u64,
15    pub data: Vec<u8>,
16}
17
18impl Blob {
19    pub fn new(load_address: u64, data: Vec<u8>) -> Self {
20        Self { load_address, data }
21    }
22
23    /// Borrow `bytes` directly without copying.
24    pub fn from_slice(load_address: u64, bytes: &[u8]) -> Self {
25        Self {
26            load_address,
27            data: bytes.to_vec(),
28        }
29    }
30}
31
32impl BinaryFormat for Blob {
33    fn load_address(&self) -> u64 {
34        self.load_address
35    }
36
37    fn architecture(&self) -> Arch {
38        // X64 by default
39        Arch::X86_64
40    }
41
42    /// The only entry point is the load address itself.
43    fn entry_points(&self) -> Vec<u64> {
44        vec![self.load_address]
45    }
46
47    fn byte_at(&self, addr: u64) -> Option<u8> {
48        let offset = addr.checked_sub(self.load_address)? as usize;
49        self.data.get(offset).copied()
50    }
51
52    fn bytes_at(&self, addr: u64) -> Option<&[u8]> {
53        let offset = addr.checked_sub(self.load_address)? as usize;
54        self.data.get(offset..)
55    }
56
57    fn segment_bounds(&self, addr: u64) -> Option<(u64, u64)> {
58        self.contains(addr).then(|| {
59            (
60                self.load_address,
61                self.load_address + self.data.len() as u64,
62            )
63        })
64    }
65
66    /// A blob is one region; treat it as executable (raw code/data) so resolved
67    /// jump targets in it are not filtered out.
68    fn mapped_regions(&self) -> Vec<(u64, Vec<u8>, bool, bool)> {
69        vec![(self.load_address, self.data.clone(), true, false)]
70    }
71}