| 1 | use std::collections::HashMap; |
| 2 | |
| 3 | use crate::resolve::{DylibId, SymbolId}; |
| 4 | |
| 5 | pub const STUB_SIZE: u32 = 12; |
| 6 | pub const LAZY_POINTER_SIZE: u32 = 8; |
| 7 | pub const STUB_HELPER_HEADER_SIZE: u32 = 24; |
| 8 | pub const STUB_HELPER_ENTRY_SIZE: u32 = 12; |
| 9 | pub const DYLD_PRIVATE_SIZE: u32 = 8; |
| 10 | |
| 11 | #[derive(Debug, Clone, PartialEq, Eq, Default)] |
| 12 | pub struct StubsSection { |
| 13 | pub entries: Vec<StubEntry>, |
| 14 | pub index: HashMap<SymbolId, usize>, |
| 15 | } |
| 16 | |
| 17 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 18 | pub struct StubEntry { |
| 19 | pub symbol: SymbolId, |
| 20 | pub dylib: DylibId, |
| 21 | pub weak_import: bool, |
| 22 | } |
| 23 | |
| 24 | impl StubsSection { |
| 25 | pub fn intern(&mut self, symbol: SymbolId, dylib: DylibId, weak_import: bool) -> usize { |
| 26 | if let Some(&idx) = self.index.get(&symbol) { |
| 27 | return idx; |
| 28 | } |
| 29 | let idx = self.entries.len(); |
| 30 | self.entries.push(StubEntry { |
| 31 | symbol, |
| 32 | dylib, |
| 33 | weak_import, |
| 34 | }); |
| 35 | self.index.insert(symbol, idx); |
| 36 | idx |
| 37 | } |
| 38 | |
| 39 | pub fn get(&self, symbol: SymbolId) -> Option<(usize, &StubEntry)> { |
| 40 | let idx = *self.index.get(&symbol)?; |
| 41 | Some((idx, &self.entries[idx])) |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | #[derive(Debug, Clone, PartialEq, Eq, Default)] |
| 46 | pub struct LazyPointerSection { |
| 47 | pub entries: Vec<LazyPointerEntry>, |
| 48 | pub index: HashMap<SymbolId, usize>, |
| 49 | } |
| 50 | |
| 51 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 52 | pub struct LazyPointerEntry { |
| 53 | pub symbol: SymbolId, |
| 54 | pub dylib: DylibId, |
| 55 | pub weak_import: bool, |
| 56 | } |
| 57 | |
| 58 | impl LazyPointerSection { |
| 59 | pub fn intern(&mut self, symbol: SymbolId, dylib: DylibId, weak_import: bool) -> usize { |
| 60 | if let Some(&idx) = self.index.get(&symbol) { |
| 61 | return idx; |
| 62 | } |
| 63 | let idx = self.entries.len(); |
| 64 | self.entries.push(LazyPointerEntry { |
| 65 | symbol, |
| 66 | dylib, |
| 67 | weak_import, |
| 68 | }); |
| 69 | self.index.insert(symbol, idx); |
| 70 | idx |
| 71 | } |
| 72 | |
| 73 | pub fn get(&self, symbol: SymbolId) -> Option<(usize, &LazyPointerEntry)> { |
| 74 | let idx = *self.index.get(&symbol)?; |
| 75 | Some((idx, &self.entries[idx])) |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | #[cfg(test)] |
| 80 | mod tests { |
| 81 | use super::*; |
| 82 | |
| 83 | #[test] |
| 84 | fn stubs_and_lazy_pointers_share_symbol_dedup() { |
| 85 | let mut stubs = StubsSection::default(); |
| 86 | let mut lazy = LazyPointerSection::default(); |
| 87 | |
| 88 | let a = stubs.intern(SymbolId(3), DylibId(1), false); |
| 89 | let b = stubs.intern(SymbolId(3), DylibId(1), true); |
| 90 | let c = lazy.intern(SymbolId(3), DylibId(1), false); |
| 91 | let d = lazy.intern(SymbolId(4), DylibId(2), true); |
| 92 | |
| 93 | assert_eq!(a, 0); |
| 94 | assert_eq!(b, 0); |
| 95 | assert_eq!(c, 0); |
| 96 | assert_eq!(d, 1); |
| 97 | assert_eq!(stubs.entries.len(), 1); |
| 98 | assert_eq!(lazy.entries.len(), 2); |
| 99 | } |
| 100 | } |
| 101 |