Skip to content

Commit 3f21b81

Browse files
author
Yuki Okushi
authored
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`.
2 parents fa8f77a + 93ef4b3 commit 3f21b81

File tree

1 file changed

+22
-9
lines changed
  • library/std/src/personality/dwarf

1 file changed

+22
-9
lines changed

library/std/src/personality/dwarf/eh.rs

+22-9
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
8484
let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding)?;
8585
let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding)?;
8686
let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding)?;
87-
let cs_action = reader.read_uleb128();
87+
let cs_action_entry = reader.read_uleb128();
8888
// Callsite table is sorted by cs_start, so if we've passed the ip, we
8989
// may stop searching.
9090
if ip < func_start + cs_start {
@@ -95,7 +95,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
9595
return Ok(EHAction::None);
9696
} else {
9797
let lpad = lpad_base + cs_lpad;
98-
return Ok(interpret_cs_action(cs_action, lpad));
98+
return Ok(interpret_cs_action(action_table as *mut u8, cs_action_entry, lpad));
9999
}
100100
}
101101
}
@@ -113,26 +113,39 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
113113
let mut idx = ip;
114114
loop {
115115
let cs_lpad = reader.read_uleb128();
116-
let cs_action = reader.read_uleb128();
116+
let cs_action_entry = reader.read_uleb128();
117117
idx -= 1;
118118
if idx == 0 {
119119
// Can never have null landing pad for sjlj -- that would have
120120
// been indicated by a -1 call site index.
121121
let lpad = (cs_lpad + 1) as usize;
122-
return Ok(interpret_cs_action(cs_action, lpad));
122+
return Ok(interpret_cs_action(action_table as *mut u8, cs_action_entry, lpad));
123123
}
124124
}
125125
}
126126
}
127127

128-
fn interpret_cs_action(cs_action: u64, lpad: usize) -> EHAction {
129-
if cs_action == 0 {
130-
// If cs_action is 0 then this is a cleanup (Drop::drop). We run these
128+
unsafe fn interpret_cs_action(
129+
action_table: *mut u8,
130+
cs_action_entry: u64,
131+
lpad: usize,
132+
) -> EHAction {
133+
if cs_action_entry == 0 {
134+
// If cs_action_entry is 0 then this is a cleanup (Drop::drop). We run these
131135
// for both Rust panics and foreign exceptions.
132136
EHAction::Cleanup(lpad)
133137
} else {
134-
// Stop unwinding Rust panics at catch_unwind.
135-
EHAction::Catch(lpad)
138+
// If lpad != 0 and cs_action_entry != 0, we have to check ttype_index.
139+
// If ttype_index == 0 under the condition, we take cleanup action.
140+
let action_record = (action_table as *mut u8).offset(cs_action_entry as isize - 1);
141+
let mut action_reader = DwarfReader::new(action_record);
142+
let ttype_index = action_reader.read_sleb128();
143+
if ttype_index == 0 {
144+
EHAction::Cleanup(lpad)
145+
} else {
146+
// Stop unwinding Rust panics at catch_unwind.
147+
EHAction::Catch(lpad)
148+
}
136149
}
137150
}
138151

0 commit comments

Comments
 (0)