1use alloc::vec::Vec;
2
3use crate::read::{Object, ObjectSection, ObjectSymbol, ObjectSymbolTable};
4use crate::{SymbolKind, SymbolScope};
5
6pub trait SymbolMapEntry {
8 fn address(&self) -> u64;
10
11 fn size(&self) -> u64 {
16 0
17 }
18}
19
20#[derive(Debug, Default, Clone)]
26pub struct SymbolMap<T: SymbolMapEntry> {
27 symbols: Vec<T>,
28}
29
30impl<T: SymbolMapEntry> SymbolMap<T> {
31 pub fn new(mut symbols: Vec<T>) -> Self {
35 symbols.sort_by_key(|s| s.address());
36 SymbolMap { symbols }
37 }
38
39 #[deprecated = "use before or containing"]
41 pub fn get(&self, address: u64) -> Option<&T> {
42 self.before(address)
43 }
44
45 pub fn before(&self, address: u64) -> Option<&T> {
47 let index = match self
48 .symbols
49 .binary_search_by_key(&address, |symbol| symbol.address())
50 {
51 Ok(index) => index,
52 Err(index) => index.checked_sub(1)?,
53 };
54 self.symbols.get(index)
55 }
56
57 pub fn containing(&self, address: u64) -> Option<&T> {
59 self.before(address).filter(|entry| {
60 entry.size() == 0 || address.wrapping_sub(entry.address()) < entry.size()
61 })
62 }
63
64 #[inline]
66 pub fn symbols(&self) -> &[T] {
67 &self.symbols
68 }
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
73pub struct SymbolMapName<'data> {
74 address: u64,
75 size: u64,
76 name: &'data str,
77}
78
79impl<'data> SymbolMapName<'data> {
80 pub fn new(address: u64, size: u64, name: &'data str) -> Self {
82 SymbolMapName {
83 address,
84 size,
85 name,
86 }
87 }
88
89 #[inline]
91 pub fn address(&self) -> u64 {
92 self.address
93 }
94
95 #[inline]
97 pub fn size(&self) -> u64 {
98 self.size
99 }
100
101 #[inline]
103 pub fn name(&self) -> &'data str {
104 self.name
105 }
106}
107
108impl<'data> SymbolMapEntry for SymbolMapName<'data> {
109 #[inline]
110 fn address(&self) -> u64 {
111 self.address
112 }
113
114 #[inline]
115 fn size(&self) -> u64 {
116 self.size
117 }
118}
119
120#[derive(Debug, Default, Clone)]
126pub struct ObjectMap<'data> {
127 symbols: SymbolMap<ObjectMapEntry<'data>>,
128 objects: Vec<ObjectMapFile<'data>>,
129}
130
131impl<'data> ObjectMap<'data> {
132 #[cfg(feature = "macho")]
133 pub(super) fn new(
134 symbols: Vec<ObjectMapEntry<'data>>,
135 objects: Vec<ObjectMapFile<'data>>,
136 ) -> Self {
137 ObjectMap {
138 symbols: SymbolMap::new(symbols),
139 objects,
140 }
141 }
142
143 pub fn get(&self, address: u64) -> Option<&ObjectMapEntry<'data>> {
145 self.symbols.containing(address)
146 }
147
148 #[inline]
150 pub fn symbols(&self) -> &[ObjectMapEntry<'data>] {
151 self.symbols.symbols()
152 }
153
154 #[inline]
156 pub fn objects(&self) -> &[ObjectMapFile<'data>] {
157 &self.objects
158 }
159}
160
161#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
163pub struct ObjectMapEntry<'data> {
164 address: u64,
165 size: u64,
166 name: &'data [u8],
167 object: usize,
168}
169
170impl<'data> ObjectMapEntry<'data> {
171 #[cfg(feature = "macho")]
172 pub(super) fn new(address: u64, size: u64, name: &'data [u8], object: usize) -> Self {
173 ObjectMapEntry {
174 address,
175 size,
176 name,
177 object,
178 }
179 }
180
181 #[inline]
183 pub fn address(&self) -> u64 {
184 self.address
185 }
186
187 #[inline]
191 pub fn size(&self) -> u64 {
192 self.size
193 }
194
195 #[inline]
197 pub fn name(&self) -> &'data [u8] {
198 self.name
199 }
200
201 #[inline]
203 pub fn object_index(&self) -> usize {
204 self.object
205 }
206
207 #[inline]
209 pub fn object<'a>(&self, map: &'a ObjectMap<'data>) -> &'a ObjectMapFile<'data> {
210 &map.objects[self.object]
211 }
212}
213
214impl<'data> SymbolMapEntry for ObjectMapEntry<'data> {
215 #[inline]
216 fn address(&self) -> u64 {
217 self.address
218 }
219
220 #[inline]
221 fn size(&self) -> u64 {
222 self.size
223 }
224}
225
226#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
228pub struct ObjectMapFile<'data> {
229 path: &'data [u8],
230 member: Option<&'data [u8]>,
231}
232
233impl<'data> ObjectMapFile<'data> {
234 #[cfg(feature = "macho")]
235 pub(super) fn new(path: &'data [u8], member: Option<&'data [u8]>) -> Self {
236 ObjectMapFile { path, member }
237 }
238
239 #[inline]
241 pub fn path(&self) -> &'data [u8] {
242 self.path
243 }
244
245 #[inline]
247 pub fn member(&self) -> Option<&'data [u8]> {
248 self.member
249 }
250}
251
252#[derive(Debug, Default)]
258pub struct SymbolMapBuilder(());
259
260impl SymbolMapBuilder {
261 pub fn new() -> Self {
263 Self::default()
264 }
265
266 pub fn build<'data, O>(self, object: &O) -> SymbolMap<SymbolMapName<'data>>
280 where
281 O: Object<'data> + ?Sized,
282 {
283 let mut symbols = Vec::new();
284 if let Some(table) = object
285 .symbol_table()
286 .or_else(|| object.dynamic_symbol_table())
287 {
288 let mut all_symbols = Vec::new();
290 for symbol in table.symbols() {
291 if !symbol.is_definition() {
293 continue;
294 }
295 let name = match symbol.name() {
297 Ok(name) => name,
298 _ => continue,
299 };
300 if name.is_empty() {
301 continue;
302 }
303 let address = symbol.address();
304 let size = symbol.size();
305
306 let mut priority = 0u32;
308
309 match symbol.kind() {
311 SymbolKind::Text | SymbolKind::Data => {}
312 SymbolKind::Unknown => priority += 1,
313 _ => continue,
314 }
315
316 priority *= 2;
319 #[cfg(feature = "xcoff")]
320 if let crate::SymbolFlags::Xcoff { x_smtyp, .. } = symbol.flags() {
321 priority += (x_smtyp != crate::xcoff::XTY_LD) as u32;
322 if size != 0 {
323 all_symbols.push((address.saturating_add(size), !0, !0, !0, ""));
325 }
326 }
327
328 priority *= 2;
330 priority += (size == 0) as u32;
331
332 priority *= 4;
334 priority += match symbol.scope() {
335 SymbolScope::Unknown => 3,
336 SymbolScope::Compilation => 2,
337 SymbolScope::Linkage => 1,
338 SymbolScope::Dynamic => 0,
339 };
340
341 let index = !0 - symbol.index().0;
343
344 all_symbols.push((address, priority, index, size, name));
346 }
347
348 for section in object.sections() {
350 let address = section.address().saturating_add(section.size());
351 all_symbols.push((address, !0, !0, !0, ""));
352 }
353
354 all_symbols.sort_unstable();
356
357 let mut previous_address = !0;
358 for (address, _priority, _index, size, name) in all_symbols {
359 if address != previous_address {
360 symbols.push(SymbolMapName::new(address, size, name));
361 previous_address = address;
362 }
363 }
364
365 let mut symbol_iter = symbols.iter_mut().rev();
367 let mut previous_address = symbol_iter.next().map(|s| s.address).unwrap_or(0);
368 for symbol in symbol_iter {
369 if symbol.size == 0 {
370 symbol.size = previous_address.saturating_sub(symbol.address);
371 }
372 previous_address = symbol.address;
373 }
374
375 symbols.retain(|x| !x.name.is_empty());
377 }
378 SymbolMap::new(symbols)
379 }
380}