Fix ARM unwinding.

This commit is contained in:
Vadim Chugunov 2014-01-03 23:34:15 -08:00
parent 8bfd2a84cf
commit cefb2c7e45
3 changed files with 130 additions and 49 deletions

View File

@ -157,6 +157,7 @@ CFG_GCCISH_DEF_FLAG_x86_64-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-l
CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-linux-gnu := -Wl,-whole-archive
CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-linux-gnu := -Wl,-no-whole-archive
CFG_DEF_SUFFIX_x86_64-unknown-linux-gnu := .linux.def
CFG_LLC_FLAGS_x86_64-unknown-linux-gnu :=
CFG_INSTALL_NAME_x86_64-unknown-linux-gnu =
CFG_LIBUV_LINK_FLAGS_x86_64-unknown-linux-gnu =
CFG_LLVM_BUILD_ENV_x86_64-unknown-linux-gnu="CXXFLAGS=-fno-omit-frame-pointer"
@ -184,6 +185,7 @@ CFG_GCCISH_DEF_FLAG_i686-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-lis
CFG_GCCISH_PRE_LIB_FLAGS_i686-unknown-linux-gnu := -Wl,-whole-archive
CFG_GCCISH_POST_LIB_FLAGS_i686-unknown-linux-gnu := -Wl,-no-whole-archive
CFG_DEF_SUFFIX_i686-unknown-linux-gnu := .linux.def
CFG_LLC_FLAGS_i686-unknown-linux-gnu :=
CFG_INSTALL_NAME_i686-unknown-linux-gnu =
CFG_LIBUV_LINK_FLAGS_i686-unknown-linux-gnu =
CFG_LLVM_BUILD_ENV_i686-unknown-linux-gnu="CXXFLAGS=-fno-omit-frame-pointer"
@ -213,6 +215,7 @@ CFG_GCCISH_DEF_FLAG_arm-apple-darwin := -Wl,-exported_symbols_list,
CFG_GCCISH_PRE_LIB_FLAGS_arm-apple-darwin :=
CFG_GCCISH_POST_LIB_FLAGS_arm-apple-darwin :=
CFG_DEF_SUFFIX_arm-apple-darwin := .darwin.def
CFG_LLC_FLAGS_arm-apple-darwin := -arm-enable-ehabi -arm-enable-ehabi-descriptors
CFG_INSTALL_NAME_arm-apple-darwin = -Wl,-install_name,@rpath/$(1)
CFG_LIBUV_LINK_FLAGS_arm-apple-darwin =
CFG_EXE_SUFFIX_arm-apple-darwin :=
@ -240,6 +243,7 @@ CFG_GCCISH_DEF_FLAG_x86_64-apple-darwin := -Wl,-exported_symbols_list,
CFG_GCCISH_PRE_LIB_FLAGS_x86_64-apple-darwin :=
CFG_GCCISH_POST_LIB_FLAGS_x86_64-apple-darwin :=
CFG_DEF_SUFFIX_x86_64-apple-darwin := .darwin.def
CFG_LLC_FLAGS_x86_64-apple-darwin :=
CFG_INSTALL_NAME_x86_64-apple-darwin = -Wl,-install_name,@rpath/$(1)
CFG_LIBUV_LINK_FLAGS_x86_64-apple-darwin =
CFG_EXE_SUFFIX_x86_64-apple-darwin :=
@ -266,6 +270,7 @@ CFG_GCCISH_DEF_FLAG_i686-apple-darwin := -Wl,-exported_symbols_list,
CFG_GCCISH_PRE_LIB_FLAGS_i686-apple-darwin :=
CFG_GCCISH_POST_LIB_FLAGS_i686-apple-darwin :=
CFG_DEF_SUFFIX_i686-apple-darwin := .darwin.def
CFG_LLC_FLAGS_i686-apple-darwin :=
CFG_INSTALL_NAME_i686-apple-darwin = -Wl,-install_name,@rpath/$(1)
CFG_LIBUV_LINK_FLAGS_i686-apple-darwin =
CFG_EXE_SUFFIX_i686-apple-darwin :=
@ -292,6 +297,7 @@ CFG_GCCISH_DEF_FLAG_arm-linux-androideabi := -Wl,--export-dynamic,--dynamic-list
CFG_GCCISH_PRE_LIB_FLAGS_arm-linux-androideabi := -Wl,-whole-archive
CFG_GCCISH_POST_LIB_FLAGS_arm-linux-androideabi := -Wl,-no-whole-archive
CFG_DEF_SUFFIX_arm-linux-androideabi := .android.def
CFG_LLC_FLAGS_arm-linux-androideabi := -arm-enable-ehabi -arm-enable-ehabi-descriptors
CFG_INSTALL_NAME_arm-linux-androideabi =
CFG_LIBUV_LINK_FLAGS_arm-linux-androideabi =
CFG_EXE_SUFFIX_arm-linux-androideabi :=
@ -321,6 +327,7 @@ CFG_GCCISH_DEF_FLAG_arm-unknown-linux-gnueabihf := -Wl,--export-dynamic,--dynami
CFG_GCCISH_PRE_LIB_FLAGS_arm-unknown-linux-gnueabihf := -Wl,-whole-archive
CFG_GCCISH_POST_LIB_FLAGS_arm-unknown-linux-gnueabihf := -Wl,-no-whole-archive
CFG_DEF_SUFFIX_arm-unknown-linux-gnueabihf := .linux.def
CFG_LLC_FLAGS_arm-unknown-linux-gnueabihf := -arm-enable-ehabi -arm-enable-ehabi-descriptors
CFG_INSTALL_NAME_ar,-unknown-linux-gnueabihf =
CFG_LIBUV_LINK_FLAGS_arm-unknown-linux-gnueabihf =
CFG_EXE_SUFFIX_arm-unknown-linux-gnueabihf :=
@ -350,6 +357,7 @@ CFG_GCCISH_DEF_FLAG_arm-unknown-linux-gnueabi := -Wl,--export-dynamic,--dynamic-
CFG_GCCISH_PRE_LIB_FLAGS_arm-unknown-linux-gnueabi := -Wl,-whole-archive
CFG_GCCISH_POST_LIB_FLAGS_arm-unknown-linux-gnueabi := -Wl,-no-whole-archive
CFG_DEF_SUFFIX_arm-unknown-linux-gnueabi := .linux.def
CFG_LLC_FLAGS_arm-unknown-linux-gnueabi := -arm-enable-ehabi -arm-enable-ehabi-descriptors
CFG_INSTALL_NAME_arm-unknown-linux-gnueabi =
CFG_LIBUV_LINK_FLAGS_arm-unknown-linux-gnueabi =
CFG_EXE_SUFFIX_arm-unknown-linux-gnueabi :=
@ -378,6 +386,7 @@ CFG_GCCISH_DEF_FLAG_mips-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-lis
CFG_GCCISH_PRE_LIB_FLAGS_mips-unknown-linux-gnu := -Wl,-whole-archive
CFG_GCCISH_POST_LIB_FLAGS_mips-unknown-linux-gnu := -Wl,-no-whole-archive
CFG_DEF_SUFFIX_mips-unknown-linux-gnu := .linux.def
CFG_LLC_FLAGS_mips-unknown-linux-gnu :=
CFG_INSTALL_NAME_mips-unknown-linux-gnu =
CFG_LIBUV_LINK_FLAGS_mips-unknown-linux-gnu =
CFG_EXE_SUFFIX_mips-unknown-linux-gnu :=
@ -405,6 +414,7 @@ CFG_GCCISH_DEF_FLAG_i686-pc-mingw32 :=
CFG_GCCISH_PRE_LIB_FLAGS_i686-pc-mingw32 :=
CFG_GCCISH_POST_LIB_FLAGS_i686-pc-mingw32 :=
CFG_DEF_SUFFIX_i686-pc-mingw32 := .mingw32.def
CFG_LLC_FLAGS_i686-pc-mingw32 :=
CFG_INSTALL_NAME_i686-pc-mingw32 =
CFG_LIBUV_LINK_FLAGS_i686-pc-mingw32 := -lws2_32 -lpsapi -liphlpapi
CFG_LLVM_BUILD_ENV_i686-pc-mingw32 := CPATH=$(CFG_SRC_DIR)src/etc/mingw-fix-include
@ -432,6 +442,7 @@ CFG_GCCISH_DEF_FLAG_i586-mingw32msvc :=
CFG_GCCISH_PRE_LIB_FLAGS_i586-mingw32msvc :=
CFG_GCCISH_POST_LIB_FLAGS_i586-mingw32msvc :=
CFG_DEF_SUFFIX_i586-mingw32msvc := .mingw32.def
CFG_LLC_FLAGS_i586-mingw32msvc :=
CFG_INSTALL_NAME_i586-mingw32msvc =
CFG_LIBUV_LINK_FLAGS_i586-mingw32msvc := -L$(CFG_MINGW32_CROSS_PATH)/i586-mingw32msvc/lib -lws2_32 -lpsapi -liphlpapi
CFG_EXE_SUFFIX_i586-mingw32msvc := .exe
@ -461,6 +472,7 @@ CFG_GCCISH_DEF_FLAG_i686-w64-mingw32 :=
CFG_GCCISH_PRE_LIB_FLAGS_i686-w64-mingw32 :=
CFG_GCCISH_POST_LIB_FLAGS_i686-w64-mingw32 :=
CFG_DEF_SUFFIX_i686-w64-mingw32 := .mingw32.def
CFG_LLC_FLAGS_i686-w64-mingw32 :=
CFG_INSTALL_NAME_i686-w64-mingw32 =
CFG_LIBUV_LINK_FLAGS_i686-w64-mingw32 := -lws2_32 -lpsapi -liphlpapi
CFG_EXE_SUFFIX_i686-w64-mingw32 := .exe
@ -489,6 +501,7 @@ CFG_GCCISH_DEF_FLAG_x86_64-w64-mingw32 :=
CFG_GCCISH_PRE_LIB_FLAGS_x86_64-w64-mingw32 :=
CFG_GCCISH_POST_LIB_FLAGS_x86_64-w64-mingw32 :=
CFG_DEF_SUFFIX_x86_64-w64-mingw32 := .mingw32.def
CFG_LLC_FLAGS_x86_64-w64-mingw32 :=
CFG_INSTALL_NAME_x86_64-w64-mingw32 =
CFG_LIBUV_LINK_FLAGS_x86_64-w64-mingw32 := -lws2_32 -lpsapi -liphlpapi
CFG_EXE_SUFFIX_x86_64-w64-mingw32 := .exe
@ -515,6 +528,7 @@ CFG_GCCISH_DEF_FLAG_x86_64-unknown-freebsd := -Wl,--export-dynamic,--dynamic-lis
CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-freebsd := -Wl,-whole-archive
CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-freebsd := -Wl,-no-whole-archive
CFG_DEF_SUFFIX_x86_64-unknown-freebsd := .bsd.def
CFG_LLC_FLAGS_x86_64-unknown-freebsd :=
CFG_INSTALL_NAME_x86_64-unknown-freebsd =
CFG_LIBUV_LINK_FLAGS_x86_64-unknown-freebsd := -pthread -lkvm
CFG_EXE_SUFFIX_x86_64-unknown-freebsd :=

