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,6 +83,12 @@ 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(GNU_HASH, 0x6FFFFEF5) // Reference to the GNU hash table. DYNAMIC_TAG(TLSDESC_PLT, 0x6FFFFEF6) // Location of PLT entry for TLS // descriptor resolver calls. 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,9 @@ } }; +// Relocation entry without explicit addend or info (relative relocations only). +typedef Elf32_Word Elf32_Relr; // 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 +1109,9 @@ } }; +// Relocation entry without explicit addend or info (relative relocations only). +typedef Elf64_Xword Elf64_Relr; // 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 @@ -32,6 +32,7 @@ namespace object { StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type); +uint32_t getELFRelrRelocationType(uint32_t Machine); StringRef getELFSectionTypeName(uint32_t Machine, uint32_t Type); // Subclasses of ELFFile may need this for template instantiation @@ -60,6 +61,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 +77,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 { @@ -110,6 +113,7 @@ StringRef getRelocationTypeName(uint32_t Type) const; void getRelocationTypeName(uint32_t Type, SmallVectorImpl &Result) const; + uint32_t getRelrRelocationType() const; /// Get the symbol for a given relocation. Expected getRelocationSymbol(const Elf_Rel *Rel, @@ -143,6 +147,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. @@ -397,6 +407,11 @@ } } +template +uint32_t ELFFile::getRelrRelocationType() const { + return getELFRelrRelocationType(getHeader()->e_machine); +} + template Expected ELFFile::getRelocationSymbol(const Elf_Rel *Rel, Index: include/llvm/Object/ELFTypes.h =================================================================== --- include/llvm/Object/ELFTypes.h +++ include/llvm/Object/ELFTypes.h @@ -62,6 +62,7 @@ using Phdr = Elf_Phdr_Impl>; using Rel = Elf_Rel_Impl, false>; using Rela = Elf_Rel_Impl, true>; + using Relr = packed; using Verdef = Elf_Verdef_Impl>; using Verdaux = Elf_Verdaux_Impl>; using Verneed = Elf_Verneed_Impl>; @@ -79,6 +80,7 @@ using SymRange = ArrayRef; using RelRange = ArrayRef; using RelaRange = ArrayRef; + using RelrRange = ArrayRef; using PhdrRange = ArrayRef; using Half = packed; Index: lib/Object/ELF.cpp =================================================================== --- lib/Object/ELF.cpp +++ lib/Object/ELF.cpp @@ -154,6 +154,52 @@ #undef ELF_RELOC +uint32_t llvm::object::getELFRelrRelocationType(uint32_t Machine) { + switch (Machine) { + case ELF::EM_X86_64: + return ELF::R_X86_64_RELATIVE; + case ELF::EM_386: + case ELF::EM_IAMCU: + return ELF::R_386_RELATIVE; + case ELF::EM_MIPS: + break; + case ELF::EM_AARCH64: + return ELF::R_AARCH64_RELATIVE; + case ELF::EM_ARM: + return ELF::R_ARM_RELATIVE; + case ELF::EM_ARC_COMPACT: + case ELF::EM_ARC_COMPACT2: + return ELF::R_ARC_RELATIVE; + case ELF::EM_AVR: + break; + case ELF::EM_HEXAGON: + return ELF::R_HEX_RELATIVE; + case ELF::EM_LANAI: + break; + case ELF::EM_PPC: + break; + case ELF::EM_PPC64: + return ELF::R_PPC64_RELATIVE; + case ELF::EM_RISCV: + return ELF::R_RISCV_RELATIVE; + case ELF::EM_S390: + return ELF::R_390_RELATIVE; + case ELF::EM_SPARC: + case ELF::EM_SPARC32PLUS: + case ELF::EM_SPARCV9: + return ELF::R_SPARC_RELATIVE; + case ELF::EM_WEBASSEMBLY: + break; + case ELF::EM_AMDGPU: + break; + case ELF::EM_BPF: + break; + default: + break; + } + return 0; +} + StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) { switch (Machine) { case ELF::EM_ARM: @@ -202,8 +248,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 +265,58 @@ } } +// Decode relocations in SHT_RELR section. +// 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; + Rela.setType(getRelrRelocationType(), false); + std::vector Relocs; + + // Word type: uint32_t for Elf32, and uint64_t for Elf64. + typedef typename ELFT::uint Word; + + // Word size in number of bytes. + const size_t WordSize = sizeof(Word); + + // Number of bits used for the relocation offsets bitmap. + // These many relative relocations can be encoded in a single entry. + const size_t NBits = 8*WordSize - 1; + + Word Base = 0; + for (const Elf_Relr &R : relrs) { + Word Entry = R; + 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. + Word 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 NBits words. + Base += NBits * 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,172 @@ +# 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 \ +# RUN: | llvm-readobj -elf-output-style=LLVM -relocations - \ +# RUN: | FileCheck --check-prefix=LLVM1 %s +# LLVM1: Section (1) .relr.dyn { +# LLVM1-NEXT: 0x10D60 R_RELR_RELATIVE - 0x0 +# LLVM1-NEXT: 0x103 R_RELR_RELATIVE - 0x0 +# LLVM1-NEXT: 0x20000 R_RELR_RELATIVE - 0x0 +# LLVM1-NEXT: 0xF0501 R_RELR_RELATIVE - 0x0 +# LLVM1-NEXT: 0xA700550400009 R_RELR_RELATIVE - 0x0 +# LLVM1-NEXT: } + +# RUN: yaml2obj -docnum 1 %s \ +# RUN: | llvm-readobj -elf-output-style=LLVM -relocations -decode-relr - \ +# RUN: | FileCheck --check-prefix=DLLVM1 %s +# DLLVM1: Section (1) .relr.dyn { +# DLLVM1-NEXT: 0x10D60 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x10D68 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x10DA0 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x20000 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x20040 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x20050 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x20080 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x20088 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x20090 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x20098 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x20210 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x202A8 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x202D8 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x202E8 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x202F8 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x20308 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x20358 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x20360 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x20368 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x20380 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: 0x20390 R_X86_64_RELATIVE - 0x0 +# DLLVM1-NEXT: } + +# RUN: yaml2obj -docnum 1 %s \ +# RUN: | llvm-readobj -elf-output-style=GNU -relocations - \ +# RUN: | FileCheck --check-prefix=GNU1 %s +# GNU1: Relocation section '.relr.dyn' at offset 0x180 contains 5 entries: +# GNU1: 0000000000010d60 0000000000000000 R_RELR_RELATIVE +# GNU1-NEXT: 0000000000000103 0000000000000000 R_RELR_RELATIVE +# GNU1-NEXT: 0000000000020000 0000000000000000 R_RELR_RELATIVE +# GNU1-NEXT: 00000000000f0501 0000000000000000 R_RELR_RELATIVE +# GNU1-NEXT: 000a700550400009 0000000000000000 R_RELR_RELATIVE + +# RUN: yaml2obj -docnum 1 %s \ +# RUN: | llvm-readobj -elf-output-style=GNU -relocations -decode-relr - \ +# RUN: | FileCheck --check-prefix=DGNU1 %s +# DGNU1: Relocation section '.relr.dyn' at offset 0x180 contains 21 entries: +# DGNU1: 0000000000010d60 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 0000000000010d68 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 0000000000010da0 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 0000000000020000 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 0000000000020040 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 0000000000020050 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 0000000000020080 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 0000000000020088 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 0000000000020090 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 0000000000020098 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 0000000000020210 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 00000000000202a8 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 00000000000202d8 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 00000000000202e8 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 00000000000202f8 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 0000000000020308 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 0000000000020358 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 0000000000020360 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 0000000000020368 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 0000000000020380 0000000000000008 R_X86_64_RELATIVE +# DGNU1-NEXT: 0000000000020390 0000000000000008 R_X86_64_RELATIVE + +# 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 \ +# RUN: | llvm-readobj -elf-output-style=LLVM -relocations - \ +# RUN: | FileCheck --check-prefix=LLVM2 %s +# LLVM2: Section (1) .relr.dyn { +# LLVM2-NEXT: 0x10D60 R_RELR_RELATIVE - 0x0 +# LLVM2-NEXT: 0x103 R_RELR_RELATIVE - 0x0 +# LLVM2-NEXT: 0x20000 R_RELR_RELATIVE - 0x0 +# LLVM2-NEXT: 0xF0501 R_RELR_RELATIVE - 0x0 +# LLVM2-NEXT: 0x50400009 R_RELR_RELATIVE - 0x0 +# LLVM2-NEXT: } + +# RUN: yaml2obj -docnum 2 %s \ +# RUN: | llvm-readobj -elf-output-style=LLVM -relocations -decode-relr - \ +# RUN: | FileCheck --check-prefix=DLLVM2 %s +# DLLVM2: Section (1) .relr.dyn { +# DLLVM2-NEXT: 0x10D60 R_386_RELATIVE - 0x0 +# DLLVM2-NEXT: 0x10D64 R_386_RELATIVE - 0x0 +# DLLVM2-NEXT: 0x10D80 R_386_RELATIVE - 0x0 +# DLLVM2-NEXT: 0x20000 R_386_RELATIVE - 0x0 +# DLLVM2-NEXT: 0x20020 R_386_RELATIVE - 0x0 +# DLLVM2-NEXT: 0x20028 R_386_RELATIVE - 0x0 +# DLLVM2-NEXT: 0x20040 R_386_RELATIVE - 0x0 +# DLLVM2-NEXT: 0x20044 R_386_RELATIVE - 0x0 +# DLLVM2-NEXT: 0x20048 R_386_RELATIVE - 0x0 +# DLLVM2-NEXT: 0x2004C R_386_RELATIVE - 0x0 +# DLLVM2-NEXT: 0x20088 R_386_RELATIVE - 0x0 +# DLLVM2-NEXT: 0x200D4 R_386_RELATIVE - 0x0 +# DLLVM2-NEXT: 0x200EC R_386_RELATIVE - 0x0 +# DLLVM2-NEXT: 0x200F4 R_386_RELATIVE - 0x0 +# DLLVM2-NEXT: } + +# RUN: yaml2obj -docnum 2 %s \ +# RUN: | llvm-readobj -elf-output-style=GNU -relocations - \ +# RUN: | FileCheck --check-prefix=GNU2 %s +# GNU2: Relocation section '.relr.dyn' at offset 0xfc contains 5 entries: +# GNU2: 00010d60 00000000 R_RELR_RELATIVE +# GNU2-NEXT: 00000103 00000000 R_RELR_RELATIVE +# GNU2-NEXT: 00020000 00000000 R_RELR_RELATIVE +# GNU2-NEXT: 000f0501 00000000 R_RELR_RELATIVE +# GNU2-NEXT: 50400009 00000000 R_RELR_RELATIVE + +# RUN: yaml2obj -docnum 2 %s \ +# RUN: | llvm-readobj -elf-output-style=GNU -relocations -decode-relr - \ +# RUN: | FileCheck --check-prefix=DGNU2 %s +# DGNU2: Relocation section '.relr.dyn' at offset 0xfc contains 14 entries: +# DGNU2: 00010d60 00000008 R_386_RELATIVE +# DGNU2-NEXT: 00010d64 00000008 R_386_RELATIVE +# DGNU2-NEXT: 00010d80 00000008 R_386_RELATIVE +# DGNU2-NEXT: 00020000 00000008 R_386_RELATIVE +# DGNU2-NEXT: 00020020 00000008 R_386_RELATIVE +# DGNU2-NEXT: 00020028 00000008 R_386_RELATIVE +# DGNU2-NEXT: 00020040 00000008 R_386_RELATIVE +# DGNU2-NEXT: 00020044 00000008 R_386_RELATIVE +# DGNU2-NEXT: 00020048 00000008 R_386_RELATIVE +# DGNU2-NEXT: 0002004c 00000008 R_386_RELATIVE +# DGNU2-NEXT: 00020088 00000008 R_386_RELATIVE +# DGNU2-NEXT: 000200d4 00000008 R_386_RELATIVE +# DGNU2-NEXT: 000200ec 00000008 R_386_RELATIVE +# DGNU2-NEXT: 000200f4 00000008 R_386_RELATIVE + +# 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; \ @@ -206,6 +208,7 @@ const ELFO *Obj; DynRegionInfo DynRelRegion; DynRegionInfo DynRelaRegion; + DynRegionInfo DynRelrRegion; DynRegionInfo DynPLTRelRegion; DynRegionInfo DynSymRegion; DynRegionInfo DynamicTable; @@ -257,6 +260,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, @@ -271,6 +275,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; } @@ -392,13 +397,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); @@ -430,8 +436,9 @@ void printMipsPLT(const MipsGOTParser &Parser) override; private: - void printRelocation(const ELFO *Obj, Elf_Rela Rel, const Elf_Shdr *SymTab); - void printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel); + void printRelocation(const ELFO *Obj, Elf_Rela Rel, const Elf_Shdr *SymTab, + unsigned SType); + void printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel, unsigned SType); void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First, StringRef StrTable, bool IsDynamic) override; @@ -1492,6 +1499,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); @@ -1525,6 +1544,11 @@ return DynRelaRegion.getAsArrayRef(); } +template +typename ELFDumper::Elf_Relr_Range ELFDumper::dyn_relrs() const { + return DynRelrRegion.getAsArrayRef(); +} + template void ELFDumper::printFileHeaders() { ELFDumperStyle->printFileHeaders(Obj); @@ -2579,25 +2603,30 @@ 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)); StringRef TargetName; 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. Field Fields[5] = {0, 10 + Bias, 19 + 2 * Bias, 42 + 2 * Bias, 53 + 2 * Bias}; - Obj->getRelocationTypeName(R.getType(Obj->isMips64EL()), RelocName); + if (IsRelr && !opts::DecodeRelr) + RelocName = "R_RELR_RELATIVE"; + else + Obj->getRelocationTypeName(R.getType(Obj->isMips64EL()), RelocName); Sym = unwrapOrError(Obj->getRelocationSymbol(&R, SymTab)); if (Sym && Sym->getType() == ELF::STT_SECTION) { const Elf_Shdr *Sec = unwrapOrError( Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable())); TargetName = unwrapOrError(Obj->getSectionName(Sec)); } else if (Sym) { + StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab)); TargetName = unwrapOrError(Sym->getName(StrTable)); } @@ -2629,24 +2658,36 @@ OS << "\n"; } -static inline void printRelocHeader(raw_ostream &OS, bool Is64, bool IsRela) { - if (Is64) - OS << " Offset Info Type" +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 << " "; + else + OS << " "; + if (IsRelr && !opts::DecodeRelr) + OS << "Data "; + else + OS << "Offset"; + if (ELFT::Is64Bits) + OS << " Info Type" << " Symbol's Value Symbol's Name"; else - OS << " Offset Info Type Sym. Value " - << "Symbol's Name"; + OS << " Info Type Sym. Value Symbol's Name"; if (IsRela) - OS << (IsRela ? " + Addend" : ""); + 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)); @@ -2659,13 +2700,20 @@ AndroidRelas = unwrapOrError(Obj->android_relas(&Sec)); Entries = AndroidRelas.size(); } + std::vector RelrRelas; + if (opts::DecodeRelr && (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: @@ -2674,17 +2722,33 @@ 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: + if (opts::DecodeRelr) { + for (const auto &R : RelrRelas) { + printRelocation(Obj, SymTab, R, Sec.sh_type); + } + } else { + for (const auto &R : unwrapOrError(Obj->relrs(&Sec))) { + Elf_Rela Rela; + Rela.r_offset = R; + Rela.r_info = 0; + Rela.r_addend = 0; + printRelocation(Obj, SymTab, Rela, 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; } } @@ -2762,6 +2826,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: @@ -3252,18 +3319,23 @@ 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}; uint32_t SymIndex = R.getSymbol(Obj->isMips64EL()); const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex; - Obj->getRelocationTypeName(R.getType(Obj->isMips64EL()), RelocName); + if (IsRelr && !opts::DecodeRelr) + RelocName = "R_RELR_RELATIVE"; + else + Obj->getRelocationTypeName(R.getType(Obj->isMips64EL()), RelocName); SymbolName = unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable())); std::string Addend, Info, Offset, Value; @@ -3300,28 +3372,51 @@ 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(); + if (opts::DecodeRelr) { + std::vector RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); + for (const Elf_Rela &Rela : RelrRelas) { + printDynamicRelocation(Obj, Rela, ELF::SHT_RELR); + } + } else { + for (const Elf_Relr &Relr : Relrs) { + Elf_Rela Rela; + Rela.r_offset = Relr; + Rela.r_info = 0; + Rela.r_addend = 0; + printDynamicRelocation(Obj, Rela, ELF::SHT_RELR); + } } } if (DynPLTRelRegion.Size) { @@ -3331,17 +3426,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); } } } @@ -3956,9 +4051,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)); @@ -3984,26 +4082,50 @@ Rela.r_offset = R.r_offset; Rela.r_info = R.r_info; Rela.r_addend = 0; - printRelocation(Obj, Rela, SymTab); + printRelocation(Obj, Rela, SymTab, Sec->sh_type); } break; case ELF::SHT_RELA: for (const Elf_Rela &R : unwrapOrError(Obj->relas(Sec))) - printRelocation(Obj, R, SymTab); + printRelocation(Obj, R, SymTab, Sec->sh_type); break; + case ELF::SHT_RELR: + case ELF::SHT_ANDROID_RELR: { + Elf_Relr_Range Relrs = unwrapOrError(Obj->relrs(Sec)); + if (opts::DecodeRelr) { + std::vector RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); + for (const Elf_Rela &R : RelrRelas) { + printRelocation(Obj, R, SymTab, Sec->sh_type); + } + } else { + for (const Elf_Relr &R : Relrs) { + Elf_Rela Rela; + Rela.r_offset = R; + Rela.r_info = 0; + Rela.r_addend = 0; + printRelocation(Obj, Rela, SymTab, Sec->sh_type); + } + } + break; + } case ELF::SHT_ANDROID_REL: case ELF::SHT_ANDROID_RELA: for (const Elf_Rela &R : unwrapOrError(Obj->android_relas(Sec))) - printRelocation(Obj, R, SymTab); + printRelocation(Obj, R, SymTab, Sec->sh_type); break; } } template void LLVMStyle::printRelocation(const ELFO *Obj, Elf_Rela Rel, - const Elf_Shdr *SymTab) { + const Elf_Shdr *SymTab, + unsigned SType) { + bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR; SmallString<32> RelocName; - Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); + if (IsRelr && !opts::DecodeRelr) + RelocName = "R_RELR_RELATIVE"; + else + Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); StringRef TargetName; const Elf_Sym *Sym = unwrapOrError(Obj->getRelocationSymbol(&Rel, SymTab)); if (Sym && Sym->getType() == ELF::STT_SECTION) { @@ -4171,6 +4293,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"); @@ -4178,34 +4301,56 @@ W.indent(); if (DynRelaRegion.Size > 0) for (const Elf_Rela &Rela : this->dumper()->dyn_relas()) - printDynamicRelocation(Obj, Rela); + printDynamicRelocation(Obj, Rela, ELF::SHT_RELA); else 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); + printDynamicRelocation(Obj, Rela, ELF::SHT_REL); } + if (DynRelrRegion.Size > 0) { + Elf_Relr_Range Relrs = this->dumper()->dyn_relrs(); + if (opts::DecodeRelr) { + std::vector RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs)); + for (const Elf_Rela &Rela : RelrRelas) { + printDynamicRelocation(Obj, Rela, ELF::SHT_RELR); + } + } else { + for (const Elf_Relr &Relr : Relrs) { + Elf_Rela Rela; + Rela.r_offset = Relr; + Rela.r_info = 0; + Rela.r_addend = 0; + printDynamicRelocation(Obj, Rela, ELF::SHT_RELR); + } + } + } if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef()) - printDynamicRelocation(Obj, Rela); + printDynamicRelocation(Obj, Rela, ELF::SHT_RELA); else 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); + printDynamicRelocation(Obj, Rela, ELF::SHT_REL); } W.unindent(); W.startLine() << "}\n"; } template -void LLVMStyle::printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel) { +void LLVMStyle::printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel, + unsigned SType) { + bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR; SmallString<32> RelocName; - Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); + if (IsRelr && !opts::DecodeRelr) + RelocName = "R_RELR_RELATIVE"; + else + Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); StringRef SymbolName; uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL()); const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex; Index: tools/llvm-readobj/llvm-readobj.h =================================================================== --- tools/llvm-readobj/llvm-readobj.h +++ tools/llvm-readobj/llvm-readobj.h @@ -60,6 +60,7 @@ extern llvm::cl::opt DynamicSymbols; extern llvm::cl::opt UnwindInfo; extern llvm::cl::opt ExpandRelocs; + extern llvm::cl::opt DecodeRelr; extern llvm::cl::opt CodeView; extern llvm::cl::opt CodeViewSubsectionBytes; extern llvm::cl::opt ARMAttributes; Index: tools/llvm-readobj/llvm-readobj.cpp =================================================================== --- tools/llvm-readobj/llvm-readobj.cpp +++ tools/llvm-readobj/llvm-readobj.cpp @@ -164,6 +164,10 @@ cl::opt ExpandRelocs("expand-relocs", cl::desc("Expand each shown relocation to multiple lines")); + // -decode-relr + cl::opt DecodeRelr("decode-relr", + cl::desc("Decode SHT_RELR section and print relocation offsets")); + // -codeview cl::opt CodeView("codeview", cl::desc("Display CodeView debug information")); 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; }