From b5ee24f896c2bc8c2d0ed0de60ffb7aa70c93e84 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Tue, 13 Jun 2023 20:26:52 +0200 Subject: [PATCH] uwu wind --- eh_frame_hdr.bin | Bin 0 -> 35124 bytes src/dwarf/divination.rs | 159 +++++++++++++++++++++++++++++++++++++--- src/lib.rs | 4 +- src/stdext.rs | 18 ++--- test.c | 18 +++-- 5 files changed, 171 insertions(+), 28 deletions(-) create mode 100644 eh_frame_hdr.bin diff --git a/eh_frame_hdr.bin b/eh_frame_hdr.bin new file mode 100644 index 0000000000000000000000000000000000000000..28c33db45014e4841809a6a5b23f771352913e42 GIT binary patch literal 35124 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 literal 0 HcmV?d00001 diff --git a/src/dwarf/divination.rs b/src/dwarf/divination.rs index a27e65d..b23039b 100644 --- a/src/dwarf/divination.rs +++ b/src/dwarf/divination.rs @@ -9,11 +9,12 @@ //! the GNU extension (`_dl_find_object`)[https://www.gnu.org/software/libc/manual/html_node/Dynamic-Linker-Introspection.html]. //! then, we parse that as beautiful DWARF call frame information, as god (or rather, the x86-64 psABI) intended. -use core::ffi; +#![allow(non_camel_case_types)] + +use core::{ffi, fmt, ptr::addr_of}; use crate::stdext::with_last_os_error_str; -#[allow(non_camel_case_types)] #[repr(C)] struct dl_find_object { dlfo_flags: ffi::c_ulonglong, @@ -29,26 +30,115 @@ extern "C" { #[derive(Debug, Clone, Copy)] pub struct DwarfInfo { - /// PT_GNU_EH_FRAME - pub(crate) eh_frame: *const u8, + /// A pointer to the `PT_GNU_EH_FRAME` segment (the `.eh_frame_hdr` section). + pub(crate) eh_frame_hdr: *const u8, +} + +/// The `.eh_frame_hdr` section. +/// See +/// and . +#[repr(C)] +struct EhFrameHeader { + version: u8, + eh_frame_ptr_enc: EhHeaderEncoded, + fde_count_enc: EhHeaderEncoded, + table_enc: EhHeaderEncoded, + encoded_fields: (), +} + +impl EhFrameHeader { + unsafe fn encoded_fields(&self) -> *const u8 { + addr_of!((*self).encoded_fields).cast::() + } + + unsafe fn eh_frame(&self, pc: *const ffi::c_void) -> Option<*const u8> { + let ValueFormat::DW_EH_PE_sdata4 = self.eh_frame_ptr_enc.format() else { + return None; + }; + let ValueApplication::DW_EH_PE_pcrel = self.eh_frame_ptr_enc.application() else { + return None; + }; + + let eh_frame_ptr = unsafe { self.encoded_fields().cast::().read_unaligned() }; + + Some(pc.cast::().offset(eh_frame_ptr as isize)) + } + + fn fde_count(&self) -> Option { + let ValueFormat::DW_EH_PE_udata4 = self.fde_count_enc.format() else { + return None; + }; + let ValueApplication::DW_EH_PE_absptr = self.fde_count_enc.application() else { + return None; + }; + let fde_count = unsafe { self.encoded_fields().add(4).cast::().read() }; + Some(fde_count as _) + } +} + +impl fmt::Debug for EhFrameHeader { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("EhFrameHeader") + .field("version", &self.version) + .field("eh_frame_ptr_enc", &self.eh_frame_ptr_enc) + .field("fde_count_enc", &self.fde_count_enc) + .field("table_enc", &self.table_enc) + .field("fde_count", &self.fde_count()) + .finish() + } +} + +struct EhHeaderEncoded(u8); +impl EhHeaderEncoded { + fn format(&self) -> ValueFormat { + match self.0 & 0b1111 { + 0x01 => ValueFormat::DW_EH_PE_uleb128, + 0x02 => ValueFormat::DW_EH_PE_udata2, + 0x03 => ValueFormat::DW_EH_PE_udata4, + 0x04 => ValueFormat::DW_EH_PE_udata8, + 0x09 => ValueFormat::DW_EH_PE_sleb128, + 0x0A => ValueFormat::DW_EH_PE_sdata2, + 0x0B => ValueFormat::DW_EH_PE_sdata4, + 0x0C => ValueFormat::DW_EH_PE_sdata8, + _ => panic!("Invalid header value format"), + } + } + fn application(&self) -> ValueApplication { + match self.0 >> 4 { + 0x0 => ValueApplication::DW_EH_PE_absptr, + 0x1 => ValueApplication::DW_EH_PE_pcrel, + 0x2 => ValueApplication::DW_EH_PE_textrel, + 0x3 => ValueApplication::DW_EH_PE_datarel, + 0x4 => ValueApplication::DW_EH_PE_funcrel, + 0x5 => ValueApplication::DW_EH_PE_aligned, + v => panic!("invalid header value application: {v}"), + } + } +} + +impl fmt::Debug for EhHeaderEncoded { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?} | {:?}", self.application(), self.format()) + } } pub fn dwarf_info(addr: *const ffi::c_void) -> Option { unsafe { let mut out = core::mem::zeroed(); let ret = _dl_find_object(addr, &mut out); - trace!("dl_find_object returned {ret}"); + trace!("_dl_find_object returned {ret}"); if ret != 0 { with_last_os_error_str(|err| trace!("dl_find_object error: {err}")); return None; } if out.dlfo_eh_frame.is_null() { + trace!("dlfo_eh_frame is null"); return None; } let text_len = out.dlfo_map_end as usize - out.dlfo_map_start as usize; trace!( - "dwarf info; map: ({:p}, {:x}), dwarf: {:p}", + "dwarf info; map: ({:p}, {:x}), dlfo_map_end: {:p}", out.dlfo_map_start, text_len, out.dlfo_eh_frame @@ -59,8 +149,59 @@ pub fn dwarf_info(addr: *const ffi::c_void) -> Option { return None; } - Some(DwarfInfo { - eh_frame: out.dlfo_eh_frame as _, - }) + let header = &*out.dlfo_eh_frame.cast::(); + if header.version != 1 { + trace!("eh_frame_hdr version is not 1"); + return None; + } + + trace!("eh_frame_hdr: {:#?}", header); + + let Some(ptr) = header.eh_frame(addr) else { + trace!("could not find .eh_frame"); + return None; + }; + trace!("eh_frame pointer: {ptr:?}"); + + trace!("eh_frame start: {:?}", core::slice::from_raw_parts(ptr, 10)); + + crate::stdext::abort(); } } + +#[derive(Debug, Clone, Copy)] +#[repr(u8)] +enum ValueFormat { + /// Unsigned value is encoded using the Little Endian Base 128 (LEB128) as defined by DWARF Debugging Information Format, Revision 2.0.0 (July 27, 1993). + DW_EH_PE_uleb128 = 0x01, + /// A 2 bytes unsigned value. + DW_EH_PE_udata2 = 0x02, + /// A 4 bytes unsigned value. + DW_EH_PE_udata4 = 0x03, + /// An 8 bytes unsigned value. + DW_EH_PE_udata8 = 0x04, + /// Signed value is encoded using the Little Endian Base 128 (LEB128) as defined by DWARF Debugging Information Format, Revision 2.0.0 (July 27, 1993). + DW_EH_PE_sleb128 = 0x09, + /// A 2 bytes signed value. + DW_EH_PE_sdata2 = 0x0A, + /// A 4 bytes signed value. + DW_EH_PE_sdata4 = 0x0B, + /// An 8 bytes signed value. + DW_EH_PE_sdata8 = 0x0C, +} + +#[derive(Debug)] +#[repr(u8)] +enum ValueApplication { + DW_EH_PE_absptr = 0x00, + /// Value is relative to the current program counter. + DW_EH_PE_pcrel = 0x10, + /// Value is relative to the beginning of the .text section. + DW_EH_PE_textrel = 0x20, + /// Value is relative to the beginning of the .got or .eh_frame_hdr section. + DW_EH_PE_datarel = 0x30, + /// Value is relative to the beginning of the function. + DW_EH_PE_funcrel = 0x40, + /// Value is aligned to an address unit sized boundary. + DW_EH_PE_aligned = 0x50, +} diff --git a/src/lib.rs b/src/lib.rs index ce2bb12..992b608 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,8 +20,8 @@ pub unsafe extern "C" fn _UnwindRaiseException( exception_object: *mut uw::_Unwind_Exception, ) -> uw::_Unwind_Reason_Code { trace!("someone raised an exception with addr {exception_object:p}"); - let di = crate::dwarf::dwarf_info(arch::get_rip() as _).unwrap(); - crate::dwarf::uwutables(di.eh_frame); + let _di = crate::dwarf::dwarf_info(arch::get_rip() as _).unwrap(); + crate::dwarf::uwutables(core::ptr::null()); stdext::abort(); } diff --git a/src/stdext.rs b/src/stdext.rs index 72977dd..0a8a090 100644 --- a/src/stdext.rs +++ b/src/stdext.rs @@ -22,15 +22,14 @@ pub fn print(args: fmt::Arguments<'_>) -> fmt::Result { write!(LibCStdoutWriter, "{}", args) } -macro_rules! print { - ($($tt:tt)*) => {{ - $crate::stdext::print(format_args!($($tt)*)).unwrap(); - }}; -} - macro_rules! trace { ($($tt:tt)*) => { - print!("UWUWIND TRACE | uwuwind/{}:{}: {}\n", file!(), line!(), format_args!($($tt)*)) + // We separate out the format_args for rust-analyzer support. + match format_args!($($tt)*) { + args => { + $crate::stdext::print(::core::format_args!("UWUWIND TRACE | uwuwind/{}:{}: {}\n", file!(), line!(), args)).expect("failed to trace") + } + } }; } @@ -49,11 +48,6 @@ fn errno() -> i32 { pub(crate) fn with_last_os_error_str(f: impl FnOnce(&str) -> R) -> R { let mut buf: [u8; 512] = [0; 512]; - extern "C" { - // the libc crate only has the definition for the POSIX version, but a GNU system has the GNU version. - fn strerror_r(errnum: i32, buf: *mut ffi::c_char, buflen: usize) -> i32; - } - // SAFETY: Our buffer length is passed correctly let error = unsafe { libc::strerror_r(errno(), buf.as_mut_ptr().cast(), buf.len()) }; // SAFETY: strerror_r writes the string to buf, even if it didnt write anything, we did zero init it. diff --git a/test.c b/test.c index 93cb891..03fd6bc 100644 --- a/test.c +++ b/test.c @@ -1,8 +1,16 @@ -#include +#include #define __USE_GNU -#include -#include +#include +#include -int main() { - printf("%d", PT_GNU_EH_FRAME); +void *get_eh_frame(void *addr) +{ + struct dl_find_object out; + int ret = _dl_find_object(addr, &out); + if (ret != 0) + { + return NULL; + } + + return out.dlfo_eh_frame; } \ No newline at end of file