94 lines
2.1 KiB
Rust
Raw Normal View History

2024-11-30 21:10:16 +02:00
use core::{
mem::MaybeUninit,
ops::{Index, IndexMut},
};
use gimli::{LittleEndian, X86_64};
pub type HostEndian = LittleEndian;
pub fn host_endian() -> HostEndian {
LittleEndian
}
#[derive(Default)]
pub struct RegisterSet {
pub rip: Option<u64>,
pub rsp: Option<u64>,
pub rbp: Option<u64>,
pub ret: Option<u64>,
}
#[derive(Debug)]
#[repr(C)]
struct UnwindEntryInfo {
rip: usize,
rbp: usize,
rsp: usize,
}
impl RegisterSet {
pub fn current() -> Self {
let mut cx = MaybeUninit::uninit();
let cx = unsafe { get_context(&mut cx) };
Self {
rip: Some(cx.rip as _),
rsp: Some(cx.rsp as _),
rbp: Some(cx.rbp as _),
ret: None,
}
}
pub fn iter() -> impl Iterator<Item = gimli::Register> {
[X86_64::RA, X86_64::RBP, X86_64::RSP].into_iter()
}
}
impl Index<gimli::Register> for RegisterSet {
type Output = Option<u64>;
fn index(&self, index: gimli::Register) -> &Self::Output {
match index {
X86_64::RA => &self.ret,
X86_64::RSP => &self.rsp,
X86_64::RBP => &self.rbp,
_ => panic!("Unhandled register"),
}
}
}
impl IndexMut<gimli::Register> for RegisterSet {
fn index_mut(&mut self, index: gimli::Register) -> &mut Self::Output {
match index {
X86_64::RA => &mut self.ret,
X86_64::RSP => &mut self.rsp,
X86_64::RBP => &mut self.rbp,
_ => panic!("Unhandled register"),
}
}
}
#[naked]
unsafe extern "C" fn get_context(unw: &mut MaybeUninit<UnwindEntryInfo>) -> &UnwindEntryInfo {
// %rsp: return address (%rip)
// %rdi: *mut UnwindInfo unw
// %rax clobbered
core::arch::naked_asm!(
r#"
// unw.rip = [%rsp]
mov (%rsp), %rax
mov %rax, 0(%rdi)
// unw.rsp = %rsp + 8
mov %rsp, %rax
add $8, %rax
mov %rax, 16(%rdi)
// unw.rbp = %rbp
mov %rbp, 8(%rdi)
mov %rdi, %rax
ret
"#,
options(att_syntax)
)
}