Index: include/llvm/BinaryFormat/DynamicTags.def =================================================================== --- include/llvm/BinaryFormat/DynamicTags.def +++ include/llvm/BinaryFormat/DynamicTags.def @@ -65,6 +65,12 @@ DYNAMIC_TAG(SYMTAB_SHNDX, 34) // Address of the SHT_SYMTAB_SHNDX section. +// Experimental support for SHT_RELR sections. For details, see proposal +// at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg +DYNAMIC_TAG(RELRSZ, 35) // Size of Relr relocation table. +DYNAMIC_TAG(RELR, 36) // Address of relocation table (Relr entries). +DYNAMIC_TAG(RELRENT, 37) // Size of a Relr relocation entry. + DYNAMIC_TAG_MARKER(LOOS, 0x60000000) // Start of environment specific tags. DYNAMIC_TAG_MARKER(HIOS, 0x6FFFFFFF) // End of environment specific tags. DYNAMIC_TAG_MARKER(LOPROC, 0x70000000) // Start of processor specific tags. @@ -77,11 +83,19 @@ DYNAMIC_TAG(ANDROID_RELA, 0x60000011) DYNAMIC_TAG(ANDROID_RELASZ, 0x60000012) +// Android's experimental support for SHT_RELR sections. +// https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#253 +DYNAMIC_TAG(ANDROID_RELR, 0x6FFFE000) // Address of relocation table (Relr entries). +DYNAMIC_TAG(ANDROID_RELRSZ, 0x6FFFE001) // Size of Relr relocation table. +DYNAMIC_TAG(ANDROID_RELRENT, 0x6FFFE003) // Size of a Relr relocation entry. +DYNAMIC_TAG(ANDROID_RELRCOUNT, 0x6FFFE005) // ELF32_Relr count. + DYNAMIC_TAG(GNU_HASH, 0x6FFFFEF5) // Reference to the GNU hash table. DYNAMIC_TAG(TLSDESC_PLT, 0x6FFFFEF6) // Location of PLT entry for TLS // descriptor resolver calls. DYNAMIC_TAG(TLSDESC_GOT, 0x6FFFFEF7) // Location of GOT entry used by TLS // descriptor resolver PLT entry. +DYNAMIC_TAG(RELRCOUNT, 0x6FFFFFF8) // ELF32_Relr count. DYNAMIC_TAG(RELACOUNT, 0x6FFFFFF9) // ELF32_Rela count. DYNAMIC_TAG(RELCOUNT, 0x6FFFFFFA) // ELF32_Rel count. Index: include/llvm/BinaryFormat/ELF.h =================================================================== --- include/llvm/BinaryFormat/ELF.h +++ include/llvm/BinaryFormat/ELF.h @@ -796,6 +796,9 @@ SHT_PREINIT_ARRAY = 16, // Pointers to pre-init functions. SHT_GROUP = 17, // Section group. SHT_SYMTAB_SHNDX = 18, // Indices for SHN_XINDEX entries. + // Experimental support for SHT_RELR sections. For details, see proposal + // at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg + SHT_RELR = 19, // Relocation entries; only offsets. SHT_LOOS = 0x60000000, // Lowest operating system-specific type. // Android packed relocation section types. // https://android.googlesource.com/platform/bionic/+/6f12bfece5dcc01325e0abba56a46b1bcf991c69/tools/relocation_packer/src/elf_file.cc#37 @@ -804,6 +807,9 @@ SHT_LLVM_ODRTAB = 0x6fff4c00, // LLVM ODR table. SHT_LLVM_LINKER_OPTIONS = 0x6fff4c01, // LLVM Linker Options. SHT_LLVM_CALL_GRAPH_PROFILE = 0x6fff4c02, // LLVM Call Graph Profile. + // Android's experimental support for SHT_RELR sections. + // https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512 + SHT_ANDROID_RELR = 0x6fffff00, // Relocation entries; only offsets. SHT_GNU_ATTRIBUTES = 0x6ffffff5, // Object attributes. SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table. SHT_GNU_verdef = 0x6ffffffd, // GNU version definitions. @@ -1067,6 +1073,11 @@ } }; +// Relocation entry without explicit addend or info (relative relocations only). +struct Elf32_Relr { + Elf32_Word r_data; // offset/bitmap for relative relocations +}; + // Relocation entry, without explicit addend. struct Elf64_Rel { Elf64_Addr r_offset; // Location (file byte offset, or program virtual addr). @@ -1100,6 +1111,11 @@ } }; +// Relocation entry without explicit addend or info (relative relocations only). +struct Elf64_Relr { + Elf64_Xword r_data; // offset/bitmap for relative relocations +}; + // Program header for ELF32. struct Elf32_Phdr { Elf32_Word p_type; // Type of segment Index: include/llvm/Object/ELF.h =================================================================== --- include/llvm/Object/ELF.h +++ include/llvm/Object/ELF.h @@ -60,6 +60,7 @@ using Elf_Phdr = typename ELFT::Phdr; using Elf_Rel = typename ELFT::Rel; using Elf_Rela = typename ELFT::Rela; + using Elf_Relr = typename ELFT::Relr; using Elf_Verdef = typename ELFT::Verdef; using Elf_Verdaux = typename ELFT::Verdaux; using Elf_Verneed = typename ELFT::Verneed; @@ -75,6 +76,7 @@ using Elf_Sym_Range = typename ELFT::SymRange; using Elf_Rel_Range = typename ELFT::RelRange; using Elf_Rela_Range = typename ELFT::RelaRange; + using Elf_Relr_Range = typename ELFT::RelrRange; using Elf_Phdr_Range = typename ELFT::PhdrRange; const uint8_t *base() const { @@ -143,6 +145,12 @@ return getSectionContentsAsArray(Sec); } + Expected relrs(const Elf_Shdr *Sec) const { + return getSectionContentsAsArray(Sec); + } + + Expected> decode_relrs(Elf_Relr_Range relrs) const; + Expected> android_relas(const Elf_Shdr *Sec) const; /// Iterate over program header table. Index: include/llvm/Object/ELFTypes.h =================================================================== --- include/llvm/Object/ELFTypes.h +++ include/llvm/Object/ELFTypes.h @@ -32,6 +32,7 @@ template struct Elf_Dyn_Impl; template struct Elf_Phdr_Impl; template struct Elf_Rel_Impl; +template struct Elf_Relr_Impl; template struct Elf_Verdef_Impl; template struct Elf_Verdaux_Impl; template struct Elf_Verneed_Impl; @@ -62,6 +63,7 @@ using Phdr = Elf_Phdr_Impl>; using Rel = Elf_Rel_Impl, false>; using Rela = Elf_Rel_Impl, true>; + using Relr = Elf_Relr_Impl>; using Verdef = Elf_Verdef_Impl>; using Verdaux = Elf_Verdaux_Impl>; using Verneed = Elf_Verneed_Impl>; @@ -79,6 +81,7 @@ using SymRange = ArrayRef; using RelRange = ArrayRef; using RelaRange = ArrayRef; + using RelrRange = ArrayRef; using PhdrRange = ArrayRef; using Half = packed; @@ -446,6 +449,18 @@ Elf_Sxword r_addend; // Compute value for relocatable field by adding this. }; +template +struct Elf_Relr_Impl> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) + Elf_Word r_data; // offset/bitmap for relative relocations +}; + +template +struct Elf_Relr_Impl> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) + Elf_Xword r_data; // offset/bitmap for relative relocations +}; + template struct Elf_Ehdr_Impl { LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) Index: lib/Object/ELF.cpp =================================================================== --- lib/Object/ELF.cpp +++ lib/Object/ELF.cpp @@ -202,8 +202,10 @@ STRINGIFY_ENUM_CASE(ELF, SHT_PREINIT_ARRAY); STRINGIFY_ENUM_CASE(ELF, SHT_GROUP); STRINGIFY_ENUM_CASE(ELF, SHT_SYMTAB_SHNDX); + STRINGIFY_ENUM_CASE(ELF, SHT_RELR); STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_REL); STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_RELA); + STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_RELR); STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_ODRTAB); STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_LINKER_OPTIONS); STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_CALL_GRAPH_PROFILE); @@ -217,6 +219,49 @@ } } +// Decode relocations in SHT_RELR section (experimental). +// Details of the encoding are described in this post: +// https://groups.google.com/d/msg/generic-abi/bX460iggiKg/Pi9aSwwABgAJ +template +Expected> +ELFFile::decode_relrs(Elf_Relr_Range relrs) const { + Elf_Rela Rela; + Rela.r_info = 0; + Rela.r_addend = 0; + std::vector Relocs; + size_t WordSize = sizeof(Elf_Addr); + + typename ELFT::uint Base = 0; + for (const Elf_Relr &R : relrs) { + typename ELFT::uint Entry = R.r_data; + if ((Entry&1) == 0) { + // Even entry: encodes the offset for next relocation. + Rela.r_offset = Entry; + Relocs.push_back(Rela); + // Set base offset for subsequent bitmap entries. + Base = Entry + WordSize; + continue; + } + + // Odd entry: encodes bitmap for relocations starting at base. + typename ELFT::uint Offset = Base; + while (Entry != 0) { + Entry >>= 1; + if ((Entry&1) != 0) { + Rela.r_offset = Offset; + Relocs.push_back(Rela); + } + 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 Relocs; +} + template Expected> ELFFile::android_relas(const Elf_Shdr *Sec) const { Index: lib/ObjectYAML/ELFYAML.cpp =================================================================== --- lib/ObjectYAML/ELFYAML.cpp +++ lib/ObjectYAML/ELFYAML.cpp @@ -436,9 +436,11 @@ ECase(SHT_PREINIT_ARRAY); ECase(SHT_GROUP); ECase(SHT_SYMTAB_SHNDX); + ECase(SHT_RELR); ECase(SHT_LOOS); ECase(SHT_ANDROID_REL); ECase(SHT_ANDROID_RELA); + ECase(SHT_ANDROID_RELR); ECase(SHT_LLVM_ODRTAB); ECase(SHT_LLVM_LINKER_OPTIONS); ECase(SHT_LLVM_CALL_GRAPH_PROFILE); Index: test/tools/llvm-readobj/Inputs/elf-relr-relocs1.s =================================================================== --- /dev/null +++ test/tools/llvm-readobj/Inputs/elf-relr-relocs1.s @@ -0,0 +1,5 @@ +.quad 0x0000000000010d60 // Initial offset +.quad 0x0000000000000103 // Continuation bitmap +.quad 0x0000000000020000 // New offset +.quad 0x00000000000f0501 // Continuation bitmap +.quad 0x000a700550400009 // Continuation bitmap Index: test/tools/llvm-readobj/Inputs/elf-relr-relocs2.s =================================================================== --- /dev/null +++ test/tools/llvm-readobj/Inputs/elf-relr-relocs2.s @@ -0,0 +1,5 @@ +.long 0x00010d60 // Initial offset +.long 0x00000103 // Continuation bitmap +.long 0x00020000 // New offset +.long 0x000f0501 // Continuation bitmap +.long 0x50400009 // Continuation bitmap Index: test/tools/llvm-readobj/elf-relr-relocs.test =================================================================== --- /dev/null +++ test/tools/llvm-readobj/elf-relr-relocs.test @@ -0,0 +1,122 @@ +# The binary blobs in this file were created like this: +# llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu Inputs/elf-relr-relocs1.s -o - | obj2yaml | grep Content: + +# RUN: yaml2obj -docnum 1 %s | llvm-readobj -elf-output-style=LLVM -relocations - | FileCheck --check-prefix=LLVM1 %s +# LLVM1: Section (1) .relr.dyn { +# LLVM1-NEXT: 0x10D60 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x10D68 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x10DA0 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x20000 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x20040 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x20050 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x20080 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x20088 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x20090 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x20098 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x20210 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x202A8 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x202D8 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x202E8 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x202F8 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x20308 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x20358 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x20360 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x20368 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x20380 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: 0x20390 R_X86_64_NONE - 0x0 +# LLVM1-NEXT: } + +# RUN: yaml2obj -docnum 1 %s | llvm-readobj -elf-output-style=GNU -relocations - | FileCheck --check-prefix=GNU1 %s +# GNU1: Relocation section '.relr.dyn' at offset 0x180 contains 21 entries: +# GNU1: 0000000000010d60 +# GNU1-NEXT: 0000000000010d68 +# GNU1-NEXT: 0000000000010da0 +# GNU1-NEXT: 0000000000020000 +# GNU1-NEXT: 0000000000020040 +# GNU1-NEXT: 0000000000020050 +# GNU1-NEXT: 0000000000020080 +# GNU1-NEXT: 0000000000020088 +# GNU1-NEXT: 0000000000020090 +# GNU1-NEXT: 0000000000020098 +# GNU1-NEXT: 0000000000020210 +# GNU1-NEXT: 00000000000202a8 +# GNU1-NEXT: 00000000000202d8 +# GNU1-NEXT: 00000000000202e8 +# GNU1-NEXT: 00000000000202f8 +# GNU1-NEXT: 0000000000020308 +# GNU1-NEXT: 0000000000020358 +# GNU1-NEXT: 0000000000020360 +# GNU1-NEXT: 0000000000020368 +# GNU1-NEXT: 0000000000020380 +# GNU1-NEXT: 0000000000020390 + +# elf-relr-relocs1.s +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 + Entry: 0x0000000000001000 +Sections: + - Name: .relr.dyn + Type: SHT_RELR + Flags: [ SHF_ALLOC ] + Address: 0x00000000000001C8 + Link: .symtab + AddressAlign: 0x0000000000000001 + Content: 600D0100000000000301000000000000000002000000000001050F00000000000900405005700A00 +... + +# RUN: yaml2obj -docnum 2 %s | llvm-readobj -elf-output-style=LLVM -relocations - | FileCheck --check-prefix=LLVM2 %s +# LLVM2: Section (1) .relr.dyn { +# LLVM2-NEXT: 0x10D60 R_386_NONE - 0x0 +# LLVM2-NEXT: 0x10D64 R_386_NONE - 0x0 +# LLVM2-NEXT: 0x10D80 R_386_NONE - 0x0 +# LLVM2-NEXT: 0x20000 R_386_NONE - 0x0 +# LLVM2-NEXT: 0x20020 R_386_NONE - 0x0 +# LLVM2-NEXT: 0x20028 R_386_NONE - 0x0 +# LLVM2-NEXT: 0x20040 R_386_NONE - 0x0 +# LLVM2-NEXT: 0x20044 R_386_NONE - 0x0 +# LLVM2-NEXT: 0x20048 R_386_NONE - 0x0 +# LLVM2-NEXT: 0x2004C R_386_NONE - 0x0 +# LLVM2-NEXT: 0x20088 R_386_NONE - 0x0 +# LLVM2-NEXT: 0x200D4 R_386_NONE - 0x0 +# LLVM2-NEXT: 0x200EC R_386_NONE - 0x0 +# LLVM2-NEXT: 0x200F4 R_386_NONE - 0x0 +# LLVM2-NEXT: } + +# RUN: yaml2obj -docnum 2 %s | llvm-readobj -elf-output-style=GNU -relocations - | FileCheck --check-prefix=GNU2 %s +# GNU2: Relocation section '.relr.dyn' at offset 0xfc contains 14 entries: +# GNU2: 00010d60 +# GNU2-NEXT: 00010d64 +# GNU2-NEXT: 00010d80 +# GNU2-NEXT: 00020000 +# GNU2-NEXT: 00020020 +# GNU2-NEXT: 00020028 +# GNU2-NEXT: 00020040 +# GNU2-NEXT: 00020044 +# GNU2-NEXT: 00020048 +# GNU2-NEXT: 0002004c +# GNU2-NEXT: 00020088 +# GNU2-NEXT: 000200d4 +# GNU2-NEXT: 000200ec +# GNU2-NEXT: 000200f4 + +# elf-relr-relocs2.s +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_386 + Entry: 0x00001000 +Sections: + - Name: .relr.dyn + Type: SHT_RELR + Flags: [ SHF_ALLOC ] + Address: 0x000001C8 + Link: .symtab + AddressAlign: 0x00000001 + Content: 600D0100030100000000020001050F0009004050 +... Index: tools/llvm-readobj/ELFDumper.cpp =================================================================== --- tools/llvm-readobj/ELFDumper.cpp +++ tools/llvm-readobj/ELFDumper.cpp @@ -85,8 +85,10 @@ using Elf_Dyn_Range = typename ELFT::DynRange; \ using Elf_Rel = typename ELFT::Rel; \ using Elf_Rela = typename ELFT::Rela; \ + using Elf_Relr = typename ELFT::Relr; \ using Elf_Rel_Range = typename ELFT::RelRange; \ using Elf_Rela_Range = typename ELFT::RelaRange; \ + using Elf_Relr_Range = typename ELFT::RelrRange; \ using Elf_Phdr = typename ELFT::Phdr; \ using Elf_Half = typename ELFT::Half; \ using Elf_Ehdr = typename ELFT::Ehdr; \ @@ -205,6 +207,7 @@ const ELFO *Obj; DynRegionInfo DynRelRegion; DynRegionInfo DynRelaRegion; + DynRegionInfo DynRelrRegion; DynRegionInfo DynPLTRelRegion; DynRegionInfo DynSymRegion; DynRegionInfo DynamicTable; @@ -256,6 +259,7 @@ Elf_Rel_Range dyn_rels() const; Elf_Rela_Range dyn_relas() const; + Elf_Relr_Range dyn_relrs() const; std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable, bool IsDynamic) const; void getSectionNameIndex(const Elf_Sym *Symbol, const Elf_Sym *FirstSym, @@ -270,6 +274,7 @@ StringRef getDynamicStringTable() const { return DynamicStringTable; } const DynRegionInfo &getDynRelRegion() const { return DynRelRegion; } const DynRegionInfo &getDynRelaRegion() const { return DynRelaRegion; } + const DynRegionInfo &getDynRelrRegion() const { return DynRelrRegion; } const DynRegionInfo &getDynPLTRelRegion() const { return DynPLTRelRegion; } const Elf_Hash *getHashTable() const { return HashTable; } const Elf_GnuHash *getGnuHashTable() const { return GnuHashTable; } @@ -388,13 +393,14 @@ } void printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym, uint32_t Sym, StringRef StrTable, uint32_t Bucket); + void printRelocHeader(unsigned SType); void printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, - const Elf_Rela &R, bool IsRela); + const Elf_Rela &R, unsigned SType); void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First, StringRef StrTable, bool IsDynamic) override; std::string getSymbolSectionNdx(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *FirstSym); - void printDynamicRelocation(const ELFO *Obj, Elf_Rela R, bool IsRela); + void printDynamicRelocation(const ELFO *Obj, Elf_Rela R, unsigned SType); bool checkTLSSections(const Elf_Phdr &Phdr, const Elf_Shdr &Sec); bool checkoffsets(const Elf_Phdr &Phdr, const Elf_Shdr &Sec); bool checkVMA(const Elf_Phdr &Phdr, const Elf_Shdr &Sec); @@ -1487,6 +1493,18 @@ case ELF::DT_RELENT: DynRelRegion.EntSize = Dyn.getVal(); break; + case ELF::DT_RELR: + case ELF::DT_ANDROID_RELR: + DynRelrRegion.Addr = toMappedAddr(Dyn.getPtr()); + break; + case ELF::DT_RELRSZ: + case ELF::DT_ANDROID_RELRSZ: + DynRelrRegion.Size = Dyn.getVal(); + break; + case ELF::DT_RELRENT: + case ELF::DT_ANDROID_RELRENT: + DynRelrRegion.EntSize = Dyn.getVal(); + break; case ELF::DT_PLTREL: if (Dyn.getVal() == DT_REL) DynPLTRelRegion.EntSize = sizeof(Elf_Rel); @@ -1520,6 +1538,11 @@ return DynRelaRegion.getAsArrayRef(); } +template +typename ELFDumper::Elf_Relr_Range ELFDumper::dyn_relrs() const { + return DynRelrRegion.getAsArrayRef(); +} + template void ELFDumper::printFileHeaders() { ELFDumperStyle->printFileHeaders(Obj); @@ -2569,7 +2592,7 @@ template void GNUStyle::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, - const Elf_Rela &R, bool IsRela) { + const Elf_Rela &R, unsigned SType) { std::string Offset, Info, Addend, Value; SmallString<32> RelocName; StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab)); @@ -2577,6 +2600,8 @@ const Elf_Sym *Sym = nullptr; unsigned Width = ELFT::Is64Bits ? 16 : 8; unsigned Bias = ELFT::Is64Bits ? 8 : 0; + bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA; + bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR; // First two fields are bit width dependent. The rest of them are after are // fixed width. @@ -2609,34 +2634,46 @@ Value = to_string(format_hex_no_prefix(Sym->getValue(), Width)); Fields[0].Str = Offset; - Fields[1].Str = Info; - Fields[2].Str = RelocName; - Fields[3].Str = Value; - Fields[4].Str = TargetName; + if (!IsRelr) { + Fields[1].Str = Info; + Fields[2].Str = RelocName; + Fields[3].Str = Value; + Fields[4].Str = TargetName; + } for (auto &field : Fields) printField(field); OS << Addend; OS << "\n"; } -static inline void printRelocHeader(raw_ostream &OS, bool Is64, bool IsRela) { - if (Is64) - OS << " Offset Info Type" - << " Symbol's Value Symbol's Name"; +template void GNUStyle::printRelocHeader(unsigned SType) { + bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA; + bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR; + if (ELFT::Is64Bits) + OS << " Offset"; else - OS << " Offset Info Type Sym. Value " - << "Symbol's Name"; - if (IsRela) - OS << (IsRela ? " + Addend" : ""); + OS << " Offset"; + if (!IsRelr) { + if (ELFT::Is64Bits) + OS << " Info Type" + << " Symbol's Value Symbol's Name"; + else + OS << " Info Type Sym. Value Symbol's Name"; + if (IsRela) + OS << " + Addend"; + } OS << "\n"; } template void GNUStyle::printRelocations(const ELFO *Obj) { bool HasRelocSections = false; for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { - if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA && + if (Sec.sh_type != ELF::SHT_REL && + Sec.sh_type != ELF::SHT_RELA && + Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_REL && - Sec.sh_type != ELF::SHT_ANDROID_RELA) + Sec.sh_type != ELF::SHT_ANDROID_RELA && + Sec.sh_type != ELF::SHT_ANDROID_RELR) continue; HasRelocSections = true; StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); @@ -2649,13 +2686,20 @@ AndroidRelas = unwrapOrError(Obj->android_relas(&Sec)); Entries = AndroidRelas.size(); } + std::vector RelrRelas; + if (Sec.sh_type == ELF::SHT_RELR || + Sec.sh_type == ELF::SHT_ANDROID_RELR) { + // .relr.dyn relative relocation section needs to be unpacked first + // to get the actual number of entries. + Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(&Sec)); + RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); + Entries = RelrRelas.size(); + } uintX_t Offset = Sec.sh_offset; OS << "\nRelocation section '" << Name << "' at offset 0x" << to_hexString(Offset, false) << " contains " << Entries << " entries:\n"; - printRelocHeader(OS, ELFT::Is64Bits, - Sec.sh_type == ELF::SHT_RELA || - Sec.sh_type == ELF::SHT_ANDROID_RELA); + printRelocHeader(Sec.sh_type); const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec.sh_link)); switch (Sec.sh_type) { case ELF::SHT_REL: @@ -2664,17 +2708,23 @@ Rela.r_offset = R.r_offset; Rela.r_info = R.r_info; Rela.r_addend = 0; - printRelocation(Obj, SymTab, Rela, false); + printRelocation(Obj, SymTab, Rela, Sec.sh_type); } break; case ELF::SHT_RELA: for (const auto &R : unwrapOrError(Obj->relas(&Sec))) - printRelocation(Obj, SymTab, R, true); + printRelocation(Obj, SymTab, R, Sec.sh_type); + break; + case ELF::SHT_RELR: + case ELF::SHT_ANDROID_RELR: + for (const auto &R : RelrRelas) { + printRelocation(Obj, SymTab, R, Sec.sh_type); + } break; case ELF::SHT_ANDROID_REL: case ELF::SHT_ANDROID_RELA: for (const auto &R : AndroidRelas) - printRelocation(Obj, SymTab, R, Sec.sh_type == ELF::SHT_ANDROID_RELA); + printRelocation(Obj, SymTab, R, Sec.sh_type); break; } } @@ -2752,6 +2802,9 @@ return "GROUP"; case SHT_SYMTAB_SHNDX: return "SYMTAB SECTION INDICES"; + case SHT_RELR: + case SHT_ANDROID_RELR: + return "RELR"; case SHT_LLVM_ODRTAB: return "LLVM_ODRTAB"; case SHT_LLVM_LINKER_OPTIONS: @@ -3212,11 +3265,13 @@ template void GNUStyle::printDynamicRelocation(const ELFO *Obj, Elf_Rela R, - bool IsRela) { + unsigned SType) { SmallString<32> RelocName; StringRef SymbolName; unsigned Width = ELFT::Is64Bits ? 16 : 8; unsigned Bias = ELFT::Is64Bits ? 8 : 0; + bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA; + bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR; // First two fields are bit width dependent. The rest of them are after are // fixed width. Field Fields[5] = {0, 10 + Bias, 19 + 2 * Bias, 42 + 2 * Bias, 53 + 2 * Bias}; @@ -3246,10 +3301,12 @@ Fields[0].Str = Offset; - Fields[1].Str = Info; - Fields[2].Str = RelocName.c_str(); - Fields[3].Str = Value; - Fields[4].Str = SymbolName; + if (!IsRelr) { + Fields[1].Str = Info; + Fields[2].Str = RelocName.c_str(); + Fields[3].Str = Value; + Fields[4].Str = SymbolName; + } for (auto &Field : Fields) printField(Field); OS << Addend; @@ -3260,28 +3317,41 @@ void GNUStyle::printDynamicRelocations(const ELFO *Obj) { const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion(); const DynRegionInfo &DynRelaRegion = this->dumper()->getDynRelaRegion(); + const DynRegionInfo &DynRelrRegion = this->dumper()->getDynRelrRegion(); const DynRegionInfo &DynPLTRelRegion = this->dumper()->getDynPLTRelRegion(); if (DynRelaRegion.Size > 0) { OS << "\n'RELA' relocation section at offset " << format_hex(reinterpret_cast(DynRelaRegion.Addr) - Obj->base(), 1) << " contains " << DynRelaRegion.Size << " bytes:\n"; - printRelocHeader(OS, ELFT::Is64Bits, true); + printRelocHeader(ELF::SHT_RELA); for (const Elf_Rela &Rela : this->dumper()->dyn_relas()) - printDynamicRelocation(Obj, Rela, true); + printDynamicRelocation(Obj, Rela, ELF::SHT_RELA); } if (DynRelRegion.Size > 0) { OS << "\n'REL' relocation section at offset " << format_hex(reinterpret_cast(DynRelRegion.Addr) - Obj->base(), 1) << " contains " << DynRelRegion.Size << " bytes:\n"; - printRelocHeader(OS, ELFT::Is64Bits, false); + printRelocHeader(ELF::SHT_REL); for (const Elf_Rel &Rel : this->dumper()->dyn_rels()) { Elf_Rela Rela; Rela.r_offset = Rel.r_offset; Rela.r_info = Rel.r_info; Rela.r_addend = 0; - printDynamicRelocation(Obj, Rela, false); + printDynamicRelocation(Obj, Rela, ELF::SHT_REL); + } + } + if (DynRelrRegion.Size > 0) { + OS << "\n'RELR' relocation section at offset " + << format_hex(reinterpret_cast(DynRelrRegion.Addr) - + Obj->base(), + 1) << " contains " << DynRelrRegion.Size << " bytes:\n"; + printRelocHeader(ELF::SHT_RELR); + Elf_Relr_Range Relrs = this->dumper()->dyn_relrs(); + std::vector RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); + for (const Elf_Rela &Rela : RelrRelas) { + printDynamicRelocation(Obj, Rela, ELF::SHT_RELR); } } if (DynPLTRelRegion.Size) { @@ -3291,17 +3361,17 @@ 1) << " contains " << DynPLTRelRegion.Size << " bytes:\n"; } if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) { - printRelocHeader(OS, ELFT::Is64Bits, true); + printRelocHeader(ELF::SHT_RELA); for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef()) - printDynamicRelocation(Obj, Rela, true); + printDynamicRelocation(Obj, Rela, ELF::SHT_RELA); } else { - printRelocHeader(OS, ELFT::Is64Bits, false); + printRelocHeader(ELF::SHT_REL); for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef()) { Elf_Rela Rela; Rela.r_offset = Rel.r_offset; Rela.r_info = Rel.r_info; Rela.r_addend = 0; - printDynamicRelocation(Obj, Rela, false); + printDynamicRelocation(Obj, Rela, ELF::SHT_REL); } } } @@ -3916,9 +3986,12 @@ for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { ++SectionNumber; - if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA && + if (Sec.sh_type != ELF::SHT_REL && + Sec.sh_type != ELF::SHT_RELA && + Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_REL && - Sec.sh_type != ELF::SHT_ANDROID_RELA) + Sec.sh_type != ELF::SHT_ANDROID_RELA && + Sec.sh_type != ELF::SHT_ANDROID_RELR) continue; StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); @@ -3951,6 +4024,15 @@ for (const Elf_Rela &R : unwrapOrError(Obj->relas(Sec))) printRelocation(Obj, R, SymTab); break; + case ELF::SHT_RELR: + case ELF::SHT_ANDROID_RELR: { + Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(Sec)); + std::vector RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); + for (const Elf_Rela &R : RelrRelas) { + printRelocation(Obj, R, SymTab); + } + break; + } case ELF::SHT_ANDROID_REL: case ELF::SHT_ANDROID_RELA: for (const Elf_Rela &R : unwrapOrError(Obj->android_relas(Sec))) @@ -4131,6 +4213,7 @@ void LLVMStyle::printDynamicRelocations(const ELFO *Obj) { const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion(); const DynRegionInfo &DynRelaRegion = this->dumper()->getDynRelaRegion(); + const DynRegionInfo &DynRelrRegion = this->dumper()->getDynRelrRegion(); const DynRegionInfo &DynPLTRelRegion = this->dumper()->getDynPLTRelRegion(); if (DynRelRegion.Size && DynRelaRegion.Size) report_fatal_error("There are both REL and RELA dynamic relocations"); @@ -4147,6 +4230,13 @@ Rela.r_addend = 0; printDynamicRelocation(Obj, Rela); } + if (DynRelrRegion.Size > 0) { + Elf_Relr_Range Relrs = this->dumper()->dyn_relrs(); + std::vector RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); + for (const Elf_Rela &Rela : RelrRelas) { + printDynamicRelocation(Obj, Rela); + } + } if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef()) printDynamicRelocation(Obj, Rela); Index: tools/yaml2obj/yaml2elf.cpp =================================================================== --- tools/yaml2obj/yaml2elf.cpp +++ tools/yaml2obj/yaml2elf.cpp @@ -114,6 +114,7 @@ typedef typename ELFT::Sym Elf_Sym; typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rela Elf_Rela; + typedef typename ELFT::Relr Elf_Relr; enum class SymtabType { Static, Dynamic }; @@ -459,7 +460,10 @@ Section.Content.writeAsBinary(OS); for (auto i = Section.Content.binary_size(); i < Section.Size; ++i) OS.write(0); - SHeader.sh_entsize = 0; + if (Section.Type == llvm::ELF::SHT_RELR) + SHeader.sh_entsize = sizeof(Elf_Relr); + else + SHeader.sh_entsize = 0; SHeader.sh_size = Section.Size; }