RISC-V unwinder support
This commit is contained in:
parent
f34aa1824f
commit
57b6852c97
@ -2,3 +2,8 @@
|
||||
mod x86_64;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub use x86_64::*;
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
mod riscv64;
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use riscv64::*;
|
||||
|
195
src/unwinder/arch/riscv64.rs
Normal file
195
src/unwinder/arch/riscv64.rs
Normal file
@ -0,0 +1,195 @@
|
||||
use core::fmt;
|
||||
use core::ops;
|
||||
use gimli::{Register, RiscV};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Context {
|
||||
pub gp: [usize; 32],
|
||||
pub fp: [usize; 32],
|
||||
}
|
||||
|
||||
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..=31 {
|
||||
fmt.field(RiscV::register_name(Register(i as _)).unwrap(), &self.gp[i]);
|
||||
}
|
||||
for i in 0..=31 {
|
||||
fmt.field(
|
||||
RiscV::register_name(Register((i + 32) as _)).unwrap(),
|
||||
&self.fp[i],
|
||||
);
|
||||
}
|
||||
fmt.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Index<Register> for Context {
|
||||
type Output = usize;
|
||||
|
||||
fn index(&self, reg: Register) -> &usize {
|
||||
match reg {
|
||||
Register(0..=31) => &self.gp[reg.0 as usize],
|
||||
Register(32..=63) => &self.fp[(reg.0 - 32) as usize],
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::IndexMut<gimli::Register> for Context {
|
||||
fn index_mut(&mut self, reg: Register) -> &mut usize {
|
||||
match reg {
|
||||
Register(0..=31) => &mut self.gp[reg.0 as usize],
|
||||
Register(32..=63) => &mut self.fp[(reg.0 - 32) as usize],
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! code {
|
||||
(save_gp) => {
|
||||
"
|
||||
sd x0, 0x00(a0)
|
||||
sd ra, 0x08(a0)
|
||||
sd sp, 0x10(a0)
|
||||
sd gp, 0x18(a0)
|
||||
sd tp, 0x20(a0)
|
||||
sd s0, 0x40(a0)
|
||||
sd s1, 0x48(a0)
|
||||
sd s2, 0x90(a0)
|
||||
sd s3, 0x98(a0)
|
||||
sd s4, 0xA0(a0)
|
||||
sd s5, 0xA8(a0)
|
||||
sd s6, 0xB0(a0)
|
||||
sd s7, 0xB8(a0)
|
||||
sd s8, 0xC0(a0)
|
||||
sd s9, 0xC8(a0)
|
||||
sd s10, 0xD0(a0)
|
||||
sd s11, 0xD8(a0)
|
||||
"
|
||||
};
|
||||
(save_fp) => {
|
||||
"
|
||||
fsd fs0, 0x140(a0)
|
||||
fsd fs1, 0x148(a0)
|
||||
fsd fs2, 0x190(a0)
|
||||
fsd fs3, 0x198(a0)
|
||||
fsd fs4, 0x1A0(a0)
|
||||
fsd fs5, 0x1A8(a0)
|
||||
fsd fs6, 0x1B0(a0)
|
||||
fsd fs7, 0x1B8(a0)
|
||||
fsd fs8, 0x1C0(a0)
|
||||
fsd fs9, 0x1C8(a0)
|
||||
fsd fs10, 0x1D0(a0)
|
||||
fsd fs11, 0x1D8(a0)
|
||||
"
|
||||
};
|
||||
(restore_gp) => {
|
||||
"
|
||||
ld ra, 0x08(a0)
|
||||
ld sp, 0x10(a0)
|
||||
ld gp, 0x18(a0)
|
||||
ld tp, 0x20(a0)
|
||||
ld t0, 0x28(a0)
|
||||
ld t1, 0x30(a0)
|
||||
ld t2, 0x38(a0)
|
||||
ld s0, 0x40(a0)
|
||||
ld s1, 0x48(a0)
|
||||
ld a1, 0x58(a0)
|
||||
ld a2, 0x60(a0)
|
||||
ld a3, 0x68(a0)
|
||||
ld a4, 0x70(a0)
|
||||
ld a5, 0x78(a0)
|
||||
ld a6, 0x80(a0)
|
||||
ld a7, 0x88(a0)
|
||||
ld s2, 0x90(a0)
|
||||
ld s3, 0x98(a0)
|
||||
ld s4, 0xA0(a0)
|
||||
ld s5, 0xA8(a0)
|
||||
ld s6, 0xB0(a0)
|
||||
ld s7, 0xB8(a0)
|
||||
ld s8, 0xC0(a0)
|
||||
ld s9, 0xC8(a0)
|
||||
ld s10, 0xD0(a0)
|
||||
ld s11, 0xD8(a0)
|
||||
ld t3, 0xE0(a0)
|
||||
ld t4, 0xE8(a0)
|
||||
ld t5, 0xF0(a0)
|
||||
ld t6, 0xF8(a0)
|
||||
"
|
||||
};
|
||||
(restore_fp) => {
|
||||
"
|
||||
fld ft0, 0x100(a0)
|
||||
fld ft1, 0x108(a0)
|
||||
fld ft2, 0x110(a0)
|
||||
fld ft3, 0x118(a0)
|
||||
fld ft4, 0x120(a0)
|
||||
fld ft5, 0x128(a0)
|
||||
fld ft6, 0x130(a0)
|
||||
fld ft7, 0x138(a0)
|
||||
fld fs0, 0x140(a0)
|
||||
fld fs1, 0x148(a0)
|
||||
fld fa0, 0x150(a0)
|
||||
fld fa1, 0x158(a0)
|
||||
fld fa2, 0x160(a0)
|
||||
fld fa3, 0x168(a0)
|
||||
fld fa4, 0x170(a0)
|
||||
fld fa5, 0x178(a0)
|
||||
fld fa6, 0x180(a0)
|
||||
fld fa7, 0x188(a0)
|
||||
fld fs2, 0x190(a0)
|
||||
fld fs3, 0x198(a0)
|
||||
fld fs4, 0x1A0(a0)
|
||||
fld fs5, 0x1A8(a0)
|
||||
fld fs6, 0x1B0(a0)
|
||||
fld fs7, 0x1B8(a0)
|
||||
fld fs8, 0x1C0(a0)
|
||||
fld fs9, 0x1C8(a0)
|
||||
fld fs10, 0x1D0(a0)
|
||||
fld fs11, 0x1D8(a0)
|
||||
fld ft8, 0x1E0(a0)
|
||||
fld ft9, 0x1E8(a0)
|
||||
fld ft10, 0x1F0(a0)
|
||||
fld ft11, 0x1F8(a0)
|
||||
"
|
||||
};
|
||||
}
|
||||
|
||||
#[naked]
|
||||
pub extern "C-unwind" fn save_context() -> Context {
|
||||
// No need to save caller-saved registers here.
|
||||
#[cfg(target_feature = "d")]
|
||||
unsafe {
|
||||
asm!(
|
||||
concat!(code!(save_gp), code!(save_fp), "ret"),
|
||||
options(noreturn)
|
||||
);
|
||||
}
|
||||
#[cfg(not(target_feature = "d"))]
|
||||
unsafe {
|
||||
asm!(
|
||||
concat!(code!(save_gp), "ret"),
|
||||
options(noreturn)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[naked]
|
||||
pub unsafe extern "C" fn restore_context(ctx: &Context) -> ! {
|
||||
#[cfg(target_feature = "d")]
|
||||
unsafe {
|
||||
asm!(
|
||||
concat!(code!(restore_fp), code!(restore_gp), "ld a0, 0x50(a0)\nret"),
|
||||
options(noreturn)
|
||||
);
|
||||
}
|
||||
#[cfg(not(target_feature = "d"))]
|
||||
unsafe {
|
||||
asm!(
|
||||
concat!(code!(restore_gp), "ld a0, 0x50(a0)\nret"),
|
||||
options(noreturn)
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user