ship one record per function: merge the release set, gen reads it, descriptions as doc comments, gates for what was only claimed; v3.0
Some checks failed
CI / fuzz (push) Successful in 2m2s
CI / lint (push) Successful in 15s
CI / test (push) Failing after 18s

This commit is contained in:
Kamal Tufekcic 2026-08-02 22:01:36 +03:00
commit 3410a79b6a
28 changed files with 30596 additions and 955 deletions

View file

@ -109,6 +109,21 @@ fn kind_tag_of(sym: &str) -> Option<KindTag> {
const PT_GNU_EH_FRAME: u32 = 0x6474_e550;
impl CodeImage {
/// A bare image wrapping one executable span — enough for a decoder test to run the REAL analysis
/// over hand-assembled bytes instead of a parallel mock of it.
#[cfg(test)]
pub fn for_test(vaddr: u64, code: &[u8]) -> Self {
Self {
data: code.to_vec(),
exec: vec![(0, vaddr, code.len())],
secs: Vec::new(),
sym_addr: HashMap::new(),
reloc: HashMap::new(),
reloc_by_val: HashMap::new(),
kind_at: HashMap::new(),
}
}
pub fn load(path: &Path) -> Result<Self> {
let data = std::fs::read(path).with_context(|| format!("read {}", path.display()))?;
Self::from_bytes(data)
@ -406,6 +421,16 @@ impl CodeImage {
self.data_at(vaddr, 8).map(|b| u64le(b, 0))
}
/// Does a relocation land ON this slot — i.e. is the qword here a POINTER the linker resolved,
/// rather than a compile-time literal?
///
/// The distinction is what separates two records that are otherwise byte-compatible: a table of
/// `{ name, integer }` pairs and a table of `{ name, pointer }` pairs read identically until you ask
/// whether the second word was relocated.
pub fn is_reloc_slot(&self, vaddr: u64) -> bool {
self.reloc.contains_key(&vaddr)
}
/// Slot vaddrs whose (relocated) pointer value equals `target`.
pub fn ptrs_to(&self, target: u64) -> &[u64] {
self.reloc_by_val.get(&target).map_or(&[], |v| v.as_slice())