Merge "linker: simpler encoding for SHT_RELR sections."

This commit is contained in:
Treehugger Robot 2018-01-27 00:00:17 +00:00 committed by Gerrit Code Review
commit 2e2a8930e5
3 changed files with 33 additions and 21 deletions

View file

@ -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

View file

@ -2614,31 +2614,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<ElfW(Addr)*>(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<ElfW(Addr)>(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<ElfW(Addr)>(r_offset + load_bias);
ElfW(Addr) addend = *reinterpret_cast<ElfW(Addr)*>(reloc);
*reinterpret_cast<ElfW(Addr)*>(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;
}

View file

@ -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