View File

@ -116,7 +116,7 @@ $$(RT_BUILD_DIR_$(1)_$(2))/%.o: rt/%.S $$(MKFILE_DEPS) \
$$(RT_BUILD_DIR_$(1)_$(2))/%.o: rt/%.ll $$(MKFILE_DEPS) \
$$(LLVM_CONFIG_$$(CFG_BUILD))
@$$(call E, compile: $$@)
$$(Q)$(LLC_$(CFG_BUILD)) -filetype=obj -mtriple=$(1) -relocation-model=pic -o $$@ $$<
$$(Q)$(LLC_$(CFG_BUILD)) $$(CFG_LLC_FLAGS_$(1)) -filetype=obj -mtriple=$(1) -relocation-model=pic -o $$@ $$<
$$(RT_BUILD_DIR_$(1)_$(2))/arch/$$(HOST_$(1))/libmorestack.a: $$(MORESTACK_OBJS_$(1)_$(2))
@$$(call E, link: $$@)

View File

@ -59,8 +59,7 @@ use any::{Any, AnyRefExt};
use c_str::CString;
use cast;
use kinds::Send;
use libc::{c_char, size_t};
use libc::{c_void, c_int};
use libc::{c_void, c_char, size_t};
use option::{Some, None, Option};
use result::{Err, Ok};
use rt::local::Local;
@ -78,6 +77,7 @@ mod libunwind {
use libc::{uintptr_t, uint64_t};
#[cfg(not(target_os = "android"))]
#[repr(C)]
pub enum _Unwind_Action
{
@ -88,6 +88,18 @@ mod libunwind {
_UA_END_OF_STACK = 16,
}
#[cfg(target_os = "android")]
#[repr(C)]
pub enum _Unwind_State
{
_US_VIRTUAL_UNWIND_FRAME = 0,
_US_UNWIND_FRAME_STARTING = 1,
_US_UNWIND_FRAME_RESUME = 2,
_US_ACTION_MASK = 3,
_US_FORCE_UNWIND = 8,
_US_END_OF_STACK = 16
}
#[repr(C)]
pub enum _Unwind_Reason_Code {
_URC_NO_REASON = 0,
@ -99,6 +111,7 @@ mod libunwind {
_URC_HANDLER_FOUND = 6,
_URC_INSTALL_CONTEXT = 7,
_URC_CONTINUE_UNWIND = 8,
_URC_FAILURE = 9, // used only by ARM EABI
}
pub type _Unwind_Exception_Class = uint64_t;
@ -108,8 +121,7 @@ mod libunwind {
pub struct _Unwind_Exception {
exception_class: _Unwind_Exception_Class,
exception_cleanup: _Unwind_Exception_Cleanup_Fn,
private_1: _Unwind_Word,
private_2: _Unwind_Word,
private: [_Unwind_Word, ..20],
}
pub enum _Unwind_Context {}
@ -148,7 +160,7 @@ impl Unwinder {
let ep = rust_try(try_fn, closure.code as *c_void,
closure.env as *c_void);
if !ep.is_null() {
rtdebug!("Caught {}", (*ep).exception_class);
rtdebug!("caught {}", (*ep).exception_class);
uw::_Unwind_DeleteException(ep);
}
}
@ -190,8 +202,7 @@ impl Unwinder {
let exception = ~uw::_Unwind_Exception {
exception_class: rust_exception_class(),
exception_cleanup: exception_cleanup,
private_1: 0,
private_2: 0
private: [0, ..20],
};
let error = uw::_Unwind_RaiseException(cast::transmute(exception));
rtabort!("Could not unwind stack, error = {}", error as int)
@ -242,51 +253,107 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
// This is achieved by overriding the return value in search phase to always
// say "catch!".
extern "C" {
fn __gcc_personality_v0(version: c_int,
actions: uw::_Unwind_Action,
exception_class: uw::_Unwind_Exception_Class,
ue_header: *uw::_Unwind_Exception,
context: *uw::_Unwind_Context)
-> uw::_Unwind_Reason_Code;
}
#[cfg(not(target_os = "android"))]
pub mod eabi {
use uw = super::libunwind;
use libc::c_int;
#[lang="eh_personality"]
#[no_mangle] // so we can reference it by name from middle/trans/base.rs
#[doc(hidden)]
#[cfg(not(test))]
pub extern "C" fn rust_eh_personality(
version: c_int,
actions: uw::_Unwind_Action,
exception_class: uw::_Unwind_Exception_Class,
ue_header: *uw::_Unwind_Exception,
context: *uw::_Unwind_Context
) -> uw::_Unwind_Reason_Code
{
unsafe {
__gcc_personality_v0(version, actions, exception_class, ue_header,
context)
extern "C" {
fn __gcc_personality_v0(version: c_int,
actions: uw::_Unwind_Action,
exception_class: uw::_Unwind_Exception_Class,
ue_header: *uw::_Unwind_Exception,
context: *uw::_Unwind_Context)
-> uw::_Unwind_Reason_Code;
}
}
#[no_mangle] // referenced from rust_try.ll
#[doc(hidden)]
#[cfg(not(test))]
pub extern "C" fn rust_eh_personality_catch(
version: c_int,
actions: uw::_Unwind_Action,
exception_class: uw::_Unwind_Exception_Class,
ue_header: *uw::_Unwind_Exception,
context: *uw::_Unwind_Context
) -> uw::_Unwind_Reason_Code
{
if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
uw::_URC_HANDLER_FOUND // catch!
}
else { // cleanup phase
#[lang="eh_personality"]
#[no_mangle] // so we can reference it by name from middle/trans/base.rs
#[doc(hidden)]
#[cfg(not(test))]
pub extern "C" fn rust_eh_personality(
version: c_int,
actions: uw::_Unwind_Action,
exception_class: uw::_Unwind_Exception_Class,
ue_header: *uw::_Unwind_Exception,
context: *uw::_Unwind_Context
) -> uw::_Unwind_Reason_Code
{
unsafe {
__gcc_personality_v0(version, actions, exception_class, ue_header,
context)
__gcc_personality_v0(version, actions, exception_class, ue_header,
context)
}
}
#[no_mangle] // referenced from rust_try.ll
#[doc(hidden)]
#[cfg(not(test))]
pub extern "C" fn rust_eh_personality_catch(
version: c_int,
actions: uw::_Unwind_Action,
exception_class: uw::_Unwind_Exception_Class,
ue_header: *uw::_Unwind_Exception,
context: *uw::_Unwind_Context
) -> uw::_Unwind_Reason_Code
{
if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase
uw::_URC_HANDLER_FOUND // catch!
}
else { // cleanup phase
unsafe {
__gcc_personality_v0(version, actions, exception_class, ue_header,
context)
}
}
}
}
// ARM EHABI uses a slightly different personality routine signature,
// but otherwise works the same.
#[cfg(target_os = "android")]
pub mod eabi {
use uw = super::libunwind;
use libc::c_int;
extern "C" {
fn __gcc_personality_v0(state: uw::_Unwind_State,
ue_header: *uw::_Unwind_Exception,
context: *uw::_Unwind_Context)
-> uw::_Unwind_Reason_Code;
}
#[lang="eh_personality"]
#[no_mangle] // so we can reference it by name from middle/trans/base.rs
#[doc(hidden)]
#[cfg(not(test))]
pub extern "C" fn rust_eh_personality(
state: uw::_Unwind_State,
ue_header: *uw::_Unwind_Exception,
context: *uw::_Unwind_Context
) -> uw::_Unwind_Reason_Code
{
unsafe {
__gcc_personality_v0(state, ue_header, context)
}
}
#[no_mangle] // referenced from rust_try.ll
#[doc(hidden)]
#[cfg(not(test))]
pub extern "C" fn rust_eh_personality_catch(
state: uw::_Unwind_State,
ue_header: *uw::_Unwind_Exception,
context: *uw::_Unwind_Context
) -> uw::_Unwind_Reason_Code
{
if (state as c_int & uw::_US_ACTION_MASK as c_int)
== uw::_US_VIRTUAL_UNWIND_FRAME as c_int { // search phase
uw::_URC_HANDLER_FOUND // catch!
}
else { // cleanup phase
unsafe {
__gcc_personality_v0(state, ue_header, context)
}
}
}
}