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 { 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 bytes.extend(self.rel_type.to_le_bytes());
125 } else if self.rel_type == 0x0a {
126 bytes.extend((self.rel_type as u32).to_le_bytes());
128 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}