x86 unwinding support
This commit is contained in:
parent
8e6e2d9954
commit
60a08d03b1
@ -3,6 +3,11 @@ mod x86_64;
|
|||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub use x86_64::*;
|
pub use x86_64::*;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86")]
|
||||||
|
mod x86;
|
||||||
|
#[cfg(target_arch = "x86")]
|
||||||
|
pub use x86::*;
|
||||||
|
|
||||||
#[cfg(target_arch = "riscv64")]
|
#[cfg(target_arch = "riscv64")]
|
||||||
mod riscv64;
|
mod riscv64;
|
||||||
#[cfg(target_arch = "riscv64")]
|
#[cfg(target_arch = "riscv64")]
|
||||||
@ -15,6 +20,7 @@ pub use aarch64::*;
|
|||||||
|
|
||||||
#[cfg(not(any(
|
#[cfg(not(any(
|
||||||
target_arch = "x86_64",
|
target_arch = "x86_64",
|
||||||
|
target_arch = "x86",
|
||||||
target_arch = "riscv64",
|
target_arch = "riscv64",
|
||||||
target_arch = "aarch64"
|
target_arch = "aarch64"
|
||||||
)))]
|
)))]
|
||||||
|
120
src/unwinder/arch/x86.rs
Normal file
120
src/unwinder/arch/x86.rs
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
use core::fmt;
|
||||||
|
use core::ops;
|
||||||
|
use gimli::{Register, X86};
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub struct Context {
|
||||||
|
pub registers: [usize; 8],
|
||||||
|
pub ra: usize,
|
||||||
|
pub mcxsr: usize,
|
||||||
|
pub fcw: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Context {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let mut fmt = fmt.debug_struct("Context");
|
||||||
|
for i in 0..=7 {
|
||||||
|
fmt.field(
|
||||||
|
X86::register_name(Register(i as _)).unwrap(),
|
||||||
|
&self.registers[i],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
fmt.field("ra", &self.ra)
|
||||||
|
.field("mcxsr", &self.mcxsr)
|
||||||
|
.field("fcw", &self.fcw)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Index<Register> for Context {
|
||||||
|
type Output = usize;
|
||||||
|
|
||||||
|
fn index(&self, reg: Register) -> &usize {
|
||||||
|
match reg {
|
||||||
|
Register(0..=7) => &self.registers[reg.0 as usize],
|
||||||
|
X86::RA => &self.ra,
|
||||||
|
X86::MXCSR => &self.mcxsr,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::IndexMut<gimli::Register> for Context {
|
||||||
|
fn index_mut(&mut self, reg: Register) -> &mut usize {
|
||||||
|
match reg {
|
||||||
|
Register(0..=7) => &mut self.registers[reg.0 as usize],
|
||||||
|
X86::RA => &mut self.ra,
|
||||||
|
X86::MXCSR => &mut self.mcxsr,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[naked]
|
||||||
|
pub extern "C-unwind" fn save_context() -> Context {
|
||||||
|
// No need to save caller-saved registers here.
|
||||||
|
unsafe {
|
||||||
|
asm!(
|
||||||
|
"
|
||||||
|
mov eax, [esp + 4]
|
||||||
|
mov [eax + 4], ecx
|
||||||
|
mov [eax + 8], edx
|
||||||
|
mov [eax + 12], ebx
|
||||||
|
mov [eax + 20], ebp
|
||||||
|
mov [eax + 24], esi
|
||||||
|
mov [eax + 28], edi
|
||||||
|
|
||||||
|
/* Adjust the stack to account for the return address */
|
||||||
|
lea edx, [esp + 4]
|
||||||
|
mov [eax + 16], edx
|
||||||
|
|
||||||
|
mov edx, [esp]
|
||||||
|
mov [eax + 32], edx
|
||||||
|
stmxcsr [eax + 36]
|
||||||
|
fnstcw [eax + 40]
|
||||||
|
ret 4
|
||||||
|
",
|
||||||
|
options(noreturn)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[naked]
|
||||||
|
pub unsafe extern "C" fn restore_context(ctx: &Context) -> ! {
|
||||||
|
unsafe {
|
||||||
|
asm!(
|
||||||
|
"
|
||||||
|
mov edx, [esp + 4]
|
||||||
|
|
||||||
|
/* Restore stack */
|
||||||
|
mov esp, [edx + 16]
|
||||||
|
|
||||||
|
/* Restore callee-saved control registers */
|
||||||
|
ldmxcsr [edx + 36]
|
||||||
|
fldcw [edx + 40]
|
||||||
|
|
||||||
|
/* Restore return address */
|
||||||
|
mov eax, [edx + 32]
|
||||||
|
push eax
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restore general-purpose registers. Non-callee-saved registers are
|
||||||
|
* also restored because sometimes it's used to pass unwind arguments.
|
||||||
|
*/
|
||||||
|
mov eax, [edx + 0]
|
||||||
|
mov ecx, [edx + 4]
|
||||||
|
mov ebx, [edx + 12]
|
||||||
|
mov ebp, [edx + 20]
|
||||||
|
mov esi, [edx + 24]
|
||||||
|
mov edi, [edx + 28]
|
||||||
|
|
||||||
|
/* EDX restored last */
|
||||||
|
mov edx, [edx + 8]
|
||||||
|
|
||||||
|
ret
|
||||||
|
",
|
||||||
|
options(noreturn)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user