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 { name, info, other, shndx, value, size }
16    }
17
18    pub fn bytecode(&self) -> Vec<u8> {
19        let mut bytes = Vec::new();
20        bytes.extend(self.name.to_le_bytes());
21        bytes.push(self.info);
22        bytes.push(self.other);
23        bytes.extend(self.shndx.to_le_bytes());
24        bytes.extend(self.value.to_le_bytes());
25        bytes.extend(self.size.to_le_bytes());
26        bytes
27    }
28
29    pub fn get_name(&self) -> u32 {
30        self.name
31    }
32}
33
34#[derive(Debug, Clone, PartialEq)]
35pub enum SymbolKind {
36    EntryPoint,
37    CallTarget,
38}
39
40
41
42#[derive(Debug)]
43pub struct DynamicSymbolMap {
44    symbols: BTreeMap<String, Vec<(SymbolKind, u64)>>,
45}
46
47impl DynamicSymbolMap {
48    pub fn new() -> Self {
49        Self {
50            symbols: BTreeMap::new(),
51        }
52    }
53
54    pub fn copy(&self) -> Self {
55        Self {
56            symbols: self.symbols.clone()
57        }
58    }
59
60    pub fn add_symbol(&mut self, name: String, kind: SymbolKind, offset: u64) {
61        self.symbols
62            .entry(name)
63            .or_default()
64            .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.iter()
85            .filter(|(_, symbols)| symbols.iter().any(|(k, _)| *k == kind))
86            .map(|(name, symbols)| (name.clone(), symbols.iter().find(|(k, _)| *k == kind).unwrap().1))
87            .collect()
88    }
89
90    pub fn get_symbol(&self, name: &str) -> Option<&Vec<(SymbolKind, u64)>> {
91        self.symbols.get(name)
92    }
93
94    pub fn get_symbols(&self) -> &BTreeMap<String, Vec<(SymbolKind, u64)>> {
95        &self.symbols
96    }
97}
98
99#[derive(Debug, Clone, Copy, PartialEq)]
100#[repr(u64)]
101pub enum RelocationType {
102    RSbf64Relative = 0x08,
103    RSbfSyscall = 0x0a,
104}
105
106#[derive(Debug, Clone, PartialEq)]
107pub struct RelDyn {
108    offset: u64,
109    rel_type: u64,
110    dynstr_offset: u64,
111}  
112
113impl RelDyn {
114    pub fn new(offset: u64, rel_type: u64, dynstr_offset: u64) -> Self {
115        Self { offset, rel_type, dynstr_offset }
116    }
117
118    pub fn bytecode(&self) -> Vec<u8> {
119        let mut bytes = Vec::new();
120        bytes.extend(self.offset.to_le_bytes());
121
122        if self.rel_type == 0x08 {
123            // 8 bytes rel_type
124            bytes.extend(self.rel_type.to_le_bytes());
125        } else if self.rel_type == 0x0a {
126            // 4 bytes rel_type
127            bytes.extend((self.rel_type as u32).to_le_bytes());
128            // 4 bytes dynstr_offset
129            bytes.extend((self.dynstr_offset as u32).to_le_bytes());
130        }
131
132        bytes
133    }
134}
135
136#[derive(Debug)]
137pub struct RelDynMap {
138    rel_dyns: BTreeMap<u64, Vec<(RelocationType, String)>>,
139}
140
141impl RelDynMap {
142    pub fn new() -> Self {
143        Self { rel_dyns: BTreeMap::new() }
144    }
145
146    pub fn add_rel_dyn(&mut self, offset: u64, rel_type: RelocationType, name: String) {
147        self.rel_dyns.entry(offset).or_default().push((rel_type, name));
148    }
149
150    pub fn get_rel_dyns(&self) -> Vec<(u64, RelocationType, String)> {
151        self.rel_dyns.iter()
152            .flat_map(|(offset, rel_types)| {
153                rel_types.iter().map(move |(rel_type, name)| (*offset, *rel_type, name.clone()))
154            })
155            .collect()
156    }
157
158    pub fn copy(&self) -> Self {
159        Self { rel_dyns: self.rel_dyns.clone() }
160    }
161}