1use std::collections::BTreeMap;
2
3#[derive(Debug)]
4pub struct DynamicSymbol {
5 name: u32, info: u8, other: u8, shndx: u16, value: u64, size: u64, }
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 bytes.extend(self.rel_type.to_le_bytes());
135 } else if self.rel_type == 0x0a {
136 bytes.extend((self.rel_type as u32).to_le_bytes());
138 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}