Gary Guo 3 роки тому
батько
коміт
789082f176
3 змінених файлів з 152 додано та 0 видалено
  1. 18 0
      src/arch.rs
  2. 129 0
      src/unwinder/arch/aarch64.rs
  3. 5 0
      src/unwinder/arch/mod.rs

+ 18 - 0
src/arch.rs

@@ -33,3 +33,21 @@ mod riscv {
 }
 #[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))]
 pub use riscv::*;
+
+#[cfg(target_arch = "aarch64")]
+mod aarch64 {
+    use gimli::{AArch64, Register};
+
+    pub struct Arch;
+
+    #[allow(unused)]
+    impl Arch {
+        pub const SP: Register = AArch64::SP;
+        pub const RA: Register = AArch64::X30;
+
+        pub const UNWIND_DATA_REG: (Register, Register) = (AArch64::X0, AArch64::X1);
+        pub const UNWIND_PRIVATE_DATA_SIZE: usize = 2;
+    }
+}
+#[cfg(target_arch = "aarch64")]
+pub use aarch64::*;

+ 129 - 0
src/unwinder/arch/aarch64.rs

@@ -0,0 +1,129 @@
+use core::fmt;
+use core::ops;
+use gimli::{AArch64, Register};
+
+#[repr(C)]
+#[derive(Clone, Default)]
+pub struct Context {
+    pub gp: [usize; 31],
+    pub sp: usize,
+    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..=30 {
+            fmt.field(
+                AArch64::register_name(Register(i as _)).unwrap(),
+                &self.gp[i],
+            );
+        }
+        fmt.field("sp", &self.sp);
+        for i in 0..=31 {
+            fmt.field(
+                AArch64::register_name(Register((i + 64) 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..=30) => &self.gp[reg.0 as usize],
+            AArch64::SP => &self.sp,
+            Register(64..=95) => &self.fp[(reg.0 - 64) as usize],
+            _ => unimplemented!(),
+        }
+    }
+}
+
+impl ops::IndexMut<gimli::Register> for Context {
+    fn index_mut(&mut self, reg: Register) -> &mut usize {
+        match reg {
+            Register(0..=30) => &mut self.gp[reg.0 as usize],
+            AArch64::SP => &mut self.sp,
+            Register(64..=95) => &mut self.fp[(reg.0 - 64) as usize],
+            _ => unimplemented!(),
+        }
+    }
+}
+
+#[naked]
+pub extern "C-unwind" fn save_context() -> Context {
+    // No need to save caller-saved registers here.
+    unsafe {
+        asm!(
+            "
+            stp d8, d9, [x8, 0x140]
+            stp d10, d11, [x8, 0x150]
+            stp d12, d13, [x8, 0x160]
+            stp d14, d15, [x8, 0x170]
+
+            str x19, [x8, 0x98]
+            stp x20, x21, [x8, 0xA0]
+            stp x22, x23, [x8, 0xB0]
+            stp x24, x25, [x8, 0xC0]
+            stp x26, x27, [x8, 0xD0]
+            stp x28, x29, [x8, 0xE0]
+            mov x0, sp
+            stp x30, x0, [x8, 0xF0]
+
+            ret
+            ",
+            options(noreturn)
+        );
+    }
+}
+
+#[naked]
+pub unsafe extern "C" fn restore_context(ctx: &Context) -> ! {
+    unsafe {
+        asm!(
+            "
+            ldp d0, d1, [x0, 0x100]
+            ldp d2, d3, [x0, 0x110]
+            ldp d4, d5, [x0, 0x120]
+            ldp d6, d7, [x0, 0x130]
+            ldp d8, d9, [x0, 0x140]
+            ldp d10, d11, [x0, 0x150]
+            ldp d12, d13, [x0, 0x160]
+            ldp d14, d15, [x0, 0x170]
+            ldp d16, d17, [x0, 0x180]
+            ldp d18, d19, [x0, 0x190]
+            ldp d20, d21, [x0, 0x1A0]
+            ldp d22, d23, [x0, 0x1B0]
+            ldp d24, d25, [x0, 0x1C0]
+            ldp d26, d27, [x0, 0x1D0]
+            ldp d28, d29, [x0, 0x1E0]
+            ldp d30, d31, [x0, 0x1F0]
+
+            ldp x2, x3, [x0, 0x10]
+            ldp x4, x5, [x0, 0x20]
+            ldp x6, x7, [x0, 0x30]
+            ldp x8, x9, [x0, 0x40]
+            ldp x10, x11, [x0, 0x50]
+            ldp x12, x13, [x0, 0x60]
+            ldp x14, x15, [x0, 0x70]
+            ldp x16, x17, [x0, 0x80]
+            ldp x18, x19, [x0, 0x90]
+            ldp x20, x21, [x0, 0xA0]
+            ldp x22, x23, [x0, 0xB0]
+            ldp x24, x25, [x0, 0xC0]
+            ldp x26, x27, [x0, 0xD0]
+            ldp x28, x29, [x0, 0xE0]
+            ldp x30, x1, [x0, 0xF0]
+            mov sp, x1
+
+            ldp x0, x1, [x0, 0x00]
+            ret
+            ",
+            options(noreturn)
+        );
+    }
+}

+ 5 - 0
src/unwinder/arch/mod.rs

@@ -7,3 +7,8 @@ pub use x86_64::*;
 mod riscv64;
 #[cfg(target_arch = "riscv64")]
 pub use riscv64::*;
+
+#[cfg(target_arch = "aarch64")]
+mod aarch64;
+#[cfg(target_arch = "aarch64")]
+pub use aarch64::*;