[2/2] symtab: fix up 64-bit ARM address which may contain tags
Commit Message
64-bit ARM addresses normally have bits 47 to 63 as either all 0 or
all 1. If tagging is used, bits 56 to 63 can vary, but the
interpretation of such values is as if the bits were all the same as
bit 55.
Such tagging is used for HWASAN and this affects the ELF symbol values
seen in shared libraries.
This commit changes the interpretation of 64-bit ARM symbol values by
unconditionally extending bit 55 into bits 56 to 63.
This fixes missing types for symbols in HWASAN-compiled libraries.
* src/abg-elf-helpers.cc: (architecture_is_arm64): Add helper.
* src/abg-elf-helpers.h: Likewise.
* src/abg-symtab-reader.cc: (get_symbol_value): Adjust 64-bit
ARM symbol values by extending bit 55 into bits 56 to 63.
Signed-off-by: Giuliano Procida <gprocida@google.com>
---
src/abg-elf-helpers.cc | 17 +++++++++++++++++
src/abg-elf-helpers.h | 3 +++
src/abg-symtab-reader.cc | 6 ++++++
3 files changed, 26 insertions(+)
Comments
Hello Giuliano,
Giuliano Procida <gprocida@google.com> a écrit:
> 64-bit ARM addresses normally have bits 47 to 63 as either all 0 or
> all 1. If tagging is used, bits 56 to 63 can vary, but the
> interpretation of such values is as if the bits were all the same as
> bit 55.
>
> Such tagging is used for HWASAN and this affects the ELF symbol values
> seen in shared libraries.
>
> This commit changes the interpretation of 64-bit ARM symbol values by
> unconditionally extending bit 55 into bits 56 to 63.
>
> This fixes missing types for symbols in HWASAN-compiled libraries.
>
> * src/abg-elf-helpers.cc: (architecture_is_arm64): Add helper.
> * src/abg-elf-helpers.h: Likewise.
> * src/abg-symtab-reader.cc: (get_symbol_value): Adjust 64-bit
> ARM symbol values by extending bit 55 into bits 56 to 63.
>
> Signed-off-by: Giuliano Procida <gprocida@google.com>
Applied to master, thanks!
[...]
Cheers,
@@ -900,6 +900,23 @@ architecture_is_arm32(Elf* elf_handle)
return (elf_header && elf_header->e_machine == EM_ARM);
}
+/// Test if the architecture of the current binary is arm64.
+///
+/// @param elf_handle the ELF handle to consider.
+///
+/// @return true iff the architecture of the current binary is arm64.
+bool
+architecture_is_arm64(Elf* elf_handle)
+{
+#ifdef HAVE_EM_AARCH64_MACRO
+ GElf_Ehdr eh_mem;
+ GElf_Ehdr* elf_header = gelf_getehdr(elf_handle, &eh_mem);
+ return (elf_header && elf_header->e_machine == EM_AARCH64);
+#else
+ return false;
+#endif
+}
+
/// Test if the endianness of the current binary is Big Endian.
///
/// https://en.wikipedia.org/wiki/Endianness.
@@ -147,6 +147,9 @@ architecture_is_ppc64(Elf* elf_handle);
bool
architecture_is_arm32(Elf* elf_handle);
+bool
+architecture_is_arm64(Elf* elf_handle);
+
bool
architecture_is_big_endian(Elf* elf_handle);
@@ -481,6 +481,7 @@ symtab::get_symbol_value(Elf* elf_handle,
const elf_symbol_sptr& symbol_sptr)
{
const bool is_arm32 = elf_helpers::architecture_is_arm32(elf_handle);
+ const bool is_arm64 = elf_helpers::architecture_is_arm64(elf_handle);
const bool is_ppc64 = elf_helpers::architecture_is_ppc64(elf_handle);
GElf_Addr symbol_value =
@@ -498,6 +499,11 @@ symtab::get_symbol_value(Elf* elf_handle,
update_function_entry_address_symbol_map(elf_handle, elf_symbol,
symbol_sptr);
}
+ if (is_arm64)
+ // Copy bit 55 over bits 56 to 63 which may be tag information.
+ symbol_value = symbol_value & (1ULL<<55)
+ ? symbol_value | (0xffULL<<56)
+ : symbol_value &~ (0xffULL<<56);
return symbol_value;
}