sbpf_assembler/
dynsym.rs

1use std::collections::BTreeMap;
2
3#[derive(Debug)]
4pub struct DynamicSymbol {
5    name: u32,  // index into .dynstr section
6    info: u8,   // symbol binding and type
7    other: u8,  // symbol visibility
8    shndx: u16, // section index
9    value: u64, // symbol value
10    size: u64,  // symbol size
11}
12
13impl DynamicSymbol {
14    pub fn new(name: u32, info: u8, other: u8, shndx: u16, value: u64, size: u64) -> Self {
15        Self {
16            name,
17            info,
18            other,
19            shndx,
20            value,
21            size,
22        }
23    }
24
25    pub fn bytecode(&self) -> Vec<u8> {
26        let mut bytes = Vec::new();
27        bytes.extend(self.name.to_le_bytes());
28        bytes.push(self.info);
29        bytes.push(self.other);
30        bytes.extend(self.shndx.to_le_bytes());
31        bytes.extend(self.value.to_le_bytes());
32        bytes.extend(self.size.to_le_bytes());
33        bytes
34    }
35
36    pub fn get_name(&self) -> u32 {
37        self.name
38    }
39}
40
41#[derive(Debug, Clone, PartialEq)]
42pub enum SymbolKind {
43    EntryPoint,
44    CallTarget,
45}
46
47#[derive(Debug, Default)]
48pub struct DynamicSymbolMap {
49    symbols: BTreeMap<String, Vec<(SymbolKind, u64)>>,
50}
51
52impl DynamicSymbolMap {
53    pub fn new() -> Self {
54        Self::default()
55    }
56
57    pub fn copy(&self) -> Self {
58        Self {
59            symbols: self.symbols.clone(),
60        }
61    }
62
63    pub fn add_symbol(&mut self, name: String, kind: SymbolKind, offset: u64) {
64        self.symbols.entry(name).or_default().push((kind, offset));
65    }
66
67    pub fn add_entry_point(&mut self, name: String, offset: u64) {
68        self.add_symbol(name, SymbolKind::EntryPoint, offset);
69    }
70
71    pub fn add_call_target(&mut self, name: String, offset: u64) {
72        self.add_symbol(name, SymbolKind::CallTarget, offset);
73    }
74
75    pub fn get_entry_points(&self) -> Vec<(String, u64)> {
76        self.get_symbols_by_kind(SymbolKind::EntryPoint)
77    }
78
79    pub fn get_call_targets(&self) -> Vec<(String, u64)> {
80        self.get_symbols_by_kind(SymbolKind::CallTarget)
81    }
82
83    fn get_symbols_by_kind(&self, kind: SymbolKind) -> Vec<(String, u64)> {
84        self.symbols
85            .iter()
86            .filter(|(_, symbols)| symbols.iter().any(|(k, _)| *k == kind))
87            .map(|(name, symbols)| {
88                (
89                    name.clone(),
90                    symbols.iter().find(|(k, _)| *k == kind).unwrap().1,
91                )
92            })
93            .collect()
94    }
95
96    pub fn get_symbol(&self, name: &str) -> Option<&Vec<(SymbolKind, u64)>> {
97        self.symbols.get(name)
98    }
99
100    pub fn get_symbols(&self) -> &BTreeMap<String, Vec<(SymbolKind, u64)>> {
101        &self.symbols
102    }
103}
104
105#[derive(Debug, Clone, Copy, PartialEq)]
106#[repr(u64)]
107pub enum RelocationType {
108    RSbf64Relative = 0x08,
109    RSbfSyscall = 0x0a,
110}
111
112#[derive(Debug, Clone, PartialEq)]
113pub struct RelDyn {
114    offset: u64,
115    rel_type: u64,
116    dynstr_offset: u64,
117}
118
119impl RelDyn {
120    pub fn new(offset: u64, rel_type: u64, dynstr_offset: u64) -> Self {
121        Self {
122            offset,
123            rel_type,
124            dynstr_offset,
125        }
126    }
127
128    pub fn bytecode(&self) -> Vec<u8> {
129        let mut bytes = Vec::new();
130        bytes.extend(self.offset.to_le_bytes());
131
132        if self.rel_type == 0x08 {
133            // 8 bytes rel_type
134            bytes.extend(self.rel_type.to_le_bytes());
135        } else if self.rel_type == 0x0a {
136            // 4 bytes rel_type
137            bytes.extend((self.rel_type as u32).to_le_bytes());
138            // 4 bytes dynstr_offset
139            bytes.extend((self.dynstr_offset as u32).to_le_bytes());
140        }
141
142        bytes
143    }
144}
145
146#[derive(Debug, Default)]
147pub struct RelDynMap {
148    rel_dyns: BTreeMap<u64, Vec<(RelocationType, String)>>,
149}
150
151impl RelDynMap {
152    pub fn new() -> Self {
153        Self::default()
154    }
155
156    pub fn add_rel_dyn(&mut self, offset: u64, rel_type: RelocationType, name: String) {
157        self.rel_dyns
158            .entry(offset)
159            .or_default()
160            .push((rel_type, name));
161    }
162
163    pub fn get_rel_dyns(&self) -> Vec<(u64, RelocationType, String)> {
164        self.rel_dyns
165            .iter()
166            .flat_map(|(offset, rel_types)| {
167                rel_types
168                    .iter()
169                    .map(move |(rel_type, name)| (*offset, *rel_type, name.clone()))
170            })
171            .collect()
172    }
173
174    pub fn copy(&self) -> Self {
175        Self {
176            rel_dyns: self.rel_dyns.clone(),
177        }
178    }
179}