diff --git a/Cargo.toml b/Cargo.toml index f171efb..c2ab217 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ alloc = [] unwinder = [] fde-phdr = ["libc"] fde-registry = ["alloc"] +fde-static = [] dwarf-expr = [] hide-trace = [] personality = [] diff --git a/src/unwinder/find_fde/fixed.rs b/src/unwinder/find_fde/fixed.rs new file mode 100644 index 0000000..c9d6193 --- /dev/null +++ b/src/unwinder/find_fde/fixed.rs @@ -0,0 +1,44 @@ +use super::FDESearchResult; +use crate::util::*; + +use gimli::{BaseAddresses, EhFrame, NativeEndian, UnwindSection}; + +pub struct StaticFinder(()); + +pub fn get_finder() -> &'static StaticFinder { + &StaticFinder(()) +} + +extern "C" { + static __executable_start: u8; + static __etext: u8; + static __eh_frame: u8; +} + +impl super::FDEFinder for StaticFinder { + fn find_fde(&self, pc: usize) -> Option { + unsafe { + let text_start = &__executable_start as *const u8 as usize; + let text_end = &__etext as *const u8 as usize; + if !(text_start..text_end).contains(&pc) { + return None; + } + + let eh_frame = &__eh_frame as *const u8 as usize; + let bases = BaseAddresses::default() + .set_eh_frame(eh_frame as _) + .set_text(text_start as _); + let eh_frame = EhFrame::new(get_unlimited_slice(eh_frame as _), NativeEndian); + + if let Ok(fde) = eh_frame.fde_for_address(&bases, pc as _, EhFrame::cie_from_offset) { + return Some(FDESearchResult { + fde, + bases, + eh_frame, + }); + } + + None + } + } +} diff --git a/src/unwinder/find_fde/mod.rs b/src/unwinder/find_fde/mod.rs index 22a0e3f..714c9df 100644 --- a/src/unwinder/find_fde/mod.rs +++ b/src/unwinder/find_fde/mod.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "fde-static")] +mod fixed; #[cfg(feature = "fde-phdr")] mod phdr; #[cfg(feature = "fde-registry")] @@ -29,6 +31,10 @@ impl FDEFinder for GlobalFinder { if let Some(v) = phdr::get_finder().find_fde(pc) { return Some(v); } + #[cfg(feature = "fde-static")] + if let Some(v) = fixed::get_finder().find_fde(pc) { + return Some(v); + } None } }