From 1be126606d8eb6e8bc07ac7fb87930ccaba72c55 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Wed, 29 Jan 2025 16:23:38 +0000 Subject: [PATCH] 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]: https://github.com/gcc-mirror/gcc/blob/2a77afa0ee41cb8a3664679dcd4545ccd1aa3b35/libgcc/unwind-pe.h#L265 --- src/libdwarf/src/eh.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/libdwarf/src/eh.rs b/src/libdwarf/src/eh.rs index aa79e7d..9cac2f3 100644 --- a/src/libdwarf/src/eh.rs +++ b/src/libdwarf/src/eh.rs @@ -75,17 +75,23 @@ unsafe fn get_ttype_entry( ttype_base: usize, ttype: *const u8, ) -> Result, ()> { + 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::(); + if (offset == 0) { + Ok(None) + } else { + Ok(Some(original_ptr.add(offset))) + } } pub unsafe fn find_eh_action(