Skip to main content

binate_core/
symbol.rs

1use crate::error::Result;
2use object::{Object, ObjectSection, ObjectSymbol, SymbolKind};
3use serde::Serialize;
4use std::collections::BTreeMap;
5use std::ops::Range;
6
7#[derive(Debug, Clone, Serialize)]
8pub struct ResolvedSymbol {
9    pub name: String,
10    pub address: u64,
11    pub size: u64,
12    pub section: Option<String>,
13}
14
15pub struct SymbolTable {
16    by_address: BTreeMap<u64, ResolvedSymbol>,
17}
18
19impl SymbolTable {
20    pub fn build(file: &object::File<'_>) -> Result<Self> {
21        let mut by_address = BTreeMap::new();
22        for sym in file.symbols() {
23            if matches!(sym.kind(), SymbolKind::Unknown | SymbolKind::Label) {
24                continue;
25            }
26            let address = sym.address();
27            if address == 0 {
28                continue;
29            }
30            let name = sym.name().unwrap_or("<unknown>").to_owned();
31            let size = sym.size();
32            let section = sym
33                .section_index()
34                .and_then(|idx| file.section_by_index(idx).ok())
35                .and_then(|s| s.name().ok().map(|n: &str| n.to_owned()));
36            by_address.insert(address, ResolvedSymbol { name, address, size, section });
37        }
38        Ok(Self { by_address })
39    }
40
41    /// Find the symbol whose range contains `address`.
42    pub fn symbol_at(&self, address: u64) -> Option<&ResolvedSymbol> {
43        self.by_address
44            .range(..=address)
45            .next_back()
46            .map(|(_, sym)| sym)
47            .filter(|sym| sym.size == 0 || address < sym.address + sym.size)
48    }
49
50    pub fn symbols_in(&self, range: Range<u64>) -> impl Iterator<Item = &ResolvedSymbol> {
51        self.by_address
52            .range(range.clone())
53            .map(|(_, sym)| sym)
54            .filter(move |sym| sym.address < range.end)
55    }
56
57    pub fn iter(&self) -> impl Iterator<Item = &ResolvedSymbol> {
58        self.by_address.values()
59    }
60}