diff --git a/.cargo/config.toml b/.cargo/config.toml deleted file mode 100644 index e83e3e7..0000000 --- a/.cargo/config.toml +++ /dev/null @@ -1,5 +0,0 @@ -[target.x86_64-unknown-linux-gnu] -rustflags = [ - "-Cforce-frame-pointers=yes", # for the uwuwind fp stack walker - "-Clink-arg=-Wl,-E" # for dladdr -] diff --git a/uwuwind/.gitignore b/uwuwind/.gitignore deleted file mode 100644 index c41cc9e..0000000 --- a/uwuwind/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target \ No newline at end of file diff --git a/uwuwind/Cargo.lock b/uwuwind/Cargo.lock deleted file mode 100644 index 3723bc5..0000000 --- a/uwuwind/Cargo.lock +++ /dev/null @@ -1,72 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "fallible-iterator" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" - -[[package]] -name = "gimli" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" -dependencies = [ - "fallible-iterator", - "indexmap", - "stable_deref_trait", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "indexmap" -version = "1.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "libc" -version = "0.2.140" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" - -[[package]] -name = "memmap2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" -dependencies = [ - "libc", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "uwuwind" -version = "0.1.0" -dependencies = [ - "gimli", - "libc", - "memmap2", -] diff --git a/uwuwind/Cargo.toml b/uwuwind/Cargo.toml deleted file mode 100644 index c053f7c..0000000 --- a/uwuwind/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[workspace] - -[package] -name = "uwuwind" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -gimli = "0.27.2" -libc = { version = "0.2.140", default-features = false, features = ["extra_traits"] } -memmap2 = "0.5.10" - -[profile.dev] -panic = "abort" - -[profile.release] -panic = "abort" diff --git a/uwuwind/a.cpp b/uwuwind/a.cpp deleted file mode 100644 index 1d1b89d..0000000 --- a/uwuwind/a.cpp +++ /dev/null @@ -1,61 +0,0 @@ - -bool findUnwindSections(int_t targetAddr, UnwindInfoSections &info) -{ - // Use DLFO_STRUCT_HAS_EH_DBASE to determine the existence of - // `_dl_find_object`. Use _LIBUNWIND_SUPPORT_DWARF_INDEX, because libunwind - // support for _dl_find_object on other unwind formats is not implemented, - // yet. -#if defined(DLFO_STRUCT_HAS_EH_DBASE) & defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) - // We expect `_dl_find_object` to return PT_GNU_EH_FRAME. -#if DLFO_EH_SEGMENT_TYPE != PT_GNU_EH_FRAME -#error _dl_find_object retrieves an unexpected section type -#endif - // We look-up `dl_find_object` dynamically at runtime to ensure backwards - // compatibility with earlier version of glibc not yet providing it. On older - // systems, we gracefully fallback to `dl_iterate_phdr`. Cache the pointer - // so we only look it up once. Do manual lock to avoid _cxa_guard_acquire. - static decltype(_dl_find_object) *dlFindObject; - static bool dlFindObjectChecked = false; - if (!dlFindObjectChecked) - { - dlFindObject = reinterpret_cast( - dlsym(RTLD_DEFAULT, "_dl_find_object")); - dlFindObjectChecked = true; - } - // Try to find the unwind info using `dl_find_object` - dl_find_object findResult; - if (dlFindObject && dlFindObject((void *)targetAddr, &findResult) == 0) - { - if (findResult.dlfo_eh_frame == nullptr) - { - // Found an entry for `targetAddr`, but there is no unwind info. - return false; - } - info.dso_base = reinterpret_cast(findResult.dlfo_map_start); - info.text_segment_length = static_cast( - (char *)findResult.dlfo_map_end - (char *)findResult.dlfo_map_start); - - // Record the start of PT_GNU_EH_FRAME. - info.dwarf_index_section = - reinterpret_cast(findResult.dlfo_eh_frame); - // `_dl_find_object` does not give us the size of PT_GNU_EH_FRAME. - // Setting length to `SIZE_MAX` effectively disables all range checks. - info.dwarf_index_section_length = SIZE_MAX; - EHHeaderParser::EHHeaderInfo hdrInfo; - if (!EHHeaderParser::decodeEHHdr( - *this, info.dwarf_index_section, info.dwarf_index_section_length, - hdrInfo)) - { - return false; - } - // Record the start of the FDE and use SIZE_MAX to indicate that we do - // not know the end address. - info.dwarf_section = hdrInfo.eh_frame_ptr; - info.dwarf_section_length = SIZE_MAX; - return true; - } -#endif - dl_iterate_cb_data cb_data = {this, &info, targetAddr}; - int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data); - return static_cast(found); -} diff --git a/uwuwind/src/arch.rs b/uwuwind/src/arch.rs deleted file mode 100644 index 886befb..0000000 --- a/uwuwind/src/arch.rs +++ /dev/null @@ -1,26 +0,0 @@ -use core::ffi; -use std::arch::asm; - -pub fn get_rbp() -> *const usize { - let mut out; - unsafe { - asm!( - "mov {out}, rbp", - out = out(reg) out, - options(nostack, readonly) - ); - } - out -} - -pub fn get_rip() -> *const ffi::c_void { - let mut out; - unsafe { - asm!( - "lea {out}, [rip]", - out = out(reg) out, - options(nostack, readonly), - ); - } - out -} diff --git a/uwuwind/src/dwarf.rs b/uwuwind/src/dwarf.rs deleted file mode 100644 index ab2a181..0000000 --- a/uwuwind/src/dwarf.rs +++ /dev/null @@ -1,57 +0,0 @@ -use core::ffi; -use std::{ffi::CStr, fmt::Debug}; - -use gimli::UnwindTable; - -#[allow(non_camel_case_types)] -#[repr(C)] -struct dl_find_object { - dlfo_flags: ffi::c_ulonglong, - dlfo_map_start: *const ffi::c_void, - dlfo_map_end: *const ffi::c_void, - dlf_link_map: *const ffi::c_void, - dlfo_eh_frame: *const ffi::c_void, -} - -extern "C" { - fn _dl_find_object(address: *const ffi::c_void, result: *mut dl_find_object) -> ffi::c_int; -} - -#[derive(Debug)] -pub struct DwarfInfo { - /// The text segment - map: *const [u8], - /// PT_GNU_EH_FRAME - dwarf: *const u8, -} - -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}"); - if ret != 0 { - return None; - } - if out.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}", - out.dlfo_map_start, - text_len, - out.dlfo_eh_frame - ); - Some(DwarfInfo { - map: core::ptr::slice_from_raw_parts(out.dlfo_map_start as _, text_len), - dwarf: out.dlfo_eh_frame as _, - }) - } -} - -pub fn uwutables() { - let UnwindTabley -} \ No newline at end of file diff --git a/uwuwind/src/identify.rs b/uwuwind/src/identify.rs deleted file mode 100644 index 17936ad..0000000 --- a/uwuwind/src/identify.rs +++ /dev/null @@ -1,36 +0,0 @@ -use std::ffi::CStr; - -pub fn identify(addr: usize) -> Option<&'static CStr> { - unsafe { - let mut info: libc::Dl_info = std::mem::zeroed(); - - libc::dladdr(addr as _, &mut info); - - if !info.dli_sname.is_null() { - let sym_name = CStr::from_ptr(info.dli_sname); - return Some(sym_name); - } - - /* - let parse = |str| usize::from_str_radix(str, 16).ok(); - let maps = std::fs::read_to_string("/proc/self/maps").unwrap(); - maps.lines() - .filter_map(|line| { - let mut ws = line.split_ascii_whitespace(); - - let addr_range = ws.next()?; - let mut addr_range = addr_range.split("-"); - let addr_range = (parse(addr_range.next()?)?)..(parse(addr_range.next()?)?); - - if addr_range.contains(&addr) { - ws.nth(4).map(ToOwned::to_owned) - } else { - None - } - }) - .next() - */ - - None - } -} diff --git a/uwuwind/src/lib.rs b/uwuwind/src/lib.rs deleted file mode 100644 index 9fcd1ab..0000000 --- a/uwuwind/src/lib.rs +++ /dev/null @@ -1,38 +0,0 @@ -#![allow(dead_code)] - -use std::sync::atomic::AtomicPtr; - -macro_rules! trace { - ($($tt:tt)*) => { - eprintln!("UWUWIND TRACE | uwuwind/{}:{}: {}", file!(), line!(), format_args!($($tt)*)); - }; -} - -pub mod uw; - -mod arch; -mod dwarf; -mod identify; -mod walk; - -#[allow(nonstandard_style)] -pub unsafe extern "C" fn _UnwindRaiseException( - exception_object: *mut uw::_Unwind_Exception, -) -> uw::_Unwind_Reason_Code { - println!("someone raised an exception with addr {exception_object:p}"); - - crate::dwarf::dwarf_info(arch::get_rip() as _); - - // walk::fp::walk(); - - std::process::abort(); -} - -// This is normally provided by the language runtime through the unwind info block. -// We don't want to access that usually because Rust messes with it :(. -static PERSONALITY_ROUTINE: AtomicPtr<()> = AtomicPtr::new(core::ptr::null_mut()); - -pub unsafe fn set_personality_routine(routine: uw::PersonalityRoutine) { - let ptr: *mut () = std::mem::transmute(routine); - PERSONALITY_ROUTINE.store(ptr, std::sync::atomic::Ordering::Relaxed); -} diff --git a/uwuwind/src/main.rs b/uwuwind/src/main.rs deleted file mode 100644 index dcdde56..0000000 --- a/uwuwind/src/main.rs +++ /dev/null @@ -1,35 +0,0 @@ -use uwuwind::uw; - -#[repr(C)] -struct Exception { - _uwe: uw::_Unwind_Exception, - uwu: &'static str, -} - -fn main() { - unsafe { - uwuwind::set_personality_routine(personality_routine); - - let exception = Box::into_raw(Box::new(Exception { - _uwe: uw::_Unwind_Exception { - exception_class: 123456, - exception_cleanup0: |_, _| {}, - private_1: 0, - private_2: 0, - }, - uwu: "meow :3", - })); - - uwuwind::_UnwindRaiseException(exception.cast::()); - } -} - -fn personality_routine( - _version: i32, - _actions: uw::_UnwindAction, - _exception_class: u64, - _exception_object: *mut uw::_Unwind_Exception, - _context: *mut uw::_Unwind_Context, -) -> uw::_Unwind_Reason_Code { - uw::_Unwind_Reason_Code::_URC_NO_REASON -} diff --git a/uwuwind/src/uw.rs b/uwuwind/src/uw.rs deleted file mode 100644 index b697e03..0000000 --- a/uwuwind/src/uw.rs +++ /dev/null @@ -1,52 +0,0 @@ -#![allow(nonstandard_style)] // Closely follow the spec here - -#[repr(C)] -pub enum _Unwind_Reason_Code { - _URC_NO_REASON = 0, - /// This indicates that a different runtime caught this exception. - /// Nested foreign exceptions, or re-throwing a foreign exception, result in - /// undefined behavior. - _URC_FOREIGN_EXCEPTION_CAUGHT = 1, - /// The personality routine encountered an error during phase 1, other than the specific error codes defined. - _URC_FATAL_PHASE1_ERROR = 3, - /// The personality routine encountered an error during phase 2, for instance a stack corruption. - _URC_FATAL_PHASE2_ERROR = 2, - _URC_NORMAL_STOP = 4, - /// The unwinder encountered the end of the stack during phase 1, without finding a handler. - /// The unwind runtime will not have modified the stack. - /// The C++ runtime will normally call uncaught_exception() in this case - _URC_END_OF_STACK = 5, - _URC_HANDLER_FOUND = 6, - _URC_INSTALL_CONTEXT = 7, - _URC_CONTINUE_UNWIND = 8, -} - -#[repr(C, align(8))] -pub struct _Unwind_Exception { - pub exception_class: u64, - pub exception_cleanup0: _Unwind_Exception_Cleanup_Fn, - pub private_1: u64, - pub private_2: u64, -} - -pub type _Unwind_Exception_Cleanup_Fn = - fn(reason: _Unwind_Reason_Code, exc: *const _Unwind_Exception); - -/// The _Unwind_Context type is an opaque type used to refer to a system-specific data structure used by the system unwinder. -/// This context is created and destroyed by the system, and passed to the personality routine during unwinding -pub struct _Unwind_Context {} - -pub type PersonalityRoutine = fn( - version: i32, - actions: _UnwindAction, - exceptionClass: u64, - exception_object: *mut _Unwind_Exception, - context: *mut _Unwind_Context, -) -> _Unwind_Reason_Code; - -pub type _UnwindAction = i32; - -const _UA_SEARCH_PHASE: _UnwindAction = 1; -const _UA_CLEANUP_PHASE: _UnwindAction = 2; -const _UA_HANDLER_FRAME: _UnwindAction = 4; -const _UA_FORCE_UNWIND: _UnwindAction = 8; diff --git a/uwuwind/src/walk/fp.rs b/uwuwind/src/walk/fp.rs deleted file mode 100644 index 9952431..0000000 --- a/uwuwind/src/walk/fp.rs +++ /dev/null @@ -1,22 +0,0 @@ -//! Test frame pointer walker. Not very good. - -use crate::arch::get_rbp; - -pub(crate) unsafe fn walk() { - let mut current_rbp = get_rbp(); - loop { - println!("walk... rbp={current_rbp:p}"); - - let return_addr = current_rbp.add(1).read() as *const usize; - println!("walk... return_addr={return_addr:p}"); - - println!( - "walk... frame={:?}", - crate::identify::identify(return_addr as usize) - ); - - println!("no read yet"); - - current_rbp = current_rbp.read() as *const usize; - } -} diff --git a/uwuwind/src/walk/mod.rs b/uwuwind/src/walk/mod.rs deleted file mode 100644 index 3cdd361..0000000 --- a/uwuwind/src/walk/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod fp; \ No newline at end of file diff --git a/uwuwind/test b/uwuwind/test deleted file mode 100755 index a478771..0000000 Binary files a/uwuwind/test and /dev/null differ diff --git a/uwuwind/test.c b/uwuwind/test.c deleted file mode 100644 index 93cb891..0000000 --- a/uwuwind/test.c +++ /dev/null @@ -1,8 +0,0 @@ -#include -#define __USE_GNU -#include -#include - -int main() { - printf("%d", PT_GNU_EH_FRAME); -} \ No newline at end of file diff --git a/uwuwind/test.rs b/uwuwind/test.rs deleted file mode 100644 index 5d26406..0000000 --- a/uwuwind/test.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - panic!(); -} \ No newline at end of file