summaryrefslogtreecommitdiffstats
path: root/library/std/src/sys/personality/dwarf
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /library/std/src/sys/personality/dwarf
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/std/src/sys/personality/dwarf')
-rw-r--r--library/std/src/sys/personality/dwarf/eh.rs131
1 files changed, 90 insertions, 41 deletions
diff --git a/library/std/src/sys/personality/dwarf/eh.rs b/library/std/src/sys/personality/dwarf/eh.rs
index 79624703a..a78084de0 100644
--- a/library/std/src/sys/personality/dwarf/eh.rs
+++ b/library/std/src/sys/personality/dwarf/eh.rs
@@ -1,6 +1,7 @@
//! Parsing of GCC-style Language-Specific Data Area (LSDA)
//! For details see:
//! * <https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html>
+//! * <https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html>
//! * <https://itanium-cxx-abi.github.io/cxx-abi/exceptions.pdf>
//! * <https://www.airs.com/blog/archives/460>
//! * <https://www.airs.com/blog/archives/464>
@@ -37,17 +38,19 @@ pub const DW_EH_PE_indirect: u8 = 0x80;
#[derive(Copy, Clone)]
pub struct EHContext<'a> {
- pub ip: usize, // Current instruction pointer
- pub func_start: usize, // Address of the current function
- pub get_text_start: &'a dyn Fn() -> usize, // Get address of the code section
- pub get_data_start: &'a dyn Fn() -> usize, // Get address of the data section
+ pub ip: *const u8, // Current instruction pointer
+ pub func_start: *const u8, // Pointer to the current function
+ pub get_text_start: &'a dyn Fn() -> *const u8, // Get pointer to the code section
+ pub get_data_start: &'a dyn Fn() -> *const u8, // Get pointer to the data section
}
+/// Landing pad.
+type LPad = *const u8;
pub enum EHAction {
None,
- Cleanup(usize),
- Catch(usize),
- Filter(usize),
+ Cleanup(LPad),
+ Catch(LPad),
+ Filter(LPad),
Terminate,
}
@@ -81,22 +84,24 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
let ip = context.ip;
if !USING_SJLJ_EXCEPTIONS {
+ // read the callsite table
while reader.ptr < action_table {
- 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)?;
+ // these are offsets rather than pointers;
+ let cs_start = read_encoded_offset(&mut reader, call_site_encoding)?;
+ let cs_len = read_encoded_offset(&mut reader, call_site_encoding)?;
+ let cs_lpad = read_encoded_offset(&mut reader, call_site_encoding)?;
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 {
+ if ip < func_start.wrapping_add(cs_start) {
break;
}
- if ip < func_start + cs_start + cs_len {
+ if ip < func_start.wrapping_add(cs_start + cs_len) {
if cs_lpad == 0 {
return Ok(EHAction::None);
} else {
- let lpad = lpad_base + cs_lpad;
- return Ok(interpret_cs_action(action_table as *mut u8, cs_action_entry, lpad));
+ let lpad = lpad_base.wrapping_add(cs_lpad);
+ return Ok(interpret_cs_action(action_table, cs_action_entry, lpad));
}
}
}
@@ -106,12 +111,12 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
// SjLj version:
// The "IP" is an index into the call-site table, with two exceptions:
// -1 means 'no-action', and 0 means 'terminate'.
- match ip as isize {
+ match ip.addr() as isize {
-1 => return Ok(EHAction::None),
0 => return Ok(EHAction::Terminate),
_ => (),
}
- let mut idx = ip;
+ let mut idx = ip.addr();
loop {
let cs_lpad = reader.read_uleb128();
let cs_action_entry = reader.read_uleb128();
@@ -119,17 +124,18 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
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(action_table as *mut u8, cs_action_entry, lpad));
+ // FIXME(strict provenance)
+ let lpad = ptr::from_exposed_addr((cs_lpad + 1) as usize);
+ return Ok(interpret_cs_action(action_table, cs_action_entry, lpad));
}
}
}
}
unsafe fn interpret_cs_action(
- action_table: *mut u8,
+ action_table: *const u8,
cs_action_entry: u64,
- lpad: usize,
+ lpad: LPad,
) -> EHAction {
if cs_action_entry == 0 {
// If cs_action_entry is 0 then this is a cleanup (Drop::drop). We run these
@@ -138,7 +144,7 @@ unsafe fn interpret_cs_action(
} else {
// 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 action_record = action_table.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 {
@@ -157,22 +163,24 @@ fn round_up(unrounded: usize, align: usize) -> Result<usize, ()> {
if align.is_power_of_two() { Ok((unrounded + align - 1) & !(align - 1)) } else { Err(()) }
}
-unsafe fn read_encoded_pointer(
- reader: &mut DwarfReader,
- context: &EHContext<'_>,
- encoding: u8,
-) -> Result<usize, ()> {
- if encoding == DW_EH_PE_omit {
+/// Read a offset (`usize`) from `reader` whose encoding is described by `encoding`.
+///
+/// `encoding` must be a [DWARF Exception Header Encoding as described by the LSB spec][LSB-dwarf-ext].
+/// In addition the upper ("application") part must be zero.
+///
+/// # Errors
+/// Returns `Err` if `encoding`
+/// * is not a valid DWARF Exception Header Encoding,
+/// * is `DW_EH_PE_omit`, or
+/// * has a non-zero application part.
+///
+/// [LSB-dwarf-ext]: https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html
+unsafe fn read_encoded_offset(reader: &mut DwarfReader, encoding: u8) -> Result<usize, ()> {
+ if encoding == DW_EH_PE_omit || encoding & 0xF0 != 0 {
return Err(());
}
-
- // DW_EH_PE_aligned implies it's an absolute pointer value
- if encoding == DW_EH_PE_aligned {
- reader.ptr = reader.ptr.with_addr(round_up(reader.ptr.addr(), mem::size_of::<usize>())?);
- return Ok(reader.read::<usize>());
- }
-
- let mut result = match encoding & 0x0F {
+ let result = match encoding & 0x0F {
+ // despite the name, LLVM also uses absptr for offsets instead of pointers
DW_EH_PE_absptr => reader.read::<usize>(),
DW_EH_PE_uleb128 => reader.read_uleb128() as usize,
DW_EH_PE_udata2 => reader.read::<u16>() as usize,
@@ -184,25 +192,66 @@ unsafe fn read_encoded_pointer(
DW_EH_PE_sdata8 => reader.read::<i64>() as usize,
_ => return Err(()),
};
+ Ok(result)
+}
+
+/// Read a pointer from `reader` whose encoding is described by `encoding`.
+///
+/// `encoding` must be a [DWARF Exception Header Encoding as described by the LSB spec][LSB-dwarf-ext].
+///
+/// # Errors
+/// Returns `Err` if `encoding`
+/// * is not a valid DWARF Exception Header Encoding,
+/// * is `DW_EH_PE_omit`, or
+/// * combines `DW_EH_PE_absptr` or `DW_EH_PE_aligned` application part with an integer encoding
+/// (not `DW_EH_PE_absptr`) in the value format part.
+///
+/// [LSB-dwarf-ext]: https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html
+unsafe fn read_encoded_pointer(
+ reader: &mut DwarfReader,
+ context: &EHContext<'_>,
+ encoding: u8,
+) -> Result<*const u8, ()> {
+ if encoding == DW_EH_PE_omit {
+ return Err(());
+ }
- result += match encoding & 0x70 {
- DW_EH_PE_absptr => 0,
+ let base_ptr = match encoding & 0x70 {
+ DW_EH_PE_absptr => core::ptr::null(),
// relative to address of the encoded value, despite the name
- DW_EH_PE_pcrel => reader.ptr.expose_addr(),
+ DW_EH_PE_pcrel => reader.ptr,
DW_EH_PE_funcrel => {
- if context.func_start == 0 {
+ if context.func_start.is_null() {
return Err(());
}
context.func_start
}
DW_EH_PE_textrel => (*context.get_text_start)(),
DW_EH_PE_datarel => (*context.get_data_start)(),
+ // aligned means the value is aligned to the size of a pointer
+ DW_EH_PE_aligned => {
+ reader.ptr =
+ reader.ptr.with_addr(round_up(reader.ptr.addr(), mem::size_of::<*const u8>())?);
+ core::ptr::null()
+ }
_ => return Err(()),
};
+ let mut ptr = if base_ptr.is_null() {
+ // any value encoding other than absptr would be nonsensical here;
+ // there would be no source of pointer provenance
+ if encoding & 0x0F != DW_EH_PE_absptr {
+ return Err(());
+ }
+ reader.read::<*const u8>()
+ } else {
+ let offset = read_encoded_offset(reader, encoding & 0x0F)?;
+ base_ptr.wrapping_add(offset)
+ };
+
if encoding & DW_EH_PE_indirect != 0 {
- result = *ptr::from_exposed_addr::<usize>(result);
+ ptr = *(ptr.cast::<*const u8>());
}
- Ok(result)
+ Ok(ptr)
}