Read DWARF type entries as TARGET2 values

Under the ARM EHABI, type information is encoded as a TARGET2 value,
rather than a DWARF pointer.

For the kernel ELF object, we have a ttype_encoding of DW_EH_PE_absptr,
which we combine with DW_EH_PE_pcrel when reading the type info.

For non-null pointers, this is equivalent to TARGET2 - we read a 32bit
value, and then use it as an offset from the current DWARF info. However,
null pointers should *not* apply an offset, and should instead return 0
directly.

An alternative fix here would be to change read_encoded_pointer_with_base
to skip adding base/original_ptr when reading 0. This is what GCC
does[^1], but feels a more dangerous change.

[^1]: 2a77afa0ee/libgcc/unwind-pe.h (L265)
This commit is contained in:
Jonathan Coates 2025-01-29 16:23:38 +00:00
parent 63157588bb
commit 1be126606d

View File

@ -75,17 +75,23 @@ unsafe fn get_ttype_entry(
ttype_base: usize,
ttype: *const u8,
) -> Result<Option<*const u8>, ()> {
if encoding != DW_EH_PE_absptr {
return Err(());
}
let i = (offset * size_of_encoded_value(encoding)) as isize;
read_encoded_pointer_with_base(
&mut DwarfReader::new(ttype.offset(-i)),
// the DW_EH_PE_pcrel is a hack.
// It seems that the default encoding is absolute, but we have to take reallocation into
// account. Unsure if we can fix this in the compiler setting or if this would be affected
// by updating the compiler
encoding | DW_EH_PE_pcrel,
ttype_base,
)
.map(|v| (v != ttype_base).then(|| v as *const u8))
// Read in a target2 value. See "Personality routine exception-handling table
// entries" in the ehabi32 spec, and the ARM_EHABI version of `get_shim_type_info`
// in LLVM's libcxxabi/src/cxa_personality.cpp.
let mut reader = DwarfReader::new(ttype.offset(-i));
let original_ptr = reader.ptr;
let offset = reader.read::<usize>();
if (offset == 0) {
Ok(None)
} else {
Ok(Some(original_ptr.add(offset)))
}
}
pub unsafe fn find_eh_action(