From f16b65932bb7adb1568a3a1e11ffa750d18e30ae Mon Sep 17 00:00:00 2001 From: Rahul Chaudhry Date: Thu, 25 Jan 2018 15:34:15 -0800 Subject: [PATCH] linker: simpler encoding for SHT_RELR sections. This change modifies the encoding used in SHT_RELR sections to a simpler version that gives better results. This encoding was suggested by Andrew Grieve and is described in this post on generic-abi@googlegroups.com: https://groups.google.com/d/msg/generic-abi/bX460iggiKg/Pi9aSwwABgAJ Bug: None Test: Built image for marlin, flashed on device, ran arm and aarch64 binaries containing '.relr.dyn' sections using the new encoding. Change-Id: I266affe0fbad91dc375995985a221cb02499447b --- libc/include/elf.h | 6 +----- linker/linker.cpp | 47 ++++++++++++++++++++++++++++-------------- linker/linker_soinfo.h | 1 + 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/libc/include/elf.h b/libc/include/elf.h index bda11f577..a8d62db66 100644 --- a/libc/include/elf.h +++ b/libc/include/elf.h @@ -194,13 +194,9 @@ typedef struct { Elf64_Word vna_next; } Elf64_Vernaux; -/* Relocation table entry for relative (in section of type SHT_RELR). */ +/* Relocation table entry for relative (in section of type SHT_RELR). */ typedef Elf32_Word Elf32_Relr; typedef Elf64_Xword Elf64_Relr; -#define ELF32_R_JUMP(val) ((val) >> 24) -#define ELF32_R_BITS(val) ((val) & 0xffffff) -#define ELF64_R_JUMP(val) ((val) >> 56) -#define ELF64_R_BITS(val) ((val) & 0xffffffffffffff) /* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html */ #define DF_ORIGIN 0x00000001 diff --git a/linker/linker.cpp b/linker/linker.cpp index 05efc5500..748972144 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -2595,31 +2595,46 @@ bool soinfo::lookup_version_info(const VersionTracker& version_tracker, ElfW(Wor return true; } +void soinfo::apply_relr_reloc(ElfW(Addr) offset) { + ElfW(Addr) address = offset + load_bias; + *reinterpret_cast(address) += load_bias; +} + // Process relocations in SHT_RELR section (experimental). -// See the original proposal for details of the encoding: -// - https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg +// Details of the encoding are described in this post: +// https://groups.google.com/d/msg/generic-abi/bX460iggiKg/Pi9aSwwABgAJ bool soinfo::relocate_relr() { ElfW(Relr)* begin = relr_; ElfW(Relr)* end = relr_ + relr_count_; + constexpr size_t wordsize = sizeof(ElfW(Addr)); - ElfW(Addr) offset = 0; + ElfW(Addr) base = 0; for (ElfW(Relr)* current = begin; current < end; ++current) { - ElfW(Addr) jump = ELFW(R_JUMP)(*current); - ElfW(Addr) bits = ELFW(R_BITS)(*current); - offset += jump * sizeof(ElfW(Addr)); - if (jump == 0) { - ++current; - offset = *current; + ElfW(Relr) entry = *current; + ElfW(Addr) offset; + + if ((entry&1) == 0) { + // Even entry: encodes the offset for next relocation. + offset = static_cast(entry); + apply_relr_reloc(offset); + // Set base offset for subsequent bitmap entries. + base = offset + wordsize; + continue; } - ElfW(Addr) r_offset = offset; - for (; bits != 0; bits >>= 1) { - if ((bits&1) != 0) { - ElfW(Addr) reloc = static_cast(r_offset + load_bias); - ElfW(Addr) addend = *reinterpret_cast(reloc); - *reinterpret_cast(reloc) = (load_bias + addend); + + // Odd entry: encodes bitmap for relocations starting at base. + offset = base; + while (entry != 0) { + entry >>= 1; + if ((entry&1) != 0) { + apply_relr_reloc(offset); } - r_offset += sizeof(ElfW(Addr)); + offset += wordsize; } + + // Advance base offset by 63 words for 64-bit platforms, + // or 31 words for 32-bit platforms. + base += (8*wordsize - 1) * wordsize; } return true; } diff --git a/linker/linker_soinfo.h b/linker/linker_soinfo.h index cb607a904..447c7c39c 100644 --- a/linker/linker_soinfo.h +++ b/linker/linker_soinfo.h @@ -310,6 +310,7 @@ struct soinfo { bool relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator, const soinfo_list_t& global_group, const soinfo_list_t& local_group); bool relocate_relr(); + void apply_relr_reloc(ElfW(Addr) offset); private: // This part of the structure is only available