From 90c96ea66dcf11f49d6736316734ecd94ead22eb Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Sun, 24 Feb 2019 14:31:51 +1000 Subject: [PATCH 1/3] Update gimli to 0.17.0 --- unwind/Cargo.toml | 2 +- unwind/src/find_cfi/baremetal.rs | 20 +++++++----- unwind/src/find_cfi/ld.rs | 10 +++--- unwind/src/find_cfi/mod.rs | 4 +-- unwind/src/glue.rs | 53 ++++++++++++++++---------------- unwind/src/lib.rs | 29 +++++++++-------- unwind/src/libunwind_shim.rs | 15 ++++----- unwind/src/registers.rs | 42 +++++++------------------ 8 files changed, 82 insertions(+), 93 deletions(-) diff --git a/unwind/Cargo.toml b/unwind/Cargo.toml index cf54f4e..671e8e0 100644 --- a/unwind/Cargo.toml +++ b/unwind/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" authors = ["main() "] [dependencies] -gimli = "0.16.1" +gimli = "0.17" libc = "0.2" fallible-iterator = "0.1" log = "0.4" diff --git a/unwind/src/find_cfi/baremetal.rs b/unwind/src/find_cfi/baremetal.rs index bf9bbe7..cb1fa7b 100644 --- a/unwind/src/find_cfi/baremetal.rs +++ b/unwind/src/find_cfi/baremetal.rs @@ -14,17 +14,21 @@ pub fn find_cfi_sections() -> Vec { unsafe { // Safety: None of those are actual accesses - we only get the address // of those values. - let text_start = &__text_start as *const _ as u64; - let text_end = &__text_end as *const _ as u64; - let cfi_start = &__ehframehdr_start as *const _ as u64; - let cfi_end = &__ehframehdr_end as *const _ as u64; - let ehframe_end = &__ehframe_end as *const _ as u64; + let text = AddrRange { + start: &__text_start as *const _ as u64, + end: &__text_end as *const _ as u64, + }; + let eh_frame_hdr = AddrRange { + start: &__ehframehdr_start as *const _ as u64, + end: &__ehframehdr_end as *const _ as u64, + }; + let eh_frame_end = &__ehframe_end as *const _ as u64; cfi.push(EhRef { obj_base: 0, - text: AddrRange { start: text_start, end: text_end }, - cfi: AddrRange { start: cfi_start, end: cfi_end }, - ehframe_end, + text, + eh_frame_hdr, + eh_frame_end, }); } trace!("CFI sections: {:?}", cfi); diff --git a/unwind/src/find_cfi/ld.rs b/unwind/src/find_cfi/ld.rs index ca0feac..4ea604a 100644 --- a/unwind/src/find_cfi/ld.rs +++ b/unwind/src/find_cfi/ld.rs @@ -58,18 +58,18 @@ extern "C" fn callback(info: *const DlPhdrInfo, size: usize, data: *mut c_void) let phdr = slice::from_raw_parts((*info).phdr, (*info).phnum as usize); if let Some(text) = phdr.iter().filter(|x| x.type_ == PT_LOAD && x.flags & PF_X != 0).next() { - if let Some(eh_frame) = phdr.iter().filter(|x| x.type_ == PT_GNU_EH_FRAME).next() { + if let Some(eh_frame_hdr) = phdr.iter().filter(|x| x.type_ == PT_GNU_EH_FRAME).next() { let start_addr = (*info).addr + text.vaddr; - let cfi_start = (*info).addr + eh_frame.vaddr; + let eh_frame_hdr_start = (*info).addr + eh_frame_hdr.vaddr; let max_vaddr = phdr.iter().filter(|x| x.type_ == PT_LOAD) .fold(0, |vaddr, x| cmp::max(vaddr, x.vaddr + x.memsz)); // This is an upper bound, not the exact address. - let ehframe_end = (*info).addr + max_vaddr; + let eh_frame_end = (*info).addr + max_vaddr; (*data).push(EhRef { obj_base: (*info).addr, text: AddrRange { start: start_addr, end: start_addr + text.memsz }, - cfi: AddrRange { start: cfi_start, end: cfi_start + eh_frame.memsz }, - ehframe_end, + eh_frame_hdr: AddrRange { start: eh_frame_hdr_start, end: eh_frame_hdr_start + eh_frame_hdr.memsz }, + eh_frame_end, }); } } diff --git a/unwind/src/find_cfi/mod.rs b/unwind/src/find_cfi/mod.rs index fcfa223..df37ecd 100644 --- a/unwind/src/find_cfi/mod.rs +++ b/unwind/src/find_cfi/mod.rs @@ -4,8 +4,8 @@ use range::AddrRange; pub struct EhRef { pub obj_base: u64, pub text: AddrRange, - pub cfi: AddrRange, - pub ehframe_end: u64, + pub eh_frame_hdr: AddrRange, + pub eh_frame_end: u64, } #[cfg(unix)] diff --git a/unwind/src/glue.rs b/unwind/src/glue.rs index 03de7d5..5380a8a 100644 --- a/unwind/src/glue.rs +++ b/unwind/src/glue.rs @@ -1,5 +1,6 @@ +use gimli::X86_64; use super::{UnwindPayload, StackFrames}; -use registers::{Registers, DwarfRegister}; +use registers::Registers; #[allow(improper_ctypes)] // trampoline just forwards the ptr extern "C" { @@ -96,14 +97,14 @@ pub unsafe extern "C" fn unwind_recorder(payload: *mut UnwindPayload, stack: u64 let saved_regs = &*saved_regs; let mut registers = Registers::default(); - registers[DwarfRegister::Rbx] = Some(saved_regs.rbx); - registers[DwarfRegister::Rbp] = Some(saved_regs.rbp); - registers[DwarfRegister::SP] = Some(stack + 8); - registers[DwarfRegister::R12] = Some(saved_regs.r12); - registers[DwarfRegister::R13] = Some(saved_regs.r13); - registers[DwarfRegister::R14] = Some(saved_regs.r14); - registers[DwarfRegister::R15] = Some(saved_regs.r15); - registers[DwarfRegister::IP] = Some(*(stack as *const u64)); + registers[X86_64::RBX] = Some(saved_regs.rbx); + registers[X86_64::RBP] = Some(saved_regs.rbp); + registers[X86_64::RSP] = Some(stack + 8); + registers[X86_64::R12] = Some(saved_regs.r12); + registers[X86_64::R13] = Some(saved_regs.r13); + registers[X86_64::R14] = Some(saved_regs.r14); + registers[X86_64::R15] = Some(saved_regs.r15); + registers[X86_64::RA] = Some(*(stack as *const u64)); let mut frames = StackFrames { unwinder: payload.unwinder, @@ -116,24 +117,24 @@ pub unsafe extern "C" fn unwind_recorder(payload: *mut UnwindPayload, stack: u64 pub unsafe fn land(regs: &Registers) { let mut lr = LandingRegisters { - rax: regs[DwarfRegister::Rax].unwrap_or(0), - rbx: regs[DwarfRegister::Rbx].unwrap_or(0), - rcx: regs[DwarfRegister::Rcx].unwrap_or(0), - rdx: regs[DwarfRegister::Rdx].unwrap_or(0), - rdi: regs[DwarfRegister::Rdi].unwrap_or(0), - rsi: regs[DwarfRegister::Rsi].unwrap_or(0), - rbp: regs[DwarfRegister::Rbp].unwrap_or(0), - r8: regs[DwarfRegister::R8 ].unwrap_or(0), - r9: regs[DwarfRegister::R9 ].unwrap_or(0), - r10: regs[DwarfRegister::R10].unwrap_or(0), - r11: regs[DwarfRegister::R11].unwrap_or(0), - r12: regs[DwarfRegister::R12].unwrap_or(0), - r13: regs[DwarfRegister::R13].unwrap_or(0), - r14: regs[DwarfRegister::R14].unwrap_or(0), - r15: regs[DwarfRegister::R15].unwrap_or(0), - rsp: regs[DwarfRegister::SP].unwrap(), + rax: regs[X86_64::RAX].unwrap_or(0), + rbx: regs[X86_64::RBX].unwrap_or(0), + rcx: regs[X86_64::RCX].unwrap_or(0), + rdx: regs[X86_64::RDX].unwrap_or(0), + rdi: regs[X86_64::RDI].unwrap_or(0), + rsi: regs[X86_64::RSI].unwrap_or(0), + rbp: regs[X86_64::RBP].unwrap_or(0), + r8: regs[X86_64::R8 ].unwrap_or(0), + r9: regs[X86_64::R9 ].unwrap_or(0), + r10: regs[X86_64::R10].unwrap_or(0), + r11: regs[X86_64::R11].unwrap_or(0), + r12: regs[X86_64::R12].unwrap_or(0), + r13: regs[X86_64::R13].unwrap_or(0), + r14: regs[X86_64::R14].unwrap_or(0), + r15: regs[X86_64::R15].unwrap_or(0), + rsp: regs[X86_64::RSP].unwrap(), }; lr.rsp -= 8; - *(lr.rsp as *mut u64) = regs[DwarfRegister::IP].unwrap(); + *(lr.rsp as *mut u64) = regs[X86_64::RA].unwrap(); unwind_lander(&lr); } diff --git a/unwind/src/lib.rs b/unwind/src/lib.rs index 9cf97d0..50c168b 100644 --- a/unwind/src/lib.rs +++ b/unwind/src/lib.rs @@ -5,7 +5,7 @@ extern crate libc; extern crate fallible_iterator; #[macro_use] extern crate log; -use gimli::{UnwindSection, UnwindTable, UnwindTableRow, EhFrame, BaseAddresses, UninitializedUnwindContext, Pointer, Reader, EndianSlice, NativeEndian, CfaRule, RegisterRule, EhFrameHdr, ParsedEhFrameHdr}; +use gimli::{UnwindSection, UnwindTable, UnwindTableRow, EhFrame, BaseAddresses, UninitializedUnwindContext, Pointer, Reader, EndianSlice, NativeEndian, CfaRule, RegisterRule, EhFrameHdr, ParsedEhFrameHdr, X86_64}; use fallible_iterator::FallibleIterator; mod registers; @@ -13,7 +13,7 @@ mod find_cfi; mod range; pub mod libunwind_shim; pub mod glue; -use registers::{Registers, DwarfRegister}; +use registers::Registers; use find_cfi::EhRef; @@ -53,20 +53,23 @@ impl Default for DwarfUnwinder { fn default() -> DwarfUnwinder { let cfi = find_cfi::find_cfi_sections().into_iter().map(|er| { unsafe { - let bases = BaseAddresses::default().set_cfi(er.cfi.start); + // TODO: set_got() + let bases = BaseAddresses::default() + .set_eh_frame_hdr(er.eh_frame_hdr.start) + .set_text(er.text.start); - let eh_frame_hdr: &'static [u8] = std::slice::from_raw_parts(er.cfi.start as *const u8, er.cfi.len() as usize); + let eh_frame_hdr: &'static [u8] = std::slice::from_raw_parts(er.eh_frame_hdr.start as *const u8, er.eh_frame_hdr.len() as usize); let eh_frame_hdr = EhFrameHdr::new(eh_frame_hdr, NativeEndian).parse(&bases, 8).unwrap(); - let cfi_addr = deref_ptr(eh_frame_hdr.eh_frame_ptr()); - let cfi_sz = er.ehframe_end.saturating_sub(cfi_addr); + let eh_frame_addr = deref_ptr(eh_frame_hdr.eh_frame_ptr()); + let eh_frame_sz = er.eh_frame_end.saturating_sub(eh_frame_addr); - let eh_frame: &'static [u8] = std::slice::from_raw_parts(cfi_addr as *const u8, cfi_sz as usize); - trace!("cfi at {:p} sz {:x}", cfi_addr as *const u8, cfi_sz); + let eh_frame: &'static [u8] = std::slice::from_raw_parts(eh_frame_addr as *const u8, eh_frame_sz as usize); + trace!("eh_frame at {:p} sz {:x}", eh_frame_addr as *const u8, eh_frame_sz); let eh_frame = EhFrame::new(eh_frame, NativeEndian); - let bases = bases.set_cfi(cfi_addr).set_data(er.cfi.start); + let bases = bases.set_eh_frame(eh_frame_addr); ObjectRecord { er, eh_frame_hdr, eh_frame, bases } } @@ -167,10 +170,10 @@ impl<'a> FallibleIterator for StackFrames<'a> { if let Some((row, cfa)) = self.state.take() { let mut newregs = registers.clone(); - newregs[DwarfRegister::IP] = None; + newregs[X86_64::RA] = None; for &(reg, ref rule) in row.registers() { - trace!("rule {} {:?}", reg, rule); - assert!(reg != 7); // stack = cfa + trace!("rule {:?} {:?}", reg, rule); + assert!(reg != X86_64::RSP); // stack = cfa newregs[reg] = match *rule { RegisterRule::Undefined => unreachable!(), // registers[reg], RegisterRule::SameValue => Some(registers[reg].unwrap()), // not sure why this exists @@ -189,7 +192,7 @@ impl<'a> FallibleIterator for StackFrames<'a> { } - if let Some(mut caller) = registers[DwarfRegister::IP] { + if let Some(mut caller) = registers[X86_64::RA] { caller -= 1; // THIS IS NECESSARY debug!("caller is 0x{:x}", caller); diff --git a/unwind/src/libunwind_shim.rs b/unwind/src/libunwind_shim.rs index 58282a8..9bfdb77 100644 --- a/unwind/src/libunwind_shim.rs +++ b/unwind/src/libunwind_shim.rs @@ -2,8 +2,9 @@ use libc::{c_void, c_int}; use fallible_iterator::FallibleIterator; +use gimli::X86_64; -use registers::{Registers, DwarfRegister}; +use registers::Registers; use super::{DwarfUnwinder, Unwinder}; #[repr(C)] @@ -87,12 +88,12 @@ pub unsafe extern "C" fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Conte #[no_mangle] pub unsafe extern "C" fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: c_int, value: _Unwind_Word) { - (*(*ctx).registers)[reg_index as u8] = Some(value as u64); + (*(*ctx).registers)[reg_index as u16] = Some(value as u64); } #[no_mangle] pub unsafe extern "C" fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Word) { - (*(*ctx).registers)[DwarfRegister::IP] = Some(value as u64); + (*(*ctx).registers)[X86_64::RA] = Some(value as u64); } #[no_mangle] @@ -118,7 +119,7 @@ unsafe fn unwind_tracer(frames: &mut ::StackFrames, exception: *mut _Unwind_Exce if let Some(contptr) = (*exception).private_contptr { loop { if let Some(frame) = frames.next().unwrap() { - if frames.registers()[DwarfRegister::SP].unwrap() == contptr { + if frames.registers()[X86_64::RSP].unwrap() == contptr { break; } } else { @@ -134,12 +135,12 @@ unsafe fn unwind_tracer(frames: &mut ::StackFrames, exception: *mut _Unwind_Exce let mut ctx = _Unwind_Context { lsda: frame.lsda.unwrap(), - ip: frames.registers()[DwarfRegister::IP].unwrap(), + ip: frames.registers()[X86_64::RA].unwrap(), initial_address: frame.initial_address, registers: frames.registers(), }; - (*exception).private_contptr = frames.registers()[DwarfRegister::SP]; + (*exception).private_contptr = frames.registers()[X86_64::RSP]; // ABI specifies that phase 1 is optional, so we just run phase 2 (CLEANUP_PHASE) match personality(1, _Unwind_Action::_UA_CLEANUP_PHASE as c_int, (*exception).exception_class, @@ -160,7 +161,7 @@ pub unsafe extern "C" fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn, while let Some(frame) = frames.next().unwrap() { let mut ctx = _Unwind_Context { lsda: frame.lsda.unwrap_or(0), - ip: frames.registers()[DwarfRegister::IP].unwrap(), + ip: frames.registers()[X86_64::RA].unwrap(), initial_address: frame.initial_address, registers: frames.registers(), }; diff --git a/unwind/src/registers.rs b/unwind/src/registers.rs index f5fdc95..2f6cbd7 100644 --- a/unwind/src/registers.rs +++ b/unwind/src/registers.rs @@ -1,3 +1,4 @@ +use gimli; use std::fmt::{Debug, Formatter, Result as FmtResult}; use std::ops::{Index, IndexMut}; @@ -18,51 +19,30 @@ impl Debug for Registers { } } -impl Index for Registers { +impl Index for Registers { type Output = Option; - fn index(&self, index: u8) -> &Option { + fn index(&self, index: u16) -> &Option { &self.registers[index as usize] } } -impl IndexMut for Registers { - fn index_mut(&mut self, index: u8) -> &mut Option { +impl IndexMut for Registers { + fn index_mut(&mut self, index: u16) -> &mut Option { &mut self.registers[index as usize] } } -impl Index for Registers { +impl Index for Registers { type Output = Option; - fn index(&self, reg: DwarfRegister) -> &Option { - &self[reg as u8] + fn index(&self, reg: gimli::Register) -> &Option { + &self[reg.0] } } -impl IndexMut for Registers { - fn index_mut(&mut self, reg: DwarfRegister) -> &mut Option { - &mut self[reg as u8] +impl IndexMut for Registers { + fn index_mut(&mut self, reg: gimli::Register) -> &mut Option { + &mut self[reg.0] } } - -pub enum DwarfRegister { - SP = 7, - IP = 16, - - Rax = 0, - Rbx = 3, - Rcx = 2, - Rdx = 1, - Rdi = 5, - Rsi = 4, - Rbp = 6, - R8 = 8, - R9 = 9, - R10 = 10, - R11 = 11, - R12 = 12, - R13 = 13, - R14 = 14, - R15 = 15, -} From 1a0ee47779db77aa7c6752155bf786c228fbf8fe Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Sun, 24 Feb 2019 14:33:30 +1000 Subject: [PATCH 2/3] Delete unneeded StackFrame::object_base --- unwind/src/find_cfi/baremetal.rs | 1 - unwind/src/find_cfi/ld.rs | 1 - unwind/src/find_cfi/mod.rs | 1 - unwind/src/lib.rs | 2 -- 4 files changed, 5 deletions(-) diff --git a/unwind/src/find_cfi/baremetal.rs b/unwind/src/find_cfi/baremetal.rs index cb1fa7b..2e62a6b 100644 --- a/unwind/src/find_cfi/baremetal.rs +++ b/unwind/src/find_cfi/baremetal.rs @@ -25,7 +25,6 @@ pub fn find_cfi_sections() -> Vec { let eh_frame_end = &__ehframe_end as *const _ as u64; cfi.push(EhRef { - obj_base: 0, text, eh_frame_hdr, eh_frame_end, diff --git a/unwind/src/find_cfi/ld.rs b/unwind/src/find_cfi/ld.rs index 4ea604a..33240fd 100644 --- a/unwind/src/find_cfi/ld.rs +++ b/unwind/src/find_cfi/ld.rs @@ -66,7 +66,6 @@ extern "C" fn callback(info: *const DlPhdrInfo, size: usize, data: *mut c_void) // This is an upper bound, not the exact address. let eh_frame_end = (*info).addr + max_vaddr; (*data).push(EhRef { - obj_base: (*info).addr, text: AddrRange { start: start_addr, end: start_addr + text.memsz }, eh_frame_hdr: AddrRange { start: eh_frame_hdr_start, end: eh_frame_hdr_start + eh_frame_hdr.memsz }, eh_frame_end, diff --git a/unwind/src/find_cfi/mod.rs b/unwind/src/find_cfi/mod.rs index df37ecd..27b142a 100644 --- a/unwind/src/find_cfi/mod.rs +++ b/unwind/src/find_cfi/mod.rs @@ -2,7 +2,6 @@ use range::AddrRange; #[derive(Debug)] pub struct EhRef { - pub obj_base: u64, pub text: AddrRange, pub eh_frame_hdr: AddrRange, pub eh_frame_end: u64, diff --git a/unwind/src/lib.rs b/unwind/src/lib.rs index 50c168b..b589b4d 100644 --- a/unwind/src/lib.rs +++ b/unwind/src/lib.rs @@ -28,7 +28,6 @@ pub struct StackFrame { personality: Option, lsda: Option, initial_address: u64, - pub object_base: u64, // FIXME hack, remove this } pub trait Unwinder: Default { @@ -213,7 +212,6 @@ impl<'a> FallibleIterator for StackFrames<'a> { self.state = Some((row, cfa)); Ok(Some(StackFrame { - object_base: rec.er.obj_base, personality: personality.map(|x| unsafe { deref_ptr(x) }), lsda: lsda.map(|x| unsafe { deref_ptr(x) }), initial_address, From f5fbf20b8100142024ceb8ce1248d77d91267f26 Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Sun, 24 Feb 2019 14:59:49 +1000 Subject: [PATCH 3/3] Fix demo on nightly Also, inline asm no longer works (segmentation fault). --- unwind/Cargo.toml | 1 + unwind/build.rs | 2 +- unwind/src/glue.rs | 8 ++++---- unwind/src/lib.rs | 3 ++- unwind/src/libunwind_shim.rs | 9 +++++++++ 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/unwind/Cargo.toml b/unwind/Cargo.toml index 671e8e0..e8981b3 100644 --- a/unwind/Cargo.toml +++ b/unwind/Cargo.toml @@ -18,3 +18,4 @@ env_logger = "0.6" [features] nightly = [] +asm = ["nightly"] diff --git a/unwind/build.rs b/unwind/build.rs index 2ebae21..ec4d15c 100644 --- a/unwind/build.rs +++ b/unwind/build.rs @@ -2,7 +2,7 @@ extern crate gcc; use std::env; fn main() { - match env::var("CARGO_FEATURE_NIGHTLY") { + match env::var("CARGO_FEATURE_ASM") { Err(env::VarError::NotPresent) => { gcc::Build::new() .file("src/unwind_helper.c") diff --git a/unwind/src/glue.rs b/unwind/src/glue.rs index 5380a8a..4592630 100644 --- a/unwind/src/glue.rs +++ b/unwind/src/glue.rs @@ -4,13 +4,13 @@ use registers::Registers; #[allow(improper_ctypes)] // trampoline just forwards the ptr extern "C" { - #[cfg(not(feature = "nightly"))] + #[cfg(not(feature = "asm"))] pub fn unwind_trampoline(payload: *mut UnwindPayload); - #[cfg(not(feature = "nightly"))] + #[cfg(not(feature = "asm"))] fn unwind_lander(regs: *const LandingRegisters); } -#[cfg(feature = "nightly")] +#[cfg(feature = "asm")] #[naked] pub unsafe extern fn unwind_trampoline(_payload: *mut UnwindPayload) { asm!(" @@ -34,7 +34,7 @@ pub unsafe extern fn unwind_trampoline(_payload: *mut UnwindPayload) { ::std::hint::unreachable_unchecked(); } -#[cfg(feature = "nightly")] +#[cfg(feature = "asm")] #[naked] unsafe extern fn unwind_lander(_regs: *const LandingRegisters) { asm!(" diff --git a/unwind/src/lib.rs b/unwind/src/lib.rs index b589b4d..834c521 100644 --- a/unwind/src/lib.rs +++ b/unwind/src/lib.rs @@ -1,4 +1,5 @@ -#![cfg_attr(feature = "nightly", feature(asm, naked_functions))] +#![cfg_attr(feature = "nightly", feature(unwind_attributes))] +#![cfg_attr(feature = "asm", feature(asm, naked_functions))] extern crate gimli; extern crate libc; diff --git a/unwind/src/libunwind_shim.rs b/unwind/src/libunwind_shim.rs index 9bfdb77..cb1286f 100644 --- a/unwind/src/libunwind_shim.rs +++ b/unwind/src/libunwind_shim.rs @@ -54,6 +54,8 @@ pub type _Unwind_Trace_Fn = extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c -> _Unwind_Reason_Code; type PersonalityRoutine = extern "C" fn(version: c_int, actions: c_int, class: u64, object: *mut _Unwind_Exception, context: *mut _Unwind_Context) -> _Unwind_Reason_Code; +// FIXME: we skip over this function when unwinding, so we should ensure +// it never needs any cleanup. Currently this is not true. #[no_mangle] pub unsafe extern "C" fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> ! { DwarfUnwinder::default().trace(|frames| unwind_tracer(frames, exception)); @@ -108,6 +110,13 @@ pub unsafe extern "C" fn _Unwind_FindEnclosingFunction(pc: *mut c_void) -> *mut pc // FIXME: implement this } +// FIXME: Set `unwind(allowed)` because we need to be able to unwind this function as +// part of its operation. But this means any panics in this function are undefined +// behaviour, and we don't currently ensure it doesn't panic. +// +// On stable (1.32), `unwind(allowed)` is the default, but this will change in 1.33, with +// no stable way of setting `unwind(allowed)`, so this function will always abort in 1.33. +#[cfg_attr(feature = "nightly", unwind(allowed))] #[no_mangle] pub unsafe extern "C" fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code { (*exception).private_contptr = None;