diff options
| author | Yuki Okushi <huyuumi.dev+love@gmail.com> | 2023-01-13 05:47:21 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-01-13 05:47:21 +0900 |
| commit | 3f21b812bec836dc3bc0f56d4e34b7c46ec68af1 (patch) | |
| tree | 07315c53a463f7a78a79a40201491ce661af456d | |
| parent | fa8f77a1deb0952fa81fd4f2f0809ceec8d7f7e8 (diff) | |
| parent | 93ef4b3991d19cddf011da8f0b5a7bf9a8672541 (diff) | |
| download | rust-3f21b812bec836dc3bc0f56d4e34b7c46ec68af1.tar.gz rust-3f21b812bec836dc3bc0f56d4e34b7c46ec68af1.zip | |
Rollup merge of #106446 - bzEq:fix-unwind-lsda, r=Amanieu
[LSDA] Take ttype_index into account when taking unwind action If `cs_action != 0`, we should check the `ttype_index` field in action record. If `ttype_index == 0`, a clean up action is taken; otherwise catch action is taken. This can fix unwind failure on AIX which uses LLVM's libunwind by default. IIUC, rust's LSDA is borrowed from c++ and I'm assuming itanium-cxx-abi https://itanium-cxx-abi.github.io/cxx-abi/exceptions.pdf should be followed, so the fix follows what libcxxabi does. See https://github.com/llvm/llvm-project/blob/ec48682ce9f61d056361c5095f21e930b8365661/libcxxabi/src/cxa_personality.cpp#L152 for use of `ttype_index`.
| -rw-r--r-- | library/std/src/personality/dwarf/eh.rs | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/library/std/src/personality/dwarf/eh.rs b/library/std/src/personality/dwarf/eh.rs index a783e187004..87585a8fcd0 100644 --- a/library/std/src/personality/dwarf/eh.rs +++ b/library/std/src/personality/dwarf/eh.rs @@ -84,7 +84,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding)?; let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding)?; let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding)?; - let cs_action = reader.read_uleb128(); + let cs_action_entry = reader.read_uleb128(); // Callsite table is sorted by cs_start, so if we've passed the ip, we // may stop searching. if ip < func_start + cs_start { @@ -95,7 +95,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result return Ok(EHAction::None); } else { let lpad = lpad_base + cs_lpad; - return Ok(interpret_cs_action(cs_action, lpad)); + return Ok(interpret_cs_action(action_table as *mut u8, cs_action_entry, lpad)); } } } @@ -113,26 +113,39 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result let mut idx = ip; loop { let cs_lpad = reader.read_uleb128(); - let cs_action = reader.read_uleb128(); + let cs_action_entry = reader.read_uleb128(); idx -= 1; if idx == 0 { // Can never have null landing pad for sjlj -- that would have // been indicated by a -1 call site index. let lpad = (cs_lpad + 1) as usize; - return Ok(interpret_cs_action(cs_action, lpad)); + return Ok(interpret_cs_action(action_table as *mut u8, cs_action_entry, lpad)); } } } } -fn interpret_cs_action(cs_action: u64, lpad: usize) -> EHAction { - if cs_action == 0 { - // If cs_action is 0 then this is a cleanup (Drop::drop). We run these +unsafe fn interpret_cs_action( + action_table: *mut u8, + cs_action_entry: u64, + lpad: usize, +) -> EHAction { + if cs_action_entry == 0 { + // If cs_action_entry is 0 then this is a cleanup (Drop::drop). We run these // for both Rust panics and foreign exceptions. EHAction::Cleanup(lpad) } else { - // Stop unwinding Rust panics at catch_unwind. - EHAction::Catch(lpad) + // If lpad != 0 and cs_action_entry != 0, we have to check ttype_index. + // If ttype_index == 0 under the condition, we take cleanup action. + let action_record = (action_table as *mut u8).offset(cs_action_entry as isize - 1); + let mut action_reader = DwarfReader::new(action_record); + let ttype_index = action_reader.read_sleb128(); + if ttype_index == 0 { + EHAction::Cleanup(lpad) + } else { + // Stop unwinding Rust panics at catch_unwind. + EHAction::Catch(lpad) + } } } |
