about summary refs log tree commit diff
path: root/src/libpanic_unwind/gcc.rs
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2017-06-06 11:34:10 -0700
committerAlex Crichton <alex@alexcrichton.com>2017-06-08 07:06:43 -0700
commit52805d233b59503cdfe58ee21e894ed6bb3b1da9 (patch)
tree36df6e39ebdde78dc3001625f5d6a612d30e0fe1 /src/libpanic_unwind/gcc.rs
parentae7920153331f26f2bc144f62082e95e74c2ba31 (diff)
downloadrust-52805d233b59503cdfe58ee21e894ed6bb3b1da9.tar.gz
rust-52805d233b59503cdfe58ee21e894ed6bb3b1da9.zip
std: Avoid panics in rust_eh_personality
This commit removes a few calls to panic and/or assert in `rust_eh_personality`.
This function definitely can't itself panic (that'd probably segfault or do
something else weird) and I was also noticing that a `pub extern fn foo() {}`
cdylib was abnormally large. Turns out all that size was the panicking machinery
brought in by the personality function!

The change here is to return a `Result` internally so we can bubble up the fatal
error, eventually translating to the appropriate error code for the libunwind
ABI.
Diffstat (limited to 'src/libpanic_unwind/gcc.rs')
-rw-r--r--src/libpanic_unwind/gcc.rs14
1 files changed, 11 insertions, 3 deletions
diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs
index 84abc6bc4a5..aadbeb96b2d 100644
--- a/src/libpanic_unwind/gcc.rs
+++ b/src/libpanic_unwind/gcc.rs
@@ -156,7 +156,10 @@ unsafe extern "C" fn rust_eh_personality(version: c_int,
     if version != 1 {
         return uw::_URC_FATAL_PHASE1_ERROR;
     }
-    let eh_action = find_eh_action(context);
+    let eh_action = match find_eh_action(context) {
+        Ok(action) => action,
+        Err(_) => return uw::_URC_FATAL_PHASE1_ERROR,
+    };
     if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 {
         match eh_action {
             EHAction::None |
@@ -219,7 +222,10 @@ unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
     // _Unwind_Context in our libunwind bindings and fetch the required data from there directly,
     // bypassing DWARF compatibility functions.
 
-    let eh_action = find_eh_action(context);
+    let eh_action = match find_eh_action(context) {
+        Ok(action) => action,
+        Err(_) => return uw::_URC_FAILURE,
+    };
     if search_phase {
         match eh_action {
             EHAction::None |
@@ -260,7 +266,9 @@ unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
     }
 }
 
-unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> EHAction {
+unsafe fn find_eh_action(context: *mut uw::_Unwind_Context)
+    -> Result<EHAction, ()>
+{
     let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8;
     let mut ip_before_instr: c_int = 0;
     let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr);