1use alloc::string::String;
2use alloc::sync::Arc;
3use alloc::vec::Vec;
4use fallible_iterator::FallibleIterator;
5use gimli::{EndianSlice, LittleEndian};
6
7use crate::arch::Arch;
8use crate::cache::{AllocationPolicy, Cache};
9use crate::dwarf::{DwarfCfiIndex, DwarfUnwinder, DwarfUnwinding, UnwindSectionType};
10use crate::error::{Error, UnwinderError};
11use crate::instruction_analysis::InstructionAnalysis;
12
13#[cfg(feature = "macho")]
14use crate::macho::{
15 CompactUnwindInfoUnwinder, CompactUnwindInfoUnwinding, CuiUnwindResult, TextBytes,
16};
17#[cfg(feature = "pe")]
18use crate::pe::{DataAtRvaRange, PeUnwinding};
19use crate::rule_cache::CacheResult;
20use crate::unwind_result::UnwindResult;
21use crate::unwind_rule::UnwindRule;
22use crate::FrameAddress;
23
24use core::marker::PhantomData;
25use core::ops::{Deref, Range};
26use core::sync::atomic::{AtomicU16, Ordering};
27
28pub trait Unwinder: Clone {
31 type UnwindRegs;
33
34 type Cache;
39
40 type Module;
43
44 fn add_module(&mut self, module: Self::Module);
49
50 fn remove_module(&mut self, module_avma_range_start: u64);
54
55 fn max_known_code_address(&self) -> u64;
62
63 fn unwind_frame<F>(
66 &self,
67 address: FrameAddress,
68 regs: &mut Self::UnwindRegs,
69 cache: &mut Self::Cache,
70 read_stack: &mut F,
71 ) -> Result<Option<u64>, Error>
72 where
73 F: FnMut(u64) -> Result<u64, ()>;
74
75 fn iter_frames<'u, 'c, 'r, F>(
77 &'u self,
78 pc: u64,
79 regs: Self::UnwindRegs,
80 cache: &'c mut Self::Cache,
81 read_stack: &'r mut F,
82 ) -> UnwindIterator<'u, 'c, 'r, Self, F>
83 where
84 F: FnMut(u64) -> Result<u64, ()>,
85 {
86 UnwindIterator::new(self, pc, regs, cache, read_stack)
87 }
88}
89
90pub struct UnwindIterator<'u, 'c, 'r, U: Unwinder, F: FnMut(u64) -> Result<u64, ()>> {
109 unwinder: &'u U,
110 state: UnwindIteratorState,
111 regs: U::UnwindRegs,
112 cache: &'c mut U::Cache,
113 read_stack: &'r mut F,
114}
115
116enum UnwindIteratorState {
117 Initial(u64),
118 Unwinding(FrameAddress),
119 Done,
120}
121
122impl<'u, 'c, 'r, U: Unwinder, F: FnMut(u64) -> Result<u64, ()>> UnwindIterator<'u, 'c, 'r, U, F> {
123 pub fn new(
125 unwinder: &'u U,
126 pc: u64,
127 regs: U::UnwindRegs,
128 cache: &'c mut U::Cache,
129 read_stack: &'r mut F,
130 ) -> Self {
131 Self {
132 unwinder,
133 state: UnwindIteratorState::Initial(pc),
134 regs,
135 cache,
136 read_stack,
137 }
138 }
139}
140
141impl<U: Unwinder, F: FnMut(u64) -> Result<u64, ()>> UnwindIterator<'_, '_, '_, U, F> {
142 #[allow(clippy::should_implement_trait)]
151 pub fn next(&mut self) -> Result<Option<FrameAddress>, Error> {
152 let next = match self.state {
153 UnwindIteratorState::Initial(pc) => {
154 self.state = UnwindIteratorState::Unwinding(FrameAddress::InstructionPointer(pc));
155 return Ok(Some(FrameAddress::InstructionPointer(pc)));
156 }
157 UnwindIteratorState::Unwinding(address) => {
158 self.unwinder
159 .unwind_frame(address, &mut self.regs, self.cache, self.read_stack)?
160 }
161 UnwindIteratorState::Done => return Ok(None),
162 };
163 match next {
164 Some(return_address) => {
165 let return_address = FrameAddress::from_return_address(return_address)
166 .ok_or(Error::ReturnAddressIsNull)?;
167 self.state = UnwindIteratorState::Unwinding(return_address);
168 Ok(Some(return_address))
169 }
170 None => {
171 self.state = UnwindIteratorState::Done;
172 Ok(None)
173 }
174 }
175 }
176}
177
178impl<U: Unwinder, F: FnMut(u64) -> Result<u64, ()>> FallibleIterator
179 for UnwindIterator<'_, '_, '_, U, F>
180{
181 type Item = FrameAddress;
182 type Error = Error;
183
184 fn next(&mut self) -> Result<Option<FrameAddress>, Error> {
185 self.next()
186 }
187}
188
189static GLOBAL_MODULES_GENERATION: AtomicU16 = AtomicU16::new(0);
196
197fn next_global_modules_generation() -> u16 {
198 GLOBAL_MODULES_GENERATION.fetch_add(1, Ordering::Relaxed)
199}
200
201cfg_if::cfg_if! {
202 if #[cfg(all(feature = "macho", feature = "pe"))] {
203 pub trait Unwinding:
204 Arch + DwarfUnwinding + InstructionAnalysis + CompactUnwindInfoUnwinding + PeUnwinding {}
205 impl<T: Arch + DwarfUnwinding + InstructionAnalysis + CompactUnwindInfoUnwinding + PeUnwinding>
206 Unwinding for T {}
207 } else if #[cfg(feature = "macho")] {
208 pub trait Unwinding:
209 Arch + DwarfUnwinding + InstructionAnalysis + CompactUnwindInfoUnwinding {}
210 impl<T: Arch + DwarfUnwinding + InstructionAnalysis + CompactUnwindInfoUnwinding> Unwinding for T {}
211 } else if #[cfg(feature = "pe")] {
212 pub trait Unwinding:
213 Arch + DwarfUnwinding + InstructionAnalysis + PeUnwinding {}
214 impl<T: Arch + DwarfUnwinding + InstructionAnalysis + PeUnwinding> Unwinding for T {}
215 } else {
216 pub trait Unwinding: Arch + DwarfUnwinding + InstructionAnalysis {}
217 impl<T: Arch + DwarfUnwinding + InstructionAnalysis> Unwinding for T {}
218 }
219}
220
221pub struct UnwinderInternal<D, A, P> {
222 modules: Vec<Module<D>>,
224 modules_generation: u16,
226 _arch: PhantomData<A>,
227 _allocation_policy: PhantomData<P>,
228}
229
230impl<D, A, P> Default for UnwinderInternal<D, A, P> {
231 fn default() -> Self {
232 Self::new()
233 }
234}
235
236impl<D, A, P> Clone for UnwinderInternal<D, A, P> {
237 fn clone(&self) -> Self {
238 Self {
239 modules: self.modules.clone(),
240 modules_generation: self.modules_generation,
241 _arch: PhantomData,
242 _allocation_policy: PhantomData,
243 }
244 }
245}
246
247impl<D, A, P> UnwinderInternal<D, A, P> {
248 pub fn new() -> Self {
249 Self {
250 modules: Vec::new(),
251 modules_generation: next_global_modules_generation(),
252 _arch: PhantomData,
253 _allocation_policy: PhantomData,
254 }
255 }
256}
257
258impl<D: Deref<Target = [u8]>, A: Unwinding, P: AllocationPolicy> UnwinderInternal<D, A, P> {
259 pub fn add_module(&mut self, module: Module<D>) {
260 let insertion_index = match self
261 .modules
262 .binary_search_by_key(&module.avma_range.start, |module| module.avma_range.start)
263 {
264 Ok(i) => i, Err(i) => i,
266 };
267 self.modules.insert(insertion_index, module);
268 self.modules_generation = next_global_modules_generation();
269 }
270
271 pub fn remove_module(&mut self, module_address_range_start: u64) {
272 if let Ok(index) = self
273 .modules
274 .binary_search_by_key(&module_address_range_start, |module| {
275 module.avma_range.start
276 })
277 {
278 self.modules.remove(index);
279 self.modules_generation = next_global_modules_generation();
280 };
281 }
282
283 pub fn max_known_code_address(&self) -> u64 {
284 self.modules.last().map_or(0, |m| m.avma_range.end)
285 }
286
287 fn find_module_for_address(&self, address: u64) -> Option<(usize, u32)> {
288 let (module_index, module) = match self
289 .modules
290 .binary_search_by_key(&address, |m| m.avma_range.start)
291 {
292 Ok(i) => (i, &self.modules[i]),
293 Err(insertion_index) => {
294 if insertion_index == 0 {
295 return None;
297 }
298 let i = insertion_index - 1;
299 let module = &self.modules[i];
300 if module.avma_range.end <= address {
301 return None;
303 }
304 (i, module)
305 }
306 };
307 if address < module.base_avma {
308 return None;
310 }
311 let relative_address = u32::try_from(address - module.base_avma).ok()?;
312 Some((module_index, relative_address))
313 }
314
315 fn with_cache<F, G>(
316 &self,
317 address: FrameAddress,
318 regs: &mut A::UnwindRegs,
319 cache: &mut Cache<A::UnwindRule, P>,
320 read_stack: &mut F,
321 callback: G,
322 ) -> Result<Option<u64>, Error>
323 where
324 F: FnMut(u64) -> Result<u64, ()>,
325 G: FnOnce(
326 &Module<D>,
327 FrameAddress,
328 u32,
329 &mut A::UnwindRegs,
330 &mut Cache<A::UnwindRule, P>,
331 &mut F,
332 ) -> Result<UnwindResult<A::UnwindRule>, UnwinderError>,
333 {
334 let lookup_address = address.address_for_lookup();
335 let is_first_frame = !address.is_return_address();
336 let cache_handle = match cache
337 .rule_cache
338 .lookup(lookup_address, self.modules_generation)
339 {
340 CacheResult::Hit(unwind_rule) => {
341 return unwind_rule.exec(is_first_frame, regs, read_stack);
342 }
343 CacheResult::Miss(handle) => handle,
344 };
345
346 let unwind_rule = match self.find_module_for_address(lookup_address) {
347 None => A::UnwindRule::fallback_rule(),
348 Some((module_index, relative_lookup_address)) => {
349 let module = &self.modules[module_index];
350 match callback(
351 module,
352 address,
353 relative_lookup_address,
354 regs,
355 cache,
356 read_stack,
357 ) {
358 Ok(UnwindResult::ExecRule(rule)) => rule,
359 Ok(UnwindResult::Uncacheable(return_address)) => {
360 return Ok(Some(return_address))
361 }
362 Err(_err) => {
363 A::UnwindRule::fallback_rule()
365 }
366 }
367 }
368 };
369 cache.rule_cache.insert(cache_handle, unwind_rule);
370 unwind_rule.exec(is_first_frame, regs, read_stack)
371 }
372
373 pub fn unwind_frame<F>(
374 &self,
375 address: FrameAddress,
376 regs: &mut A::UnwindRegs,
377 cache: &mut Cache<A::UnwindRule, P>,
378 read_stack: &mut F,
379 ) -> Result<Option<u64>, Error>
380 where
381 F: FnMut(u64) -> Result<u64, ()>,
382 {
383 self.with_cache(address, regs, cache, read_stack, Self::unwind_frame_impl)
384 }
385
386 fn unwind_frame_impl<F>(
387 module: &Module<D>,
388 address: FrameAddress,
389 rel_lookup_address: u32,
390 regs: &mut A::UnwindRegs,
391 cache: &mut Cache<A::UnwindRule, P>,
392 read_stack: &mut F,
393 ) -> Result<UnwindResult<A::UnwindRule>, UnwinderError>
394 where
395 F: FnMut(u64) -> Result<u64, ()>,
396 {
397 let is_first_frame = !address.is_return_address();
398 let unwind_result = match &*module.unwind_data {
399 #[cfg(feature = "macho")]
400 ModuleUnwindDataInternal::CompactUnwindInfoAndEhFrame {
401 unwind_info,
402 eh_frame,
403 stubs_svma: stubs,
404 stub_helper_svma: stub_helper,
405 base_addresses,
406 text_data,
407 } => {
408 let text_bytes = text_data.as_ref().and_then(|data| {
410 let offset_from_base =
411 u32::try_from(data.svma_range.start.checked_sub(module.base_svma)?).ok()?;
412 Some(TextBytes::new(offset_from_base, &data.bytes[..]))
413 });
414 let stubs_range = if let Some(stubs_range) = stubs {
415 (
416 (stubs_range.start - module.base_svma) as u32,
417 (stubs_range.end - module.base_svma) as u32,
418 )
419 } else {
420 (0, 0)
421 };
422 let stub_helper_range = if let Some(stub_helper_range) = stub_helper {
423 (
424 (stub_helper_range.start - module.base_svma) as u32,
425 (stub_helper_range.end - module.base_svma) as u32,
426 )
427 } else {
428 (0, 0)
429 };
430 let mut unwinder = CompactUnwindInfoUnwinder::<A>::new(
431 &unwind_info[..],
432 text_bytes,
433 stubs_range,
434 stub_helper_range,
435 );
436
437 let unwind_result = unwinder.unwind_frame(rel_lookup_address, is_first_frame)?;
438 match unwind_result {
439 CuiUnwindResult::ExecRule(rule) => UnwindResult::ExecRule(rule),
440 CuiUnwindResult::NeedDwarf(fde_offset) => {
441 let eh_frame_data =
442 eh_frame.as_deref().ok_or(UnwinderError::NoDwarfData)?;
443 let mut dwarf_unwinder = DwarfUnwinder::<_, A, _>::new(
444 EndianSlice::new(eh_frame_data, LittleEndian),
445 UnwindSectionType::EhFrame,
446 None,
447 &mut cache.gimli_unwind_context,
448 base_addresses.clone(),
449 module.base_svma,
450 );
451 dwarf_unwinder.unwind_frame_with_fde::<_, P::GimliEvaluationStorage<_>>(
452 regs,
453 is_first_frame,
454 rel_lookup_address,
455 fde_offset,
456 read_stack,
457 )?
458 }
459 }
460 }
461 ModuleUnwindDataInternal::EhFrameHdrAndEhFrame {
462 eh_frame_hdr,
463 eh_frame,
464 base_addresses,
465 } => {
466 let eh_frame_hdr_data = &eh_frame_hdr[..];
467 let mut dwarf_unwinder = DwarfUnwinder::<_, A, _>::new(
468 EndianSlice::new(eh_frame, LittleEndian),
469 UnwindSectionType::EhFrame,
470 Some(eh_frame_hdr_data),
471 &mut cache.gimli_unwind_context,
472 base_addresses.clone(),
473 module.base_svma,
474 );
475 let fde_offset = dwarf_unwinder
476 .get_fde_offset_for_relative_address(rel_lookup_address)
477 .ok_or(UnwinderError::EhFrameHdrCouldNotFindAddress)?;
478 dwarf_unwinder.unwind_frame_with_fde::<_, P::GimliEvaluationStorage<_>>(
479 regs,
480 is_first_frame,
481 rel_lookup_address,
482 fde_offset,
483 read_stack,
484 )?
485 }
486 ModuleUnwindDataInternal::DwarfCfiIndexAndEhFrame {
487 index,
488 eh_frame,
489 base_addresses,
490 } => {
491 let mut dwarf_unwinder = DwarfUnwinder::<_, A, _>::new(
492 EndianSlice::new(eh_frame, LittleEndian),
493 UnwindSectionType::EhFrame,
494 None,
495 &mut cache.gimli_unwind_context,
496 base_addresses.clone(),
497 module.base_svma,
498 );
499 let fde_offset = index
500 .fde_offset_for_relative_address(rel_lookup_address)
501 .ok_or(UnwinderError::DwarfCfiIndexCouldNotFindAddress)?;
502 dwarf_unwinder.unwind_frame_with_fde::<_, P::GimliEvaluationStorage<_>>(
503 regs,
504 is_first_frame,
505 rel_lookup_address,
506 fde_offset,
507 read_stack,
508 )?
509 }
510 ModuleUnwindDataInternal::DwarfCfiIndexAndDebugFrame {
511 index,
512 debug_frame,
513 base_addresses,
514 } => {
515 let mut dwarf_unwinder = DwarfUnwinder::<_, A, _>::new(
516 EndianSlice::new(debug_frame, LittleEndian),
517 UnwindSectionType::DebugFrame,
518 None,
519 &mut cache.gimli_unwind_context,
520 base_addresses.clone(),
521 module.base_svma,
522 );
523 let fde_offset = index
524 .fde_offset_for_relative_address(rel_lookup_address)
525 .ok_or(UnwinderError::DwarfCfiIndexCouldNotFindAddress)?;
526 dwarf_unwinder.unwind_frame_with_fde::<_, P::GimliEvaluationStorage<_>>(
527 regs,
528 is_first_frame,
529 rel_lookup_address,
530 fde_offset,
531 read_stack,
532 )?
533 }
534 #[cfg(feature = "pe")]
535 ModuleUnwindDataInternal::PeUnwindInfo {
536 pdata,
537 rdata,
538 xdata,
539 text,
540 } => <A as PeUnwinding>::unwind_frame(
541 crate::pe::PeSections {
542 pdata,
543 rdata: rdata.as_ref(),
544 xdata: xdata.as_ref(),
545 text: text.as_ref(),
546 },
547 rel_lookup_address,
548 regs,
549 is_first_frame,
550 read_stack,
551 )?,
552 ModuleUnwindDataInternal::None => return Err(UnwinderError::NoModuleUnwindData),
553 };
554 Ok(unwind_result)
555 }
556}
557
558enum ModuleUnwindDataInternal<D> {
571 #[cfg(feature = "macho")]
575 CompactUnwindInfoAndEhFrame {
576 unwind_info: D,
577 eh_frame: Option<D>,
578 stubs_svma: Option<Range<u64>>,
579 stub_helper_svma: Option<Range<u64>>,
580 base_addresses: crate::dwarf::BaseAddresses,
581 text_data: Option<TextByteData<D>>,
582 },
583 EhFrameHdrAndEhFrame {
586 eh_frame_hdr: D,
587 eh_frame: D,
588 base_addresses: crate::dwarf::BaseAddresses,
589 },
590 DwarfCfiIndexAndEhFrame {
594 index: DwarfCfiIndex,
595 eh_frame: D,
596 base_addresses: crate::dwarf::BaseAddresses,
597 },
598 DwarfCfiIndexAndDebugFrame {
602 index: DwarfCfiIndex,
603 debug_frame: D,
604 base_addresses: crate::dwarf::BaseAddresses,
605 },
606 #[cfg(feature = "pe")]
608 PeUnwindInfo {
609 pdata: D,
610 rdata: Option<DataAtRvaRange<D>>,
611 xdata: Option<DataAtRvaRange<D>>,
612 text: Option<DataAtRvaRange<D>>,
613 },
614 None,
617}
618
619impl<D: Deref<Target = [u8]>> ModuleUnwindDataInternal<D> {
620 fn new(section_info: &mut impl ModuleSectionInfo<D>) -> Self {
621 use crate::dwarf::base_addresses_for_sections;
622
623 #[cfg(feature = "macho")]
624 if let Some(unwind_info) = section_info.section_data(b"__unwind_info") {
625 let eh_frame = section_info.section_data(b"__eh_frame");
626 let stubs = section_info.section_svma_range(b"__stubs");
627 let stub_helper = section_info.section_svma_range(b"__stub_helper");
628 let text_data = if let (Some(bytes), Some(svma_range)) = (
635 section_info.segment_data(b"__TEXT"),
636 section_info.segment_svma_range(b"__TEXT"),
637 ) {
638 Some(TextByteData { bytes, svma_range })
639 } else if let (Some(bytes), Some(svma_range)) = (
640 section_info.section_data(b"__text"),
641 section_info.section_svma_range(b"__text"),
642 ) {
643 Some(TextByteData { bytes, svma_range })
644 } else {
645 None
646 };
647 return ModuleUnwindDataInternal::CompactUnwindInfoAndEhFrame {
648 unwind_info,
649 eh_frame,
650 stubs_svma: stubs,
651 stub_helper_svma: stub_helper,
652 base_addresses: base_addresses_for_sections(section_info),
653 text_data,
654 };
655 }
656
657 #[cfg(feature = "pe")]
658 if let Some(pdata) = section_info.section_data(b".pdata") {
659 let mut range_and_data = |name| {
660 let rva_range = section_info.section_svma_range(name).and_then(|range| {
661 Some(Range {
662 start: (range.start - section_info.base_svma()).try_into().ok()?,
663 end: (range.end - section_info.base_svma()).try_into().ok()?,
664 })
665 })?;
666 let data = section_info.section_data(name)?;
667 Some(DataAtRvaRange { data, rva_range })
668 };
669 return ModuleUnwindDataInternal::PeUnwindInfo {
670 pdata,
671 rdata: range_and_data(b".rdata"),
672 xdata: range_and_data(b".xdata"),
673 text: range_and_data(b".text"),
674 };
675 }
676
677 if let Some(eh_frame) = section_info
678 .section_data(b".eh_frame")
679 .or_else(|| section_info.section_data(b"__eh_frame"))
680 {
681 if let Some(eh_frame_hdr) = section_info
682 .section_data(b".eh_frame_hdr")
683 .or_else(|| section_info.section_data(b"__eh_frame_hdr"))
684 {
685 ModuleUnwindDataInternal::EhFrameHdrAndEhFrame {
686 eh_frame_hdr,
687 eh_frame,
688 base_addresses: base_addresses_for_sections(section_info),
689 }
690 } else {
691 match DwarfCfiIndex::try_new_eh_frame(&eh_frame, section_info) {
692 Ok(index) => ModuleUnwindDataInternal::DwarfCfiIndexAndEhFrame {
693 index,
694 eh_frame,
695 base_addresses: base_addresses_for_sections(section_info),
696 },
697 Err(_) => ModuleUnwindDataInternal::None,
698 }
699 }
700 } else if let Some(debug_frame) = section_info.section_data(b".debug_frame") {
701 match DwarfCfiIndex::try_new_debug_frame(&debug_frame, section_info) {
702 Ok(index) => ModuleUnwindDataInternal::DwarfCfiIndexAndDebugFrame {
703 index,
704 debug_frame,
705 base_addresses: base_addresses_for_sections(section_info),
706 },
707 Err(_) => ModuleUnwindDataInternal::None,
708 }
709 } else {
710 ModuleUnwindDataInternal::None
711 }
712 }
713}
714
715#[cfg(feature = "macho")]
733struct TextByteData<D> {
734 pub bytes: D,
735 pub svma_range: Range<u64>,
736}
737
738pub struct Module<D> {
752 #[allow(unused)]
754 name: String,
755 avma_range: Range<u64>,
757 base_avma: u64,
760 base_svma: u64,
762 unwind_data: Arc<ModuleUnwindDataInternal<D>>,
764}
765
766impl<D> Clone for Module<D> {
767 fn clone(&self) -> Self {
768 Self {
769 name: self.name.clone(),
770 avma_range: self.avma_range.clone(),
771 base_avma: self.base_avma,
772 base_svma: self.base_svma,
773 unwind_data: self.unwind_data.clone(),
774 }
775 }
776}
777
778pub trait ModuleSectionInfo<D> {
790 fn base_svma(&self) -> u64;
797
798 fn section_svma_range(&mut self, name: &[u8]) -> Option<Range<u64>>;
800
801 fn section_data(&mut self, name: &[u8]) -> Option<D>;
803
804 fn segment_svma_range(&mut self, _name: &[u8]) -> Option<Range<u64>> {
806 None
807 }
808
809 fn segment_data(&mut self, _name: &[u8]) -> Option<D> {
811 None
812 }
813}
814
815#[derive(Clone, Debug, Default, PartialEq, Eq)]
827pub struct ExplicitModuleSectionInfo<D> {
828 pub base_svma: u64,
833 pub text_svma: Option<Range<u64>>,
838 pub text: Option<D>,
843 pub stubs_svma: Option<Range<u64>>,
851 pub stub_helper_svma: Option<Range<u64>>,
860 pub got_svma: Option<Range<u64>>,
863 pub unwind_info: Option<D>,
865 pub eh_frame_svma: Option<Range<u64>>,
868 pub eh_frame: Option<D>,
871 pub eh_frame_hdr_svma: Option<Range<u64>>,
874 pub eh_frame_hdr: Option<D>,
877 pub debug_frame: Option<D>,
879 pub text_segment_svma: Option<Range<u64>>,
881 pub text_segment: Option<D>,
883}
884
885impl<D> ModuleSectionInfo<D> for ExplicitModuleSectionInfo<D>
886where
887 D: Deref<Target = [u8]>,
888{
889 fn base_svma(&self) -> u64 {
890 self.base_svma
891 }
892
893 fn section_svma_range(&mut self, name: &[u8]) -> Option<Range<u64>> {
894 match name {
895 b"__text" | b".text" => self.text_svma.clone(),
896 b"__stubs" => self.stubs_svma.clone(),
897 b"__stub_helper" => self.stub_helper_svma.clone(),
898 b"__eh_frame" | b".eh_frame" => self.eh_frame_svma.clone(),
899 b"__eh_frame_hdr" | b".eh_frame_hdr" => self.eh_frame_hdr_svma.clone(),
900 b"__got" | b".got" => self.got_svma.clone(),
901 _ => None,
902 }
903 }
904 fn section_data(&mut self, name: &[u8]) -> Option<D> {
905 match name {
906 b"__text" | b".text" => self.text.take(),
907 b"__unwind_info" => self.unwind_info.take(),
908 b"__eh_frame" | b".eh_frame" => self.eh_frame.take(),
909 b"__eh_frame_hdr" | b".eh_frame_hdr" => self.eh_frame_hdr.take(),
910 b"__debug_frame" | b".debug_frame" => self.debug_frame.take(),
911 _ => None,
912 }
913 }
914 fn segment_svma_range(&mut self, name: &[u8]) -> Option<Range<u64>> {
915 match name {
916 b"__TEXT" => self.text_segment_svma.clone(),
917 _ => None,
918 }
919 }
920 fn segment_data(&mut self, name: &[u8]) -> Option<D> {
921 match name {
922 b"__TEXT" => self.text_segment.take(),
923 _ => None,
924 }
925 }
926}
927
928impl<D: Deref<Target = [u8]>> Module<D> {
929 pub fn new(
930 name: String,
931 avma_range: core::ops::Range<u64>,
932 base_avma: u64,
933 mut section_info: impl ModuleSectionInfo<D>,
934 ) -> Self {
935 let unwind_data = ModuleUnwindDataInternal::new(&mut section_info);
936
937 Self {
938 name,
939 avma_range,
940 base_avma,
941 base_svma: section_info.base_svma(),
942 unwind_data: Arc::new(unwind_data),
943 }
944 }
945
946 pub fn avma_range(&self) -> core::ops::Range<u64> {
947 self.avma_range.clone()
948 }
949
950 pub fn base_avma(&self) -> u64 {
951 self.base_avma
952 }
953
954 pub fn name(&self) -> &str {
955 &self.name
956 }
957}