[llvm-readobj] Add experimental support for SHT_RELR sections

This change adds experimental support for SHT_RELR sections, proposed
here: https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg

Definitions for the new ELF section type and dynamic array tags, as well
as the encoding used in the new section are all under discussion and are
subject to change. Use with caution!

Author: rahulchaudhry

Differential Revision: https://reviews.llvm.org/D47919

llvm-svn: 335922
This commit is contained in:
Jake Ehrlich 2018-06-28 21:07:34 +00:00
parent a1f629c4cf
commit 0f440d832f
13 changed files with 471 additions and 19 deletions

View File

@ -65,6 +65,12 @@ DYNAMIC_TAG(PREINIT_ARRAYSZ, 33) // Size of the DT_PREINIT_ARRAY array.
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_RELSZ, 0x60000010)
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.

View File

@ -796,6 +796,9 @@ enum : unsigned {
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 @@ enum : unsigned {
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 @@ struct Elf32_Rela {
}
};
// 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 @@ struct Elf64_Rela {
}
};
// 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

View File

@ -32,6 +32,7 @@ namespace llvm {
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 @@ public:
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 @@ public:
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 @@ public:
StringRef getRelocationTypeName(uint32_t Type) const;
void getRelocationTypeName(uint32_t Type,
SmallVectorImpl<char> &Result) const;
uint32_t getRelrRelocationType() const;
/// Get the symbol for a given relocation.
Expected<const Elf_Sym *> getRelocationSymbol(const Elf_Rel *Rel,
@ -143,6 +147,12 @@ public:
return getSectionContentsAsArray<Elf_Rel>(Sec);
}
Expected<Elf_Relr_Range> relrs(const Elf_Shdr *Sec) const {
return getSectionContentsAsArray<Elf_Relr>(Sec);
}
Expected<std::vector<Elf_Rela>> decode_relrs(Elf_Relr_Range relrs) const;
Expected<std::vector<Elf_Rela>> android_relas(const Elf_Shdr *Sec) const;
/// Iterate over program header table.
@ -397,6 +407,11 @@ void ELFFile<ELFT>::getRelocationTypeName(uint32_t Type,
}
}
template <class ELFT>
uint32_t ELFFile<ELFT>::getRelrRelocationType() const {
return getELFRelrRelocationType(getHeader()->e_machine);
}
template <class ELFT>
Expected<const typename ELFT::Sym *>
ELFFile<ELFT>::getRelocationSymbol(const Elf_Rel *Rel,

View File

@ -62,6 +62,7 @@ public:
using Phdr = Elf_Phdr_Impl<ELFType<E, Is64>>;
using Rel = Elf_Rel_Impl<ELFType<E, Is64>, false>;
using Rela = Elf_Rel_Impl<ELFType<E, Is64>, true>;
using Relr = packed<uint>;
using Verdef = Elf_Verdef_Impl<ELFType<E, Is64>>;
using Verdaux = Elf_Verdaux_Impl<ELFType<E, Is64>>;
using Verneed = Elf_Verneed_Impl<ELFType<E, Is64>>;
@ -79,6 +80,7 @@ public:
using SymRange = ArrayRef<Sym>;
using RelRange = ArrayRef<Rel>;
using RelaRange = ArrayRef<Rela>;
using RelrRange = ArrayRef<Relr>;
using PhdrRange = ArrayRef<Phdr>;
using Half = packed<uint16_t>;

View File

@ -154,6 +154,52 @@ StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine,
#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 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) {
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,85 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) {
}
}
template <class ELFT>
Expected<std::vector<typename ELFT::Rela>>
ELFFile<ELFT>::decode_relrs(Elf_Relr_Range relrs) const {
// This function decodes the contents of an SHT_RELR packed relocation
// section.
//
// Proposal for adding SHT_RELR sections to generic-abi is here:
// https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg
//
// The encoded sequence of Elf64_Relr entries in a SHT_RELR section looks
// like [ AAAAAAAA BBBBBBB1 BBBBBBB1 ... AAAAAAAA BBBBBB1 ... ]
//
// i.e. start with an address, followed by any number of bitmaps. The address
// entry encodes 1 relocation. The subsequent bitmap entries encode up to 63
// relocations each, at subsequent offsets following the last address entry.
//
// The bitmap entries must have 1 in the least significant bit. The assumption
// here is that an address cannot have 1 in lsb. Odd addresses are not
// supported.
//
// Excluding the least significant bit in the bitmap, each non-zero bit in
// the bitmap represents a relocation to be applied to a corresponding machine
// word that follows the base address word. The second least significant bit
// represents the machine word immediately following the initial address, and
// each bit that follows represents the next word, in linear order. As such,
// a single bitmap can encode up to 31 relocations in a 32-bit object, and
// 63 relocations in a 64-bit object.
//
// This encoding has a couple of interesting properties:
// 1. Looking at any entry, it is clear whether it's an address or a bitmap:
// even means address, odd means bitmap.
// 2. Just a simple list of addresses is a valid encoding.
Elf_Rela Rela;
Rela.r_info = 0;
Rela.r_addend = 0;
Rela.setType(getRelrRelocationType(), false);
std::vector<Elf_Rela> 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 <class ELFT>
Expected<std::vector<typename ELFT::Rela>>
ELFFile<ELFT>::android_relas(const Elf_Shdr *Sec) const {

View File

@ -436,9 +436,11 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration(
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);

View File

@ -0,0 +1,5 @@
.quad 0x0000000000010d60 // Initial offset
.quad 0x0000000000000103 // Continuation bitmap
.quad 0x0000000000020000 // New offset
.quad 0x00000000000f0501 // Continuation bitmap
.quad 0x000a700550400009 // Continuation bitmap

View File

@ -0,0 +1,5 @@
.long 0x00010d60 // Initial offset
.long 0x00000103 // Continuation bitmap
.long 0x00020000 // New offset
.long 0x000f0501 // Continuation bitmap
.long 0x50400009 // Continuation bitmap

View File

@ -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 -raw-relr - \
# RUN: | FileCheck --check-prefix=RAW-LLVM1 %s
# RAW-LLVM1: Section (1) .relr.dyn {
# RAW-LLVM1-NEXT: 0x10D60
# RAW-LLVM1-NEXT: 0x103
# RAW-LLVM1-NEXT: 0x20000
# RAW-LLVM1-NEXT: 0xF0501
# RAW-LLVM1-NEXT: 0xA700550400009
# RAW-LLVM1-NEXT: }
# 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_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x10D68 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x10DA0 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x20000 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x20040 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x20050 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x20080 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x20088 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x20090 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x20098 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x20210 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x202A8 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x202D8 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x202E8 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x202F8 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x20308 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x20358 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x20360 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x20368 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x20380 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: 0x20390 R_X86_64_RELATIVE - 0x0
# LLVM1-NEXT: }
# RUN: yaml2obj -docnum 1 %s \
# RUN: | llvm-readobj -elf-output-style=GNU -relocations -raw-relr - \
# RUN: | FileCheck --check-prefix=RAW-GNU1 %s
# RAW-GNU1: Relocation section '.relr.dyn' at offset 0x180 contains 5 entries:
# RAW-GNU1: 0000000000010d60
# RAW-GNU1-NEXT: 0000000000000103
# RAW-GNU1-NEXT: 0000000000020000
# RAW-GNU1-NEXT: 00000000000f0501
# RAW-GNU1-NEXT: 000a700550400009
# 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 21 entries:
# GNU1: 0000000000010d60 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 0000000000010d68 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 0000000000010da0 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 0000000000020000 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 0000000000020040 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 0000000000020050 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 0000000000020080 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 0000000000020088 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 0000000000020090 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 0000000000020098 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 0000000000020210 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 00000000000202a8 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 00000000000202d8 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 00000000000202e8 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 00000000000202f8 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 0000000000020308 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 0000000000020358 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 0000000000020360 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 0000000000020368 0000000000000008 R_X86_64_RELATIVE
# GNU1-NEXT: 0000000000020380 0000000000000008 R_X86_64_RELATIVE
# GNU1-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 -raw-relr - \
# RUN: | FileCheck --check-prefix=RAW-LLVM2 %s
# RAW-LLVM2: Section (1) .relr.dyn {
# RAW-LLVM2-NEXT: 0x10D60
# RAW-LLVM2-NEXT: 0x103
# RAW-LLVM2-NEXT: 0x20000
# RAW-LLVM2-NEXT: 0xF0501
# RAW-LLVM2-NEXT: 0x50400009
# RAW-LLVM2-NEXT: }
# 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_386_RELATIVE - 0x0
# LLVM2-NEXT: 0x10D64 R_386_RELATIVE - 0x0
# LLVM2-NEXT: 0x10D80 R_386_RELATIVE - 0x0
# LLVM2-NEXT: 0x20000 R_386_RELATIVE - 0x0
# LLVM2-NEXT: 0x20020 R_386_RELATIVE - 0x0
# LLVM2-NEXT: 0x20028 R_386_RELATIVE - 0x0
# LLVM2-NEXT: 0x20040 R_386_RELATIVE - 0x0
# LLVM2-NEXT: 0x20044 R_386_RELATIVE - 0x0
# LLVM2-NEXT: 0x20048 R_386_RELATIVE - 0x0
# LLVM2-NEXT: 0x2004C R_386_RELATIVE - 0x0
# LLVM2-NEXT: 0x20088 R_386_RELATIVE - 0x0
# LLVM2-NEXT: 0x200D4 R_386_RELATIVE - 0x0
# LLVM2-NEXT: 0x200EC R_386_RELATIVE - 0x0
# LLVM2-NEXT: 0x200F4 R_386_RELATIVE - 0x0
# LLVM2-NEXT: }
# RUN: yaml2obj -docnum 2 %s \
# RUN: | llvm-readobj -elf-output-style=GNU -relocations -raw-relr - \
# RUN: | FileCheck --check-prefix=RAW-GNU2 %s
# RAW-GNU2: Relocation section '.relr.dyn' at offset 0xfc contains 5 entries:
# RAW-GNU2: 00010d60
# RAW-GNU2-NEXT: 00000103
# RAW-GNU2-NEXT: 00020000
# RAW-GNU2-NEXT: 000f0501
# RAW-GNU2-NEXT: 50400009
# 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 14 entries:
# GNU2: 00010d60 00000008 R_386_RELATIVE
# GNU2-NEXT: 00010d64 00000008 R_386_RELATIVE
# GNU2-NEXT: 00010d80 00000008 R_386_RELATIVE
# GNU2-NEXT: 00020000 00000008 R_386_RELATIVE
# GNU2-NEXT: 00020020 00000008 R_386_RELATIVE
# GNU2-NEXT: 00020028 00000008 R_386_RELATIVE
# GNU2-NEXT: 00020040 00000008 R_386_RELATIVE
# GNU2-NEXT: 00020044 00000008 R_386_RELATIVE
# GNU2-NEXT: 00020048 00000008 R_386_RELATIVE
# GNU2-NEXT: 0002004c 00000008 R_386_RELATIVE
# GNU2-NEXT: 00020088 00000008 R_386_RELATIVE
# GNU2-NEXT: 000200d4 00000008 R_386_RELATIVE
# GNU2-NEXT: 000200ec 00000008 R_386_RELATIVE
# GNU2-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
...

View File

@ -85,8 +85,10 @@ using namespace ELF;
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 @@ private:
const ELFO *Obj;
DynRegionInfo DynRelRegion;
DynRegionInfo DynRelaRegion;
DynRegionInfo DynRelrRegion;
DynRegionInfo DynPLTRelRegion;
DynRegionInfo DynSymRegion;
DynRegionInfo DynamicTable;
@ -257,6 +260,7 @@ public:
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 @@ public:
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,6 +397,7 @@ private:
}
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);
void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First,
@ -1492,6 +1498,18 @@ void ELFDumper<ELFT>::parseDynamicTable(
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 +1543,11 @@ typename ELFDumper<ELFT>::Elf_Rela_Range ELFDumper<ELFT>::dyn_relas() const {
return DynRelaRegion.getAsArrayRef<Elf_Rela>();
}
template <typename ELFT>
typename ELFDumper<ELFT>::Elf_Relr_Range ELFDumper<ELFT>::dyn_relrs() const {
return DynRelrRegion.getAsArrayRef<Elf_Relr>();
}
template<class ELFT>
void ELFDumper<ELFT>::printFileHeaders() {
ELFDumperStyle->printFileHeaders(Obj);
@ -2582,7 +2605,6 @@ void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab,
const Elf_Rela &R, bool IsRela) {
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;
@ -2598,6 +2620,7 @@ void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab,
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 +2652,36 @@ void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab,
OS << "\n";
}
static inline void printRelocHeader(raw_ostream &OS, bool Is64, bool IsRela) {
if (Is64)
OS << " Offset Info Type"
template <class ELFT> void GNUStyle<ELFT>::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::RawRelr)
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 <class ELFT> void GNUStyle<ELFT>::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 +2694,20 @@ template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) {
AndroidRelas = unwrapOrError(Obj->android_relas(&Sec));
Entries = AndroidRelas.size();
}
std::vector<Elf_Rela> RelrRelas;
if (!opts::RawRelr && (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:
@ -2681,6 +2723,16 @@ template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) {
for (const auto &R : unwrapOrError(Obj->relas(&Sec)))
printRelocation(Obj, SymTab, R, true);
break;
case ELF::SHT_RELR:
case ELF::SHT_ANDROID_RELR:
if (opts::RawRelr)
for (const auto &R : unwrapOrError(Obj->relrs(&Sec)))
OS << to_string(format_hex_no_prefix(R, ELFT::Is64Bits ? 16 : 8))
<< "\n";
else
for (const auto &R : RelrRelas)
printRelocation(Obj, SymTab, R, false);
break;
case ELF::SHT_ANDROID_REL:
case ELF::SHT_ANDROID_RELA:
for (const auto &R : AndroidRelas)
@ -2762,6 +2814,9 @@ std::string getSectionTypeString(unsigned Arch, unsigned Type) {
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:
@ -3300,13 +3355,14 @@ template <class ELFT>
void GNUStyle<ELFT>::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<const uint8_t *>(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);
}
@ -3315,7 +3371,7 @@ void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) {
<< format_hex(reinterpret_cast<const uint8_t *>(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;
@ -3324,6 +3380,18 @@ void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) {
printDynamicRelocation(Obj, Rela, false);
}
}
if (DynRelrRegion.Size > 0) {
OS << "\n'RELR' relocation section at offset "
<< format_hex(reinterpret_cast<const uint8_t *>(DynRelrRegion.Addr) -
Obj->base(),
1) << " contains " << DynRelrRegion.Size << " bytes:\n";
printRelocHeader(ELF::SHT_REL);
Elf_Relr_Range Relrs = this->dumper()->dyn_relrs();
std::vector<Elf_Rela> RelrRelas = unwrapOrError(Obj->decode_relrs(Relrs));
for (const Elf_Rela &Rela : RelrRelas) {
printDynamicRelocation(Obj, Rela, false);
}
}
if (DynPLTRelRegion.Size) {
OS << "\n'PLT' relocation section at offset "
<< format_hex(reinterpret_cast<const uint8_t *>(DynPLTRelRegion.Addr) -
@ -3331,11 +3399,11 @@ void GNUStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) {
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<Elf_Rela>())
printDynamicRelocation(Obj, Rela, true);
} else {
printRelocHeader(OS, ELFT::Is64Bits, false);
printRelocHeader(ELF::SHT_REL);
for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef<Elf_Rel>()) {
Elf_Rela Rela;
Rela.r_offset = Rel.r_offset;
@ -3956,9 +4024,12 @@ template <class ELFT> void LLVMStyle<ELFT>::printRelocations(const ELFO *Obj) {
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));
@ -3991,6 +4062,19 @@ void LLVMStyle<ELFT>::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) {
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));
if (opts::RawRelr) {
for (const Elf_Relr &R : Relrs)
W.startLine() << W.hex(R) << "\n";
} else {
std::vector<Elf_Rela> 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)))
@ -4171,6 +4255,7 @@ template <class ELFT>
void LLVMStyle<ELFT>::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");
@ -4187,6 +4272,12 @@ void LLVMStyle<ELFT>::printDynamicRelocations(const ELFO *Obj) {
Rela.r_addend = 0;
printDynamicRelocation(Obj, Rela);
}
if (DynRelrRegion.Size > 0) {
Elf_Relr_Range Relrs = this->dumper()->dyn_relrs();
std::vector<Elf_Rela> 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<Elf_Rela>())
printDynamicRelocation(Obj, Rela);

View File

@ -164,6 +164,10 @@ namespace opts {
cl::opt<bool> ExpandRelocs("expand-relocs",
cl::desc("Expand each shown relocation to multiple lines"));
// -raw-relr
cl::opt<bool> RawRelr("raw-relr",
cl::desc("Do not decode relocations in SHT_RELR section, display raw contents"));
// -codeview
cl::opt<bool> CodeView("codeview",
cl::desc("Display CodeView debug information"));

View File

@ -60,6 +60,7 @@ namespace opts {
extern llvm::cl::opt<bool> DynamicSymbols;
extern llvm::cl::opt<bool> UnwindInfo;
extern llvm::cl::opt<bool> ExpandRelocs;
extern llvm::cl::opt<bool> RawRelr;
extern llvm::cl::opt<bool> CodeView;
extern llvm::cl::opt<bool> CodeViewSubsectionBytes;
extern llvm::cl::opt<bool> ARMAttributes;

View File

@ -114,6 +114,7 @@ class ELFState {
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 @@ ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
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;
}