Add a way to find .eh_frame_hdr
using __GNU_EH_FRAME_HDR
.
GNU ld on at least some platforms adds a symbol `__GNU_EH_FRAME_HDR` for the `.eh_frame_hdr` section. Add a cargo feature `fde-gnu-eh-frame-hdr` to enable use of this.
This commit is contained in:
parent
32ad71301c
commit
c40a114e23
@ -21,6 +21,7 @@ unwinder = []
|
||||
fde-phdr = ["libc"]
|
||||
fde-registry = ["alloc"]
|
||||
fde-static = []
|
||||
fde-gnu-eh-frame-hdr = []
|
||||
dwarf-expr = []
|
||||
hide-trace = []
|
||||
personality = []
|
||||
|
66
src/unwinder/find_fde/gnu_eh_frame_hdr.rs
Normal file
66
src/unwinder/find_fde/gnu_eh_frame_hdr.rs
Normal file
@ -0,0 +1,66 @@
|
||||
use super::FDESearchResult;
|
||||
use crate::util::*;
|
||||
|
||||
use gimli::{BaseAddresses, EhFrame, EhFrameHdr, NativeEndian, UnwindSection};
|
||||
|
||||
pub struct StaticFinder(());
|
||||
|
||||
pub fn get_finder() -> &'static StaticFinder {
|
||||
&StaticFinder(())
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
static __executable_start: u8;
|
||||
static __etext: u8;
|
||||
static __GNU_EH_FRAME_HDR: u8;
|
||||
}
|
||||
|
||||
impl super::FDEFinder for StaticFinder {
|
||||
fn find_fde(&self, pc: usize) -> Option<FDESearchResult> {
|
||||
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_hdr = &__GNU_EH_FRAME_HDR as *const u8 as usize;
|
||||
let bases = BaseAddresses::default()
|
||||
.set_text(text_start as _)
|
||||
.set_eh_frame_hdr(eh_frame_hdr as _);
|
||||
let eh_frame_hdr = EhFrameHdr::new(
|
||||
get_unlimited_slice(eh_frame_hdr as usize as _),
|
||||
NativeEndian,
|
||||
)
|
||||
.parse(&bases, core::mem::size_of::<usize>() as _)
|
||||
.ok()?;
|
||||
let eh_frame = deref_pointer(eh_frame_hdr.eh_frame_ptr());
|
||||
let bases = bases.set_eh_frame(eh_frame as _);
|
||||
let eh_frame = EhFrame::new(get_unlimited_slice(eh_frame as _), NativeEndian);
|
||||
|
||||
// Use binary search table for address if available.
|
||||
if let Some(table) = eh_frame_hdr.table() {
|
||||
if let Ok(fde) =
|
||||
table.fde_for_address(&eh_frame, &bases, pc as _, EhFrame::cie_from_offset)
|
||||
{
|
||||
return Some(FDESearchResult {
|
||||
fde,
|
||||
bases,
|
||||
eh_frame,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise do the linear search.
|
||||
if let Ok(fde) = eh_frame.fde_for_address(&bases, pc as _, EhFrame::cie_from_offset) {
|
||||
return Some(FDESearchResult {
|
||||
fde,
|
||||
bases,
|
||||
eh_frame,
|
||||
});
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
#[cfg(feature = "fde-static")]
|
||||
mod fixed;
|
||||
#[cfg(feature = "fde-gnu-eh-frame-hdr")]
|
||||
mod gnu_eh_frame_hdr;
|
||||
#[cfg(feature = "fde-phdr")]
|
||||
mod phdr;
|
||||
#[cfg(feature = "fde-registry")]
|
||||
@ -35,6 +37,10 @@ impl FDEFinder for GlobalFinder {
|
||||
if let Some(v) = fixed::get_finder().find_fde(pc) {
|
||||
return Some(v);
|
||||
}
|
||||
#[cfg(feature = "fde-gnu-eh-frame-hdr")]
|
||||
if let Some(v) = gnu_eh_frame_hdr::get_finder().find_fde(pc) {
|
||||
return Some(v);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user