From cefb2c7e45140e1492b3cb45601a538478f40577 Mon Sep 17 00:00:00 2001 From: Vadim Chugunov Date: Fri, 3 Jan 2014 23:34:15 -0800 Subject: [PATCH] Fix ARM unwinding. --- mk/platform.mk | 14 ++++ mk/rt.mk | 2 +- src/libstd/rt/unwind.rs | 163 ++++++++++++++++++++++++++++------------ 3 files changed, 130 insertions(+), 49 deletions(-) diff --git a/mk/platform.mk b/mk/platform.mk index 4070ccaf270..10c597e61d1 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -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 := diff --git a/mk/rt.mk b/mk/rt.mk index ddffcb3ffb9..38cc233b933 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -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: $$@) diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind.rs index 358df7260f4..3904be179c2 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind.rs @@ -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) + } } } }