1
Fork 0

std: unsafe-wrap personality::dwarf::eh

In so doing, move the forbid up to the top of personality::dwarf
This commit is contained in:
Jubilee Young 2024-07-22 00:42:35 -07:00
parent 92c6c03805
commit e2137a2487
2 changed files with 61 additions and 53 deletions

View file

@ -70,45 +70,51 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
let func_start = context.func_start; let func_start = context.func_start;
let mut reader = DwarfReader::new(lsda); let mut reader = DwarfReader::new(lsda);
let lpad_base = unsafe {
let start_encoding = reader.read::<u8>(); let start_encoding = reader.read::<u8>();
// base address for landing pad offsets // base address for landing pad offsets
let lpad_base = if start_encoding != DW_EH_PE_omit { if start_encoding != DW_EH_PE_omit {
read_encoded_pointer(&mut reader, context, start_encoding)? read_encoded_pointer(&mut reader, context, start_encoding)?
} else { } else {
func_start func_start
}
}; };
let call_site_encoding = unsafe {
let ttype_encoding = reader.read::<u8>();
if ttype_encoding != DW_EH_PE_omit {
// Rust doesn't analyze exception types, so we don't care about the type table
reader.read_uleb128();
}
let ttype_encoding = reader.read::<u8>(); reader.read::<u8>()
if ttype_encoding != DW_EH_PE_omit { };
// Rust doesn't analyze exception types, so we don't care about the type table let action_table = unsafe {
reader.read_uleb128(); let call_site_table_length = reader.read_uleb128();
} reader.ptr.add(call_site_table_length as usize)
};
let call_site_encoding = reader.read::<u8>();
let call_site_table_length = reader.read_uleb128();
let action_table = reader.ptr.add(call_site_table_length as usize);
let ip = context.ip; let ip = context.ip;
if !USING_SJLJ_EXCEPTIONS { if !USING_SJLJ_EXCEPTIONS {
// read the callsite table // read the callsite table
while reader.ptr < action_table { while reader.ptr < action_table {
// these are offsets rather than pointers; unsafe {
let cs_start = read_encoded_offset(&mut reader, call_site_encoding)?; // these are offsets rather than pointers;
let cs_len = read_encoded_offset(&mut reader, call_site_encoding)?; let cs_start = read_encoded_offset(&mut reader, call_site_encoding)?;
let cs_lpad = read_encoded_offset(&mut reader, call_site_encoding)?; let cs_len = read_encoded_offset(&mut reader, call_site_encoding)?;
let cs_action_entry = reader.read_uleb128(); let cs_lpad = read_encoded_offset(&mut reader, call_site_encoding)?;
// Callsite table is sorted by cs_start, so if we've passed the ip, we let cs_action_entry = reader.read_uleb128();
// may stop searching. // Callsite table is sorted by cs_start, so if we've passed the ip, we
if ip < func_start.wrapping_add(cs_start) { // may stop searching.
break; if ip < func_start.wrapping_add(cs_start) {
} break;
if ip < func_start.wrapping_add(cs_start + cs_len) { }
if cs_lpad == 0 { if ip < func_start.wrapping_add(cs_start + cs_len) {
return Ok(EHAction::None); if cs_lpad == 0 {
} else { return Ok(EHAction::None);
let lpad = lpad_base.wrapping_add(cs_lpad); } else {
return Ok(interpret_cs_action(action_table, cs_action_entry, lpad)); let lpad = lpad_base.wrapping_add(cs_lpad);
return Ok(interpret_cs_action(action_table, cs_action_entry, lpad));
}
} }
} }
} }
@ -125,15 +131,15 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
} }
let mut idx = ip.addr(); let mut idx = ip.addr();
loop { loop {
let cs_lpad = reader.read_uleb128(); let cs_lpad = unsafe { reader.read_uleb128() };
let cs_action_entry = reader.read_uleb128(); let cs_action_entry = unsafe { reader.read_uleb128() };
idx -= 1; idx -= 1;
if idx == 0 { if idx == 0 {
// Can never have null landing pad for sjlj -- that would have // Can never have null landing pad for sjlj -- that would have
// been indicated by a -1 call site index. // been indicated by a -1 call site index.
// FIXME(strict provenance) // FIXME(strict provenance)
let lpad = ptr::with_exposed_provenance((cs_lpad + 1) as usize); let lpad = ptr::with_exposed_provenance((cs_lpad + 1) as usize);
return Ok(interpret_cs_action(action_table, cs_action_entry, lpad)); return Ok(unsafe { interpret_cs_action(action_table, cs_action_entry, lpad) });
} }
} }
} }
@ -151,9 +157,9 @@ unsafe fn interpret_cs_action(
} else { } else {
// If lpad != 0 and cs_action_entry != 0, we have to check ttype_index. // 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. // If ttype_index == 0 under the condition, we take cleanup action.
let action_record = action_table.offset(cs_action_entry as isize - 1); let action_record = unsafe { action_table.offset(cs_action_entry as isize - 1) };
let mut action_reader = DwarfReader::new(action_record); let mut action_reader = DwarfReader::new(action_record);
let ttype_index = action_reader.read_sleb128(); let ttype_index = unsafe { action_reader.read_sleb128() };
if ttype_index == 0 { if ttype_index == 0 {
EHAction::Cleanup(lpad) EHAction::Cleanup(lpad)
} else if ttype_index > 0 { } else if ttype_index > 0 {
@ -186,18 +192,20 @@ unsafe fn read_encoded_offset(reader: &mut DwarfReader, encoding: u8) -> Result<
if encoding == DW_EH_PE_omit || encoding & 0xF0 != 0 { if encoding == DW_EH_PE_omit || encoding & 0xF0 != 0 {
return Err(()); return Err(());
} }
let result = match encoding & 0x0F { let result = unsafe {
// despite the name, LLVM also uses absptr for offsets instead of pointers match encoding & 0x0F {
DW_EH_PE_absptr => reader.read::<usize>(), // despite the name, LLVM also uses absptr for offsets instead of pointers
DW_EH_PE_uleb128 => reader.read_uleb128() as usize, DW_EH_PE_absptr => reader.read::<usize>(),
DW_EH_PE_udata2 => reader.read::<u16>() as usize, DW_EH_PE_uleb128 => reader.read_uleb128() as usize,
DW_EH_PE_udata4 => reader.read::<u32>() as usize, DW_EH_PE_udata2 => reader.read::<u16>() as usize,
DW_EH_PE_udata8 => reader.read::<u64>() as usize, DW_EH_PE_udata4 => reader.read::<u32>() as usize,
DW_EH_PE_sleb128 => reader.read_sleb128() as usize, DW_EH_PE_udata8 => reader.read::<u64>() as usize,
DW_EH_PE_sdata2 => reader.read::<i16>() as usize, DW_EH_PE_sleb128 => reader.read_sleb128() as usize,
DW_EH_PE_sdata4 => reader.read::<i32>() as usize, DW_EH_PE_sdata2 => reader.read::<i16>() as usize,
DW_EH_PE_sdata8 => reader.read::<i64>() as usize, DW_EH_PE_sdata4 => reader.read::<i32>() as usize,
_ => return Err(()), DW_EH_PE_sdata8 => reader.read::<i64>() as usize,
_ => return Err(()),
}
}; };
Ok(result) Ok(result)
} }
@ -250,14 +258,14 @@ unsafe fn read_encoded_pointer(
if encoding & 0x0F != DW_EH_PE_absptr { if encoding & 0x0F != DW_EH_PE_absptr {
return Err(()); return Err(());
} }
reader.read::<*const u8>() unsafe { reader.read::<*const u8>() }
} else { } else {
let offset = read_encoded_offset(reader, encoding & 0x0F)?; let offset = unsafe { read_encoded_offset(reader, encoding & 0x0F)? };
base_ptr.wrapping_add(offset) base_ptr.wrapping_add(offset)
}; };
if encoding & DW_EH_PE_indirect != 0 { if encoding & DW_EH_PE_indirect != 0 {
ptr = *(ptr.cast::<*const u8>()); ptr = unsafe { *(ptr.cast::<*const u8>()) };
} }
Ok(ptr) Ok(ptr)

View file

@ -5,6 +5,7 @@
// This module is used only by x86_64-pc-windows-gnu for now, but we // This module is used only by x86_64-pc-windows-gnu for now, but we
// are compiling it everywhere to avoid regressions. // are compiling it everywhere to avoid regressions.
#![allow(unused)] #![allow(unused)]
#![forbid(unsafe_op_in_unsafe_fn)]
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
@ -17,7 +18,6 @@ pub struct DwarfReader {
pub ptr: *const u8, pub ptr: *const u8,
} }
#[forbid(unsafe_op_in_unsafe_fn)]
impl DwarfReader { impl DwarfReader {
pub fn new(ptr: *const u8) -> DwarfReader { pub fn new(ptr: *const u8) -> DwarfReader {
DwarfReader { ptr } DwarfReader { ptr }