From 07d305b23561f56ec3b238bd4eb0a40f4dfa538a Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Mon, 21 Oct 2024 14:52:22 +0800 Subject: [PATCH] Only add CFI instructions for panic=unwind build --- src/unwinder/arch/aarch64.rs | 22 ++++++++++++++-------- src/unwinder/arch/mod.rs | 18 ++++++++++++++++++ src/unwinder/arch/riscv32.rs | 26 ++++++++++++++------------ src/unwinder/arch/riscv64.rs | 26 ++++++++++++++------------ src/unwinder/arch/x86.rs | 19 +++++++++++-------- src/unwinder/arch/x86_64.rs | 12 +++++++----- 6 files changed, 78 insertions(+), 45 deletions(-) diff --git a/src/unwinder/arch/aarch64.rs b/src/unwinder/arch/aarch64.rs index 8c64753..c2bfc35 100644 --- a/src/unwinder/arch/aarch64.rs +++ b/src/unwinder/arch/aarch64.rs @@ -2,6 +2,8 @@ use core::fmt; use core::ops; use gimli::{AArch64, Register}; +use super::maybe_cfi; + // Match DWARF_FRAME_REGISTERS in libgcc pub const MAX_REG_RULES: usize = 97; @@ -61,13 +63,15 @@ macro_rules! save { (gp$(, $fp:ident)?) => { // No need to save caller-saved registers here. core::arch::naked_asm!( - " - stp x29, x30, [sp, -16]! + "stp x29, x30, [sp, -16]!", + maybe_cfi!(" .cfi_def_cfa_offset 16 .cfi_offset x29, -16 .cfi_offset x30, -8 - sub sp, sp, 512 - .cfi_def_cfa_offset 528 + "), + "sub sp, sp, 512", + maybe_cfi!(".cfi_def_cfa_offset 528"), + " mov x8, x0 mov x0, sp ", @@ -85,13 +89,15 @@ macro_rules! save { blr x8 add sp, sp, 512 - .cfi_def_cfa_offset 16 - ldp x29, x30, [sp], 16 + ", + maybe_cfi!(".cfi_def_cfa_offset 16"), + "ldp x29, x30, [sp], 16", + maybe_cfi!(" .cfi_def_cfa_offset 0 .cfi_restore x29 .cfi_restore x30 - ret - ", + "), + "ret", ); }; (maybesavefp(fp)) => { diff --git a/src/unwinder/arch/mod.rs b/src/unwinder/arch/mod.rs index 8158353..3cdbfce 100644 --- a/src/unwinder/arch/mod.rs +++ b/src/unwinder/arch/mod.rs @@ -31,3 +31,21 @@ pub use aarch64::*; target_arch = "aarch64" )))] compile_error!("Current architecture is not supported"); + +// CFI directives cannot be used if neither debuginfo nor panic=unwind is enabled. +// We don't have an easy way to check the former, so just check based on panic strategy. +#[cfg(panic = "abort")] +macro_rules! maybe_cfi { + ($x: literal) => { + "" + }; +} + +#[cfg(panic = "unwind")] +macro_rules! maybe_cfi { + ($x: literal) => { + $x + }; +} + +pub(crate) use maybe_cfi; diff --git a/src/unwinder/arch/riscv32.rs b/src/unwinder/arch/riscv32.rs index a5aeff7..b26cb4f 100644 --- a/src/unwinder/arch/riscv32.rs +++ b/src/unwinder/arch/riscv32.rs @@ -2,6 +2,8 @@ use core::fmt; use core::ops; use gimli::{Register, RiscV}; +use super::maybe_cfi; + // Match DWARF_FRAME_REGISTERS in libgcc pub const MAX_REG_RULES: usize = 65; @@ -176,10 +178,10 @@ pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), p " mv t0, sp add sp, sp, -0x190 - .cfi_def_cfa_offset 0x190 - sw ra, 0x180(sp) - .cfi_offset ra, -16 ", + maybe_cfi!(".cfi_def_cfa_offset 0x190"), + "sw ra, 0x180(sp)", + maybe_cfi!(".cfi_offset ra, -16"), code!(save_gp), code!(save_fp), " @@ -188,10 +190,10 @@ pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), p jalr t0 lw ra, 0x180(sp) add sp, sp, 0x190 - .cfi_def_cfa_offset 0 - .cfi_restore ra - ret ", + maybe_cfi!(".cfi_def_cfa_offset 0"), + maybe_cfi!(".cfi_restore ra"), + "ret", ); } #[cfg(not(target_feature = "d"))] @@ -200,10 +202,10 @@ pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), p " mv t0, sp add sp, sp, -0x90 - .cfi_def_cfa_offset 0x90 - sw ra, 0x80(sp) - .cfi_offset ra, -16 ", + maybe_cfi!(".cfi_def_cfa_offset 0x90"), + "sw ra, 0x80(sp)", + maybe_cfi!(".cfi_offset ra, -16"), code!(save_gp), " mv t0, a0 @@ -211,10 +213,10 @@ pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), p jalr t0 lw ra, 0x80(sp) add sp, sp, 0x90 - .cfi_def_cfa_offset 0 - .cfi_restore ra - ret ", + maybe_cfi!(".cfi_def_cfa_offset 0"), + maybe_cfi!(".cfi_restore ra"), + "ret", ); } } diff --git a/src/unwinder/arch/riscv64.rs b/src/unwinder/arch/riscv64.rs index f2f11ea..30d3131 100644 --- a/src/unwinder/arch/riscv64.rs +++ b/src/unwinder/arch/riscv64.rs @@ -2,6 +2,8 @@ use core::fmt; use core::ops; use gimli::{Register, RiscV}; +use super::maybe_cfi; + // Match DWARF_FRAME_REGISTERS in libgcc pub const MAX_REG_RULES: usize = 65; @@ -176,10 +178,10 @@ pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), p " mv t0, sp add sp, sp, -0x210 - .cfi_def_cfa_offset 0x210 - sd ra, 0x200(sp) - .cfi_offset ra, -16 ", + maybe_cfi!(".cfi_def_cfa_offset 0x210"), + "sd ra, 0x200(sp)", + maybe_cfi!(".cfi_offset ra, -16"), code!(save_gp), code!(save_fp), " @@ -188,10 +190,10 @@ pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), p jalr t0 ld ra, 0x200(sp) add sp, sp, 0x210 - .cfi_def_cfa_offset 0 - .cfi_restore ra - ret ", + maybe_cfi!(".cfi_def_cfa_offset 0"), + maybe_cfi!(".cfi_restore ra"), + "ret", ); } #[cfg(not(target_feature = "d"))] @@ -200,10 +202,10 @@ pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), p " mv t0, sp add sp, sp, -0x110 - .cfi_def_cfa_offset 0x110 - sd ra, 0x100(sp) - .cfi_offset ra, -16 ", + maybe_cfi!(".cfi_def_cfa_offset 0x110"), + "sd ra, 0x100(sp)", + maybe_cfi!(".cfi_offset ra, -16"), code!(save_gp), " mv t0, a0 @@ -211,10 +213,10 @@ pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), p jalr t0 ld ra, 0x100(sp) add sp, sp, 0x110 - .cfi_def_cfa_offset 0 - .cfi_restore ra - ret ", + maybe_cfi!(".cfi_def_cfa_offset 0"), + maybe_cfi!(".cfi_restore ra"), + "ret", ); } } diff --git a/src/unwinder/arch/x86.rs b/src/unwinder/arch/x86.rs index 22d3b90..5b471a5 100644 --- a/src/unwinder/arch/x86.rs +++ b/src/unwinder/arch/x86.rs @@ -2,6 +2,8 @@ use core::fmt; use core::ops; use gimli::{Register, X86}; +use super::maybe_cfi; + // Match DWARF_FRAME_REGISTERS in libgcc pub const MAX_REG_RULES: usize = 17; @@ -59,10 +61,9 @@ pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), p // No need to save caller-saved registers here. unsafe { core::arch::naked_asm!( + "sub esp, 52", + maybe_cfi!(".cfi_def_cfa_offset 56"), " - sub esp, 52 - .cfi_def_cfa_offset 56 - mov [esp + 4], ecx mov [esp + 8], edx mov [esp + 12], ebx @@ -85,15 +86,17 @@ pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), p mov eax, [esp + 60] mov ecx, esp push eax - .cfi_adjust_cfa_offset 4 - push ecx - .cfi_adjust_cfa_offset 4 + ", + maybe_cfi!(".cfi_adjust_cfa_offset 4"), + "push ecx", + maybe_cfi!(".cfi_adjust_cfa_offset 4"), + " call [esp + 64] add esp, 60 - .cfi_def_cfa_offset 4 - ret ", + maybe_cfi!(".cfi_def_cfa_offset 4"), + "ret", ); } } diff --git a/src/unwinder/arch/x86_64.rs b/src/unwinder/arch/x86_64.rs index 575e5eb..1e9bc21 100644 --- a/src/unwinder/arch/x86_64.rs +++ b/src/unwinder/arch/x86_64.rs @@ -2,6 +2,8 @@ use core::fmt; use core::ops; use gimli::{Register, X86_64}; +use super::maybe_cfi; + // Match DWARF_FRAME_REGISTERS in libgcc pub const MAX_REG_RULES: usize = 17; @@ -61,9 +63,9 @@ pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), p // No need to save caller-saved registers here. unsafe { core::arch::naked_asm!( + "sub rsp, 0x98", + maybe_cfi!(".cfi_def_cfa_offset 0xA0"), " - sub rsp, 0x98 - .cfi_def_cfa_offset 0xA0 mov [rsp + 0x18], rbx mov [rsp + 0x30], rbp @@ -87,9 +89,9 @@ pub extern "C-unwind" fn save_context(f: extern "C" fn(&mut Context, *mut ()), p mov rdi, rsp call rax add rsp, 0x98 - .cfi_def_cfa_offset 8 - ret - " + ", + maybe_cfi!(".cfi_def_cfa_offset 8"), + "ret" ); } }