mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-27 05:50:12 +00:00
[BOLT] Update dynamic relocations from section relocations
This patch changes patchELFAllocatableRelaSections from going through old relocations sections and update the relocation offsets to emitting the relocations stored in binary sections. This is needed in case we would like to remove and add dynamic relocations during BOLT work and it is used by golang support pass. Note: Currently we emit relocations in the old sections, so the total number of them should be equal or less of old number. Testing: No special tests are neeeded, since this patch does not fix anything or add new functionality (it only prepares to add). Every PIC-compiled test binary will use this code and thus become a test. But just in case the aarch64 dynamic relocations tests were added. Vladislav Khmelevsky, Advanced Software Technology Lab, Huawei Reviewed By: maksfb Differential Revision: https://reviews.llvm.org/D117612
This commit is contained in:
parent
c9032f1a69
commit
729d29e167
@ -296,6 +296,16 @@ public:
|
||||
return make_range(Relocations.begin(), Relocations.end());
|
||||
}
|
||||
|
||||
/// Iterate over all dynamic relocations for this section.
|
||||
iterator_range<RelocationSetType::iterator> dynamicRelocations() {
|
||||
return make_range(DynamicRelocations.begin(), DynamicRelocations.end());
|
||||
}
|
||||
|
||||
/// Iterate over all dynamic relocations for this section.
|
||||
iterator_range<RelocationSetType::const_iterator> dynamicRelocations() const {
|
||||
return make_range(DynamicRelocations.begin(), DynamicRelocations.end());
|
||||
}
|
||||
|
||||
/// Does this section have any non-pending relocations?
|
||||
bool hasRelocations() const { return !Relocations.empty(); }
|
||||
|
||||
|
@ -89,6 +89,9 @@ struct Relocation {
|
||||
/// Return true if relocation type is for thread local storage.
|
||||
static bool isTLS(uint64_t Type);
|
||||
|
||||
/// Return code for a NONE relocation
|
||||
static uint64_t getNone();
|
||||
|
||||
/// Return code for a PC-relative 4-byte relocation
|
||||
static uint64_t getPC32();
|
||||
|
||||
@ -98,6 +101,10 @@ struct Relocation {
|
||||
/// Return true if this relocation is PC-relative. Return false otherwise.
|
||||
bool isPCRelative() const { return isPCRelative(Type); }
|
||||
|
||||
/// Return true if this relocation is R_*_RELATIVE type. Return false
|
||||
/// otherwise.
|
||||
bool isRelative() const { return isRelative(Type); }
|
||||
|
||||
/// Emit relocation at a current \p Streamer' position. The caller is
|
||||
/// responsible for setting the position correctly.
|
||||
size_t emit(MCStreamer *Streamer) const;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -124,7 +125,7 @@ private:
|
||||
void processLKSMPLocks();
|
||||
|
||||
/// Read relocations from a given section.
|
||||
void readDynamicRelocations(const object::SectionRef &Section);
|
||||
void readDynamicRelocations(const object::SectionRef &Section, bool IsJmpRel);
|
||||
|
||||
/// Read relocations from a given section.
|
||||
void readRelocations(const object::SectionRef &Section);
|
||||
@ -201,6 +202,10 @@ private:
|
||||
/// \p OldAddress address in the original binary.
|
||||
uint64_t getNewFunctionAddress(uint64_t OldAddress);
|
||||
|
||||
/// Return address of a function or moved data in the new binary
|
||||
/// corresponding to \p OldAddress address in the original binary.
|
||||
uint64_t getNewFunctionOrDataAddress(uint64_t OldAddress);
|
||||
|
||||
/// Return value for the symbol \p Name in the output.
|
||||
uint64_t getNewValueForSymbol(const StringRef Name);
|
||||
|
||||
@ -299,6 +304,14 @@ private:
|
||||
const std::vector<uint32_t> &NewSectionIndex, WriteFuncTy Write,
|
||||
StrTabFuncTy AddToStrTab);
|
||||
|
||||
/// Get output index in dynamic symbol table.
|
||||
uint32_t getOutputDynamicSymbolIndex(const MCSymbol *Symbol) {
|
||||
auto It = SymbolIndex.find(Symbol);
|
||||
if (It != SymbolIndex.end())
|
||||
return It->second;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Add a notes section containing the BOLT revision and command line options.
|
||||
void addBoltInfoSection();
|
||||
|
||||
@ -426,11 +439,19 @@ private:
|
||||
/// Location and size of dynamic relocations.
|
||||
Optional<uint64_t> DynamicRelocationsAddress;
|
||||
uint64_t DynamicRelocationsSize{0};
|
||||
uint64_t DynamicRelativeRelocationsCount{0};
|
||||
|
||||
/// PLT relocations are special kind of dynamic relocations stored separately.
|
||||
Optional<uint64_t> PLTRelocationsAddress;
|
||||
uint64_t PLTRelocationsSize{0};
|
||||
|
||||
/// True if relocation of specified type came from .rela.plt
|
||||
DenseMap<uint64_t, bool> IsJmpRelocation;
|
||||
|
||||
/// Index of specified symbol in the dynamic symbol table. NOTE Currently it
|
||||
/// is filled and used only with the relocations-related symbols.
|
||||
std::unordered_map<const MCSymbol *, uint32_t> SymbolIndex;
|
||||
|
||||
/// Store all non-zero symbols in this map for a quick address lookup.
|
||||
std::map<uint64_t, llvm::object::SymbolRef> FileSymRefs;
|
||||
|
||||
|
@ -533,11 +533,7 @@ bool Relocation::isGOT(uint64_t Type) {
|
||||
return isGOTX86(Type);
|
||||
}
|
||||
|
||||
bool Relocation::isNone(uint64_t Type) {
|
||||
if (Arch == Triple::aarch64)
|
||||
return Type == ELF::R_AARCH64_NONE;
|
||||
return Type == ELF::R_X86_64_NONE;
|
||||
}
|
||||
bool Relocation::isNone(uint64_t Type) { return Type == getNone(); }
|
||||
|
||||
bool Relocation::isRelative(uint64_t Type) {
|
||||
if (Arch == Triple::aarch64)
|
||||
@ -557,10 +553,10 @@ bool Relocation::isTLS(uint64_t Type) {
|
||||
return isTLSX86(Type);
|
||||
}
|
||||
|
||||
bool Relocation::isPCRelative(uint64_t Type) {
|
||||
uint64_t Relocation::getNone() {
|
||||
if (Arch == Triple::aarch64)
|
||||
return isPCRelativeAArch64(Type);
|
||||
return isPCRelativeX86(Type);
|
||||
return ELF::R_AARCH64_NONE;
|
||||
return ELF::R_X86_64_NONE;
|
||||
}
|
||||
|
||||
uint64_t Relocation::getPC32() {
|
||||
@ -575,6 +571,12 @@ uint64_t Relocation::getPC64() {
|
||||
return ELF::R_X86_64_PC64;
|
||||
}
|
||||
|
||||
bool Relocation::isPCRelative(uint64_t Type) {
|
||||
if (Arch == Triple::aarch64)
|
||||
return isPCRelativeAArch64(Type);
|
||||
return isPCRelativeX86(Type);
|
||||
}
|
||||
|
||||
size_t Relocation::emit(MCStreamer *Streamer) const {
|
||||
const size_t Size = getSizeForType(Type);
|
||||
MCContext &Ctx = Streamer->getContext();
|
||||
|
@ -1683,6 +1683,40 @@ int64_t getRelocationAddend(const ELFObjectFileBase *Obj,
|
||||
auto *ELF64BE = cast<ELF64BEObjectFile>(Obj);
|
||||
return getRelocationAddend(ELF64BE, Rel);
|
||||
}
|
||||
|
||||
template <typename ELFT>
|
||||
uint32_t getRelocationSymbol(const ELFObjectFile<ELFT> *Obj,
|
||||
const RelocationRef &RelRef) {
|
||||
using ELFShdrTy = typename ELFT::Shdr;
|
||||
uint32_t Symbol = 0;
|
||||
const ELFFile<ELFT> &EF = Obj->getELFFile();
|
||||
DataRefImpl Rel = RelRef.getRawDataRefImpl();
|
||||
const ELFShdrTy *RelocationSection = cantFail(EF.getSection(Rel.d.a));
|
||||
switch (RelocationSection->sh_type) {
|
||||
default:
|
||||
llvm_unreachable("unexpected relocation section type");
|
||||
case ELF::SHT_REL:
|
||||
Symbol = Obj->getRel(Rel)->getSymbol(EF.isMips64EL());
|
||||
break;
|
||||
case ELF::SHT_RELA:
|
||||
Symbol = Obj->getRela(Rel)->getSymbol(EF.isMips64EL());
|
||||
break;
|
||||
}
|
||||
|
||||
return Symbol;
|
||||
}
|
||||
|
||||
uint32_t getRelocationSymbol(const ELFObjectFileBase *Obj,
|
||||
const RelocationRef &Rel) {
|
||||
if (auto *ELF32LE = dyn_cast<ELF32LEObjectFile>(Obj))
|
||||
return getRelocationSymbol(ELF32LE, Rel);
|
||||
if (auto *ELF64LE = dyn_cast<ELF64LEObjectFile>(Obj))
|
||||
return getRelocationSymbol(ELF64LE, Rel);
|
||||
if (auto *ELF32BE = dyn_cast<ELF32BEObjectFile>(Obj))
|
||||
return getRelocationSymbol(ELF32BE, Rel);
|
||||
auto *ELF64BE = cast<ELF64BEObjectFile>(Obj);
|
||||
return getRelocationSymbol(ELF64BE, Rel);
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
bool RewriteInstance::analyzeRelocation(
|
||||
@ -1812,7 +1846,8 @@ void RewriteInstance::processDynamicRelocations() {
|
||||
if (PLTRelSectionOrErr->getSize() != PLTRelocationsSize)
|
||||
report_error("section size mismatch for DT_PLTRELSZ",
|
||||
errc::executable_format_error);
|
||||
readDynamicRelocations(PLTRelSectionOrErr->getSectionRef());
|
||||
readDynamicRelocations(PLTRelSectionOrErr->getSectionRef(),
|
||||
/*IsJmpRel*/ true);
|
||||
}
|
||||
|
||||
// The rest of dynamic relocations - DT_RELA.
|
||||
@ -1825,7 +1860,8 @@ void RewriteInstance::processDynamicRelocations() {
|
||||
if (DynamicRelSectionOrErr->getSize() != DynamicRelocationsSize)
|
||||
report_error("section size mismatch for DT_RELASZ",
|
||||
errc::executable_format_error);
|
||||
readDynamicRelocations(DynamicRelSectionOrErr->getSectionRef());
|
||||
readDynamicRelocations(DynamicRelSectionOrErr->getSectionRef(),
|
||||
/*IsJmpRel*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2049,7 +2085,8 @@ void RewriteInstance::processLKSMPLocks() {
|
||||
}
|
||||
}
|
||||
|
||||
void RewriteInstance::readDynamicRelocations(const SectionRef &Section) {
|
||||
void RewriteInstance::readDynamicRelocations(const SectionRef &Section,
|
||||
bool IsJmpRel) {
|
||||
assert(BinarySection(*BC, Section).isAllocatable() && "allocatable expected");
|
||||
|
||||
LLVM_DEBUG({
|
||||
@ -2059,7 +2096,7 @@ void RewriteInstance::readDynamicRelocations(const SectionRef &Section) {
|
||||
});
|
||||
|
||||
for (const RelocationRef &Rel : Section.relocations()) {
|
||||
uint64_t RType = Rel.getType();
|
||||
const uint64_t RType = Rel.getType();
|
||||
if (Relocation::isNone(RType))
|
||||
continue;
|
||||
|
||||
@ -2087,7 +2124,13 @@ void RewriteInstance::readDynamicRelocations(const SectionRef &Section) {
|
||||
<< " : + 0x" << Twine::utohexstr(Addend) << '\n'
|
||||
);
|
||||
|
||||
BC->addDynamicRelocation(Rel.getOffset(), Symbol, Rel.getType(), Addend);
|
||||
if (IsJmpRel)
|
||||
IsJmpRelocation[RType] = true;
|
||||
|
||||
if (Symbol)
|
||||
SymbolIndex[Symbol] = getRelocationSymbol(InputFile, Rel);
|
||||
|
||||
BC->addDynamicRelocation(Rel.getOffset(), Symbol, RType, Addend);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4700,28 +4743,108 @@ void
|
||||
RewriteInstance::patchELFAllocatableRelaSections(ELFObjectFile<ELFT> *File) {
|
||||
using Elf_Rela = typename ELFT::Rela;
|
||||
raw_fd_ostream &OS = Out->os();
|
||||
const ELFFile<ELFT> &EF = File->getELFFile();
|
||||
|
||||
for (BinarySection &RelaSection : BC->allocatableRelaSections()) {
|
||||
for (const RelocationRef &Rel : RelaSection.getSectionRef().relocations()) {
|
||||
uint64_t RType = Rel.getType();
|
||||
if (!Relocation::isRelative(RType) && !Relocation::isIRelative(RType))
|
||||
continue;
|
||||
DataRefImpl DRI = Rel.getRawDataRefImpl();
|
||||
const Elf_Rela *RelA = File->getRela(DRI);
|
||||
auto Address = RelA->r_addend;
|
||||
uint64_t NewAddress = getNewFunctionAddress(Address);
|
||||
if (!NewAddress)
|
||||
continue;
|
||||
LLVM_DEBUG(dbgs() << "BOLT-DEBUG: patching (I)RELATIVE "
|
||||
<< RelaSection.getName() << " entry 0x"
|
||||
<< Twine::utohexstr(Address) << " with 0x"
|
||||
<< Twine::utohexstr(NewAddress) << '\n');
|
||||
Elf_Rela NewRelA = *RelA;
|
||||
NewRelA.r_addend = NewAddress;
|
||||
OS.pwrite(reinterpret_cast<const char *>(&NewRelA), sizeof(NewRelA),
|
||||
reinterpret_cast<const char *>(RelA) - File->getData().data());
|
||||
uint64_t RelDynOffset = 0, RelDynEndOffset = 0;
|
||||
uint64_t RelPltOffset = 0, RelPltEndOffset = 0;
|
||||
|
||||
auto setSectionFileOffsets = [&](uint64_t Address, uint64_t &Start,
|
||||
uint64_t &End) {
|
||||
ErrorOr<BinarySection &> Section = BC->getSectionForAddress(Address);
|
||||
Start = Section->getInputFileOffset();
|
||||
End = Start + Section->getSize();
|
||||
};
|
||||
|
||||
if (!DynamicRelocationsAddress && !PLTRelocationsAddress)
|
||||
return;
|
||||
|
||||
if (DynamicRelocationsAddress)
|
||||
setSectionFileOffsets(*DynamicRelocationsAddress, RelDynOffset,
|
||||
RelDynEndOffset);
|
||||
|
||||
if (PLTRelocationsAddress)
|
||||
setSectionFileOffsets(*PLTRelocationsAddress, RelPltOffset,
|
||||
RelPltEndOffset);
|
||||
|
||||
DynamicRelativeRelocationsCount = 0;
|
||||
|
||||
auto writeRela = [&OS](const Elf_Rela *RelA, uint64_t &Offset) {
|
||||
OS.pwrite(reinterpret_cast<const char *>(RelA), sizeof(*RelA), Offset);
|
||||
Offset += sizeof(*RelA);
|
||||
};
|
||||
|
||||
auto writeRelocations = [&](bool PatchRelative) {
|
||||
for (BinarySection &Section : BC->allocatableSections()) {
|
||||
for (const Relocation &Rel : Section.dynamicRelocations()) {
|
||||
const bool IsRelative = Rel.isRelative();
|
||||
if (PatchRelative != IsRelative)
|
||||
continue;
|
||||
|
||||
if (IsRelative)
|
||||
++DynamicRelativeRelocationsCount;
|
||||
|
||||
Elf_Rela NewRelA;
|
||||
uint64_t SectionAddress = Section.getOutputAddress();
|
||||
SectionAddress =
|
||||
SectionAddress == 0 ? Section.getAddress() : SectionAddress;
|
||||
MCSymbol *Symbol = Rel.Symbol;
|
||||
uint32_t SymbolIdx = 0;
|
||||
uint64_t Addend = Rel.Addend;
|
||||
|
||||
if (Rel.Symbol) {
|
||||
SymbolIdx = getOutputDynamicSymbolIndex(Symbol);
|
||||
} else {
|
||||
// Usually this case is used for R_*_(I)RELATIVE relocations
|
||||
const uint64_t Address = getNewFunctionOrDataAddress(Addend);
|
||||
if (Address)
|
||||
Addend = Address;
|
||||
}
|
||||
|
||||
NewRelA.setSymbolAndType(SymbolIdx, Rel.Type, EF.isMips64EL());
|
||||
NewRelA.r_offset = SectionAddress + Rel.Offset;
|
||||
NewRelA.r_addend = Addend;
|
||||
|
||||
const bool IsJmpRel =
|
||||
!!(IsJmpRelocation.find(Rel.Type) != IsJmpRelocation.end());
|
||||
uint64_t &Offset = IsJmpRel ? RelPltOffset : RelDynOffset;
|
||||
const uint64_t &EndOffset =
|
||||
IsJmpRel ? RelPltEndOffset : RelDynEndOffset;
|
||||
if (!Offset || !EndOffset) {
|
||||
errs() << "BOLT-ERROR: Invalid offsets for dynamic relocation\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (Offset + sizeof(NewRelA) > EndOffset) {
|
||||
errs() << "BOLT-ERROR: Offset overflow for dynamic relocation\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
writeRela(&NewRelA, Offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// The dynamic linker expects R_*_RELATIVE relocations to be emitted first
|
||||
writeRelocations(/* PatchRelative */ true);
|
||||
writeRelocations(/* PatchRelative */ false);
|
||||
|
||||
auto fillNone = [&](uint64_t &Offset, uint64_t EndOffset) {
|
||||
if (!Offset)
|
||||
return;
|
||||
|
||||
typename ELFObjectFile<ELFT>::Elf_Rela RelA;
|
||||
RelA.setSymbolAndType(0, Relocation::getNone(), EF.isMips64EL());
|
||||
RelA.r_offset = 0;
|
||||
RelA.r_addend = 0;
|
||||
while (Offset < EndOffset)
|
||||
writeRela(&RelA, Offset);
|
||||
|
||||
assert(Offset == EndOffset && "Unexpected section overflow");
|
||||
};
|
||||
|
||||
// Fill the rest of the sections with R_*_NONE relocations
|
||||
fillNone(RelDynOffset, RelDynEndOffset);
|
||||
fillNone(RelPltOffset, RelPltEndOffset);
|
||||
}
|
||||
|
||||
template <typename ELFT>
|
||||
@ -4737,7 +4860,8 @@ void RewriteInstance::patchELFGOT(ELFObjectFile<ELFT> *File) {
|
||||
}
|
||||
}
|
||||
if (!GOTSection.getObject()) {
|
||||
errs() << "BOLT-INFO: no .got section found\n";
|
||||
if (!BC->IsStaticExecutable)
|
||||
errs() << "BOLT-INFO: no .got section found\n";
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4796,6 +4920,9 @@ void RewriteInstance::patchELFDynamic(ELFObjectFile<ELFT> *File) {
|
||||
default:
|
||||
ShouldPatch = false;
|
||||
break;
|
||||
case ELF::DT_RELACOUNT:
|
||||
NewDE.d_un.d_val = DynamicRelativeRelocationsCount;
|
||||
break;
|
||||
case ELF::DT_INIT:
|
||||
case ELF::DT_FINI: {
|
||||
if (BC->HasRelocations) {
|
||||
@ -4898,14 +5025,21 @@ void RewriteInstance::readELFDynamic(ELFObjectFile<ELFT> *File) {
|
||||
case ELF::DT_PLTRELSZ:
|
||||
PLTRelocationsSize = Dyn.getVal();
|
||||
break;
|
||||
case ELF::DT_RELACOUNT:
|
||||
DynamicRelativeRelocationsCount = Dyn.getVal();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!DynamicRelocationsAddress)
|
||||
if (!DynamicRelocationsAddress || !DynamicRelocationsSize) {
|
||||
DynamicRelocationsAddress.reset();
|
||||
DynamicRelocationsSize = 0;
|
||||
}
|
||||
|
||||
if (!PLTRelocationsAddress)
|
||||
if (!PLTRelocationsAddress || !PLTRelocationsSize) {
|
||||
PLTRelocationsAddress.reset();
|
||||
PLTRelocationsSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t RewriteInstance::getNewFunctionAddress(uint64_t OldAddress) {
|
||||
@ -4918,6 +5052,17 @@ uint64_t RewriteInstance::getNewFunctionAddress(uint64_t OldAddress) {
|
||||
return Function->getOutputAddress();
|
||||
}
|
||||
|
||||
uint64_t RewriteInstance::getNewFunctionOrDataAddress(uint64_t OldAddress) {
|
||||
if (uint64_t Function = getNewFunctionAddress(OldAddress))
|
||||
return Function;
|
||||
|
||||
const BinaryData *BD = BC->getBinaryDataAtAddress(OldAddress);
|
||||
if (BD && BD->isMoved())
|
||||
return BD->getOutputAddress();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RewriteInstance::rewriteFile() {
|
||||
std::error_code EC;
|
||||
Out = std::make_unique<ToolOutputFile>(opts::OutputFilename, EC,
|
||||
@ -5090,14 +5235,14 @@ void RewriteInstance::rewriteFile() {
|
||||
// Copy non-allocatable sections once allocatable part is finished.
|
||||
rewriteNoteSections();
|
||||
|
||||
// Patch dynamic section/segment.
|
||||
patchELFDynamic();
|
||||
|
||||
if (BC->HasRelocations) {
|
||||
patchELFAllocatableRelaSections();
|
||||
patchELFGOT();
|
||||
}
|
||||
|
||||
// Patch dynamic section/segment.
|
||||
patchELFDynamic();
|
||||
|
||||
// Update ELF book-keeping info.
|
||||
patchELFSectionHeaderTable();
|
||||
|
||||
|
13
bolt/test/runtime/AArch64/Inputs/runtime_relocs.c
Normal file
13
bolt/test/runtime/AArch64/Inputs/runtime_relocs.c
Normal file
@ -0,0 +1,13 @@
|
||||
int a = 1;
|
||||
__attribute__((used)) int *b = &a; // R_*_ABS64
|
||||
|
||||
static int c;
|
||||
__attribute__((used)) static int *d = &c; // R_*_RELATIVE
|
||||
|
||||
__thread int t1 = 0;
|
||||
|
||||
int inc(int var) {
|
||||
++a; // R_*_GLOB_DAT
|
||||
++t1; // R_*_TLSDESC
|
||||
return var + 1;
|
||||
}
|
155
bolt/test/runtime/AArch64/Inputs/tls_ld.yaml
Normal file
155
bolt/test/runtime/AArch64/Inputs/tls_ld.yaml
Normal file
@ -0,0 +1,155 @@
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_DYN
|
||||
Machine: EM_AARCH64
|
||||
Entry: 0x590
|
||||
ProgramHeaders:
|
||||
- Type: PT_LOAD
|
||||
Flags: [ PF_X, PF_R, PF_W ]
|
||||
FirstSec: .dynsym
|
||||
LastSec: .got
|
||||
Align: 0x10000
|
||||
- Type: PT_DYNAMIC
|
||||
Flags: [ PF_W, PF_R ]
|
||||
FirstSec: .dynamic
|
||||
LastSec: .dynamic
|
||||
VAddr: 0x10DF0
|
||||
Align: 0x8
|
||||
- Type: PT_TLS
|
||||
Flags: [ PF_R ]
|
||||
FirstSec: .tbss
|
||||
LastSec: .tbss
|
||||
VAddr: 0x10DE0
|
||||
Align: 0x4
|
||||
- Type: PT_GNU_EH_FRAME
|
||||
Flags: [ PF_R ]
|
||||
FirstSec: .eh_frame_hdr
|
||||
LastSec: .eh_frame_hdr
|
||||
VAddr: 0x6B8
|
||||
Align: 0x4
|
||||
Sections:
|
||||
- Name: .dynsym
|
||||
Type: SHT_DYNSYM
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Address: 0x250
|
||||
Link: .dynstr
|
||||
AddressAlign: 0x8
|
||||
- Name: .dynstr
|
||||
Type: SHT_STRTAB
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Address: 0x340
|
||||
AddressAlign: 0x1
|
||||
- Name: .plt
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
||||
Address: 0x540
|
||||
AddressAlign: 0x10
|
||||
EntSize: 0x10
|
||||
Content: F07BBFA99000009011FE47F910E23F9120021FD61F2003D51F2003D51F2003D5900000B0110240F91002009120021FD6900000B0110640F91022009120021FD6900000B0110A40F91042009120021FD6
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
||||
Address: 0x590
|
||||
AddressAlign: 0x8
|
||||
Content: 8000009000F047F9400000B4F9FFFF17C0035FD61F2003D5800000B000800091810000B0218000913F0000EBC00000548100009021E447F9610000B4F00301AA00021FD6C0035FD6800000B000800091810000B021800091210000CB22FC7FD3410C818BFF0781EB21FC4193C00000548200009042E047F9620000B4F00302AA00021FD6C0035FD6FD7BBEA9FD030091F30B00F9930000B060824039400100358000009000DC47F9800000B4800000B0000C40F9C7FFFF97D8FFFF972000805260820039F30B40F9FD7BC2A8C0035FD6DEFFFF171F2003D5FD7BBEA9FD030091F30B00F9F303002A8000009000403F91BCFFFF971F2003D5E10300AA60060011F30B40F9220040B942040011220000B9FD7BC2A8C0035FD6
|
||||
- Name: .rela.text
|
||||
Type: SHT_RELA
|
||||
Flags: [ SHF_INFO_LINK ]
|
||||
Link: .symtab
|
||||
AddressAlign: 0x8
|
||||
Info: .text
|
||||
Relocations:
|
||||
- Offset: 0x5C4
|
||||
Symbol: t1
|
||||
Type: R_AARCH64_TLSDESC_LD64_LO12
|
||||
- Name: .eh_frame_hdr
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Address: 0x6B8
|
||||
AddressAlign: 0x4
|
||||
Content: 011B033B3400000005000000F0FEFFFF4C00000020FFFFFF6000000060FFFFFF74000000A8FFFFFF98000000B0FFFFFFB0000000
|
||||
- Name: .eh_frame
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Address: 0x6F0
|
||||
AddressAlign: 0x8
|
||||
Content: 1000000000000000017A520004781E011B0C1F0010000000180000009CFEFFFF3000000000000000100000002C000000B8FEFFFF40000000000000002000000040000000E4FEFFFF4800000000410E209D049E034293024EDEDDD30E00000000140000006400000008FFFFFF040000000000000000000000200000007C000000F8FEFFFF4000000000410E209D049E034293024CDEDDD30E0000000000000000
|
||||
- Name: .tbss
|
||||
Type: SHT_NOBITS
|
||||
Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
|
||||
Address: 0x10DE0
|
||||
AddressAlign: 0x4
|
||||
Offset: 0xDE0
|
||||
Size: 0x4
|
||||
- Name: .dynamic
|
||||
Type: SHT_DYNAMIC
|
||||
Flags: [ SHF_WRITE, SHF_ALLOC ]
|
||||
Address: 0x10DF0
|
||||
Link: .dynstr
|
||||
AddressAlign: 0x8
|
||||
Entries:
|
||||
- Tag: DT_STRTAB
|
||||
Value: 0x340
|
||||
- Tag: DT_SYMTAB
|
||||
Value: 0x250
|
||||
- Tag: DT_PLTRELSZ
|
||||
Value: 0x18
|
||||
- Tag: DT_PLTREL
|
||||
Value: 0x7
|
||||
- Tag: DT_JMPREL
|
||||
Value: 0x418
|
||||
- Tag: DT_NULL
|
||||
Value: 0x0
|
||||
- Name: .got
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_WRITE, SHF_ALLOC ]
|
||||
Address: 0x10FB0
|
||||
AddressAlign: 0x8
|
||||
EntSize: 0x8
|
||||
Content: F00D010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
- Name: .rela.plt
|
||||
Type: SHT_RELA
|
||||
Flags: [ SHF_ALLOC, SHF_INFO_LINK ]
|
||||
Address: 0x418
|
||||
Link: .dynsym
|
||||
AddressAlign: 0x8
|
||||
Info: .got
|
||||
Relocations:
|
||||
- Offset: 0x10fb0
|
||||
Symbol: t1
|
||||
Type: R_AARCH64_TLSDESC
|
||||
- Type: SectionHeaderTable
|
||||
Sections:
|
||||
- Name: .dynsym
|
||||
- Name: .dynstr
|
||||
- Name: .rela.plt
|
||||
- Name: .plt
|
||||
- Name: .text
|
||||
- Name: .rela.text
|
||||
- Name: .eh_frame_hdr
|
||||
- Name: .eh_frame
|
||||
- Name: .tbss
|
||||
- Name: .dynamic
|
||||
- Name: .got
|
||||
- Name: .symtab
|
||||
- Name: .strtab
|
||||
- Name: .shstrtab
|
||||
Symbols:
|
||||
- Name: .text
|
||||
Type: STT_SECTION
|
||||
Section: .text
|
||||
Value: 0x590
|
||||
- Name: t1
|
||||
Type: STT_TLS
|
||||
Section: .tbss
|
||||
Binding: STB_GLOBAL
|
||||
Size: 0x4
|
||||
DynamicSymbols:
|
||||
- Name: t1
|
||||
Type: STT_TLS
|
||||
Section: .tbss
|
||||
Binding: STB_GLOBAL
|
||||
Size: 0x4
|
||||
...
|
162
bolt/test/runtime/AArch64/Inputs/tls_trad.yaml
Normal file
162
bolt/test/runtime/AArch64/Inputs/tls_trad.yaml
Normal file
@ -0,0 +1,162 @@
|
||||
--- !ELF
|
||||
FileHeader:
|
||||
Class: ELFCLASS64
|
||||
Data: ELFDATA2LSB
|
||||
Type: ET_DYN
|
||||
Machine: EM_AARCH64
|
||||
Entry: 0x590
|
||||
ProgramHeaders:
|
||||
- Type: PT_LOAD
|
||||
Flags: [ PF_X, PF_R, PF_W ]
|
||||
FirstSec: .dynsym
|
||||
LastSec: .got
|
||||
Align: 0x10000
|
||||
- Type: PT_DYNAMIC
|
||||
Flags: [ PF_W, PF_R ]
|
||||
FirstSec: .dynamic
|
||||
LastSec: .dynamic
|
||||
VAddr: 0x10DF0
|
||||
Align: 0x8
|
||||
- Type: PT_TLS
|
||||
Flags: [ PF_R ]
|
||||
FirstSec: .tbss
|
||||
LastSec: .tbss
|
||||
VAddr: 0x10DE0
|
||||
Align: 0x4
|
||||
- Type: PT_GNU_EH_FRAME
|
||||
Flags: [ PF_R ]
|
||||
FirstSec: .eh_frame_hdr
|
||||
LastSec: .eh_frame_hdr
|
||||
VAddr: 0x6B8
|
||||
Align: 0x4
|
||||
Sections:
|
||||
- Name: .dynsym
|
||||
Type: SHT_DYNSYM
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Address: 0x250
|
||||
Link: .dynstr
|
||||
AddressAlign: 0x8
|
||||
- Name: .dynstr
|
||||
Type: SHT_STRTAB
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Address: 0x340
|
||||
AddressAlign: 0x1
|
||||
- Name: .rela.dyn
|
||||
Type: SHT_RELA
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Address: 0x400
|
||||
Link: .dynsym
|
||||
AddressAlign: 0x8
|
||||
Relocations:
|
||||
- Offset: 0x10FD0
|
||||
Symbol: t1
|
||||
Type: R_AARCH64_TLS_DTPMOD64
|
||||
- Offset: 0x10FD8
|
||||
Symbol: t1
|
||||
Type: R_AARCH64_TLS_DTPREL64
|
||||
- Name: .plt
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
||||
Address: 0x540
|
||||
AddressAlign: 0x10
|
||||
EntSize: 0x10
|
||||
Content: F07BBFA99000009011FE47F910E23F9120021FD61F2003D51F2003D51F2003D5900000B0110240F91002009120021FD6900000B0110640F91022009120021FD6900000B0110A40F91042009120021FD6
|
||||
- Name: .text
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
|
||||
Address: 0x590
|
||||
AddressAlign: 0x8
|
||||
Content: 8000009000F047F9400000B4F9FFFF17C0035FD61F2003D5800000B000800091810000B0218000913F0000EBC00000548100009021E447F9610000B4F00301AA00021FD6C0035FD6800000B000800091810000B021800091210000CB22FC7FD3410C818BFF0781EB21FC4193C00000548200009042E047F9620000B4F00302AA00021FD6C0035FD6FD7BBEA9FD030091F30B00F9930000B060824039400100358000009000DC47F9800000B4800000B0000C40F9C7FFFF97D8FFFF972000805260820039F30B40F9FD7BC2A8C0035FD6DEFFFF171F2003D5FD7BBEA9FD030091F30B00F9F303002A8000009000403F91BCFFFF971F2003D5E10300AA60060011F30B40F9220040B942040011220000B9FD7BC2A8C0035FD6
|
||||
- Name: .eh_frame_hdr
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Address: 0x6B8
|
||||
AddressAlign: 0x4
|
||||
Content: 011B033B3400000005000000F0FEFFFF4C00000020FFFFFF6000000060FFFFFF74000000A8FFFFFF98000000B0FFFFFFB0000000
|
||||
- Name: .eh_frame
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_ALLOC ]
|
||||
Address: 0x6F0
|
||||
AddressAlign: 0x8
|
||||
Content: 1000000000000000017A520004781E011B0C1F0010000000180000009CFEFFFF3000000000000000100000002C000000B8FEFFFF40000000000000002000000040000000E4FEFFFF4800000000410E209D049E034293024EDEDDD30E00000000140000006400000008FFFFFF040000000000000000000000200000007C000000F8FEFFFF4000000000410E209D049E034293024CDEDDD30E0000000000000000
|
||||
- Name: .tbss
|
||||
Type: SHT_NOBITS
|
||||
Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
|
||||
Address: 0x10DE0
|
||||
AddressAlign: 0x4
|
||||
Offset: 0xDE0
|
||||
Size: 0x4
|
||||
- Name: .dynamic
|
||||
Type: SHT_DYNAMIC
|
||||
Flags: [ SHF_WRITE, SHF_ALLOC ]
|
||||
Address: 0x10DF0
|
||||
Link: .dynstr
|
||||
AddressAlign: 0x8
|
||||
Entries:
|
||||
- Tag: DT_STRTAB
|
||||
Value: 0x340
|
||||
- Tag: DT_SYMTAB
|
||||
Value: 0x250
|
||||
- Tag: DT_RELA
|
||||
Value: 0x400
|
||||
- Tag: DT_RELASZ
|
||||
Value: 0x30
|
||||
- Tag: DT_RELAENT
|
||||
Value: 0x18
|
||||
- Tag: DT_RELACOUNT
|
||||
Value: 0x3
|
||||
- Tag: DT_NULL
|
||||
Value: 0x0
|
||||
- Name: .got
|
||||
Type: SHT_PROGBITS
|
||||
Flags: [ SHF_WRITE, SHF_ALLOC ]
|
||||
Address: 0x10FB0
|
||||
AddressAlign: 0x8
|
||||
EntSize: 0x8
|
||||
Content: F00D010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
- Name: .rela.text
|
||||
Type: SHT_RELA
|
||||
Flags: [ SHF_INFO_LINK ]
|
||||
Link: .symtab
|
||||
AddressAlign: 0x8
|
||||
Info: .text
|
||||
Relocations:
|
||||
- Offset: 0x678
|
||||
Symbol: t1
|
||||
Type: R_AARCH64_TLSGD_ADR_PAGE21
|
||||
- Offset: 0x67C
|
||||
Symbol: t1
|
||||
Type: R_AARCH64_TLSGD_ADD_LO12_NC
|
||||
- Type: SectionHeaderTable
|
||||
Sections:
|
||||
- Name: .dynsym
|
||||
- Name: .dynstr
|
||||
- Name: .rela.dyn
|
||||
- Name: .plt
|
||||
- Name: .text
|
||||
- Name: .rela.text
|
||||
- Name: .eh_frame_hdr
|
||||
- Name: .eh_frame
|
||||
- Name: .tbss
|
||||
- Name: .dynamic
|
||||
- Name: .got
|
||||
- Name: .symtab
|
||||
- Name: .strtab
|
||||
- Name: .shstrtab
|
||||
Symbols:
|
||||
- Name: .text
|
||||
Type: STT_SECTION
|
||||
Section: .text
|
||||
Value: 0x590
|
||||
- Name: t1
|
||||
Type: STT_TLS
|
||||
Section: .tbss
|
||||
Binding: STB_GLOBAL
|
||||
Size: 0x4
|
||||
DynamicSymbols:
|
||||
- Name: t1
|
||||
Type: STT_TLS
|
||||
Section: .tbss
|
||||
Binding: STB_GLOBAL
|
||||
Size: 0x4
|
||||
...
|
64
bolt/test/runtime/AArch64/runtime_relocs.c
Normal file
64
bolt/test/runtime/AArch64/runtime_relocs.c
Normal file
@ -0,0 +1,64 @@
|
||||
// This test checks dynamic relocations support for aarch64.
|
||||
|
||||
// RUN: %clang %cflags -pie -fPIC %S/Inputs/runtime_relocs.c \
|
||||
// RUN: -shared -fuse-ld=lld -o %t.so -Wl,-q -Wl,-soname=rel.so
|
||||
// RUN: %clang %cflags -no-pie %s -fuse-ld=lld \
|
||||
// RUN: -o %t.exe -Wl,-q %t.so
|
||||
// RUN: llvm-bolt %t.so -o %t.bolt.so -use-old-text=0 -lite=0
|
||||
// RUN: llvm-bolt %t.exe -o %t.bolt.exe -use-old-text=0 -lite=0
|
||||
// RUN: LD_PRELOAD=%t.bolt.so %t.bolt.exe
|
||||
|
||||
// Check relocations in library:
|
||||
//
|
||||
// RUN: llvm-readelf -r %t.bolt.so | FileCheck %s -check-prefix=CHECKLIB
|
||||
//
|
||||
// CHECKLIB: 0000000600000401 R_AARCH64_GLOB_DAT {{.*}} a + 0
|
||||
// CHECKLIB: 0000000700000407 R_AARCH64_TLSDESC {{.*}} t1 + 0
|
||||
// CHECKLIB: 0000000600000101 R_AARCH64_ABS64 {{.*}} a + 0
|
||||
|
||||
// Check relocations in executable:
|
||||
//
|
||||
// RUN: llvm-readelf -r %t.bolt.exe | FileCheck %s -check-prefix=CHECKEXE
|
||||
//
|
||||
// CHECKEXE: 0000000600000406 R_AARCH64_TLS_TPREL64 {{.*}} t1 + 0
|
||||
// CHECKEXE: 0000000800000400 R_AARCH64_COPY {{.*}} a + 0
|
||||
// CHECKEXE: 0000000700000402 R_AARCH64_JUMP_SLOT {{.*}} inc + 0
|
||||
|
||||
// Check traditional TLS relocations R_AARCH64_TLS_DTPMOD64 and
|
||||
// R_AARCH64_TLS_DTPREL64 emitted correctly after bolt. Since these
|
||||
// relocations are obsolete and clang and lld does not support them,
|
||||
// the initial binary was built with gcc and ld with -mtls-dialect=trad flag.
|
||||
//
|
||||
// RUN: yaml2obj %p/Inputs/tls_trad.yaml &> %t.trad.so
|
||||
// RUN: llvm-bolt %t.trad.so -o %t.trad.bolt.so -use-old-text=0 -lite=0
|
||||
// RUN: llvm-readelf -r %t.trad.so | FileCheck %s -check-prefix=CHECKTRAD
|
||||
//
|
||||
// CHECKTRAD: 0000000100000404 R_AARCH64_TLS_DTPMOD64 {{.*}} t1 + 0
|
||||
// CHECKTRAD: 0000000100000405 R_AARCH64_TLS_DTPREL64 {{.*}} t1 + 0
|
||||
|
||||
// The ld linker emits R_AARCH64_TLSDESC to .rela.plt section, check that
|
||||
// it is emitted correctly.
|
||||
//
|
||||
// RUN: yaml2obj %p/Inputs/tls_ld.yaml &> %t.ld.so
|
||||
// RUN: llvm-bolt %t.ld.so -o %t.ld.bolt.so -use-old-text=0 -lite=0
|
||||
// RUN: llvm-readelf -r %t.ld.bolt.so | FileCheck %s -check-prefix=CHECKLD
|
||||
//
|
||||
// CHECKLD: 0000000100000407 R_AARCH64_TLSDESC {{.*}} t1 + 0
|
||||
|
||||
extern int a; // R_*_COPY
|
||||
|
||||
extern __thread int t1; // R_*_TLS_TPREL64
|
||||
|
||||
int inc(int a); // R_*_JUMP_SLOT
|
||||
|
||||
int dec(int a) { return a - 1; }
|
||||
|
||||
void *resolver() { return dec; }
|
||||
|
||||
int ifuncDec(int a) __attribute__((ifunc("resolver"))); // R_*_IRELATIVE
|
||||
|
||||
int main() {
|
||||
++t1;
|
||||
ifuncDec(a);
|
||||
inc(a);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user