[MC,llvm-readobj,yaml2obj] Support CREL relocation format
CREL is a compact relocation format for the ELF object file format. This patch adds integrated assembler support (using the RELA form) available with `llvm-mc -filetype=obj -crel a.s -o a.o`. A dependent patch will add `clang -c -Wa,--crel,--allow-experimental-crel`. Also add llvm-readobj support (for both REL and RELA forms) to facilitate testing the assembler. Additionally, yaml2obj gains support for the RELA form to aid testing with llvm-readobj. We temporarily assign the section type code 0x40000020 from the generic range to `SHT_CREL`. We avoided using `SHT_LLVM_` or `SHT_GNU_` to avoid code churn and maintain broader applicability for interested psABIs. Similarly, `DT_CREL` is temporarily 0x40000026. LLVM will change the code and break compatibility. This is not an issue if all relocatable files using CREL are regenerated (aka no prebuilt relocatable files). Link: https://discourse.llvm.org/t/rfc-crel-a-compact-relocation-format-for-elf/77600 Pull Request: https://github.com/llvm/llvm-project/pull/91280
This commit is contained in:
@@ -86,6 +86,10 @@ 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.
|
||||
|
||||
// TODO: Experimental CREL relocations. LLVM will change the value and
|
||||
// break compatibility in the future.
|
||||
DYNAMIC_TAG(CREL, 0x40000026) // CREL relocation table
|
||||
|
||||
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.
|
||||
|
||||
@@ -1082,7 +1082,10 @@ enum : unsigned {
|
||||
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_RELR = 19, // Relocation entries; only offsets.
|
||||
// TODO: Experimental CREL relocations. LLVM will change the value and
|
||||
// break compatibility in the future.
|
||||
SHT_CREL = 0x40000014,
|
||||
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
|
||||
@@ -1937,6 +1940,8 @@ enum {
|
||||
ELFCOMPRESS_HIPROC = 0x7fffffff // End of processor-specific.
|
||||
};
|
||||
|
||||
constexpr unsigned CREL_HDR_ADDEND = 4;
|
||||
|
||||
/// Convert an architecture name into ELF's e_machine value.
|
||||
uint16_t convertArchNameToEMachine(StringRef Arch);
|
||||
|
||||
|
||||
@@ -61,6 +61,9 @@ public:
|
||||
|
||||
bool Dwarf64 : 1;
|
||||
|
||||
// Use CREL relocation format for ELF.
|
||||
bool Crel = false;
|
||||
|
||||
// If true, prefer R_X86_64_[REX_]GOTPCRELX to R_X86_64_GOTPCREL on x86-64
|
||||
// ELF.
|
||||
bool X86RelaxRelocations = true;
|
||||
|
||||
@@ -51,6 +51,8 @@ bool getNoTypeCheck();
|
||||
|
||||
bool getSaveTempLabels();
|
||||
|
||||
bool getCrel();
|
||||
|
||||
bool getX86RelaxRelocations();
|
||||
|
||||
std::string getABIName();
|
||||
|
||||
@@ -321,6 +321,11 @@ public:
|
||||
|
||||
std::vector<Elf_Rel> decode_relrs(Elf_Relr_Range relrs) const;
|
||||
|
||||
Expected<uint64_t> getCrelHeader(ArrayRef<uint8_t> Content) const;
|
||||
using RelsOrRelas = std::pair<std::vector<Elf_Rel>, std::vector<Elf_Rela>>;
|
||||
Expected<RelsOrRelas> decodeCrel(ArrayRef<uint8_t> Content) const;
|
||||
Expected<RelsOrRelas> crels(const Elf_Shdr &Sec) const;
|
||||
|
||||
Expected<std::vector<Elf_Rela>> android_relas(const Elf_Shdr &Sec) const;
|
||||
|
||||
/// Iterate over program header table.
|
||||
|
||||
@@ -32,6 +32,7 @@ template <class ELFT> struct Elf_Sym_Impl;
|
||||
template <class ELFT> struct Elf_Dyn_Impl;
|
||||
template <class ELFT> struct Elf_Phdr_Impl;
|
||||
template <class ELFT, bool isRela> struct Elf_Rel_Impl;
|
||||
template <bool Is64> struct Elf_Crel_Impl;
|
||||
template <class ELFT> struct Elf_Verdef_Impl;
|
||||
template <class ELFT> struct Elf_Verdaux_Impl;
|
||||
template <class ELFT> struct Elf_Verneed_Impl;
|
||||
@@ -62,6 +63,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 Crel = Elf_Crel_Impl<Is64>;
|
||||
using Relr = packed<uint>;
|
||||
using Verdef = Elf_Verdef_Impl<ELFType<E, Is64>>;
|
||||
using Verdaux = Elf_Verdaux_Impl<ELFType<E, Is64>>;
|
||||
@@ -117,6 +119,7 @@ using ELF64BE = ELFType<llvm::endianness::big, true>;
|
||||
using Elf_Phdr = typename ELFT::Phdr; \
|
||||
using Elf_Rel = typename ELFT::Rel; \
|
||||
using Elf_Rela = typename ELFT::Rela; \
|
||||
using Elf_Crel = typename ELFT::Crel; \
|
||||
using Elf_Relr = typename ELFT::Relr; \
|
||||
using Elf_Verdef = typename ELFT::Verdef; \
|
||||
using Elf_Verdaux = typename ELFT::Verdaux; \
|
||||
@@ -385,6 +388,7 @@ template <endianness Endianness>
|
||||
struct Elf_Rel_Impl<ELFType<Endianness, false>, false> {
|
||||
LLVM_ELF_IMPORT_TYPES(Endianness, false)
|
||||
static const bool HasAddend = false;
|
||||
static const bool IsCrel = false;
|
||||
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
|
||||
Elf_Word r_info; // Symbol table index and type of relocation to apply
|
||||
|
||||
@@ -421,6 +425,7 @@ struct Elf_Rel_Impl<ELFType<Endianness, false>, true>
|
||||
: public Elf_Rel_Impl<ELFType<Endianness, false>, false> {
|
||||
LLVM_ELF_IMPORT_TYPES(Endianness, false)
|
||||
static const bool HasAddend = true;
|
||||
static const bool IsCrel = false;
|
||||
Elf_Sword r_addend; // Compute value for relocatable field by adding this
|
||||
};
|
||||
|
||||
@@ -428,6 +433,7 @@ template <endianness Endianness>
|
||||
struct Elf_Rel_Impl<ELFType<Endianness, true>, false> {
|
||||
LLVM_ELF_IMPORT_TYPES(Endianness, true)
|
||||
static const bool HasAddend = false;
|
||||
static const bool IsCrel = false;
|
||||
Elf_Addr r_offset; // Location (file byte offset, or program virtual addr)
|
||||
Elf_Xword r_info; // Symbol table index and type of relocation to apply
|
||||
|
||||
@@ -474,9 +480,29 @@ struct Elf_Rel_Impl<ELFType<Endianness, true>, true>
|
||||
: public Elf_Rel_Impl<ELFType<Endianness, true>, false> {
|
||||
LLVM_ELF_IMPORT_TYPES(Endianness, true)
|
||||
static const bool HasAddend = true;
|
||||
static const bool IsCrel = false;
|
||||
Elf_Sxword r_addend; // Compute value for relocatable field by adding this.
|
||||
};
|
||||
|
||||
// In-memory representation. The serialized representation uses LEB128.
|
||||
template <bool Is64> struct Elf_Crel_Impl {
|
||||
using uint = std::conditional_t<Is64, uint64_t, uint32_t>;
|
||||
static const bool IsRela = true;
|
||||
static const bool IsCrel = true;
|
||||
uint r_offset;
|
||||
uint32_t r_symidx;
|
||||
uint32_t r_type;
|
||||
std::conditional_t<Is64, int64_t, int32_t> r_addend;
|
||||
|
||||
// Dummy bool parameter is for compatibility with Elf_Rel_Impl.
|
||||
uint32_t getType(bool) const { return r_type; }
|
||||
uint32_t getSymbol(bool) const { return r_symidx; }
|
||||
void setSymbolAndType(uint32_t s, unsigned char t, bool) {
|
||||
r_symidx = s;
|
||||
r_type = t;
|
||||
}
|
||||
};
|
||||
|
||||
template <class ELFT>
|
||||
struct Elf_Ehdr_Impl {
|
||||
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "llvm/MC/StringTableBuilder.h"
|
||||
#include "llvm/Support/Alignment.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Compression.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/EndianStream.h"
|
||||
@@ -256,7 +257,7 @@ public:
|
||||
void recordRelocation(MCAssembler &Asm, const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue) override;
|
||||
bool usesRela(const MCSectionELF &Sec) const;
|
||||
bool usesRela(const MCTargetOptions *TO, const MCSectionELF &Sec) const;
|
||||
|
||||
void executePostLayoutBinding(MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) override;
|
||||
@@ -810,7 +811,15 @@ MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx,
|
||||
Flags = ELF::SHF_GROUP;
|
||||
|
||||
const StringRef SectionName = Sec.getName();
|
||||
const bool Rela = OWriter.usesRela(Sec);
|
||||
const MCTargetOptions *TO = Ctx.getTargetOptions();
|
||||
if (TO && TO->Crel) {
|
||||
MCSectionELF *RelaSection =
|
||||
Ctx.createELFRelSection(".crel" + SectionName, ELF::SHT_CREL, Flags,
|
||||
/*EntrySize=*/1, Sec.getGroup(), &Sec);
|
||||
return RelaSection;
|
||||
}
|
||||
|
||||
const bool Rela = OWriter.usesRela(TO, Sec);
|
||||
unsigned EntrySize;
|
||||
if (Rela)
|
||||
EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela);
|
||||
@@ -912,20 +921,61 @@ void ELFWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
|
||||
WriteWord(EntrySize); // sh_entsize
|
||||
}
|
||||
|
||||
template <class uint>
|
||||
static void encodeCrel(ArrayRef<ELFRelocationEntry> Relocs, raw_ostream &OS) {
|
||||
uint OffsetMask = 8, Offset = 0, Addend = 0;
|
||||
uint32_t SymIdx = 0, Type = 0;
|
||||
// hdr & 4 indicates 3 flag bits in delta offset and flags members.
|
||||
for (const ELFRelocationEntry &Entry : Relocs)
|
||||
OffsetMask |= Entry.Offset;
|
||||
const int Shift = llvm::countr_zero(OffsetMask);
|
||||
encodeULEB128(Relocs.size() * 8 + ELF::CREL_HDR_ADDEND + Shift, OS);
|
||||
for (const ELFRelocationEntry &Entry : Relocs) {
|
||||
// The delta offset and flags member may be larger than uint64_t. Special
|
||||
// case the first byte (3 flag bits and 4 offset bits). Other ULEB128 bytes
|
||||
// encode the remaining delta offset bits.
|
||||
auto DeltaOffset = static_cast<uint>((Entry.Offset - Offset) >> Shift);
|
||||
Offset = Entry.Offset;
|
||||
uint32_t CurSymIdx = Entry.Symbol ? Entry.Symbol->getIndex() : 0;
|
||||
uint8_t B = (DeltaOffset << 3) + (SymIdx != CurSymIdx) +
|
||||
(Type != Entry.Type ? 2 : 0) + (Addend != Entry.Addend ? 4 : 0);
|
||||
if (DeltaOffset < 0x10) {
|
||||
OS << char(B);
|
||||
} else {
|
||||
OS << char(B | 0x80);
|
||||
encodeULEB128(DeltaOffset >> 4, OS);
|
||||
}
|
||||
// Delta symidx/type/addend members (SLEB128).
|
||||
if (B & 1) {
|
||||
encodeSLEB128(static_cast<int32_t>(CurSymIdx - SymIdx), OS);
|
||||
SymIdx = CurSymIdx;
|
||||
}
|
||||
if (B & 2) {
|
||||
encodeSLEB128(static_cast<int32_t>(Entry.Type - Type), OS);
|
||||
Type = Entry.Type;
|
||||
}
|
||||
if (B & 4) {
|
||||
encodeSLEB128(std::make_signed_t<uint>(Entry.Addend - Addend), OS);
|
||||
Addend = Entry.Addend;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ELFWriter::writeRelocations(const MCAssembler &Asm,
|
||||
const MCSectionELF &Sec) {
|
||||
std::vector<ELFRelocationEntry> &Relocs = OWriter.Relocations[&Sec];
|
||||
const bool Rela = OWriter.usesRela(Sec);
|
||||
const MCTargetOptions *TO = Asm.getContext().getTargetOptions();
|
||||
const bool Rela = OWriter.usesRela(TO, Sec);
|
||||
|
||||
// Sort the relocation entries. MIPS needs this.
|
||||
OWriter.TargetObjectWriter->sortRelocs(Asm, Relocs);
|
||||
|
||||
if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) {
|
||||
for (const ELFRelocationEntry &Entry : Relocs) {
|
||||
uint32_t Symidx = Entry.Symbol ? Entry.Symbol->getIndex() : 0;
|
||||
uint32_t SymIdx = Entry.Symbol ? Entry.Symbol->getIndex() : 0;
|
||||
if (is64Bit()) {
|
||||
write(Entry.Offset);
|
||||
write(uint32_t(Symidx));
|
||||
write(uint32_t(SymIdx));
|
||||
write(OWriter.TargetObjectWriter->getRSsym(Entry.Type));
|
||||
write(OWriter.TargetObjectWriter->getRType3(Entry.Type));
|
||||
write(OWriter.TargetObjectWriter->getRType2(Entry.Type));
|
||||
@@ -935,7 +985,7 @@ void ELFWriter::writeRelocations(const MCAssembler &Asm,
|
||||
} else {
|
||||
write(uint32_t(Entry.Offset));
|
||||
ELF::Elf32_Rela ERE32;
|
||||
ERE32.setSymbolAndType(Symidx, Entry.Type);
|
||||
ERE32.setSymbolAndType(SymIdx, Entry.Type);
|
||||
write(ERE32.r_info);
|
||||
if (Rela)
|
||||
write(uint32_t(Entry.Addend));
|
||||
@@ -955,24 +1005,29 @@ void ELFWriter::writeRelocations(const MCAssembler &Asm,
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (const ELFRelocationEntry &Entry : Relocs) {
|
||||
uint32_t Symidx = Entry.Symbol ? Entry.Symbol->getIndex() : 0;
|
||||
if (is64Bit()) {
|
||||
write(Entry.Offset);
|
||||
ELF::Elf64_Rela ERE;
|
||||
ERE.setSymbolAndType(Symidx, Entry.Type);
|
||||
write(ERE.r_info);
|
||||
if (Rela)
|
||||
write(Entry.Addend);
|
||||
} else {
|
||||
write(uint32_t(Entry.Offset));
|
||||
ELF::Elf32_Rela ERE;
|
||||
ERE.setSymbolAndType(Symidx, Entry.Type);
|
||||
write(ERE.r_info);
|
||||
if (Rela)
|
||||
write(uint32_t(Entry.Addend));
|
||||
} else if (TO && TO->Crel) {
|
||||
if (is64Bit())
|
||||
encodeCrel<uint64_t>(Relocs, W.OS);
|
||||
else
|
||||
encodeCrel<uint32_t>(Relocs, W.OS);
|
||||
} else {
|
||||
for (const ELFRelocationEntry &Entry : Relocs) {
|
||||
uint32_t Symidx = Entry.Symbol ? Entry.Symbol->getIndex() : 0;
|
||||
if (is64Bit()) {
|
||||
write(Entry.Offset);
|
||||
ELF::Elf64_Rela ERE;
|
||||
ERE.setSymbolAndType(Symidx, Entry.Type);
|
||||
write(ERE.r_info);
|
||||
if (Rela)
|
||||
write(Entry.Addend);
|
||||
} else {
|
||||
write(uint32_t(Entry.Offset));
|
||||
ELF::Elf32_Rela ERE;
|
||||
ERE.setSymbolAndType(Symidx, Entry.Type);
|
||||
write(ERE.r_info);
|
||||
if (Rela)
|
||||
write(uint32_t(Entry.Addend));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -992,7 +1047,8 @@ void ELFWriter::writeSection(const SectionIndexMapTy &SectionIndexMap,
|
||||
llvm_unreachable("SHT_DYNAMIC in a relocatable object");
|
||||
|
||||
case ELF::SHT_REL:
|
||||
case ELF::SHT_RELA: {
|
||||
case ELF::SHT_RELA:
|
||||
case ELF::SHT_CREL: {
|
||||
sh_link = SymbolTableIndex;
|
||||
assert(sh_link && ".symtab not found");
|
||||
const MCSection *InfoSection = Section.getLinkedToSection();
|
||||
@@ -1417,6 +1473,7 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
|
||||
uint64_t C = Target.getConstant();
|
||||
uint64_t FixupOffset = Asm.getFragmentOffset(*Fragment) + Fixup.getOffset();
|
||||
MCContext &Ctx = Asm.getContext();
|
||||
const MCTargetOptions *TO = Ctx.getTargetOptions();
|
||||
|
||||
if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
|
||||
const auto &SymB = cast<MCSymbolELF>(RefB->getSymbol());
|
||||
@@ -1472,7 +1529,7 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
|
||||
FixedValue = !RelocateWithSymbol && SymA && !SymA->isUndefined()
|
||||
? C + Asm.getSymbolOffset(*SymA)
|
||||
: C;
|
||||
if (usesRela(FixupSection)) {
|
||||
if (usesRela(TO, FixupSection)) {
|
||||
Addend = FixedValue;
|
||||
FixedValue = 0;
|
||||
}
|
||||
@@ -1501,9 +1558,11 @@ void ELFObjectWriter::recordRelocation(MCAssembler &Asm,
|
||||
Relocations[&FixupSection].push_back(Rec);
|
||||
}
|
||||
|
||||
bool ELFObjectWriter::usesRela(const MCSectionELF &Sec) const {
|
||||
return hasRelocationAddend() &&
|
||||
Sec.getType() != ELF::SHT_LLVM_CALL_GRAPH_PROFILE;
|
||||
bool ELFObjectWriter::usesRela(const MCTargetOptions *TO,
|
||||
const MCSectionELF &Sec) const {
|
||||
return (hasRelocationAddend() &&
|
||||
Sec.getType() != ELF::SHT_LLVM_CALL_GRAPH_PROFILE) ||
|
||||
(TO && TO->Crel);
|
||||
}
|
||||
|
||||
bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
|
||||
|
||||
@@ -47,6 +47,7 @@ MCOPT(bool, NoWarn)
|
||||
MCOPT(bool, NoDeprecatedWarn)
|
||||
MCOPT(bool, NoTypeCheck)
|
||||
MCOPT(bool, SaveTempLabels)
|
||||
MCOPT(bool, Crel)
|
||||
MCOPT(bool, X86RelaxRelocations)
|
||||
MCOPT(std::string, ABIName)
|
||||
MCOPT(std::string, AsSecureLogFile)
|
||||
@@ -128,6 +129,10 @@ llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() {
|
||||
"save-temp-labels", cl::desc("Don't discard temporary labels"));
|
||||
MCBINDOPT(SaveTempLabels);
|
||||
|
||||
static cl::opt<bool> Crel("crel",
|
||||
cl::desc("Use CREL relocation format for ELF"));
|
||||
MCBINDOPT(Crel);
|
||||
|
||||
static cl::opt<bool> X86RelaxRelocations(
|
||||
"x86-relax-relocations",
|
||||
cl::desc(
|
||||
@@ -162,6 +167,7 @@ MCTargetOptions llvm::mc::InitMCTargetOptionsFromFlags() {
|
||||
Options.MCNoDeprecatedWarn = getNoDeprecatedWarn();
|
||||
Options.MCNoTypeCheck = getNoTypeCheck();
|
||||
Options.MCSaveTempLabels = getSaveTempLabels();
|
||||
Options.Crel = getCrel();
|
||||
Options.X86RelaxRelocations = getX86RelaxRelocations();
|
||||
Options.EmitDwarfUnwind = getEmitDwarfUnwind();
|
||||
Options.EmitCompactUnwindNonCanonical = getEmitCompactUnwindNonCanonical();
|
||||
|
||||
@@ -303,6 +303,7 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) {
|
||||
STRINGIFY_ENUM_CASE(ELF, SHT_GROUP);
|
||||
STRINGIFY_ENUM_CASE(ELF, SHT_SYMTAB_SHNDX);
|
||||
STRINGIFY_ENUM_CASE(ELF, SHT_RELR);
|
||||
STRINGIFY_ENUM_CASE(ELF, SHT_CREL);
|
||||
STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_REL);
|
||||
STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_RELA);
|
||||
STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_RELR);
|
||||
@@ -392,6 +393,73 @@ ELFFile<ELFT>::decode_relrs(Elf_Relr_Range relrs) const {
|
||||
return Relocs;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
Expected<uint64_t>
|
||||
ELFFile<ELFT>::getCrelHeader(ArrayRef<uint8_t> Content) const {
|
||||
DataExtractor Data(Content, isLE(), sizeof(typename ELFT::Addr));
|
||||
Error Err = Error::success();
|
||||
uint64_t Hdr = 0;
|
||||
Hdr = Data.getULEB128(&Hdr, &Err);
|
||||
if (Err)
|
||||
return Err;
|
||||
return Hdr;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
Expected<typename ELFFile<ELFT>::RelsOrRelas>
|
||||
ELFFile<ELFT>::decodeCrel(ArrayRef<uint8_t> Content) const {
|
||||
DataExtractor Data(Content, isLE(), sizeof(typename ELFT::Addr));
|
||||
DataExtractor::Cursor Cur(0);
|
||||
const uint64_t Hdr = Data.getULEB128(Cur);
|
||||
const size_t Count = Hdr / 8;
|
||||
const size_t FlagBits = Hdr & ELF::CREL_HDR_ADDEND ? 3 : 2;
|
||||
const size_t Shift = Hdr % ELF::CREL_HDR_ADDEND;
|
||||
std::vector<Elf_Rel> Rels;
|
||||
std::vector<Elf_Rela> Relas;
|
||||
if (Hdr & ELF::CREL_HDR_ADDEND)
|
||||
Relas.resize(Count);
|
||||
else
|
||||
Rels.resize(Count);
|
||||
typename ELFT::uint Offset = 0, Addend = 0;
|
||||
uint32_t SymIdx = 0, Type = 0;
|
||||
for (size_t I = 0; I != Count; ++I) {
|
||||
// The delta offset and flags member may be larger than uint64_t. Special
|
||||
// case the first byte (2 or 3 flag bits; the rest are offset bits). Other
|
||||
// ULEB128 bytes encode the remaining delta offset bits.
|
||||
const uint8_t B = Data.getU8(Cur);
|
||||
Offset += B >> FlagBits;
|
||||
if (B >= 0x80)
|
||||
Offset += (Data.getULEB128(Cur) << (7 - FlagBits)) - (0x80 >> FlagBits);
|
||||
// Delta symidx/type/addend members (SLEB128).
|
||||
if (B & 1)
|
||||
SymIdx += Data.getSLEB128(Cur);
|
||||
if (B & 2)
|
||||
Type += Data.getSLEB128(Cur);
|
||||
if (B & 4 & Hdr)
|
||||
Addend += Data.getSLEB128(Cur);
|
||||
if (Hdr & ELF::CREL_HDR_ADDEND) {
|
||||
Relas[I].r_offset = Offset << Shift;
|
||||
Relas[I].setSymbolAndType(SymIdx, Type, false);
|
||||
Relas[I].r_addend = Addend;
|
||||
} else {
|
||||
Rels[I].r_offset = Offset << Shift;
|
||||
Rels[I].setSymbolAndType(SymIdx, Type, false);
|
||||
}
|
||||
}
|
||||
if (!Cur)
|
||||
return std::move(Cur.takeError());
|
||||
return std::make_pair(std::move(Rels), std::move(Relas));
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
Expected<typename ELFFile<ELFT>::RelsOrRelas>
|
||||
ELFFile<ELFT>::crels(const Elf_Shdr &Sec) const {
|
||||
Expected<ArrayRef<uint8_t>> ContentsOrErr = getSectionContents(Sec);
|
||||
if (!ContentsOrErr)
|
||||
return ContentsOrErr.takeError();
|
||||
return decodeCrel(*ContentsOrErr);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
Expected<std::vector<typename ELFT::Rela>>
|
||||
ELFFile<ELFT>::android_relas(const Elf_Shdr &Sec) const {
|
||||
|
||||
@@ -123,6 +123,12 @@ public:
|
||||
return encodeULEB128(Val, OS);
|
||||
}
|
||||
|
||||
unsigned writeSLEB128(int64_t Val) {
|
||||
if (!checkLimit(10))
|
||||
return 0;
|
||||
return encodeSLEB128(Val, OS);
|
||||
}
|
||||
|
||||
template <typename T> void write(T Val, llvm::endianness E) {
|
||||
if (checkLimit(sizeof(T)))
|
||||
support::endian::write<T>(OS, Val, E);
|
||||
@@ -1269,7 +1275,8 @@ void ELFState<ELFT>::writeSectionContent(
|
||||
Elf_Shdr &SHeader, const ELFYAML::RelocationSection &Section,
|
||||
ContiguousBlobAccumulator &CBA) {
|
||||
assert((Section.Type == llvm::ELF::SHT_REL ||
|
||||
Section.Type == llvm::ELF::SHT_RELA) &&
|
||||
Section.Type == llvm::ELF::SHT_RELA ||
|
||||
Section.Type == llvm::ELF::SHT_CREL) &&
|
||||
"Section type is not SHT_REL nor SHT_RELA");
|
||||
|
||||
if (!Section.RelocatableSec.empty())
|
||||
@@ -1278,29 +1285,70 @@ void ELFState<ELFT>::writeSectionContent(
|
||||
if (!Section.Relocations)
|
||||
return;
|
||||
|
||||
const bool IsCrel = Section.Type == llvm::ELF::SHT_CREL;
|
||||
const bool IsRela = Section.Type == llvm::ELF::SHT_RELA;
|
||||
typename ELFT::uint OffsetMask = 8, Offset = 0, Addend = 0;
|
||||
uint32_t SymIdx = 0, Type = 0;
|
||||
uint64_t CurrentOffset = CBA.getOffset();
|
||||
if (IsCrel)
|
||||
for (const ELFYAML::Relocation &Rel : *Section.Relocations)
|
||||
OffsetMask |= Rel.Offset;
|
||||
const int Shift = llvm::countr_zero(OffsetMask);
|
||||
if (IsCrel)
|
||||
CBA.writeULEB128(Section.Relocations->size() * 8 + ELF::CREL_HDR_ADDEND +
|
||||
Shift);
|
||||
for (const ELFYAML::Relocation &Rel : *Section.Relocations) {
|
||||
const bool IsDynamic = Section.Link && (*Section.Link == ".dynsym");
|
||||
unsigned SymIdx =
|
||||
uint32_t CurSymIdx =
|
||||
Rel.Symbol ? toSymbolIndex(*Rel.Symbol, Section.Name, IsDynamic) : 0;
|
||||
if (IsRela) {
|
||||
if (IsCrel) {
|
||||
// The delta offset and flags member may be larger than uint64_t. Special
|
||||
// case the first byte (3 flag bits and 4 offset bits). Other ULEB128
|
||||
// bytes encode the remaining delta offset bits.
|
||||
auto DeltaOffset =
|
||||
(static_cast<typename ELFT::uint>(Rel.Offset) - Offset) >> Shift;
|
||||
Offset = Rel.Offset;
|
||||
uint8_t B =
|
||||
DeltaOffset * 8 + (SymIdx != CurSymIdx) + (Type != Rel.Type ? 2 : 0) +
|
||||
(Addend != static_cast<typename ELFT::uint>(Rel.Addend) ? 4 : 0);
|
||||
if (DeltaOffset < 0x10) {
|
||||
CBA.write(B);
|
||||
} else {
|
||||
CBA.write(B | 0x80);
|
||||
CBA.writeULEB128(DeltaOffset >> 4);
|
||||
}
|
||||
// Delta symidx/type/addend members (SLEB128).
|
||||
if (B & 1) {
|
||||
CBA.writeSLEB128(
|
||||
std::make_signed_t<typename ELFT::uint>(CurSymIdx - SymIdx));
|
||||
SymIdx = CurSymIdx;
|
||||
}
|
||||
if (B & 2) {
|
||||
CBA.writeSLEB128(static_cast<int32_t>(Rel.Type - Type));
|
||||
Type = Rel.Type;
|
||||
}
|
||||
if (B & 4) {
|
||||
CBA.writeSLEB128(
|
||||
std::make_signed_t<typename ELFT::uint>(Rel.Addend - Addend));
|
||||
Addend = Rel.Addend;
|
||||
}
|
||||
} else if (IsRela) {
|
||||
Elf_Rela REntry;
|
||||
zero(REntry);
|
||||
REntry.r_offset = Rel.Offset;
|
||||
REntry.r_addend = Rel.Addend;
|
||||
REntry.setSymbolAndType(SymIdx, Rel.Type, isMips64EL(Doc));
|
||||
REntry.setSymbolAndType(CurSymIdx, Rel.Type, isMips64EL(Doc));
|
||||
CBA.write((const char *)&REntry, sizeof(REntry));
|
||||
} else {
|
||||
Elf_Rel REntry;
|
||||
zero(REntry);
|
||||
REntry.r_offset = Rel.Offset;
|
||||
REntry.setSymbolAndType(SymIdx, Rel.Type, isMips64EL(Doc));
|
||||
REntry.setSymbolAndType(CurSymIdx, Rel.Type, isMips64EL(Doc));
|
||||
CBA.write((const char *)&REntry, sizeof(REntry));
|
||||
}
|
||||
}
|
||||
|
||||
SHeader.sh_size = (IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel)) *
|
||||
Section.Relocations->size();
|
||||
SHeader.sh_size = CBA.getOffset() - CurrentOffset;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
||||
@@ -688,6 +688,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration(
|
||||
ECase(SHT_GROUP);
|
||||
ECase(SHT_SYMTAB_SHNDX);
|
||||
ECase(SHT_RELR);
|
||||
ECase(SHT_CREL);
|
||||
ECase(SHT_ANDROID_REL);
|
||||
ECase(SHT_ANDROID_RELA);
|
||||
ECase(SHT_ANDROID_RELR);
|
||||
@@ -1622,6 +1623,7 @@ void MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::mapping(
|
||||
break;
|
||||
case ELF::SHT_REL:
|
||||
case ELF::SHT_RELA:
|
||||
case ELF::SHT_CREL:
|
||||
if (!IO.outputting())
|
||||
Section.reset(new ELFYAML::RelocationSection());
|
||||
sectionMapping(IO, *cast<ELFYAML::RelocationSection>(Section.get()));
|
||||
|
||||
19
llvm/test/MC/ELF/crel-32.s
Normal file
19
llvm/test/MC/ELF/crel-32.s
Normal file
@@ -0,0 +1,19 @@
|
||||
# REQUIRES: arm-registered-target
|
||||
## Test CREL for a 32-bit big-endian target.
|
||||
## CREL enables the RELA form even if ARM normally uses REL.
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -crel -triple=armv8 %s -o %t.o
|
||||
# RUN: llvm-readelf -Sr %t.o | FileCheck %s
|
||||
|
||||
# CHECK: [ 3] .data PROGBITS 00000000 {{.*}} 000008 00 WA 0 0 1
|
||||
# CHECK-NEXT: [ 4] .crel.data CREL 00000000 {{.*}} 00000a 01 I 5 3 1
|
||||
|
||||
# CHECK: Relocation section '.crel.data' at offset {{.*}} contains 2 entries:
|
||||
# CHECK-NEXT: Offset Info Type Sym. Value Symbol's Name + Addend
|
||||
# CHECK-NEXT: 00000000 {{.*}} R_ARM_NONE 00000000 a0 - 1
|
||||
# CHECK-NEXT: 00000004 {{.*}} R_ARM_ABS32 00000000 a3 + 4000
|
||||
|
||||
.data
|
||||
.reloc .+0, BFD_RELOC_NONE, a0-1
|
||||
.reloc .+4, BFD_RELOC_32, a3+0x4000
|
||||
.quad 0
|
||||
106
llvm/test/MC/ELF/crel.s
Normal file
106
llvm/test/MC/ELF/crel.s
Normal file
@@ -0,0 +1,106 @@
|
||||
# RUN: llvm-mc -filetype=obj -crel -triple=x86_64 %s -o %t.o
|
||||
# RUN: llvm-readelf -Sr -x .crelrodata2 -x .crelrodata16 %t.o | FileCheck %s
|
||||
|
||||
# RUN: %if aarch64-registered-target %{ llvm-mc -filetype=obj -crel -triple=aarch64_be %s -o %t.be.o %}
|
||||
# RUN: %if aarch64-registered-target %{ llvm-readelf -r %t.be.o | FileCheck %s --check-prefix=A64BE %}
|
||||
|
||||
# CHECK: [ 4] .data PROGBITS 0000000000000000 {{.*}} 000008 00 WA 0 0 1
|
||||
# CHECK-NEXT: [ 5] .crel.data CREL 0000000000000000 {{.*}} 00002c 01 I 14 4 1
|
||||
# CHECK-NEXT: [ 6] .rodata PROGBITS 0000000000000000 {{.*}} 00002b 00 A 0 0 1
|
||||
# CHECK-NEXT: [ 7] .crel.rodata CREL 0000000000000000 {{.*}} 000010 01 I 14 6 1
|
||||
# CHECK-NEXT: [ 8] rodata2 PROGBITS 0000000000000000 {{.*}} 000008 00 A 0 0 1
|
||||
# CHECK-NEXT: [ 9] .crelrodata2 CREL 0000000000000000 {{.*}} 000005 01 I 14 8 1
|
||||
# CHECK-NEXT: [10] rodata16 PROGBITS 0000000000000000 {{.*}} 000010 00 A 0 0 1
|
||||
# CHECK-NEXT: [11] .crelrodata16 CREL 0000000000000000 {{.*}} 000004 01 I 14 10 1
|
||||
# CHECK-NEXT: [12] noalloc PROGBITS 0000000000000000 {{.*}} 000004 00 0 0 1
|
||||
# CHECK-NEXT: [13] .crelnoalloc CREL 0000000000000000 {{.*}} 000005 01 I 14 12 1
|
||||
# CHECK-NEXT: [14] .symtab SYMTAB
|
||||
|
||||
# CHECK: Relocation section '.crel.data' at offset {{.*}} contains 8 entries:
|
||||
# CHECK-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
# CHECK-NEXT: 0000000000000000 {{.*}} R_X86_64_NONE 0000000000000000 a0 + 0
|
||||
# CHECK-NEXT: 0000000000000001 {{.*}} R_X86_64_NONE 0000000000000000 a1 - 1
|
||||
# CHECK-NEXT: 0000000000000002 {{.*}} R_X86_64_NONE 0000000000000000 a2 - 1
|
||||
# CHECK-NEXT: 0000000000000004 {{.*}} R_X86_64_32 0000000000000000 a3 + 4000
|
||||
# CHECK-NEXT: 0000000000000005 {{.*}} R_X86_64_64 0000000000000000 a3 - 8000000000000000
|
||||
# CHECK-NEXT: 0000000000000005 {{.*}} R_X86_64_64 0000000000000000 a1 + 7fffffffffffffff
|
||||
# CHECK-NEXT: 0000000000000005 {{.*}} R_X86_64_32 0000000000000000 a1 - 1
|
||||
# CHECK-NEXT: 0000000000000005 {{.*}} R_X86_64_64 0000000000000000 a2 - 1
|
||||
# CHECK-EMPTY:
|
||||
# CHECK-NEXT: Relocation section '.crel.rodata' at offset {{.*}} contains 4 entries:
|
||||
# CHECK-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
# CHECK-NEXT: 0000000000000000 {{.*}} R_X86_64_PC32 0000000000000000 foo + 0
|
||||
# CHECK-NEXT: 000000000000000f {{.*}} R_X86_64_PC32 0000000000000000 foo + 3f
|
||||
# CHECK-NEXT: 000000000000001f {{.*}} R_X86_64_PC64 0000000000000000 foo + 7f
|
||||
# CHECK-NEXT: 0000000000000027 {{.*}} R_X86_64_PC32 0000000000000000 _start - 1f81
|
||||
# CHECK-EMPTY:
|
||||
# CHECK-NEXT: Relocation section '.crelrodata2' at offset {{.*}} contains 2 entries:
|
||||
# CHECK-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
# CHECK-NEXT: 0000000000000002 {{.*}} R_X86_64_32 0000000000000000 .data + 0
|
||||
# CHECK-NEXT: 0000000000000008 {{.*}} R_X86_64_32 0000000000000000 .data + 0
|
||||
# CHECK-EMPTY:
|
||||
# CHECK-NEXT: Relocation section '.crelrodata16' at offset {{.*}} contains 1 entries:
|
||||
# CHECK-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
# CHECK-NEXT: 0000000000000008 {{.*}} R_X86_64_64 0000000000000000 rodata16 + 0
|
||||
# CHECK-EMPTY:
|
||||
# CHECK-NEXT: Relocation section '.crelnoalloc' at offset {{.*}} contains 1 entries:
|
||||
# CHECK-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
# CHECK-NEXT: 0000000000000000 {{.*}} R_X86_64_32 0000000000000000 .text + 4
|
||||
|
||||
## count * 8 + 4 + shift = 2*8+4+1 = 21
|
||||
# CHECK: Hex dump of section '.crelrodata2':
|
||||
# CHECK-NEXT: 0x00000000 150b020a 18 .
|
||||
## count * 8 + 4 + shift = 1*8+4+3 = 15
|
||||
# CHECK: Hex dump of section '.crelrodata16':
|
||||
# CHECK-NEXT: 0x00000000 0f0b0301 .
|
||||
|
||||
# A64BE: 0000000000000000 {{.*}} R_AARCH64_NONE 0000000000000000 a0 + 0
|
||||
# A64BE-NEXT: 0000000000000001 {{.*}} R_AARCH64_NONE 0000000000000000 a1 - 1
|
||||
# A64BE-NEXT: 0000000000000002 {{.*}} R_AARCH64_NONE 0000000000000000 a2 - 1
|
||||
# A64BE-NEXT: 0000000000000004 {{.*}} R_AARCH64_ABS32 0000000000000000 a3 + 4000
|
||||
# A64BE-NEXT: 0000000000000005 {{.*}} R_AARCH64_ABS64 0000000000000000 a3 - 8000000000000000
|
||||
# A64BE-NEXT: 0000000000000005 {{.*}} R_AARCH64_ABS64 0000000000000000 a1 + 7fffffffffffffff
|
||||
# A64BE-NEXT: 0000000000000005 {{.*}} R_AARCH64_ABS32 0000000000000000 a1 - 1
|
||||
# A64BE-NEXT: 0000000000000005 {{.*}} R_AARCH64_ABS64 0000000000000000 a2 - 1
|
||||
# A64BE-EMPTY:
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
ret
|
||||
|
||||
.section .text.1,"ax"
|
||||
ret
|
||||
|
||||
## Test various combinations of delta offset and flags, delta symbol index
|
||||
## (if present), delta type (if present), delta addend (if present).
|
||||
.data
|
||||
.reloc .+0, BFD_RELOC_NONE, a0
|
||||
.reloc .+1, BFD_RELOC_NONE, a1-1 // same type
|
||||
.reloc .+2, BFD_RELOC_NONE, a2-1 // same type and addend
|
||||
.reloc .+4, BFD_RELOC_32, a3+0x4000
|
||||
.reloc .+5, BFD_RELOC_64, a3-0x8000000000000000 // same symbol index
|
||||
.reloc .+5, BFD_RELOC_64, a1+0x7fffffffffffffff // same offset and type; addend+=UINT64_MAX
|
||||
.reloc .+5, BFD_RELOC_32, a1-1 // same offset and symbol index
|
||||
.reloc .+5, BFD_RELOC_64, a2-1 // same offset and addend
|
||||
.quad 0
|
||||
|
||||
.section .rodata,"a"
|
||||
.long foo - .
|
||||
.space 15-4
|
||||
.long foo - . + 63 // offset+=15
|
||||
.space 16-4
|
||||
.quad foo - . + 127 // offset+=16
|
||||
.long _start - . - 8065
|
||||
|
||||
.section rodata2,"a"
|
||||
.space 2
|
||||
.reloc ., BFD_RELOC_32, .data
|
||||
.space 6
|
||||
.reloc ., BFD_RELOC_32, .data
|
||||
|
||||
.section rodata16,"a"
|
||||
.quad 0
|
||||
.quad rodata16
|
||||
|
||||
.section noalloc
|
||||
.long .text + 4
|
||||
230
llvm/test/tools/llvm-readobj/ELF/crel.test
Normal file
230
llvm/test/tools/llvm-readobj/ELF/crel.test
Normal file
@@ -0,0 +1,230 @@
|
||||
# RUN: yaml2obj --docnum=1 %s -o %t
|
||||
# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=LLVM --match-full-lines
|
||||
# RUN: llvm-readelf -r %t | FileCheck %s --check-prefix=GNU --match-full-lines
|
||||
|
||||
# LLVM: Relocations [
|
||||
# LLVM-NEXT: Section ([[#]]) .crel.text {
|
||||
# LLVM-NEXT: 0x1 R_X86_64_32 g1 0x1
|
||||
# LLVM-NEXT: 0x2 R_X86_64_64 l1 0x2
|
||||
# LLVM-NEXT: 0x0 R_X86_64_32S g1 0xFFFFFFFFFFFFFFFF
|
||||
# LLVM-NEXT: 0x4 R_X86_64_32S .text 0x8000000000000000
|
||||
# LLVM-NEXT: }
|
||||
# LLVM-NEXT: Section ([[#]]) .crelnonalloc {
|
||||
# LLVM-NEXT: 0x10 R_X86_64_64 g1 0x1
|
||||
# LLVM-NEXT: 0x20 R_X86_64_64 g2 0x2
|
||||
# LLVM-NEXT: }
|
||||
# LLVM-NEXT: ]
|
||||
|
||||
# GNU: Relocation section '.crel.text' at offset 0x48 contains 4 entries:
|
||||
# GNU-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
# GNU-NEXT: 0000000000000001 000000030000000a R_X86_64_32 0000000000000000 g1 + 1
|
||||
# GNU-NEXT: 0000000000000002 0000000200000001 R_X86_64_64 0000000000000000 l1 + 2
|
||||
# GNU-NEXT: 0000000000000000 000000030000000b R_X86_64_32S 0000000000000000 g1 - 1
|
||||
# GNU-NEXT: 0000000000000004 000000010000000b R_X86_64_32S 0000000000000000 .text - 8000000000000000
|
||||
# GNU-EMPTY:
|
||||
# GNU-NEXT: Relocation section '.crelnonalloc' at offset 0xa2 contains 2 entries:
|
||||
# GNU-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
# GNU-NEXT: 0000000000000010 0000000300000001 R_X86_64_64 0000000000000000 g1 + 1
|
||||
# GNU-NEXT: 0000000000000020 0000000400000001 R_X86_64_64 0000000000000000 g2 + 2
|
||||
|
||||
--- !ELF
|
||||
FileHeader: !FileHeader
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
|
||||
Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
Content: "0000000000000000"
|
||||
Flags: [SHF_ALLOC]
|
||||
- Name: .crel.text
|
||||
Type: SHT_CREL
|
||||
Info: .text
|
||||
Link: .symtab
|
||||
Relocations:
|
||||
- Offset: 0x1
|
||||
Symbol: g1
|
||||
Type: R_X86_64_32
|
||||
Addend: 1
|
||||
- Offset: 0x2
|
||||
Symbol: l1
|
||||
Type: R_X86_64_64
|
||||
Addend: 2
|
||||
- Offset: 0x0
|
||||
Symbol: g1
|
||||
Type: R_X86_64_32S
|
||||
Addend: 0xffffffffffffffff
|
||||
- Offset: 0x4
|
||||
Symbol: .text
|
||||
Type: R_X86_64_32S
|
||||
Addend: 0x8000000000000000
|
||||
- Name: nonalloc
|
||||
Type: SHT_PROGBITS
|
||||
Size: 0x30
|
||||
- Name: .crelnonalloc
|
||||
Type: SHT_CREL
|
||||
Info: nonalloc
|
||||
Link: .symtab
|
||||
Relocations:
|
||||
- Offset: 0x10
|
||||
Symbol: g1
|
||||
Type: R_X86_64_64
|
||||
Addend: 1
|
||||
- Offset: 0x20
|
||||
Symbol: g2
|
||||
Type: R_X86_64_64
|
||||
Addend: 2
|
||||
|
||||
Symbols:
|
||||
- Name: .text
|
||||
Type: STT_SECTION
|
||||
Section: .text
|
||||
- Name: l1
|
||||
- Name: g1
|
||||
Section: .text
|
||||
Value: 0x0
|
||||
Size: 4
|
||||
Binding: STB_GLOBAL
|
||||
- Name: g2
|
||||
Binding: STB_GLOBAL
|
||||
|
||||
## Check relocation formatting on ELFCLASS32 as well.
|
||||
# RUN: yaml2obj --docnum=2 %s -o %t2
|
||||
# RUN: llvm-readobj -r %t2 | FileCheck %s --check-prefix=LLVM2 --match-full-lines
|
||||
# RUN: llvm-readelf -r %t2 | FileCheck %s --check-prefix=GNU2 --match-full-lines
|
||||
|
||||
# LLVM2: Relocations [
|
||||
# LLVM2-NEXT: Section (2) .crel.text {
|
||||
# LLVM2-NEXT: 0x8 R_386_PC32 l1 0x1
|
||||
# LLVM2-NEXT: 0x4 R_386_32 g1 0x0
|
||||
# LLVM2-NEXT: }
|
||||
# LLVM2-NEXT: ]
|
||||
|
||||
# GNU2: Relocation section '.crel.text' at offset {{.*}} contains 2 entries:
|
||||
# GNU2-NEXT: Offset Info Type Sym. Value Symbol's Name + Addend
|
||||
# GNU2-NEXT: 00000008 00000102 R_386_PC32 00000000 l1 + 1
|
||||
# GNU2-NEXT: 00000004 00000201 R_386_32 00000000 g1 + 0
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS32
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_386
|
||||
Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
Size: 0x10
|
||||
- Name: .crel.text
|
||||
Type: SHT_CREL
|
||||
Info: .text
|
||||
Link: .symtab
|
||||
Relocations:
|
||||
- Offset: 0x8
|
||||
Symbol: l1
|
||||
Type: R_386_PC32
|
||||
Addend: 1
|
||||
- Offset: 0x4
|
||||
Symbol: g1
|
||||
Type: R_386_32
|
||||
Symbols:
|
||||
- Name: l1
|
||||
- Name: g1
|
||||
Binding: STB_GLOBAL
|
||||
|
||||
## Check CREL with implicit addends.
|
||||
# RUN: yaml2obj --docnum=3 %s -o %t3
|
||||
# RUN: llvm-readobj -r %t3 | FileCheck %s --check-prefix=LLVM3 --match-full-lines
|
||||
# RUN: llvm-readelf -r %t3 | FileCheck %s --check-prefix=GNU3 --match-full-lines
|
||||
|
||||
# LLVM3: Relocations [
|
||||
# LLVM3-NEXT: Section (3) .crel.data {
|
||||
# LLVM3-NEXT: 0x1F R_X86_64_32 g1
|
||||
# LLVM3-NEXT: 0x3F R_X86_64_64 g1
|
||||
# LLVM3-NEXT: 0x0 R_X86_64_32S l1
|
||||
# LLVM3-NEXT: }
|
||||
# LLVM3-NEXT: ]
|
||||
|
||||
# GNU3: Relocation section '.crel.data' at offset {{.*}} contains 3 entries:
|
||||
# GNU3-NEXT: Offset Info Type Symbol's Value Symbol's Name
|
||||
# GNU3-NEXT: 000000000000001f 000000030000000a R_X86_64_32 0000000000000000 g1
|
||||
# GNU3-NEXT: 000000000000003f 0000000300000001 R_X86_64_64 0000000000000000 g1
|
||||
# GNU3-NEXT: 0000000000000000 000000020000000b R_X86_64_32S 0000000000000000 l1
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .data
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .crel.data
|
||||
Type: SHT_CREL
|
||||
Flags: [ SHF_INFO_LINK ]
|
||||
Link: .symtab
|
||||
Info: .data
|
||||
Content: 187f030a82017787feffffffffffffff077f0a
|
||||
Symbols:
|
||||
- Name: .text
|
||||
Type: STT_SECTION
|
||||
Section: .text
|
||||
- Name: l1
|
||||
Section: .text
|
||||
- Name: g1
|
||||
Section: .text
|
||||
Binding: STB_GLOBAL
|
||||
|
||||
## Test errors. See also relocation-errors.test.
|
||||
# RUN: yaml2obj --docnum=4 %s -o %t.err
|
||||
# RUN: llvm-readobj -r %t.err 2>&1 | FileCheck %s --check-prefix=ERR-LLVM -DFILE=%t.err
|
||||
# RUN: llvm-readelf -r %t.err 2>&1 | FileCheck %s --check-prefix=ERR-GNU -DFILE=%t.err
|
||||
|
||||
# ERR-LLVM: Section ([[#]]) .crel.data {
|
||||
# ERR-LLVM-NEXT: warning: '[[FILE]]': unable to read relocations from SHT_CREL section with index 3: unable to decode LEB128 at offset 0x00000000: malformed uleb128, extends past end
|
||||
# ERR-LLVM-NEXT: }
|
||||
|
||||
# ERR-GNU: warning: '[[FILE]]': unable to get the number of relocations in SHT_CREL section with index 3: unable to decode LEB128 at offset 0x00000000: malformed uleb128, extends past end
|
||||
# ERR-GNU-EMPTY:
|
||||
# ERR-GNU-NEXT: Relocation section '.crel.data' at offset 0x40 contains <?> entries:
|
||||
# ERR-GNU-NEXT: Offset Info Type Symbol's Value Symbol's Name
|
||||
# ERR-GNU-NOT: {{.}}
|
||||
|
||||
# RUN: yaml2obj --docnum=4 -DCONTENT=08 %s -o %t.err2
|
||||
# RUN: llvm-readobj -r %t.err2 2>&1 | FileCheck %s --check-prefix=ERR2-LLVM -DFILE=%t.err2
|
||||
# RUN: llvm-readelf -r %t.err2 2>&1 | FileCheck %s --check-prefix=ERR2-GNU -DFILE=%t.err2
|
||||
|
||||
# ERR2-LLVM: Section ([[#]]) .crel.data {
|
||||
# ERR2-LLVM-NEXT: warning: '[[FILE]]': unable to read relocations from SHT_CREL section with index 3: unexpected end of data at offset 0x1 while reading [0x1, 0x2)
|
||||
# ERR2-LLVM-NEXT: }
|
||||
|
||||
# ERR2-GNU: Relocation section '.crel.data' at offset 0x40 contains 1 entries:
|
||||
# ERR2-GNU-NEXT: Offset Info Type Symbol's Value Symbol's Name
|
||||
# ERR2-GNU: warning: '[[FILE]]': unable to read relocations from SHT_CREL section with index 3: unexpected end of data at offset 0x1 while reading [0x1, 0x2)
|
||||
# ERR2-GNU-NOT: {{.}}
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .data
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .crel.data
|
||||
Type: SHT_CREL
|
||||
Flags: []
|
||||
Link: .symtab
|
||||
Info: .data
|
||||
Content: [[CONTENT=""]]
|
||||
Symbols:
|
||||
- Name: .text
|
||||
Type: STT_SECTION
|
||||
Section: .text
|
||||
@@ -32,12 +32,17 @@ FileHeader:
|
||||
# RUN: --match-full-lines --check-prefixes=GNU-RELOCS,GNU-PLTRELA
|
||||
|
||||
# LLVM-RELOCS: Dynamic Relocations {
|
||||
# LLVM-RELOCS-NEXT: 0x8 R_X86_64_64 foo 0x0
|
||||
# LLVM-RELOCS-NEXT: 0x1 R_X86_64_NONE foo 0x0
|
||||
# LLVM-RELOCS-NEXT: 0x2 R_X86_64_NONE foo
|
||||
# LLVM-RELOCS-NEXT: 0x4 R_X86_64_RELATIVE
|
||||
# LLVM-RELOCS-NEXT: 0x4 R_X86_64_RELATIVE -
|
||||
# LLVM-RELOCS-NEXT: 0x8 R_X86_64_NONE foo
|
||||
# LLVM-RELOCS-NEXT: }
|
||||
|
||||
# GNU-RELOCS:'CREL' relocation section at offset 0xa8:
|
||||
# GNU-RELOCS-NEXT: Offset Info Type Symbol's Value Symbol's Name
|
||||
# GNU-RELOCS-NEXT:0000000000000008 0000000100000001 R_X86_64_64 0000000000000000 foo + 0
|
||||
# GNU-RELOCS-EMPTY:
|
||||
# GNU-RELOCS:'RELA' relocation section at offset 0x78 contains 24 bytes:
|
||||
# GNU-RELOCS-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
# GNU-RELOCS-NEXT:0000000000000001 0000000100000000 R_X86_64_NONE 0000000000000000 foo + 0
|
||||
@@ -50,10 +55,10 @@ FileHeader:
|
||||
# GNU-RELOCS-NEXT: Offset Info Type Symbol's Value Symbol's Name
|
||||
# GNU-RELOCS-NEXT:0000000000000004 0000000000000008 R_X86_64_RELATIVE {{$}}
|
||||
# GNU-RELOCS-EMPTY:
|
||||
# GNU-PLTREL-NEXT:'PLT' relocation section at offset 0xa8 contains 16 bytes:
|
||||
# GNU-PLTREL-NEXT:'PLT' relocation section at offset 0xac contains 16 bytes:
|
||||
# GNU-PLTREL-NEXT: Offset Info Type Symbol's Value Symbol's Name
|
||||
# GNU-PLTREL-NEXT:0000000000000008 0000000100000000 R_X86_64_NONE 0000000000000000 foo
|
||||
# GNU-PLTRELA-NEXT:'PLT' relocation section at offset 0xa8 contains 24 bytes:
|
||||
# GNU-PLTRELA-NEXT:'PLT' relocation section at offset 0xac contains 24 bytes:
|
||||
# GNU-PLTRELA-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
# GNU-PLTRELA-NEXT:0000000000000008 0000000100000000 R_X86_64_NONE 0000000000000000 foo + 0
|
||||
# GNU-RELOCS-EMPTY:
|
||||
@@ -82,6 +87,12 @@ Sections:
|
||||
Type: SHT_RELR
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Entries: [ 0x0000000000000004 ]
|
||||
- Name: .crel.dyn
|
||||
Type: SHT_CREL
|
||||
Relocations:
|
||||
- Type: R_X86_64_64
|
||||
Offset: 0x8
|
||||
Symbol: foo
|
||||
- Name: .plt
|
||||
Type: [[PLTTYPE=SHT_REL]]
|
||||
Relocations:
|
||||
@@ -111,9 +122,12 @@ Sections:
|
||||
Value: 0x8
|
||||
- Tag: DT_RELRENT
|
||||
Value: 0x8
|
||||
## 0x30 == offset of .plt section in the segment.
|
||||
- Tag: DT_JMPREL
|
||||
## 0x30 == offset of .crel.dyn section in the segment.
|
||||
- Tag: DT_CREL
|
||||
Value: 0x30
|
||||
## 0x34 == offset of .plt section in the segment.
|
||||
- Tag: DT_JMPREL
|
||||
Value: 0x34
|
||||
- Tag: DT_PLTREL
|
||||
Value: [[DTPLTREL=17]] ## 17 == DT_REL
|
||||
- Tag: DT_PLTRELSZ
|
||||
@@ -140,6 +154,7 @@ ProgramHeaders:
|
||||
|
||||
# PLTRELUNKNOWN-LLVM: warning: '[[FILE]]': unknown DT_PLTREL value of 255
|
||||
# PLTRELUNKNOWN-LLVM: Dynamic Relocations {
|
||||
# PLTRELUNKNOWN-LLVM-NEXT: 0x8 R_X86_64_64 foo 0x0
|
||||
# PLTRELUNKNOWN-LLVM-NEXT: 0x1 R_X86_64_NONE foo 0x0
|
||||
# PLTRELUNKNOWN-LLVM-NEXT: 0x2 R_X86_64_NONE foo{{$}}
|
||||
# PLTRELUNKNOWN-LLVM-NEXT: 0x4 R_X86_64_RELATIVE -{{$}}
|
||||
@@ -148,6 +163,10 @@ ProgramHeaders:
|
||||
|
||||
# PLTRELUNKNOWN-GNU: warning: '[[FILE]]': unknown DT_PLTREL value of 255
|
||||
# PLTRELUNKNOWN-GNU-EMPTY:
|
||||
# PLTRELUNKNOWN-GNU-NEXT: 'CREL' relocation section at offset 0xa8:
|
||||
# PLTRELUNKNOWN-GNU-NEXT: Offset Info Type Symbol's Value Symbol's Name
|
||||
# PLTRELUNKNOWN-GNU-NEXT: 0000000000000008 0000000100000001 R_X86_64_64 0000000000000000 foo + 0
|
||||
# PLTRELUNKNOWN-GNU-EMPTY:
|
||||
# PLTRELUNKNOWN-GNU-NEXT: 'RELA' relocation section at offset 0x78 contains 24 bytes:
|
||||
# PLTRELUNKNOWN-GNU-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
# PLTRELUNKNOWN-GNU-NEXT: 0000000000000001 0000000100000000 R_X86_64_NONE 0000000000000000 foo + 0
|
||||
@@ -160,6 +179,6 @@ ProgramHeaders:
|
||||
# PLTRELUNKNOWN-GNU-NEXT: Offset Info Type Symbol's Value Symbol's Name
|
||||
# PLTRELUNKNOWN-GNU-NEXT: 0000000000000004 0000000000000008 R_X86_64_RELATIVE
|
||||
# PLTRELUNKNOWN-GNU-EMPTY:
|
||||
# PLTRELUNKNOWN-GNU-NEXT: 'PLT' relocation section at offset 0xa8 contains 16 bytes:
|
||||
# PLTRELUNKNOWN-GNU-NEXT: 'PLT' relocation section at offset 0xac contains 16 bytes:
|
||||
# PLTRELUNKNOWN-GNU-NEXT: Offset Info Type Symbol's Value Symbol's Name
|
||||
# PLTRELUNKNOWN-GNU-NEXT: warning: '[[FILE]]': invalid DT_PLTRELSZ value (0x10) or PLTREL entry size (0x0)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
# RUN: llvm-readelf --dynamic-table --pretty-print --elf-output-style=JSON %t1 \
|
||||
# RUN: | FileCheck %s --strict-whitespace --check-prefix=JSON64
|
||||
|
||||
# LLVM64:DynamicSection [ (61 entries)
|
||||
# LLVM64:DynamicSection [ (62 entries)
|
||||
# LLVM64-NEXT: Tag Type Name/Value
|
||||
# LLVM64-NEXT: 0x0000000000000001 NEEDED Shared library: D
|
||||
# LLVM64-NEXT: 0x0000000000000002 PLTRELSZ 16 (bytes)
|
||||
@@ -49,6 +49,7 @@
|
||||
# LLVM64-NEXT: 0x0000000000000023 RELRSZ 16 (bytes)
|
||||
# LLVM64-NEXT: 0x0000000000000024 RELR 0x1000
|
||||
# LLVM64-NEXT: 0x0000000000000025 RELRENT 17185 (bytes)
|
||||
# LLVM64-NEXT: 0x0000000040000026 CREL 0x40
|
||||
# LLVM64-NEXT: 0x000000006000000F ANDROID_REL 0x1000
|
||||
# LLVM64-NEXT: 0x0000000060000010 ANDROID_RELSZ 16 (bytes)
|
||||
# LLVM64-NEXT: 0x0000000060000011 ANDROID_RELA 0x1000
|
||||
@@ -76,7 +77,7 @@
|
||||
# LLVM64-NEXT: 0x0000000000000000 NULL 0x0
|
||||
# LLVM64-NEXT:]
|
||||
|
||||
# GNU64:Dynamic section at offset {{.*}} contains 61 entries:
|
||||
# GNU64:Dynamic section at offset {{.*}} contains 62 entries:
|
||||
# GNU64-NEXT: Tag Type Name/Value
|
||||
# GNU64-NEXT: 0x0000000000000001 (NEEDED) Shared library: D
|
||||
# GNU64-NEXT: 0x0000000000000002 (PLTRELSZ) 16 (bytes)
|
||||
@@ -114,6 +115,7 @@
|
||||
# GNU64-NEXT: 0x0000000000000023 (RELRSZ) 16 (bytes)
|
||||
# GNU64-NEXT: 0x0000000000000024 (RELR) 0x1000
|
||||
# GNU64-NEXT: 0x0000000000000025 (RELRENT) 17185 (bytes)
|
||||
# GNU64-NEXT: 0x0000000040000026 (CREL) 0x40
|
||||
# GNU64-NEXT: 0x000000006000000f (ANDROID_REL) 0x1000
|
||||
# GNU64-NEXT: 0x0000000060000010 (ANDROID_RELSZ) 16 (bytes)
|
||||
# GNU64-NEXT: 0x0000000060000011 (ANDROID_RELA) 0x1000
|
||||
@@ -339,6 +341,11 @@
|
||||
# JSON64-NEXT: "Value": 17185
|
||||
# JSON64-NEXT: },
|
||||
# JSON64-NEXT: {
|
||||
# JSON64-NEXT: "Tag": 1073741862,
|
||||
# JSON64-NEXT: "Type": "CREL",
|
||||
# JSON64-NEXT: "Value": 64
|
||||
# JSON64-NEXT: },
|
||||
# JSON64-NEXT: {
|
||||
# JSON64-NEXT: "Tag": 1610612751,
|
||||
# JSON64-NEXT: "Type": "ANDROID_REL",
|
||||
# JSON64-NEXT: "Value": 4096
|
||||
@@ -585,6 +592,8 @@ Sections:
|
||||
Value: 0x1000
|
||||
- Tag: DT_RELRENT
|
||||
Value: 0x4321
|
||||
- Tag: DT_CREL
|
||||
Value: 0x40
|
||||
- Tag: DT_ANDROID_REL
|
||||
Value: 0x1000
|
||||
- Tag: DT_ANDROID_RELSZ
|
||||
@@ -659,7 +668,7 @@ ProgramHeaders:
|
||||
# RUN: | FileCheck %s --check-prefix=GNU32 --strict-whitespace --match-full-lines
|
||||
# RUN: llvm-readelf -d %t2 | FileCheck %s --check-prefix=GNU32 --strict-whitespace --match-full-lines
|
||||
|
||||
# LLVM32:DynamicSection [ (61 entries)
|
||||
# LLVM32:DynamicSection [ (62 entries)
|
||||
# LLVM32-NEXT: Tag Type Name/Value
|
||||
# LLVM32-NEXT: 0x00000001 NEEDED Shared library: D
|
||||
# LLVM32-NEXT: 0x00000002 PLTRELSZ 16 (bytes)
|
||||
@@ -697,6 +706,7 @@ ProgramHeaders:
|
||||
# LLVM32-NEXT: 0x00000023 RELRSZ 16 (bytes)
|
||||
# LLVM32-NEXT: 0x00000024 RELR 0x1000
|
||||
# LLVM32-NEXT: 0x00000025 RELRENT 17185 (bytes)
|
||||
# LLVM32-NEXT: 0x40000026 CREL 0x40
|
||||
# LLVM32-NEXT: 0x6000000F ANDROID_REL 0x1000
|
||||
# LLVM32-NEXT: 0x60000010 ANDROID_RELSZ 16 (bytes)
|
||||
# LLVM32-NEXT: 0x60000011 ANDROID_RELA 0x1000
|
||||
@@ -724,7 +734,7 @@ ProgramHeaders:
|
||||
# LLVM32-NEXT: 0x00000000 NULL 0x0
|
||||
# LLVM32-NEXT:]
|
||||
|
||||
# GNU32:Dynamic section at offset 0x84 contains 61 entries:
|
||||
# GNU32:Dynamic section at offset 0x84 contains 62 entries:
|
||||
# GNU32-NEXT: Tag Type Name/Value
|
||||
# GNU32-NEXT: 0x00000001 (NEEDED) Shared library: D
|
||||
# GNU32-NEXT: 0x00000002 (PLTRELSZ) 16 (bytes)
|
||||
@@ -762,6 +772,7 @@ ProgramHeaders:
|
||||
# GNU32-NEXT: 0x00000023 (RELRSZ) 16 (bytes)
|
||||
# GNU32-NEXT: 0x00000024 (RELR) 0x1000
|
||||
# GNU32-NEXT: 0x00000025 (RELRENT) 17185 (bytes)
|
||||
# GNU32-NEXT: 0x40000026 (CREL) 0x40
|
||||
# GNU32-NEXT: 0x6000000f (ANDROID_REL) 0x1000
|
||||
# GNU32-NEXT: 0x60000010 (ANDROID_RELSZ) 16 (bytes)
|
||||
# GNU32-NEXT: 0x60000011 (ANDROID_RELA) 0x1000
|
||||
@@ -848,13 +859,14 @@ Sections:
|
||||
# PHENTSIZE-WARN-NEXT: warning: '[[FILE]]': unable to parse DT_JMPREL: invalid e_phentsize: 1
|
||||
# PHENTSIZE-WARN-NEXT: warning: '[[FILE]]': unable to parse DT_SYMTAB_SHNDX: invalid e_phentsize: 1
|
||||
# PHENTSIZE-WARN-NEXT: warning: '[[FILE]]': unable to parse DT_RELR: invalid e_phentsize: 1
|
||||
# PHENTSIZE-WARN-NEXT: warning: '[[FILE]]': unable to parse DT_CREL: invalid e_phentsize: 1
|
||||
# PHENTSIZE-WARN-NEXT: warning: '[[FILE]]': unable to parse DT_ANDROID_RELR: invalid e_phentsize: 1
|
||||
# PHENTSIZE-WARN-NEXT: warning: '[[FILE]]': unable to parse DT_GNU_HASH: invalid e_phentsize: 1
|
||||
|
||||
# PHENTSIZE-LLVM: warning: '[[FILE]]': string table was not found
|
||||
# PHENTSIZE-LLVM-NEXT: LoadName: <?>
|
||||
|
||||
# PHENTSIZE-LLVM: DynamicSection [ (61 entries)
|
||||
# PHENTSIZE-LLVM: DynamicSection [ (62 entries)
|
||||
# PHENTSIZE-LLVM-NEXT: Tag Type Name/Value
|
||||
# PHENTSIZE-LLVM-NEXT: 0x0000000000000001 NEEDED Shared library: <?>
|
||||
# PHENTSIZE-LLVM-NEXT: 0x0000000000000002 PLTRELSZ 16 (bytes)
|
||||
@@ -892,6 +904,7 @@ Sections:
|
||||
# PHENTSIZE-LLVM-NEXT: 0x0000000000000023 RELRSZ 16 (bytes)
|
||||
# PHENTSIZE-LLVM-NEXT: 0x0000000000000024 RELR 0x1000
|
||||
# PHENTSIZE-LLVM-NEXT: 0x0000000000000025 RELRENT 17185 (bytes)
|
||||
# PHENTSIZE-LLVM-NEXT: 0x0000000040000026 CREL 0x40
|
||||
# PHENTSIZE-LLVM-NEXT: 0x000000006000000F ANDROID_REL 0x1000
|
||||
# PHENTSIZE-LLVM-NEXT: 0x0000000060000010 ANDROID_RELSZ 16 (bytes)
|
||||
# PHENTSIZE-LLVM-NEXT: 0x0000000060000011 ANDROID_RELA 0x1000
|
||||
@@ -919,7 +932,7 @@ Sections:
|
||||
# PHENTSIZE-LLVM-NEXT: 0x0000000000000000 NULL 0x0
|
||||
# PHENTSIZE-LLVM-NEXT: ]
|
||||
|
||||
# PHENTSIZE-GNU: Dynamic section at offset 0xc0 contains 61 entries:
|
||||
# PHENTSIZE-GNU: Dynamic section at offset 0xc0 contains 62 entries:
|
||||
# PHENTSIZE-GNU-NEXT: Tag Type Name/Value
|
||||
# PHENTSIZE-GNU-NEXT: warning: '[[FILE]]': string table was not found
|
||||
# PHENTSIZE-GNU-NEXT: 0x0000000000000001 (NEEDED) Shared library: <?>
|
||||
@@ -958,6 +971,7 @@ Sections:
|
||||
# PHENTSIZE-GNU-NEXT: 0x0000000000000023 (RELRSZ) 16 (bytes)
|
||||
# PHENTSIZE-GNU-NEXT: 0x0000000000000024 (RELR) 0x1000
|
||||
# PHENTSIZE-GNU-NEXT: 0x0000000000000025 (RELRENT) 17185 (bytes)
|
||||
# PHENTSIZE-GNU-NEXT: 0x0000000040000026 (CREL) 0x40
|
||||
# PHENTSIZE-GNU-NEXT: 0x000000006000000f (ANDROID_REL) 0x1000
|
||||
# PHENTSIZE-GNU-NEXT: 0x0000000060000010 (ANDROID_RELSZ) 16 (bytes)
|
||||
# PHENTSIZE-GNU-NEXT: 0x0000000060000011 (ANDROID_RELA) 0x1000
|
||||
|
||||
@@ -37,6 +37,23 @@
|
||||
# GNU-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
# GNU-NEXT: warning: '[[FILE]]': unable to print relocation 0 in SHT_RELA section with index 4: invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM
|
||||
|
||||
# RUN: yaml2obj -DTYPE=SHT_CREL %s -o %t64.crel
|
||||
# RUN: llvm-readelf --relocations %t64.crel 2>&1 | FileCheck %s -DFILE=%t64.crel --check-prefix=CREL-GNU
|
||||
|
||||
# CREL-GNU: Relocation section '.rel.text' at offset 0x41 contains 7 entries:
|
||||
# CREL-GNU-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
# CREL-GNU-NEXT: warning: '[[FILE]]': unable to print relocation 0 in SHT_CREL section with index 3: unable to read an entry with index 4278124286 from SHT_NULL section with index 0: section [index 0] has invalid sh_entsize: expected 24, but got 0
|
||||
# CREL-GNU-NEXT: warning: '[[FILE]]': unable to print relocation 1 in SHT_CREL section with index 3: unable to read an entry with index 4278124286 from SHT_NULL section with index 0: section [index 0] has invalid sh_entsize: expected 24, but got 0
|
||||
# CREL-GNU-NEXT: 0000000000000002 0000000000000000 R_X86_64_NONE 0
|
||||
# CREL-GNU-NEXT: warning: '[[FILE]]': unable to print relocation 3 in SHT_CREL section with index 3: unable to read an entry with index 2 from SHT_NULL section with index 0: section [index 0] has invalid sh_entsize: expected 24, but got 0
|
||||
# CREL-GNU-NEXT: warning: '[[FILE]]': unable to print relocation 4 in SHT_CREL section with index 3: unable to read an entry with index 4 from SHT_NULL section with index 0: section [index 0] has invalid sh_entsize: expected 24, but got 0
|
||||
# CREL-GNU-NEXT: warning: '[[FILE]]': unable to print relocation 5 in SHT_CREL section with index 3: unable to read an entry with index 3 from SHT_NULL section with index 0: section [index 0] has invalid sh_entsize: expected 24, but got 0
|
||||
# CREL-GNU-NEXT: warning: '[[FILE]]': unable to print relocation 6 in SHT_CREL section with index 3: unable to read an entry with index 5 from SHT_NULL section with index 0: section [index 0] has invalid sh_entsize: expected 24, but got 0
|
||||
# CREL-GNU-EMPTY:
|
||||
# CREL-GNU-NEXT: Relocation section '.rela.text' at offset 0x5a contains 1 entries:
|
||||
# CREL-GNU-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
# CREL-GNU-NEXT: warning: '[[FILE]]': unable to print relocation 0 in SHT_RELA section with index 4: invalid sh_type for symbol table, expected SHT_SYMTAB or SHT_DYNSYM
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
@@ -51,7 +68,7 @@ Sections:
|
||||
Type: SHT_PROGBITS
|
||||
ShName: 0xFEFEFEFE
|
||||
- Name: .rel.text
|
||||
Type: SHT_REL
|
||||
Type: [[TYPE=SHT_REL]]
|
||||
Info: .text
|
||||
Relocations:
|
||||
## Case 1: There is no symbol with index 0xFEFEFEFE.
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
# LLVM: Type: SHT_SYMTAB_SHNDX
|
||||
# LLVM: Name: relr
|
||||
# LLVM: Type: SHT_RELR
|
||||
# LLVM: Name: crel
|
||||
# LLVM: Type: SHT_CREL (0x40000014)
|
||||
# LLVM: Name: android_rel
|
||||
# LLVM: Type: SHT_ANDROID_REL
|
||||
# LLVM: Name: android_rela
|
||||
@@ -110,6 +112,7 @@
|
||||
# GNU-NEXT: group GROUP
|
||||
# GNU-NEXT: symtab_shndx SYMTAB SECTION INDICES
|
||||
# GNU-NEXT: relr RELR
|
||||
# GNU-NEXT: crel CREL
|
||||
# GNU-NEXT: android_rel ANDROID_REL
|
||||
# GNU-NEXT: android_rela ANDROID_RELA
|
||||
# GNU-NEXT: android_relr ANDROID_RELR
|
||||
@@ -185,6 +188,8 @@ Sections:
|
||||
Entries: [ 0, 1 ]
|
||||
- Name: relr
|
||||
Type: SHT_RELR
|
||||
- Name: crel
|
||||
Type: SHT_CREL
|
||||
- Name: android_rel
|
||||
Type: SHT_ANDROID_REL
|
||||
- Name: android_rela
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# RUN: yaml2obj %s -o %t
|
||||
# RUN: llvm-readelf -r %t | FileCheck %s
|
||||
|
||||
# RUN: yaml2obj -DTYPE=SHT_CREL %s -o %t.crel
|
||||
# RUN: llvm-readelf -r %t.crel | FileCheck %s
|
||||
|
||||
# CHECK: Relocation section '.rela.dyn' at offset {{.*}} contains 2 entries:
|
||||
# CHECK-NEXT: Offset Info Type Symbol's Value Symbol's Name
|
||||
# CHECK-NEXT: 0000000000000000 0000000100000000 R_X86_64_NONE 0000000012345678 dynamic
|
||||
@@ -24,7 +27,7 @@ Sections:
|
||||
- Name: .data
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .rela.dyn
|
||||
Type: SHT_REL
|
||||
Type: [[TYPE=SHT_REL]]
|
||||
Link: .dynsym
|
||||
Info: .data
|
||||
Relocations:
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
# ELF64: .relr.default RELR 0000000000000000 000040 000000 08
|
||||
# ELF64: .rela.custom RELA 0000000000000000 000040 000000 ff
|
||||
# ELF64: .rel.custom REL 0000000000000000 000040 000000 ff
|
||||
# ELF64: .crel.custom CREL 0000000000000000 000040 000000 ff
|
||||
# ELF64: .relr.custom RELR 0000000000000000 000040 000000 ff
|
||||
|
||||
# ELF32: Name Type Address Off Size ES
|
||||
@@ -20,6 +21,7 @@
|
||||
# ELF32: .relr.default RELR 00000000 000034 000000 04
|
||||
# ELF32: .rela.custom RELA 00000000 000034 000000 ff
|
||||
# ELF32: .rel.custom REL 00000000 000034 000000 ff
|
||||
# ELF32: .crel.custom CREL 00000000 000034 000000 ff
|
||||
# ELF32: .relr.custom RELR 00000000 000034 000000 ff
|
||||
|
||||
--- !ELF
|
||||
@@ -42,6 +44,9 @@ Sections:
|
||||
- Name: .rel.custom
|
||||
Type: SHT_REL
|
||||
EntSize: 0xFF
|
||||
- Name: .crel.custom
|
||||
Type: SHT_CREL
|
||||
EntSize: 0xFF
|
||||
- Name: .relr.custom
|
||||
Type: SHT_RELR
|
||||
EntSize: 0xFF
|
||||
|
||||
92
llvm/test/tools/yaml2obj/ELF/relocation-crel.yaml
Normal file
92
llvm/test/tools/yaml2obj/ELF/relocation-crel.yaml
Normal file
@@ -0,0 +1,92 @@
|
||||
# RUN: rm -rf %t && mkdir %t && cd %t
|
||||
# RUN: yaml2obj %s -o out
|
||||
# RUN: llvm-readelf -r out | FileCheck %s
|
||||
|
||||
# CHECK: Relocation section '.crel.text' at offset {{.*}} contains 7 entries:
|
||||
# CHECK-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
|
||||
# CHECK-NEXT: 0000000000000001 0000000100000004 R_X86_64_PLT32 0000000000000000 a0 - 4
|
||||
# CHECK-NEXT: 0000000000000005 0000000200000004 R_X86_64_PLT32 0000000000000000 a1 - 4
|
||||
# CHECK-NEXT: 000000000000000a 0000000300000004 R_X86_64_PLT32 0000000000000000 a2 + 0
|
||||
# CHECK-NEXT: 0000000000000010 0000000200000001 R_X86_64_64 0000000000000000 a1 - 4
|
||||
# CHECK-NEXT: 0000000000000018 0000000100000001 R_X86_64_64 0000000000000000 a0 + 80
|
||||
# CHECK-NEXT: 0000000000000020 0000000000000008 R_X86_64_RELATIVE 8000000000000000{{$}}
|
||||
# CHECK-NEXT: 0000000000000028 0000000400000001 R_X86_64_64 0000000000000000 a3 + 7fffffffffffffff
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .crel.text
|
||||
Type: SHT_CREL
|
||||
Info: .text
|
||||
Link: .symtab
|
||||
Relocations:
|
||||
- Offset: 1
|
||||
Type: R_X86_64_PLT32
|
||||
Symbol: a0
|
||||
Addend: -4
|
||||
- Offset: 5
|
||||
Type: R_X86_64_PLT32
|
||||
Symbol: a1
|
||||
Addend: -4
|
||||
- Offset: 10
|
||||
Type: R_X86_64_PLT32
|
||||
Symbol: a2
|
||||
Addend: 0
|
||||
- Offset: 16
|
||||
Type: R_X86_64_64
|
||||
Symbol: a1
|
||||
Addend: -4
|
||||
- Offset: 24
|
||||
Type: R_X86_64_64
|
||||
Symbol: a0
|
||||
Addend: 128
|
||||
- Offset: 32
|
||||
Type: R_X86_64_RELATIVE
|
||||
Addend: 0x8000000000000000
|
||||
- Offset: 40
|
||||
Type: R_X86_64_64
|
||||
Symbol: a3
|
||||
Addend: 0x7fffffffffffffff
|
||||
Symbols:
|
||||
- Name: a0
|
||||
- Name: a1
|
||||
Binding: STB_GLOBAL
|
||||
- Name: a2
|
||||
Binding: STB_GLOBAL
|
||||
- Name: a3
|
||||
Binding: STB_GLOBAL
|
||||
|
||||
## See output-limit.yaml. While estimating the size of the last byte of .crel.text
|
||||
## (a SLEB128), checkLimit thinks 10 byte headroom is needed while only 1 is used.
|
||||
## The file end is 1 byte away from the end of .crel.text (one-byte .strtab).
|
||||
## Therefore, the --max-size= value has to be at least 10-1-1 larger than the
|
||||
## actual file size.
|
||||
# RUN: not yaml2obj %s --docnum=2 --max-size=76 -o /dev/null
|
||||
# RUN: yaml2obj %s --docnum=2 --max-size=77 -o out
|
||||
# RUN: %python -c 'import os; print(os.path.getsize("out"))' | FileCheck %s --check-prefix=SIZE
|
||||
|
||||
# SIZE: 69
|
||||
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_REL
|
||||
Machine: EM_X86_64
|
||||
Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .crel.text
|
||||
Type: SHT_CREL
|
||||
Relocations:
|
||||
- Offset: 1
|
||||
Type: R_X86_64_64
|
||||
Addend: -4
|
||||
- Type: SectionHeaderTable
|
||||
NoHeaders: true
|
||||
@@ -2,6 +2,7 @@
|
||||
## does not exist.
|
||||
|
||||
# RUN: not yaml2obj %s -o %t 2>&1 | FileCheck %s
|
||||
# RUN: not yaml2obj -DTYPE=SHT_CREL %s -o %t 2>&1 | FileCheck %s
|
||||
|
||||
## Check we are able to report multiple errors.
|
||||
|
||||
@@ -18,7 +19,7 @@ Sections:
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
- Name: .rela.text
|
||||
Type: SHT_RELA
|
||||
Type: [[TYPE=SHT_RELA]]
|
||||
Info: .text
|
||||
Link: .symtab
|
||||
Relocations:
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
## Show that yaml2obj is able to produce relocations for an unknown e_machine kind properly.
|
||||
# RUN: yaml2obj %s -o %t1 -DMACHINE=0x1234
|
||||
# RUN: llvm-readelf %t1 --relocations | FileCheck %s -DFIRST=Unknown -DSECOND=Unknown
|
||||
# RUN: yaml2obj %s -o %t1 -DMACHINE=0x1234 -DTYPE=SHT_CREL
|
||||
# RUN: llvm-readelf %t1 --relocations | FileCheck %s -DFIRST=Unknown -DSECOND=Unknown
|
||||
|
||||
# CHECK: Relocation section '.rela.text' at offset 0x40 contains 4 entries:
|
||||
# CHECK: Offset Info Type
|
||||
@@ -23,7 +25,7 @@ FileHeader:
|
||||
Machine: [[MACHINE]]
|
||||
Sections:
|
||||
- Name: .rela.text
|
||||
Type: SHT_RELA
|
||||
Type: [[TYPE=SHT_RELA]]
|
||||
Relocations:
|
||||
## Test a few noticeable possible values: 0, 1, max(int8_t)=127, max(uint8_t)=0xFF=-1
|
||||
- Offset: 0x9
|
||||
|
||||
@@ -378,6 +378,7 @@ protected:
|
||||
|
||||
DynRegionInfo DynRelRegion;
|
||||
DynRegionInfo DynRelaRegion;
|
||||
DynRegionInfo DynCrelRegion;
|
||||
DynRegionInfo DynRelrRegion;
|
||||
DynRegionInfo DynPLTRelRegion;
|
||||
std::optional<DynRegionInfo> DynSymRegion;
|
||||
@@ -1909,7 +1910,7 @@ ELFDumper<ELFT>::ELFDumper(const object::ELFObjectFile<ELFT> &O,
|
||||
ScopedPrinter &Writer)
|
||||
: ObjDumper(Writer, O.getFileName()), ObjF(O), Obj(O.getELFFile()),
|
||||
FileName(O.getFileName()), DynRelRegion(O, *this),
|
||||
DynRelaRegion(O, *this), DynRelrRegion(O, *this),
|
||||
DynRelaRegion(O, *this), DynCrelRegion(O, *this), DynRelrRegion(O, *this),
|
||||
DynPLTRelRegion(O, *this), DynSymTabShndxRegion(O, *this),
|
||||
DynamicTable(O, *this) {
|
||||
if (!O.IsContentValid())
|
||||
@@ -2068,6 +2069,9 @@ template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {
|
||||
DynRelaRegion.EntSize = Dyn.getVal();
|
||||
DynRelaRegion.EntSizePrintName = "DT_RELAENT value";
|
||||
break;
|
||||
case ELF::DT_CREL:
|
||||
DynCrelRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
|
||||
break;
|
||||
case ELF::DT_SONAME:
|
||||
SONameOffset = Dyn.getVal();
|
||||
break;
|
||||
@@ -2108,6 +2112,8 @@ template <typename ELFT> void ELFDumper<ELFT>::parseDynamicTable() {
|
||||
DynPLTRelRegion.EntSize = sizeof(Elf_Rel);
|
||||
else if (Dyn.getVal() == DT_RELA)
|
||||
DynPLTRelRegion.EntSize = sizeof(Elf_Rela);
|
||||
else if (Dyn.getVal() == DT_CREL)
|
||||
DynPLTRelRegion.EntSize = 1;
|
||||
else
|
||||
reportUniqueWarning(Twine("unknown DT_PLTREL value of ") +
|
||||
Twine((uint64_t)Dyn.getVal()));
|
||||
@@ -2433,6 +2439,8 @@ std::string ELFDumper<ELFT>::getDynamicEntry(uint64_t Type,
|
||||
return "REL";
|
||||
if (Value == DT_RELA)
|
||||
return "RELA";
|
||||
if (Value == DT_CREL)
|
||||
return "CREL";
|
||||
[[fallthrough]];
|
||||
case DT_PLTGOT:
|
||||
case DT_HASH:
|
||||
@@ -2447,6 +2455,7 @@ std::string ELFDumper<ELFT>::getDynamicEntry(uint64_t Type,
|
||||
case DT_FINI_ARRAY:
|
||||
case DT_PREINIT_ARRAY:
|
||||
case DT_DEBUG:
|
||||
case DT_CREL:
|
||||
case DT_VERDEF:
|
||||
case DT_VERNEED:
|
||||
case DT_VERSYM:
|
||||
@@ -3845,14 +3854,15 @@ void GNUELFDumper<ELFT>::printRelRelaReloc(const Relocation<ELFT> &R,
|
||||
|
||||
template <class ELFT>
|
||||
static void printRelocHeaderFields(formatted_raw_ostream &OS, unsigned SType,
|
||||
const typename ELFT::Ehdr &EHeader) {
|
||||
const typename ELFT::Ehdr &EHeader,
|
||||
uint64_t CrelHdr = 0) {
|
||||
bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA;
|
||||
if (ELFT::Is64Bits)
|
||||
OS << " Offset Info Type Symbol's "
|
||||
"Value Symbol's Name";
|
||||
else
|
||||
OS << " Offset Info Type Sym. Value Symbol's Name";
|
||||
if (IsRela)
|
||||
if (IsRela || (SType == ELF::SHT_CREL && (CrelHdr & CREL_HDR_ADDEND)))
|
||||
OS << " + Addend";
|
||||
OS << "\n";
|
||||
}
|
||||
@@ -3862,7 +3872,10 @@ void GNUELFDumper<ELFT>::printDynamicRelocHeader(unsigned Type, StringRef Name,
|
||||
const DynRegionInfo &Reg) {
|
||||
uint64_t Offset = Reg.Addr - this->Obj.base();
|
||||
OS << "\n'" << Name.str().c_str() << "' relocation section at offset 0x"
|
||||
<< utohexstr(Offset, /*LowerCase=*/true) << " contains " << Reg.Size << " bytes:\n";
|
||||
<< utohexstr(Offset, /*LowerCase=*/true);
|
||||
if (Type != ELF::SHT_CREL)
|
||||
OS << " contains " << Reg.Size << " bytes";
|
||||
OS << ":\n";
|
||||
printRelocHeaderFields<ELFT>(OS, Type, this->Obj.getHeader());
|
||||
}
|
||||
|
||||
@@ -3870,7 +3883,8 @@ template <class ELFT>
|
||||
static bool isRelocationSec(const typename ELFT::Shdr &Sec,
|
||||
const typename ELFT::Ehdr &EHeader) {
|
||||
return 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_RELR || Sec.sh_type == ELF::SHT_CREL ||
|
||||
Sec.sh_type == ELF::SHT_ANDROID_REL ||
|
||||
Sec.sh_type == ELF::SHT_ANDROID_RELA ||
|
||||
Sec.sh_type == ELF::SHT_ANDROID_RELR ||
|
||||
(EHeader.e_machine == EM_AARCH64 &&
|
||||
@@ -3896,6 +3910,17 @@ template <class ELFT> void GNUELFDumper<ELFT>::printRelocations() {
|
||||
return RelasOrErr->size();
|
||||
}
|
||||
|
||||
if (Sec.sh_type == ELF::SHT_CREL) {
|
||||
Expected<ArrayRef<uint8_t>> ContentsOrErr =
|
||||
this->Obj.getSectionContents(Sec);
|
||||
if (!ContentsOrErr)
|
||||
return ContentsOrErr.takeError();
|
||||
auto NumOrErr = this->Obj.getCrelHeader(*ContentsOrErr);
|
||||
if (!NumOrErr)
|
||||
return NumOrErr.takeError();
|
||||
return *NumOrErr / 8;
|
||||
}
|
||||
|
||||
if (PrintAsRelr(Sec)) {
|
||||
Expected<Elf_Relr_Range> RelrsOrErr = this->Obj.relrs(Sec);
|
||||
if (!RelrsOrErr)
|
||||
@@ -3929,8 +3954,17 @@ template <class ELFT> void GNUELFDumper<ELFT>::printRelocations() {
|
||||
if (PrintAsRelr(Sec)) {
|
||||
printRelr(Sec);
|
||||
} else {
|
||||
printRelocHeaderFields<ELFT>(OS, Sec.sh_type, this->Obj.getHeader());
|
||||
this->printRelocationsHelper(Sec);
|
||||
uint64_t CrelHdr = 0;
|
||||
// For CREL, read the header and call printRelocationsHelper only if
|
||||
// GetEntriesNum(Sec) succeeded.
|
||||
if (Sec.sh_type == ELF::SHT_CREL && EntriesNum != "<?>") {
|
||||
CrelHdr = cantFail(this->Obj.getCrelHeader(
|
||||
cantFail(this->Obj.getSectionContents(Sec))));
|
||||
}
|
||||
printRelocHeaderFields<ELFT>(OS, Sec.sh_type, this->Obj.getHeader(),
|
||||
CrelHdr);
|
||||
if (Sec.sh_type != ELF::SHT_CREL || EntriesNum != "<?>")
|
||||
this->printRelocationsHelper(Sec);
|
||||
}
|
||||
}
|
||||
if (!HasRelocSections)
|
||||
@@ -4893,6 +4927,34 @@ void ELFDumper<ELFT>::printRelocationsHelper(const Elf_Shdr &Sec) {
|
||||
|
||||
template <class ELFT> void ELFDumper<ELFT>::printDynamicRelocationsHelper() {
|
||||
const bool IsMips64EL = this->Obj.isMips64EL();
|
||||
auto DumpCrelRegion = [&](DynRegionInfo &Region) {
|
||||
// While the size is unknown, a valid CREL has at least one byte. We can
|
||||
// check whether Addr is in bounds, and then decode CREL until the file
|
||||
// end.
|
||||
Region.Size = Region.EntSize = 1;
|
||||
if (!Region.template getAsArrayRef<uint8_t>().empty()) {
|
||||
const uint64_t Offset =
|
||||
Region.Addr - reinterpret_cast<const uint8_t *>(
|
||||
ObjF.getMemoryBufferRef().getBufferStart());
|
||||
const uint64_t ObjSize = ObjF.getMemoryBufferRef().getBufferSize();
|
||||
auto RelsOrRelas =
|
||||
Obj.decodeCrel(ArrayRef<uint8_t>(Region.Addr, ObjSize - Offset));
|
||||
if (!RelsOrRelas) {
|
||||
reportUniqueWarning(toString(RelsOrRelas.takeError()));
|
||||
} else {
|
||||
for (const Elf_Rel &R : RelsOrRelas->first)
|
||||
printDynamicReloc(Relocation<ELFT>(R, false));
|
||||
for (const Elf_Rela &R : RelsOrRelas->second)
|
||||
printDynamicReloc(Relocation<ELFT>(R, false));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (this->DynCrelRegion.Addr) {
|
||||
printDynamicRelocHeader(ELF::SHT_CREL, "CREL", this->DynCrelRegion);
|
||||
DumpCrelRegion(this->DynCrelRegion);
|
||||
}
|
||||
|
||||
if (this->DynRelaRegion.Size > 0) {
|
||||
printDynamicRelocHeader(ELF::SHT_RELA, "RELA", this->DynRelaRegion);
|
||||
for (const Elf_Rela &Rela :
|
||||
@@ -4921,6 +4983,8 @@ template <class ELFT> void ELFDumper<ELFT>::printDynamicRelocationsHelper() {
|
||||
for (const Elf_Rela &Rela :
|
||||
this->DynPLTRelRegion.template getAsArrayRef<Elf_Rela>())
|
||||
printDynamicReloc(Relocation<ELFT>(Rela, IsMips64EL));
|
||||
} else if (this->DynPLTRelRegion.EntSize == 1) {
|
||||
DumpCrelRegion(this->DynPLTRelRegion);
|
||||
} else {
|
||||
printDynamicRelocHeader(ELF::SHT_REL, "PLT", this->DynPLTRelRegion);
|
||||
for (const Elf_Rel &Rel :
|
||||
@@ -6415,6 +6479,17 @@ void ELFDumper<ELFT>::forEachRelocationDo(
|
||||
/*SymTab=*/nullptr);
|
||||
break;
|
||||
}
|
||||
case ELF::SHT_CREL: {
|
||||
if (auto RelsOrRelas = Obj.crels(Sec)) {
|
||||
for (const Elf_Rel &R : RelsOrRelas->first)
|
||||
RelRelaFn(Relocation<ELFT>(R, false), RelNdx++, Sec, SymTab);
|
||||
for (const Elf_Rela &R : RelsOrRelas->second)
|
||||
RelRelaFn(Relocation<ELFT>(R, false), RelNdx++, Sec, SymTab);
|
||||
} else {
|
||||
Warn(RelsOrRelas.takeError());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ELF::SHT_ANDROID_REL:
|
||||
case ELF::SHT_ANDROID_RELA:
|
||||
if (Expected<std::vector<Elf_Rela>> RelasOrErr = Obj.android_relas(Sec)) {
|
||||
|
||||
Reference in New Issue
Block a user