Skip to content

Commit

Permalink
[llvm-readobj] Add experimental support for SHT_RELR sections
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jakehehrlich committed Jun 28, 2018
1 parent a1f629c commit 0f440d8
Show file tree
Hide file tree
Showing 13 changed files with 471 additions and 19 deletions.
12 changes: 12 additions & 0 deletions llvm/include/llvm/BinaryFormat/DynamicTags.def
Expand Up @@ -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.
Expand All @@ -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.
Expand Down
12 changes: 12 additions & 0 deletions llvm/include/llvm/BinaryFormat/ELF.h
Expand Up @@ -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
Expand All @@ -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.
Expand Down Expand Up @@ -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).
Expand Down Expand Up @@ -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
Expand Down
15 changes: 15 additions & 0 deletions llvm/include/llvm/Object/ELF.h
Expand Up @@ -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
Expand Down Expand Up @@ -60,6 +61,7 @@ class ELFFile {
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;
Expand All @@ -75,6 +77,7 @@ class ELFFile {
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 {
Expand Down Expand Up @@ -110,6 +113,7 @@ class ELFFile {
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,
Expand Down Expand Up @@ -143,6 +147,12 @@ class ELFFile {
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.
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions llvm/include/llvm/Object/ELFTypes.h
Expand Up @@ -62,6 +62,7 @@ template <endianness E, bool Is64> struct ELFType {
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>>;
Expand All @@ -79,6 +80,7 @@ template <endianness E, bool Is64> struct ELFType {
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>;
Expand Down
127 changes: 127 additions & 0 deletions llvm/lib/Object/ELF.cpp
Expand Up @@ -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:
Expand Down Expand Up @@ -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);
Expand All @@ -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 {
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/ObjectYAML/ELFYAML.cpp
Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions llvm/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
5 changes: 5 additions & 0 deletions llvm/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

0 comments on commit 0f440d8

Please sign in to comment.