[PATCH] D15423: [ELF] - Place RW sections that go after relro to another memory page.
Rafael EspĂndola via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 23 07:02:46 PST 2015
Thanks!
I also refactored the code so that there is only one point where we do
page alignments.
On 23 December 2015 at 03:55, George Rimar <grimar at accesssoftek.com> wrote:
> grimar added a comment.
>
> In http://reviews.llvm.org/D15423#315938, @rafael wrote:
>
>> What do you think of the attached variation?
>
>
> Works for me. btw, updateRelro() in variation does not need Sec argument then.
>
> template <class ELFT>
> void Writer<ELFT>::updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr,
> OutputSectionBase<ELFT> *Sec, uintX_t VA) {
> if (!GnuRelroPhdr->p_type)
> setPhdr(GnuRelroPhdr, PT_GNU_RELRO, PF_R, Cur->p_offset, Cur->p_vaddr,
> VA - Cur->p_vaddr, 1 /*p_align*/);
> GnuRelroPhdr->p_filesz = VA - Cur->p_vaddr;
> GnuRelroPhdr->p_memsz = VA - Cur->p_vaddr;
> }
>
>
> http://reviews.llvm.org/D15423
>
>
>
-------------- next part --------------
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index 2440f1a..e11affc 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -1,1188 +1,1194 @@
//===- Writer.cpp ---------------------------------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "Writer.h"
#include "Config.h"
#include "OutputSections.h"
#include "SymbolTable.h"
#include "Target.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/StringSaver.h"
using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::object;
using namespace lld;
using namespace lld::elf2;
namespace {
// The writer writes a SymbolTable result to a file.
template <class ELFT> class Writer {
public:
typedef typename ELFFile<ELFT>::uintX_t uintX_t;
typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
typedef typename ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr;
typedef typename ELFFile<ELFT>::Elf_Phdr Elf_Phdr;
typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela;
Writer(SymbolTable<ELFT> &S) : Symtab(S) {}
void run();
private:
void copyLocalSymbols();
void createSections();
template <bool isRela>
void scanRelocs(InputSectionBase<ELFT> &C,
iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels);
void scanRelocs(InputSection<ELFT> &C);
void scanRelocs(InputSectionBase<ELFT> &S, const Elf_Shdr &RelSec);
- void updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr,
- OutputSectionBase<ELFT> *Sec, uintX_t VA);
+ void updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr, uintX_t VA);
void assignAddresses();
void buildSectionMap();
void openFile(StringRef OutputPath);
void writeHeader();
void writeSections();
bool isDiscarded(InputSectionBase<ELFT> *IS) const;
StringRef getOutputSectionName(StringRef S) const;
bool needsInterpSection() const {
return !Symtab.getSharedFiles().empty() && !Config->DynamicLinker.empty();
}
bool isOutputDynamic() const {
return !Symtab.getSharedFiles().empty() || Config->Shared;
}
uintX_t getEntryAddr() const;
int getPhdrsNum() const;
OutputSection<ELFT> *getBSS();
void addCommonSymbols(std::vector<DefinedCommon<ELFT> *> &Syms);
void addSharedCopySymbols(std::vector<SharedSymbol<ELFT> *> &Syms);
std::unique_ptr<llvm::FileOutputBuffer> Buffer;
SpecificBumpPtrAllocator<OutputSection<ELFT>> SecAlloc;
SpecificBumpPtrAllocator<MergeOutputSection<ELFT>> MSecAlloc;
SpecificBumpPtrAllocator<EHOutputSection<ELFT>> EHSecAlloc;
SpecificBumpPtrAllocator<MipsReginfoOutputSection<ELFT>> MReginfoSecAlloc;
BumpPtrAllocator Alloc;
std::vector<OutputSectionBase<ELFT> *> OutputSections;
unsigned getNumSections() const { return OutputSections.size() + 1; }
void addStartStopSymbols(OutputSectionBase<ELFT> *Sec);
void setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags, uintX_t FileOff,
uintX_t VA, uintX_t Size, uintX_t Align);
void copyPhdr(Elf_Phdr *PH, OutputSectionBase<ELFT> *From);
bool HasRelro = false;
SymbolTable<ELFT> &Symtab;
std::vector<Elf_Phdr> Phdrs;
uintX_t FileSize;
uintX_t SectionHeaderOff;
llvm::StringMap<llvm::StringRef> InputToOutputSection;
};
} // anonymous namespace
template <class ELFT> static bool shouldUseRela() {
ELFKind K = cast<ELFFileBase<ELFT>>(Config->FirstElf)->getELFKind();
return K == ELF64LEKind || K == ELF64BEKind;
}
template <class ELFT> void lld::elf2::writeResult(SymbolTable<ELFT> *Symtab) {
// Initialize output sections that are handled by Writer specially.
// Don't reorder because the order of initialization matters.
InterpSection<ELFT> Interp;
Out<ELFT>::Interp = &Interp;
StringTableSection<ELFT> ShStrTab(".shstrtab", false);
Out<ELFT>::ShStrTab = &ShStrTab;
StringTableSection<ELFT> StrTab(".strtab", false);
if (!Config->StripAll)
Out<ELFT>::StrTab = &StrTab;
StringTableSection<ELFT> DynStrTab(".dynstr", true);
Out<ELFT>::DynStrTab = &DynStrTab;
GotSection<ELFT> Got;
Out<ELFT>::Got = &Got;
GotPltSection<ELFT> GotPlt;
if (Target->supportsLazyRelocations())
Out<ELFT>::GotPlt = &GotPlt;
PltSection<ELFT> Plt;
Out<ELFT>::Plt = &Plt;
std::unique_ptr<SymbolTableSection<ELFT>> SymTab;
if (!Config->StripAll) {
SymTab.reset(new SymbolTableSection<ELFT>(*Symtab, *Out<ELFT>::StrTab));
Out<ELFT>::SymTab = SymTab.get();
}
SymbolTableSection<ELFT> DynSymTab(*Symtab, *Out<ELFT>::DynStrTab);
Out<ELFT>::DynSymTab = &DynSymTab;
HashTableSection<ELFT> HashTab;
if (Config->SysvHash)
Out<ELFT>::HashTab = &HashTab;
GnuHashTableSection<ELFT> GnuHashTab;
if (Config->GnuHash)
Out<ELFT>::GnuHashTab = &GnuHashTab;
bool IsRela = shouldUseRela<ELFT>();
RelocationSection<ELFT> RelaDyn(IsRela ? ".rela.dyn" : ".rel.dyn", IsRela);
Out<ELFT>::RelaDyn = &RelaDyn;
RelocationSection<ELFT> RelaPlt(IsRela ? ".rela.plt" : ".rel.plt", IsRela);
if (Target->supportsLazyRelocations())
Out<ELFT>::RelaPlt = &RelaPlt;
DynamicSection<ELFT> Dynamic(*Symtab);
Out<ELFT>::Dynamic = &Dynamic;
Writer<ELFT>(*Symtab).run();
}
// The main function of the writer.
template <class ELFT> void Writer<ELFT>::run() {
buildSectionMap();
if (!Config->DiscardAll)
copyLocalSymbols();
createSections();
assignAddresses();
openFile(Config->OutputFile);
writeHeader();
writeSections();
error(Buffer->commit());
}
namespace {
template <bool Is64Bits> struct SectionKey {
typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t;
StringRef Name;
uint32_t Type;
uintX_t Flags;
uintX_t EntSize;
};
}
namespace llvm {
template <bool Is64Bits> struct DenseMapInfo<SectionKey<Is64Bits>> {
static SectionKey<Is64Bits> getEmptyKey() {
return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getEmptyKey(), 0, 0,
0};
}
static SectionKey<Is64Bits> getTombstoneKey() {
return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getTombstoneKey(), 0,
0, 0};
}
static unsigned getHashValue(const SectionKey<Is64Bits> &Val) {
return hash_combine(Val.Name, Val.Type, Val.Flags, Val.EntSize);
}
static bool isEqual(const SectionKey<Is64Bits> &LHS,
const SectionKey<Is64Bits> &RHS) {
return DenseMapInfo<StringRef>::isEqual(LHS.Name, RHS.Name) &&
LHS.Type == RHS.Type && LHS.Flags == RHS.Flags &&
LHS.EntSize == RHS.EntSize;
}
};
}
// The reason we have to do this early scan is as follows
// * To mmap the output file, we need to know the size
// * For that, we need to know how many dynamic relocs we will have.
// It might be possible to avoid this by outputting the file with write:
// * Write the allocated output sections, computing addresses.
// * Apply relocations, recording which ones require a dynamic reloc.
// * Write the dynamic relocations.
// * Write the rest of the file.
template <class ELFT>
template <bool isRela>
void Writer<ELFT>::scanRelocs(
InputSectionBase<ELFT> &C,
iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels) {
typedef Elf_Rel_Impl<ELFT, isRela> RelType;
const ObjectFile<ELFT> &File = *C.getFile();
for (const RelType &RI : Rels) {
uint32_t SymIndex = RI.getSymbol(Config->Mips64EL);
SymbolBody *Body = File.getSymbolBody(SymIndex);
uint32_t Type = RI.getType(Config->Mips64EL);
if (Target->isGotRelative(Type))
HasGotOffRel = true;
if (Target->isTlsLocalDynamicReloc(Type)) {
if (Target->isTlsOptimized(Type, nullptr))
continue;
if (Out<ELFT>::Got->addCurrentModuleTlsIndex())
Out<ELFT>::RelaDyn->addReloc({&C, &RI});
continue;
}
// Set "used" bit for --as-needed.
if (Body && Body->isUndefined() && !Body->isWeak())
if (auto *S = dyn_cast<SharedSymbol<ELFT>>(Body->repl()))
S->File->IsUsed = true;
if (Body)
Body = Body->repl();
if (Body && Body->isTls() && Target->isTlsGlobalDynamicReloc(Type)) {
bool Opt = Target->isTlsOptimized(Type, Body);
if (!Opt && Out<ELFT>::Got->addDynTlsEntry(Body)) {
Out<ELFT>::RelaDyn->addReloc({&C, &RI});
Out<ELFT>::RelaDyn->addReloc({nullptr, nullptr});
Body->setUsedInDynamicReloc();
continue;
}
if (!canBePreempted(Body, true))
continue;
}
if (Body && Body->isTls() && !Target->isTlsDynReloc(Type, *Body))
continue;
if (Target->relocNeedsDynRelative(Type)) {
RelType *Rel = new (Alloc) RelType;
Rel->setSymbolAndType(0, Target->getRelativeReloc(), Config->Mips64EL);
Rel->r_offset = RI.r_offset;
Out<ELFT>::RelaDyn->addReloc({&C, Rel});
}
bool NeedsGot = false;
bool NeedsPlt = false;
if (Body) {
if (auto *E = dyn_cast<SharedSymbol<ELFT>>(Body)) {
if (E->NeedsCopy)
continue;
if (Target->needsCopyRel(Type, *Body))
E->NeedsCopy = true;
}
NeedsPlt = Target->relocNeedsPlt(Type, *Body);
if (NeedsPlt) {
if (Body->isInPlt())
continue;
Out<ELFT>::Plt->addEntry(Body);
}
NeedsGot = Target->relocNeedsGot(Type, *Body);
if (NeedsGot) {
if (NeedsPlt && Target->supportsLazyRelocations()) {
Out<ELFT>::GotPlt->addEntry(Body);
} else {
if (Body->isInGot())
continue;
Out<ELFT>::Got->addEntry(Body);
}
}
}
// An STT_GNU_IFUNC symbol always uses a PLT entry, and all references
// to the symbol go through the PLT. This is true even for a local
// symbol, although local symbols normally do not require PLT entries.
if (Body && isGnuIFunc<ELFT>(*Body)) {
Body->setUsedInDynamicReloc();
Out<ELFT>::RelaPlt->addReloc({&C, &RI});
continue;
}
if (Config->EMachine == EM_MIPS && NeedsGot) {
// MIPS ABI has special rules to process GOT entries
// and doesn't require relocation entries for them.
// See "Global Offset Table" in Chapter 5 in the following document
// for detailed description:
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
Body->setUsedInDynamicReloc();
continue;
}
bool CBP = canBePreempted(Body, NeedsGot);
if (!CBP && (!Config->Shared || Target->isRelRelative(Type)))
continue;
if (CBP)
Body->setUsedInDynamicReloc();
if (NeedsPlt && Target->supportsLazyRelocations())
Out<ELFT>::RelaPlt->addReloc({&C, &RI});
else
Out<ELFT>::RelaDyn->addReloc({&C, &RI});
}
}
template <class ELFT> void Writer<ELFT>::scanRelocs(InputSection<ELFT> &C) {
if (!(C.getSectionHdr()->sh_flags & SHF_ALLOC))
return;
for (const Elf_Shdr *RelSec : C.RelocSections)
scanRelocs(C, *RelSec);
}
template <class ELFT>
void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &S,
const Elf_Shdr &RelSec) {
ELFFile<ELFT> &EObj = S.getFile()->getObj();
if (RelSec.sh_type == SHT_RELA)
scanRelocs(S, EObj.relas(&RelSec));
else
scanRelocs(S, EObj.rels(&RelSec));
}
template <class ELFT>
static void reportUndefined(const SymbolTable<ELFT> &S, const SymbolBody &Sym) {
if (Config->Shared && !Config->NoUndefined)
return;
ELFFileBase<ELFT> *SymFile = findFile<ELFT>(S.getObjectFiles(), &Sym);
std::string Message = "undefined symbol: " + Sym.getName().str();
if (SymFile)
Message += " in " + SymFile->getName().str();
if (Config->NoInhibitExec)
warning(Message);
else
error(Message);
}
// Local symbols are not in the linker's symbol table. This function scans
// each object file's symbol table to copy local symbols to the output.
template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
for (const Elf_Sym &Sym : F->getLocalSymbols()) {
ErrorOr<StringRef> SymNameOrErr = Sym.getName(F->getStringTable());
error(SymNameOrErr);
StringRef SymName = *SymNameOrErr;
if (!shouldKeepInSymtab<ELFT>(*F, SymName, Sym))
continue;
if (Out<ELFT>::SymTab)
Out<ELFT>::SymTab->addLocalSymbol(SymName);
}
}
}
// PPC64 has a number of special SHT_PROGBITS+SHF_ALLOC+SHF_WRITE sections that
// we would like to make sure appear is a specific order to maximize their
// coverage by a single signed 16-bit offset from the TOC base pointer.
// Conversely, the special .tocbss section should be first among all SHT_NOBITS
// sections. This will put it next to the loaded special PPC64 sections (and,
// thus, within reach of the TOC base pointer).
static int getPPC64SectionRank(StringRef SectionName) {
return StringSwitch<int>(SectionName)
.Case(".tocbss", 0)
.Case(".branch_lt", 2)
.Case(".toc", 3)
.Case(".toc1", 4)
.Case(".opd", 5)
.Default(1);
}
template <class ELFT> static bool isRelroSection(OutputSectionBase<ELFT> *Sec) {
typename OutputSectionBase<ELFT>::uintX_t Flags = Sec->getFlags();
if (!(Flags & SHF_ALLOC) || !(Flags & SHF_WRITE))
return false;
if (Flags & SHF_TLS)
return true;
uint32_t Type = Sec->getType();
if (Type == SHT_INIT_ARRAY || Type == SHT_FINI_ARRAY ||
Type == SHT_PREINIT_ARRAY)
return true;
if (Sec == Out<ELFT>::GotPlt)
return Config->ZNow;
if (Sec == Out<ELFT>::Dynamic || Sec == Out<ELFT>::Got)
return true;
StringRef S = Sec->getName();
return S == ".data.rel.ro" || S == ".ctors" || S == ".dtors" || S == ".jcr" ||
S == ".eh_frame";
}
// Output section ordering is determined by this function.
template <class ELFT>
static bool compareOutputSections(OutputSectionBase<ELFT> *A,
OutputSectionBase<ELFT> *B) {
typedef typename ELFFile<ELFT>::uintX_t uintX_t;
uintX_t AFlags = A->getFlags();
uintX_t BFlags = B->getFlags();
// Allocatable sections go first to reduce the total PT_LOAD size and
// so debug info doesn't change addresses in actual code.
bool AIsAlloc = AFlags & SHF_ALLOC;
bool BIsAlloc = BFlags & SHF_ALLOC;
if (AIsAlloc != BIsAlloc)
return AIsAlloc;
// We don't have any special requirements for the relative order of
// two non allocatable sections.
if (!AIsAlloc)
return false;
// We want the read only sections first so that they go in the PT_LOAD
// covering the program headers at the start of the file.
bool AIsWritable = AFlags & SHF_WRITE;
bool BIsWritable = BFlags & SHF_WRITE;
if (AIsWritable != BIsWritable)
return BIsWritable;
// For a corresponding reason, put non exec sections first (the program
// header PT_LOAD is not executable).
bool AIsExec = AFlags & SHF_EXECINSTR;
bool BIsExec = BFlags & SHF_EXECINSTR;
if (AIsExec != BIsExec)
return BIsExec;
// If we got here we know that both A and B are in the same PT_LOAD.
// The TLS initialization block needs to be a single contiguous block in a R/W
// PT_LOAD, so stick TLS sections directly before R/W sections. The TLS NOBITS
// sections are placed here as they don't take up virtual address space in the
// PT_LOAD.
bool AIsTls = AFlags & SHF_TLS;
bool BIsTls = BFlags & SHF_TLS;
if (AIsTls != BIsTls)
return AIsTls;
// The next requirement we have is to put nobits sections last. The
// reason is that the only thing the dynamic linker will see about
// them is a p_memsz that is larger than p_filesz. Seeing that it
// zeros the end of the PT_LOAD, so that has to correspond to the
// nobits sections.
bool AIsNoBits = A->getType() == SHT_NOBITS;
bool BIsNoBits = B->getType() == SHT_NOBITS;
if (AIsNoBits != BIsNoBits)
return BIsNoBits;
// We place RelRo section before plain r/w ones.
bool AIsRelRo = isRelroSection(A);
bool BIsRelRo = isRelroSection(B);
if (AIsRelRo != BIsRelRo)
return AIsRelRo;
// Some architectures have additional ordering restrictions for sections
// within the same PT_LOAD.
if (Config->EMachine == EM_PPC64)
return getPPC64SectionRank(A->getName()) <
getPPC64SectionRank(B->getName());
return false;
}
template <class ELFT> OutputSection<ELFT> *Writer<ELFT>::getBSS() {
if (!Out<ELFT>::Bss) {
Out<ELFT>::Bss = new (SecAlloc.Allocate())
OutputSection<ELFT>(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
OutputSections.push_back(Out<ELFT>::Bss);
}
return Out<ELFT>::Bss;
}
// Until this function is called, common symbols do not belong to any section.
// This function adds them to end of BSS section.
template <class ELFT>
void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon<ELFT> *> &Syms) {
typedef typename ELFFile<ELFT>::uintX_t uintX_t;
typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
if (Syms.empty())
return;
// Sort the common symbols by alignment as an heuristic to pack them better.
std::stable_sort(
Syms.begin(), Syms.end(),
[](const DefinedCommon<ELFT> *A, const DefinedCommon<ELFT> *B) {
return A->MaxAlignment > B->MaxAlignment;
});
uintX_t Off = getBSS()->getSize();
for (DefinedCommon<ELFT> *C : Syms) {
const Elf_Sym &Sym = C->Sym;
uintX_t Align = C->MaxAlignment;
Off = RoundUpToAlignment(Off, Align);
C->OffsetInBSS = Off;
Off += Sym.st_size;
}
Out<ELFT>::Bss->setSize(Off);
}
template <class ELFT>
void Writer<ELFT>::addSharedCopySymbols(
std::vector<SharedSymbol<ELFT> *> &Syms) {
typedef typename ELFFile<ELFT>::uintX_t uintX_t;
typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
if (Syms.empty())
return;
uintX_t Off = getBSS()->getSize();
for (SharedSymbol<ELFT> *C : Syms) {
const Elf_Sym &Sym = C->Sym;
const Elf_Shdr *Sec = C->File->getSection(Sym);
uintX_t SecAlign = Sec->sh_addralign;
unsigned TrailingZeros =
std::min(countTrailingZeros(SecAlign),
countTrailingZeros((uintX_t)Sym.st_value));
uintX_t Align = 1 << TrailingZeros;
Out<ELFT>::Bss->updateAlign(Align);
Off = RoundUpToAlignment(Off, Align);
C->OffsetInBSS = Off;
Off += Sym.st_size;
}
Out<ELFT>::Bss->setSize(Off);
}
template <class ELFT>
StringRef Writer<ELFT>::getOutputSectionName(StringRef S) const {
auto It = InputToOutputSection.find(S);
if (It != std::end(InputToOutputSection))
return It->second;
if (S.startswith(".text."))
return ".text";
if (S.startswith(".rodata."))
return ".rodata";
if (S.startswith(".data.rel.ro"))
return ".data.rel.ro";
if (S.startswith(".data."))
return ".data";
if (S.startswith(".bss."))
return ".bss";
return S;
}
template <class ELFT>
void reportDiscarded(InputSectionBase<ELFT> *IS,
const std::unique_ptr<ObjectFile<ELFT>> &File) {
if (!Config->PrintGcSections || !IS || IS->isLive())
return;
llvm::errs() << "removing unused section from '" << IS->getSectionName()
<< "' in file '" << File->getName() << "'\n";
}
template <class ELFT>
bool Writer<ELFT>::isDiscarded(InputSectionBase<ELFT> *IS) const {
if (!IS || !IS->isLive() || IS == &InputSection<ELFT>::Discarded)
return true;
return InputToOutputSection.lookup(IS->getSectionName()) == "/DISCARD/";
}
template <class ELFT>
static bool compareSections(OutputSectionBase<ELFT> *A,
OutputSectionBase<ELFT> *B) {
auto ItA = Config->OutputSections.find(A->getName());
auto ItEnd = std::end(Config->OutputSections);
if (ItA == ItEnd)
return compareOutputSections(A, B);
auto ItB = Config->OutputSections.find(B->getName());
if (ItB == ItEnd)
return compareOutputSections(A, B);
return std::distance(ItA, ItB) > 0;
}
// A statically linked executable will have rel[a].plt section
// to hold R_[*]_IRELATIVE relocations.
// The multi-arch libc will use these symbols to locate
// these relocations at program startup time.
// If RelaPlt is empty then there is no reason to create this symbols.
template <class ELFT>
static void addIRelocMarkers(SymbolTable<ELFT> &Symtab, bool IsDynamic) {
if (IsDynamic || !Out<ELFT>::RelaPlt || !Out<ELFT>::RelaPlt->hasRelocs())
return;
bool IsRela = shouldUseRela<ELFT>();
auto AddMarker = [&](StringRef Name, typename Writer<ELFT>::Elf_Sym &Sym) {
if (SymbolBody *B = Symtab.find(Name))
if (B->isUndefined())
Symtab.addAbsolute(Name, Sym);
};
AddMarker(IsRela ? "__rela_iplt_start" : "__rel_iplt_start",
DefinedAbsolute<ELFT>::RelaIpltStart);
AddMarker(IsRela ? "__rela_iplt_end" : "__rel_iplt_end",
DefinedAbsolute<ELFT>::RelaIpltEnd);
}
// Create output section objects and add them to OutputSections.
template <class ELFT> void Writer<ELFT>::createSections() {
// .interp needs to be on the first page in the output file.
if (needsInterpSection())
OutputSections.push_back(Out<ELFT>::Interp);
SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSectionBase<ELFT> *> Map;
std::vector<OutputSectionBase<ELFT> *> RegularSections;
for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
for (InputSectionBase<ELFT> *C : F->getSections()) {
if (isDiscarded(C)) {
reportDiscarded(C, F);
continue;
}
const Elf_Shdr *H = C->getSectionHdr();
uintX_t OutFlags = H->sh_flags & ~SHF_GROUP;
// For SHF_MERGE we create different output sections for each sh_entsize.
// This makes each output section simple and keeps a single level
// mapping from input to output.
typename InputSectionBase<ELFT>::Kind K = C->SectionKind;
uintX_t EntSize = K != InputSectionBase<ELFT>::Merge ? 0 : H->sh_entsize;
uint32_t OutType = H->sh_type;
if (OutType == SHT_PROGBITS && C->getSectionName() == ".eh_frame" &&
Config->EMachine == EM_X86_64)
OutType = SHT_X86_64_UNWIND;
SectionKey<ELFT::Is64Bits> Key{getOutputSectionName(C->getSectionName()),
OutType, OutFlags, EntSize};
OutputSectionBase<ELFT> *&Sec = Map[Key];
if (!Sec) {
switch (K) {
case InputSectionBase<ELFT>::Regular:
Sec = new (SecAlloc.Allocate())
OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
break;
case InputSectionBase<ELFT>::EHFrame:
Sec = new (EHSecAlloc.Allocate())
EHOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
break;
case InputSectionBase<ELFT>::Merge:
Sec = new (MSecAlloc.Allocate())
MergeOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
break;
case InputSectionBase<ELFT>::MipsReginfo:
Sec = new (MReginfoSecAlloc.Allocate())
MipsReginfoOutputSection<ELFT>();
break;
}
OutputSections.push_back(Sec);
RegularSections.push_back(Sec);
}
switch (K) {
case InputSectionBase<ELFT>::Regular:
static_cast<OutputSection<ELFT> *>(Sec)
->addSection(cast<InputSection<ELFT>>(C));
break;
case InputSectionBase<ELFT>::EHFrame:
static_cast<EHOutputSection<ELFT> *>(Sec)
->addSection(cast<EHInputSection<ELFT>>(C));
break;
case InputSectionBase<ELFT>::Merge:
static_cast<MergeOutputSection<ELFT> *>(Sec)
->addSection(cast<MergeInputSection<ELFT>>(C));
break;
case InputSectionBase<ELFT>::MipsReginfo:
static_cast<MipsReginfoOutputSection<ELFT> *>(Sec)
->addSection(cast<MipsReginfoInputSection<ELFT>>(C));
break;
}
}
}
Out<ELFT>::Bss = static_cast<OutputSection<ELFT> *>(
Map[{".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE, 0}]);
Out<ELFT>::Dynamic->PreInitArraySec = Map.lookup(
{".preinit_array", SHT_PREINIT_ARRAY, SHF_WRITE | SHF_ALLOC, 0});
Out<ELFT>::Dynamic->InitArraySec =
Map.lookup({".init_array", SHT_INIT_ARRAY, SHF_WRITE | SHF_ALLOC, 0});
Out<ELFT>::Dynamic->FiniArraySec =
Map.lookup({".fini_array", SHT_FINI_ARRAY, SHF_WRITE | SHF_ALLOC, 0});
auto AddStartEnd = [&](StringRef Start, StringRef End,
OutputSectionBase<ELFT> *OS) {
if (OS) {
Symtab.addSynthetic(Start, *OS, 0);
Symtab.addSynthetic(End, *OS, OS->getSize());
} else {
Symtab.addIgnored(Start);
Symtab.addIgnored(End);
}
};
AddStartEnd("__preinit_array_start", "__preinit_array_end",
Out<ELFT>::Dynamic->PreInitArraySec);
AddStartEnd("__init_array_start", "__init_array_end",
Out<ELFT>::Dynamic->InitArraySec);
AddStartEnd("__fini_array_start", "__fini_array_end",
Out<ELFT>::Dynamic->FiniArraySec);
for (OutputSectionBase<ELFT> *Sec : RegularSections)
addStartStopSymbols(Sec);
// __tls_get_addr is defined by the dynamic linker for dynamic ELFs. For
// static linking the linker is required to optimize away any references to
// __tls_get_addr, so it's not defined anywhere. Create a hidden definition
// to avoid the undefined symbol error.
if (!isOutputDynamic())
Symtab.addIgnored("__tls_get_addr");
// If the "_end" symbol is referenced, it is expected to point to the address
// right after the data segment. Usually, this symbol points to the end
// of .bss section or to the end of .data section if .bss section is absent.
// The order of the sections can be affected by linker script,
// so it is hard to predict which section will be the last one.
// So, if this symbol is referenced, we just add the placeholder here
// and update its value later.
if (Symtab.find("_end"))
Symtab.addAbsolute("_end", DefinedAbsolute<ELFT>::End);
// If there is an undefined symbol "end", we should initialize it
// with the same value as "_end". In any other case it should stay intact,
// because it is an allowable name for a user symbol.
if (SymbolBody *B = Symtab.find("end"))
if (B->isUndefined())
Symtab.addAbsolute("end", DefinedAbsolute<ELFT>::End);
// Scan relocations. This must be done after every symbol is declared so that
// we can correctly decide if a dynamic relocation is needed.
for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
for (InputSectionBase<ELFT> *C : F->getSections()) {
if (isDiscarded(C))
continue;
if (auto *S = dyn_cast<InputSection<ELFT>>(C))
scanRelocs(*S);
else if (auto *S = dyn_cast<EHInputSection<ELFT>>(C))
if (S->RelocSection)
scanRelocs(*S, *S->RelocSection);
}
}
addIRelocMarkers<ELFT>(Symtab, isOutputDynamic());
std::vector<DefinedCommon<ELFT> *> CommonSymbols;
std::vector<SharedSymbol<ELFT> *> SharedCopySymbols;
for (auto &P : Symtab.getSymbols()) {
SymbolBody *Body = P.second->Body;
if (auto *U = dyn_cast<Undefined>(Body))
if (!U->isWeak() && !U->canKeepUndefined())
reportUndefined<ELFT>(Symtab, *Body);
if (auto *C = dyn_cast<DefinedCommon<ELFT>>(Body))
CommonSymbols.push_back(C);
if (auto *SC = dyn_cast<SharedSymbol<ELFT>>(Body))
if (SC->NeedsCopy)
SharedCopySymbols.push_back(SC);
if (!includeInSymtab<ELFT>(*Body))
continue;
if (Out<ELFT>::SymTab)
Out<ELFT>::SymTab->addSymbol(Body);
if (isOutputDynamic() && includeInDynamicSymtab(*Body))
Out<ELFT>::DynSymTab->addSymbol(Body);
}
addCommonSymbols(CommonSymbols);
addSharedCopySymbols(SharedCopySymbols);
// This order is not the same as the final output order
// because we sort the sections using their attributes below.
if (Out<ELFT>::SymTab)
OutputSections.push_back(Out<ELFT>::SymTab);
OutputSections.push_back(Out<ELFT>::ShStrTab);
if (Out<ELFT>::StrTab)
OutputSections.push_back(Out<ELFT>::StrTab);
if (isOutputDynamic()) {
OutputSections.push_back(Out<ELFT>::DynSymTab);
if (Out<ELFT>::GnuHashTab)
OutputSections.push_back(Out<ELFT>::GnuHashTab);
if (Out<ELFT>::HashTab)
OutputSections.push_back(Out<ELFT>::HashTab);
OutputSections.push_back(Out<ELFT>::Dynamic);
OutputSections.push_back(Out<ELFT>::DynStrTab);
if (Out<ELFT>::RelaDyn->hasRelocs())
OutputSections.push_back(Out<ELFT>::RelaDyn);
// This is a MIPS specific section to hold a space within the data segment
// of executable file which is pointed to by the DT_MIPS_RLD_MAP entry.
// See "Dynamic section" in Chapter 5 in the following document:
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
if (Config->EMachine == EM_MIPS && !Config->Shared) {
Out<ELFT>::MipsRldMap = new (SecAlloc.Allocate())
OutputSection<ELFT>(".rld_map", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
Out<ELFT>::MipsRldMap->setSize(ELFT::Is64Bits ? 8 : 4);
Out<ELFT>::MipsRldMap->updateAlign(ELFT::Is64Bits ? 8 : 4);
OutputSections.push_back(Out<ELFT>::MipsRldMap);
}
}
// We always need to add rel[a].plt to output if it has entries.
// Even during static linking it can contain R_[*]_IRELATIVE relocations.
if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
OutputSections.push_back(Out<ELFT>::RelaPlt);
Out<ELFT>::RelaPlt->Static = !isOutputDynamic();
}
bool needsGot = !Out<ELFT>::Got->empty();
// We add the .got section to the result for dynamic MIPS target because
// its address and properties are mentioned in the .dynamic section.
if (Config->EMachine == EM_MIPS)
needsGot |= isOutputDynamic();
// If we have a relocation that is relative to GOT (such as GOTOFFREL),
// we need to emit a GOT even if it's empty.
if (HasGotOffRel)
needsGot = true;
if (needsGot)
OutputSections.push_back(Out<ELFT>::Got);
if (Out<ELFT>::GotPlt && !Out<ELFT>::GotPlt->empty())
OutputSections.push_back(Out<ELFT>::GotPlt);
if (!Out<ELFT>::Plt->empty())
OutputSections.push_back(Out<ELFT>::Plt);
std::stable_sort(OutputSections.begin(), OutputSections.end(),
compareSections<ELFT>);
for (unsigned I = 0, N = OutputSections.size(); I < N; ++I) {
OutputSections[I]->SectionIndex = I + 1;
HasRelro |= (Config->ZRelro && isRelroSection(OutputSections[I]));
}
for (OutputSectionBase<ELFT> *Sec : OutputSections)
Out<ELFT>::ShStrTab->add(Sec->getName());
// Finalizers fix each section's size.
// .dynamic section's finalizer may add strings to .dynstr,
// so finalize that early.
// Likewise, .dynsym is finalized early since that may fill up .gnu.hash.
Out<ELFT>::Dynamic->finalize();
if (isOutputDynamic())
Out<ELFT>::DynSymTab->finalize();
// Fill other section headers.
for (OutputSectionBase<ELFT> *Sec : OutputSections)
Sec->finalize();
// If we have a .opd section (used under PPC64 for function descriptors),
// store a pointer to it here so that we can use it later when processing
// relocations.
Out<ELFT>::Opd = Map.lookup({".opd", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0});
}
static bool isAlpha(char C) {
return ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z') || C == '_';
}
static bool isAlnum(char C) { return isAlpha(C) || ('0' <= C && C <= '9'); }
// Returns true if S is valid as a C language identifier.
static bool isValidCIdentifier(StringRef S) {
if (S.empty() || !isAlpha(S[0]))
return false;
return std::all_of(S.begin() + 1, S.end(), isAlnum);
}
// If a section name is valid as a C identifier (which is rare because of
// the leading '.'), linkers are expected to define __start_<secname> and
// __stop_<secname> symbols. They are at beginning and end of the section,
// respectively. This is not requested by the ELF standard, but GNU ld and
// gold provide the feature, and used by many programs.
template <class ELFT>
void Writer<ELFT>::addStartStopSymbols(OutputSectionBase<ELFT> *Sec) {
StringRef S = Sec->getName();
if (!isValidCIdentifier(S))
return;
StringSaver Saver(Alloc);
StringRef Start = Saver.save("__start_" + S);
StringRef Stop = Saver.save("__stop_" + S);
if (Symtab.isUndefined(Start))
Symtab.addSynthetic(Start, *Sec, 0);
if (Symtab.isUndefined(Stop))
Symtab.addSynthetic(Stop, *Sec, Sec->getSize());
}
template <class ELFT> static bool needsPhdr(OutputSectionBase<ELFT> *Sec) {
return Sec->getFlags() & SHF_ALLOC;
}
static uint32_t toPhdrFlags(uint64_t Flags) {
uint32_t Ret = PF_R;
if (Flags & SHF_WRITE)
Ret |= PF_W;
if (Flags & SHF_EXECINSTR)
Ret |= PF_X;
return Ret;
}
template <class ELFT>
void Writer<ELFT>::updateRelro(Elf_Phdr *Cur, Elf_Phdr *GnuRelroPhdr,
- OutputSectionBase<ELFT> *Sec, uintX_t VA) {
- if (!Config->ZRelro || !(Cur->p_flags & PF_W) || !isRelroSection(Sec))
- return;
+ uintX_t VA) {
if (!GnuRelroPhdr->p_type)
setPhdr(GnuRelroPhdr, PT_GNU_RELRO, PF_R, Cur->p_offset, Cur->p_vaddr,
VA - Cur->p_vaddr, 1 /*p_align*/);
GnuRelroPhdr->p_filesz = VA - Cur->p_vaddr;
GnuRelroPhdr->p_memsz = VA - Cur->p_vaddr;
}
// Visits all sections to create PHDRs and to assign incremental,
// non-overlapping addresses to output sections.
template <class ELFT> void Writer<ELFT>::assignAddresses() {
uintX_t VA = Target->getVAStart() + sizeof(Elf_Ehdr);
uintX_t FileOff = sizeof(Elf_Ehdr);
// Calculate and reserve the space for the program header first so that
// the first section can start right after the program header.
Phdrs.resize(getPhdrsNum());
size_t PhdrSize = sizeof(Elf_Phdr) * Phdrs.size();
// The first phdr entry is PT_PHDR which describes the program header itself.
setPhdr(&Phdrs[0], PT_PHDR, PF_R, FileOff, VA, PhdrSize, /*Align=*/8);
FileOff += PhdrSize;
VA += PhdrSize;
// PT_INTERP must be the second entry if exists.
int PhdrIdx = 0;
Elf_Phdr *Interp = nullptr;
if (needsInterpSection())
Interp = &Phdrs[++PhdrIdx];
// Add the first PT_LOAD segment for regular output sections.
setPhdr(&Phdrs[++PhdrIdx], PT_LOAD, PF_R, 0, Target->getVAStart(), FileOff,
Target->getPageSize());
Elf_Phdr GnuRelroPhdr = {};
Elf_Phdr TlsPhdr{};
+ bool RelroAligned = false;
uintX_t ThreadBSSOffset = 0;
// Create phdrs as we assign VAs and file offsets to all output sections.
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
+ Elf_Phdr *PH = &Phdrs[PhdrIdx];
if (needsPhdr<ELFT>(Sec)) {
uintX_t Flags = toPhdrFlags(Sec->getFlags());
- if (Phdrs[PhdrIdx].p_flags != Flags) {
- // Flags changed. Create a new PT_LOAD.
+ bool InRelRo = Config->ZRelro && (Flags & PF_W) && isRelroSection(Sec);
+ bool FirstNonRelRo = GnuRelroPhdr.p_type && !InRelRo && !RelroAligned;
+ if (FirstNonRelRo || PH->p_flags != Flags) {
VA = RoundUpToAlignment(VA, Target->getPageSize());
FileOff = RoundUpToAlignment(FileOff, Target->getPageSize());
- Elf_Phdr *PH = &Phdrs[++PhdrIdx];
+ if (FirstNonRelRo)
+ RelroAligned = true;
+ }
+
+ if (PH->p_flags != Flags) {
+ // Flags changed. Create a new PT_LOAD.
+ PH = &Phdrs[++PhdrIdx];
setPhdr(PH, PT_LOAD, Flags, FileOff, VA, 0, Target->getPageSize());
}
if (Sec->getFlags() & SHF_TLS) {
if (!TlsPhdr.p_vaddr)
setPhdr(&TlsPhdr, PT_TLS, PF_R, FileOff, VA, 0, Sec->getAlign());
if (Sec->getType() != SHT_NOBITS)
VA = RoundUpToAlignment(VA, Sec->getAlign());
uintX_t TVA = RoundUpToAlignment(VA + ThreadBSSOffset, Sec->getAlign());
Sec->setVA(TVA);
TlsPhdr.p_memsz += Sec->getSize();
if (Sec->getType() == SHT_NOBITS) {
ThreadBSSOffset = TVA - VA + Sec->getSize();
} else {
TlsPhdr.p_filesz += Sec->getSize();
VA += Sec->getSize();
}
TlsPhdr.p_align = std::max<uintX_t>(TlsPhdr.p_align, Sec->getAlign());
} else {
VA = RoundUpToAlignment(VA, Sec->getAlign());
Sec->setVA(VA);
VA += Sec->getSize();
- updateRelro(&Phdrs[PhdrIdx], &GnuRelroPhdr, Sec, VA);
+ if (InRelRo)
+ updateRelro(PH, &GnuRelroPhdr, VA);
}
}
FileOff = RoundUpToAlignment(FileOff, Sec->getAlign());
Sec->setFileOffset(FileOff);
if (Sec->getType() != SHT_NOBITS)
FileOff += Sec->getSize();
if (needsPhdr<ELFT>(Sec)) {
- Elf_Phdr *Cur = &Phdrs[PhdrIdx];
- Cur->p_filesz = FileOff - Cur->p_offset;
- Cur->p_memsz = VA - Cur->p_vaddr;
+ PH->p_filesz = FileOff - PH->p_offset;
+ PH->p_memsz = VA - PH->p_vaddr;
}
}
if (TlsPhdr.p_vaddr) {
// The TLS pointer goes after PT_TLS. At least glibc will align it,
// so round up the size to make sure the offsets are correct.
TlsPhdr.p_memsz = RoundUpToAlignment(TlsPhdr.p_memsz, TlsPhdr.p_align);
Phdrs[++PhdrIdx] = TlsPhdr;
Out<ELFT>::TlsPhdr = &Phdrs[PhdrIdx];
}
// Add an entry for .dynamic.
if (isOutputDynamic()) {
Elf_Phdr *PH = &Phdrs[++PhdrIdx];
PH->p_type = PT_DYNAMIC;
copyPhdr(PH, Out<ELFT>::Dynamic);
}
if (HasRelro) {
Elf_Phdr *PH = &Phdrs[++PhdrIdx];
*PH = GnuRelroPhdr;
}
// PT_GNU_STACK is a special section to tell the loader to make the
// pages for the stack non-executable.
if (!Config->ZExecStack) {
Elf_Phdr *PH = &Phdrs[++PhdrIdx];
PH->p_type = PT_GNU_STACK;
PH->p_flags = PF_R | PF_W;
}
// Fix up PT_INTERP as we now know the address of .interp section.
if (Interp) {
Interp->p_type = PT_INTERP;
copyPhdr(Interp, Out<ELFT>::Interp);
}
// Add space for section headers.
SectionHeaderOff = RoundUpToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4);
FileSize = SectionHeaderOff + getNumSections() * sizeof(Elf_Shdr);
// Update "_end" and "end" symbols so that they
// point to the end of the data segment.
DefinedAbsolute<ELFT>::End.st_value = VA;
// Update __rel_iplt_start/__rel_iplt_end to wrap the
// rela.plt section.
if (Out<ELFT>::RelaPlt) {
uintX_t Start = Out<ELFT>::RelaPlt->getVA();
DefinedAbsolute<ELFT>::RelaIpltStart.st_value = Start;
DefinedAbsolute<ELFT>::RelaIpltEnd.st_value =
Start + Out<ELFT>::RelaPlt->getSize();
}
// Update MIPS _gp absolute symbol so that it points to the static data.
if (Config->EMachine == EM_MIPS)
DefinedAbsolute<ELFT>::MipsGp.st_value = getMipsGpAddr<ELFT>();
}
// Returns the number of PHDR entries.
template <class ELFT> int Writer<ELFT>::getPhdrsNum() const {
bool Tls = false;
int I = 2; // 2 for PT_PHDR and first PT_LOAD
if (needsInterpSection())
++I;
if (isOutputDynamic())
++I;
if (!Config->ZExecStack)
++I;
uintX_t Last = PF_R;
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
if (!needsPhdr<ELFT>(Sec))
continue;
if (Sec->getFlags() & SHF_TLS)
Tls = true;
uintX_t Flags = toPhdrFlags(Sec->getFlags());
if (Last != Flags) {
Last = Flags;
++I;
}
}
if (Tls)
++I;
if (HasRelro)
++I;
return I;
}
static uint32_t getELFFlags() {
if (Config->EMachine != EM_MIPS)
return 0;
// FIXME: In fact ELF flags depends on ELF flags of input object files
// and selected emulation. For now just use hadr coded values.
uint32_t V = EF_MIPS_ABI_O32 | EF_MIPS_CPIC | EF_MIPS_ARCH_32R2;
if (Config->Shared)
V |= EF_MIPS_PIC;
return V;
}
template <class ELFT> void Writer<ELFT>::writeHeader() {
uint8_t *Buf = Buffer->getBufferStart();
memcpy(Buf, "\177ELF", 4);
// Write the ELF header.
auto *EHdr = reinterpret_cast<Elf_Ehdr *>(Buf);
EHdr->e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
EHdr->e_ident[EI_DATA] = ELFT::TargetEndianness == llvm::support::little
? ELFDATA2LSB
: ELFDATA2MSB;
EHdr->e_ident[EI_VERSION] = EV_CURRENT;
auto &FirstObj = cast<ELFFileBase<ELFT>>(*Config->FirstElf);
EHdr->e_ident[EI_OSABI] = FirstObj.getOSABI();
EHdr->e_type = Config->Shared ? ET_DYN : ET_EXEC;
EHdr->e_machine = FirstObj.getEMachine();
EHdr->e_version = EV_CURRENT;
EHdr->e_entry = getEntryAddr();
EHdr->e_phoff = sizeof(Elf_Ehdr);
EHdr->e_shoff = SectionHeaderOff;
EHdr->e_flags = getELFFlags();
EHdr->e_ehsize = sizeof(Elf_Ehdr);
EHdr->e_phentsize = sizeof(Elf_Phdr);
EHdr->e_phnum = Phdrs.size();
EHdr->e_shentsize = sizeof(Elf_Shdr);
EHdr->e_shnum = getNumSections();
EHdr->e_shstrndx = Out<ELFT>::ShStrTab->SectionIndex;
// Write the program header table.
memcpy(Buf + EHdr->e_phoff, &Phdrs[0], Phdrs.size() * sizeof(Phdrs[0]));
// Write the section header table. Note that the first table entry is null.
auto SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);
for (OutputSectionBase<ELFT> *Sec : OutputSections)
Sec->writeHeaderTo(++SHdrs);
}
template <class ELFT> void Writer<ELFT>::openFile(StringRef Path) {
ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable);
error(BufferOrErr, Twine("failed to open ") + Path);
Buffer = std::move(*BufferOrErr);
}
// Write section contents to a mmap'ed file.
template <class ELFT> void Writer<ELFT>::writeSections() {
uint8_t *Buf = Buffer->getBufferStart();
// PPC64 needs to process relocations in the .opd section before processing
// relocations in code-containing sections.
if (OutputSectionBase<ELFT> *Sec = Out<ELFT>::Opd) {
Out<ELFT>::OpdBuf = Buf + Sec->getFileOff();
Sec->writeTo(Buf + Sec->getFileOff());
}
for (OutputSectionBase<ELFT> *Sec : OutputSections)
if (Sec != Out<ELFT>::Opd)
Sec->writeTo(Buf + Sec->getFileOff());
}
template <class ELFT>
typename ELFFile<ELFT>::uintX_t Writer<ELFT>::getEntryAddr() const {
if (Config->EntrySym) {
if (SymbolBody *E = Config->EntrySym->repl())
return getSymVA<ELFT>(*E);
return 0;
}
if (Config->EntryAddr != uint64_t(-1))
return Config->EntryAddr;
return 0;
}
template <class ELFT>
void Writer<ELFT>::setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags,
uintX_t FileOff, uintX_t VA, uintX_t Size,
uintX_t Align) {
PH->p_type = Type;
PH->p_flags = Flags;
PH->p_offset = FileOff;
PH->p_vaddr = VA;
PH->p_paddr = VA;
PH->p_filesz = Size;
PH->p_memsz = Size;
PH->p_align = Align;
}
template <class ELFT>
void Writer<ELFT>::copyPhdr(Elf_Phdr *PH, OutputSectionBase<ELFT> *From) {
PH->p_flags = toPhdrFlags(From->getFlags());
PH->p_offset = From->getFileOff();
PH->p_vaddr = From->getVA();
PH->p_paddr = From->getVA();
PH->p_filesz = From->getSize();
PH->p_memsz = From->getSize();
PH->p_align = From->getAlign();
}
template <class ELFT> void Writer<ELFT>::buildSectionMap() {
for (const std::pair<StringRef, std::vector<StringRef>> &OutSec :
Config->OutputSections)
for (StringRef Name : OutSec.second)
InputToOutputSection[Name] = OutSec.first;
}
template void lld::elf2::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab);
template void lld::elf2::writeResult<ELF32BE>(SymbolTable<ELF32BE> *Symtab);
template void lld::elf2::writeResult<ELF64LE>(SymbolTable<ELF64LE> *Symtab);
template void lld::elf2::writeResult<ELF64BE>(SymbolTable<ELF64BE> *Symtab);
diff --git a/test/ELF/aarch64-copy.s b/test/ELF/aarch64-copy.s
index 6fc8c5b..86d9720 100644
--- a/test/ELF/aarch64-copy.s
+++ b/test/ELF/aarch64-copy.s
@@ -1,93 +1,93 @@
// REQUIRES: aarch64
// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %p/Inputs/relocation-copy.s -o %t2.o
// RUN: ld.lld -shared %t2.o -o %t2.so
// RUN: ld.lld %t.o %t2.so -o %t3
// RUN: llvm-readobj -s -r --expand-relocs -symbols %t3 | FileCheck %s
// RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s
// RUN: llvm-objdump -s -section=.data %t3 | FileCheck -check-prefix=DATA %s
.text
.globl _start
_start:
adr x1, x
adrp x2, y
add x2, x2, :lo12:y
.data
.word z
// CHECK: Name: .bss
// CHECK-NEXT: Type: SHT_NOBITS
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
-// CHECK-NEXT: Address: 0x120B0
+// CHECK-NEXT: Address: 0x13010
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 24
// CHECK-NEXT: Link:
// CHECK-NEXT: Info:
// CHECK-NEXT: AddressAlignment: 16
// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
// CHECK-NEXT: Relocation {
-// CHECK-NEXT: Offset: 0x120B0
+// CHECK-NEXT: Offset: 0x13010
// CHECK-NEXT: Type: R_AARCH64_COPY
// CHECK-NEXT: Symbol: x
// CHECK-NEXT: Addend: 0x0
// CHECK-NEXT: }
// CHECK-NEXT: Relocation {
-// CHECK-NEXT: Offset: 0x120C0
+// CHECK-NEXT: Offset: 0x13020
// CHECK-NEXT: Type: R_AARCH64_COPY
// CHECK-NEXT: Symbol: y
// CHECK-NEXT: Addend: 0x0
// CHECK-NEXT: }
// CHECK-NEXT: Relocation {
-// CHECK-NEXT: Offset: 0x120C4
+// CHECK-NEXT: Offset: 0x13024
// CHECK-NEXT: Type: R_AARCH64_COPY
// CHECK-NEXT: Symbol: z
// CHECK-NEXT: Addend: 0x0
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK: Symbols [
// CHECK: Name: x
-// CHECK-NEXT: Value: 0x120B0
+// CHECK-NEXT: Value: 0x13010
// CHECK-NEXT: Size: 4
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: Object
// CHECK-NEXT: Other:
// CHECK-NEXT: Section: .bss
// CHECK: Name: y
-// CHECK-NEXT: Value: 0x120C0
+// CHECK-NEXT: Value: 0x13020
// CHECK-NEXT: Size: 4
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: Object
// CHECK-NEXT: Other:
// CHECK-NEXT: Section: .bss
// CHECK: Name: z
-// CHECK-NEXT: Value: 0x120C4
+// CHECK-NEXT: Value: 0x13024
// CHECK-NEXT: Size: 4
// CHECK-NEXT: Binding: Global
// CHECK-NEXT: Type: Object
// CHECK-NEXT: Other:
// CHECK-NEXT: Section: .bss
// CHECK: ]
// CODE: Disassembly of section .text:
// CODE-NEXT: _start:
-// S(x) = 0x120B0, A = 0, P = 0x11000
-// S + A - P = 0x10B0 = 4272
-// CODE-NEXT: 11000: {{.*}} adr x1, #4272
-// S(y) = 0x120C0, A = 0, P = 0x11004
-// Page(S + A) - Page(P) = 0x12000 - 0x11000 = 0x1000 - 4096
-// CODE-NEXT: 11004: {{.*}} adrp x2, #4096
-// S(y) = 0x120C0, A = 0
-// (S + A) & 0xFFF = 0xC0 = 192
-// CODE-NEXT: 11008: {{.*}} add x2, x2, #192
+// S(x) = 0x13010, A = 0, P = 0x11000
+// S + A - P = 0x10B0 = 8208
+// CODE-NEXT: 11000: {{.*}} adr x1, #8208
+// S(y) = 0x13020, A = 0, P = 0x11004
+// Page(S + A) - Page(P) = 0x13000 - 0x11000 = 0x2000 = 8192
+// CODE-NEXT: 11004: {{.*}} adrp x2, #8192
+// S(y) = 0x13020, A = 0
+// (S + A) & 0xFFF = 0x20 = 32
+// CODE-NEXT: 11008: {{.*}} add x2, x2, #32
// DATA: Contents of section .data:
-// S(z) = 0x120c4
-// DATA-NEXT: 120a0 c4200100
+// S(z) = 0x13024
+// DATA-NEXT: 13000 24300100
diff --git a/test/ELF/dynamic-reloc-index.s b/test/ELF/dynamic-reloc-index.s
index 43d9dbb..2d38c01 100644
--- a/test/ELF/dynamic-reloc-index.s
+++ b/test/ELF/dynamic-reloc-index.s
@@ -1,21 +1,21 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
// RUN: ld.lld -shared %t2.o -o %t2.so
// RUN: ld.lld %t.o %t2.so -o %t
// RUN: llvm-readobj -r %t | FileCheck %s
// We used to record the wrong symbol index for this test
// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rela.plt {
-// CHECK-NEXT: 0x120C8 R_X86_64_JUMP_SLOT bar 0x0
+// CHECK-NEXT: 0x13018 R_X86_64_JUMP_SLOT bar 0x0
// CHECK-NEXT: }
// CHECK-NEXT: ]
.global foobar
foobar:
.global zedx
zedx:
.global _start
_start:
.quad bar
diff --git a/test/ELF/dynamic-reloc.s b/test/ELF/dynamic-reloc.s
index 6de2fba..ab2a240 100644
--- a/test/ELF/dynamic-reloc.s
+++ b/test/ELF/dynamic-reloc.s
@@ -1,64 +1,64 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/dynamic-reloc.s -o %t3.o
// RUN: ld.lld -shared %t2.o -o %t2.so
// RUN: ld.lld %t.o %t3.o %t2.so -o %t
// RUN: llvm-readobj -dynamic-table -r --expand-relocs -s %t | FileCheck %s
// REQUIRES: x86
// CHECK: Index: 1
// CHECK-NEXT: Name: .dynsym
// CHECK: Name: .rela.plt
// CHECK-NEXT: Type: SHT_RELA
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: ]
// CHECK-NEXT: Address: [[RELAADDR:.*]]
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: [[RELASIZE:.*]]
// CHECK-NEXT: Link: 1
// CHECK-NEXT: Info: 0
// CHECK-NEXT: AddressAlignment: 8
// CHECK-NEXT: EntrySize: 24
// CHECK: Name: .text
// CHECK-NEXT: Type: SHT_PROGBITS
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_EXECINSTR
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x11000
// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rela.plt {
// CHECK-NEXT: Relocation {
-// CHECK-NEXT: Offset: 0x120C8
+// CHECK-NEXT: Offset: 0x13018
// CHECK-NEXT: Type: R_X86_64_JUMP_SLOT
// CHECK-NEXT: Symbol: bar
// CHECK-NEXT: Addend: 0x0
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK: DynamicSection [
// CHECK-NEXT: Tag Type Name/Value
// CHECK-NEXT: 0x0000000000000017 JMPREL
// CHECK-NEXT: 0x0000000000000002 PLTRELSZ 24 (bytes)
// CHECK-NEXT: 0x0000000000000003 PLTGOT
// CHECK-NEXT: 0x0000000000000014 PLTREL RELA
// CHECK-NEXT: 0x0000000000000006 SYMTAB
// CHECK-NEXT: 0x000000000000000B SYMENT 24 (bytes)
// CHECK-NEXT: 0x0000000000000005 STRTAB
// CHECK-NEXT: 0x000000000000000A STRSZ
// CHECK-NEXT: 0x0000000000000004 HASH
// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so)
// CHECK-NEXT: 0x0000000000000000 NULL 0x0
// CHECK-NEXT: ]
.global _start
_start:
.quad bar + 0x42
.weak foo
.quad foo
call main
diff --git a/test/ELF/mips-got-relocs.s b/test/ELF/mips-got-relocs.s
index f8b7be4..27180fb 100644
--- a/test/ELF/mips-got-relocs.s
+++ b/test/ELF/mips-got-relocs.s
@@ -1,99 +1,99 @@
# Check R_MIPS_GOT16 relocation calculation.
# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-be.o
# RUN: ld.lld %t-be.o -o %t-be.exe
# RUN: llvm-objdump -section-headers -t %t-be.exe | FileCheck -check-prefix=EXE_SYM %s
# RUN: llvm-objdump -s -section=.got %t-be.exe | FileCheck -check-prefix=EXE_GOT_BE %s
# RUN: llvm-objdump -d %t-be.exe | FileCheck -check-prefix=EXE_DIS_BE %s
# RUN: llvm-readobj -relocations %t-be.exe | FileCheck -check-prefix=NORELOC %s
# RUN: llvm-readobj -sections %t-be.exe | FileCheck -check-prefix=SHFLAGS %s
# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t-el.o
# RUN: ld.lld %t-el.o -o %t-el.exe
# RUN: llvm-objdump -section-headers -t %t-el.exe | FileCheck -check-prefix=EXE_SYM %s
# RUN: llvm-objdump -s -section=.got %t-el.exe | FileCheck -check-prefix=EXE_GOT_EL %s
# RUN: llvm-objdump -d %t-el.exe | FileCheck -check-prefix=EXE_DIS_EL %s
# RUN: llvm-readobj -relocations %t-el.exe | FileCheck -check-prefix=NORELOC %s
# RUN: llvm-readobj -sections %t-el.exe | FileCheck -check-prefix=SHFLAGS %s
# RUN: ld.lld -shared %t-be.o -o %t-be.so
# RUN: llvm-objdump -section-headers -t %t-be.so | FileCheck -check-prefix=DSO_SYM %s
# RUN: llvm-objdump -s -section=.got %t-be.so | FileCheck -check-prefix=DSO_GOT_BE %s
# RUN: llvm-objdump -d %t-be.so | FileCheck -check-prefix=DSO_DIS_BE %s
# RUN: llvm-readobj -relocations %t-be.so | FileCheck -check-prefix=NORELOC %s
# RUN: llvm-readobj -sections %t-be.so | FileCheck -check-prefix=SHFLAGS %s
# RUN: ld.lld -shared %t-el.o -o %t-el.so
# RUN: llvm-objdump -section-headers -t %t-el.so | FileCheck -check-prefix=DSO_SYM %s
# RUN: llvm-objdump -s -section=.got %t-el.so | FileCheck -check-prefix=DSO_GOT_EL %s
# RUN: llvm-objdump -d %t-el.so | FileCheck -check-prefix=DSO_DIS_EL %s
# RUN: llvm-readobj -relocations %t-el.so | FileCheck -check-prefix=NORELOC %s
# RUN: llvm-readobj -sections %t-el.so | FileCheck -check-prefix=SHFLAGS %s
# REQUIRES: mips
.text
.globl __start
__start:
lui $2, %got(v1)
.data
.globl v1
.type v1, at object
.size v1,4
v1:
.word 0
# EXE_SYM: Sections:
# EXE_SYM: .got 0000000c 0000000000030000 DATA
# EXE_SYM: SYMBOL TABLE:
# EXE_SYM: 00037ff0 *ABS* 00000000 _gp
# ^-- .got + GP offset (0x7ff0)
-# EXE_SYM: 00030010 g .data 00000004 v1
+# EXE_SYM: 00040000 g .data 00000004 v1
# EXE_GOT_BE: Contents of section .got:
-# EXE_GOT_BE: 30000 00000000 80000000 00030010
-# ^ ^ ^-- v1 (0x30010)
+# EXE_GOT_BE: 30000 00000000 80000000 00040000
+# ^ ^ ^-- v1 (0x40000)
# | +-- Module pointer (0x80000000)
# +-- Lazy resolver (0x0)
# EXE_GOT_EL: Contents of section .got:
-# EXE_GOT_EL: 30000 00000000 00000080 10000300
-# ^ ^ ^-- v1 (0x30010)
+# EXE_GOT_EL: 30000 00000000 00000080 00000400
+# ^ ^ ^-- v1 (0x40000)
# | +-- Module pointer (0x80000000)
# +-- Lazy resolver (0x0)
# v1GotAddr (0x3000c) - _gp (0x37ff4) = -0x7fe8 => 0x8018 = 32792
# EXE_DIS_BE: 20000: 3c 02 80 18 lui $2, 32792
# EXE_DIS_EL: 20000: 18 80 02 3c lui $2, 32792
# DSO_SYM: Sections:
# DSO_SYM: .got 0000000c 0000000000020000 DATA
# DSO_SYM: SYMBOL TABLE:
# DSO_SYM: 00027ff0 *ABS* 00000000 _gp
# ^-- .got + GP offset (0x7ff0)
-# DSO_SYM: 00020010 g .data 00000004 v1
+# DSO_SYM: 00030000 g .data 00000004 v1
# DSO_GOT_BE: Contents of section .got:
-# DSO_GOT_BE: 20000 00000000 80000000 00020010
-# ^ ^ ^-- v1 (0x20010)
+# DSO_GOT_BE: 20000 00000000 80000000 00030000
+# ^ ^ ^-- v1 (0x30000)
# | +-- Module pointer (0x80000000)
# +-- Lazy resolver (0x0)
# DSO_GOT_EL: Contents of section .got:
-# DSO_GOT_EL: 20000 00000000 00000080 10000200
-# ^ ^ ^-- v1 (0x20010)
+# DSO_GOT_EL: 20000 00000000 00000080 00000300
+# ^ ^ ^-- v1 (0x30000)
# | +-- Module pointer (0x80000000)
# +-- Lazy resolver (0x0)
# v1GotAddr (0x2000c) - _gp (0x27ff4) = -0x7fe8 => 0x8018 = 32792
# DSO_DIS_BE: 10000: 3c 02 80 18 lui $2, 32792
# DSO_DIS_EL: 10000: 18 80 02 3c lui $2, 32792
# NORELOC: Relocations [
# NORELOC-NEXT: ]
# SHFLAGS: Name: .got
# SHFLAGS-NEXT: Type: SHT_PROGBITS
# SHFLAGS-NEXT: Flags [ (0x10000003)
# ^-- SHF_MIPS_GPREL | SHF_ALLOC | SHF_WRITE
diff --git a/test/ELF/plt-aarch64.s b/test/ELF/plt-aarch64.s
index 3c58dae..6ea732e 100644
--- a/test/ELF/plt-aarch64.s
+++ b/test/ELF/plt-aarch64.s
@@ -1,205 +1,205 @@
// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %p/Inputs/shared.s -o %t2.o
// RUN: ld.lld -shared %t2.o -o %t2.so
// RUN: ld.lld -shared %t.o %t2.so -o %t.so
// RUN: ld.lld %t.o %t2.so -o %t.exe
// RUN: llvm-readobj -s -r %t.so | FileCheck --check-prefix=CHECKDSO %s
// RUN: llvm-objdump -s -section=.got.plt %t.so | FileCheck --check-prefix=DUMPDSO %s
// RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASMDSO %s
// RUN: llvm-readobj -s -r %t.exe | FileCheck --check-prefix=CHECKEXE %s
// RUN: llvm-objdump -s -section=.got.plt %t.exe | FileCheck --check-prefix=DUMPEXE %s
// RUN: llvm-objdump -d %t.exe | FileCheck --check-prefix=DISASMEXE %s
// REQUIRES: aarch64
// CHECKDSO: Name: .plt
// CHECKDSO-NEXT: Type: SHT_PROGBITS
// CHECKDSO-NEXT: Flags [
// CHECKDSO-NEXT: SHF_ALLOC
// CHECKDSO-NEXT: SHF_EXECINSTR
// CHECKDSO-NEXT: ]
// CHECKDSO-NEXT: Address: 0x1010
// CHECKDSO-NEXT: Offset:
// CHECKDSO-NEXT: Size: 80
// CHECKDSO-NEXT: Link:
// CHECKDSO-NEXT: Info:
// CHECKDSO-NEXT: AddressAlignment: 16
// CHECKDSO: Name: .got.plt
// CHECKDSO-NEXT: Type: SHT_PROGBITS
// CHECKDSO-NEXT: Flags [
// CHECKDSO-NEXT: SHF_ALLOC
// CHECKDSO-NEXT: SHF_WRITE
// CHECKDSO-NEXT: ]
-// CHECKDSO-NEXT: Address: 0x20B0
+// CHECKDSO-NEXT: Address: 0x3000
// CHECKDSO-NEXT: Offset:
// CHECKDSO-NEXT: Size: 48
// CHECKDSO-NEXT: Link:
// CHECKDSO-NEXT: Info:
// CHECKDSO-NEXT: AddressAlignment: 8
// CHECKDSO: Relocations [
// CHECKDSO-NEXT: Section ({{.*}}) .rela.plt {
-// &(.got.plt[3]) = 0x20B0 + 3 * 8 = 0x20C8
-// CHECKDSO-NEXT: 0x20C8 R_AARCH64_JUMP_SLOT foo
+// &(.got.plt[3]) = 0x3000 + 3 * 8 = 0x3018
+// CHECKDSO-NEXT: 0x3018 R_AARCH64_JUMP_SLOT foo
-// &(.got.plt[4]) = 0x20B0 + 4 * 8 = 0x20D0
-// CHECKDSO-NEXT: 0x20D0 R_AARCH64_JUMP_SLOT bar
+// &(.got.plt[4]) = 0x3000 + 4 * 8 = 0x3020
+// CHECKDSO-NEXT: 0x3020 R_AARCH64_JUMP_SLOT bar
-// &(.got.plt[5]) = 0x20B0 + 5 * 8 = 0x20D8
-// CHECKDSO-NEXT: 0x20D8 R_AARCH64_JUMP_SLOT weak
+// &(.got.plt[5]) = 0x3000 + 5 * 8 = 0x3028
+// CHECKDSO-NEXT: 0x3028 R_AARCH64_JUMP_SLOT weak
// CHECKDSO-NEXT: }
// CHECKDSO-NEXT: ]
// DUMPDSO: Contents of section .got.plt:
// .got.plt[0..2] = 0 (reserved)
// .got.plt[3..5] = .plt = 0x1010
-// DUMPDSO-NEXT: 20b0 00000000 00000000 00000000 00000000 ................
-// DUMPDSO-NEXT: 20c0 00000000 00000000 10100000 00000000 ................
-// DUMPDSO-NEXT: 20d0 10100000 00000000 10100000 00000000 ................
+// DUMPDSO-NEXT: 3000 00000000 00000000 00000000 00000000 ................
+// DUMPDSO-NEXT: 3010 00000000 00000000 10100000 00000000 ................
+// DUMPDSO-NEXT: 3020 10100000 00000000 10100000 00000000 ................
// DISASMDSO: _start:
// 0x1030 - 0x1000 = 0x30 = 48
// DISASMDSO-NEXT: 1000: 0c 00 00 14 b #48
// 0x1040 - 0x1004 = 0x3c = 60
// DISASMDSO-NEXT: 1004: 0f 00 00 14 b #60
// 0x1050 - 0x1008 = 0x48 = 72
// DISASMDSO-NEXT: 1008: 12 00 00 14 b #72
// DISASMDSO: foo:
// DISASMDSO-NEXT: 100c: 1f 20 03 d5 nop
// DISASMDSO: Disassembly of section .plt:
// DISASMDSO-NEXT: .plt:
// DISASMDSO-NEXT: 1010: f0 7b bf a9 stp x16, x30, [sp, #-16]!
-// &(.got.plt[2]) = 0x20B0 + 2 * 8 = 0x20C0
-// Page(0x20C0) - Page(0x1014) = 0x2000 - 0x1000 = 0x1000 = 4096
-// DISASMDSO-NEXT: 1014: 10 00 00 b0 adrp x16, #4096
-// 0x20c0 & 0xFFF = 0xC0 = 192
-// DISASMDSO-NEXT: 1018: 11 62 40 f9 ldr x17, [x16, #192]
-// DISASMDSO-NEXT: 101c: 10 02 03 91 add x16, x16, #192
+// &(.got.plt[2]) = 0x3000 + 2 * 8 = 0x3010
+// Page(0x3010) - Page(0x1014) = 0x3000 - 0x1000 = 0x2000 = 8192
+// DISASMDSO-NEXT: 1014: 10 00 00 d0 adrp x16, #8192
+// 0x3010 & 0xFFF = 0x10 = 16
+// DISASMDSO-NEXT: 1018: 11 0a 40 f9 ldr x17, [x16, #16]
+// DISASMDSO-NEXT: 101c: 10 42 00 91 add x16, x16, #16
// DISASMDSO-NEXT: 1020: 20 02 1f d6 br x17
// DISASMDSO-NEXT: 1024: 1f 20 03 d5 nop
// DISASMDSO-NEXT: 1028: 1f 20 03 d5 nop
// DISASMDSO-NEXT: 102c: 1f 20 03 d5 nop
// foo at plt
-// Page(0x20C8) - Page(0x1030) = 0x2000 - 0x1000 = 0x1000 = 4096
-// DISASMDSO-NEXT: 1030: 10 00 00 b0 adrp x16, #4096
-// 0x20C8 & 0xFFF = 0xC8 = 200
-// DISASMDSO-NEXT: 1034: 11 66 40 f9 ldr x17, [x16, #200]
-// DISASMDSO-NEXT: 1038: 10 22 03 91 add x16, x16, #200
+// Page(0x3018) - Page(0x1030) = 0x3000 - 0x1000 = 0x2000 = 8192
+// DISASMDSO-NEXT: 1030: 10 00 00 d0 adrp x16, #8192
+// 0x3018 & 0xFFF = 0x18 = 24
+// DISASMDSO-NEXT: 1034: 11 0e 40 f9 ldr x17, [x16, #24]
+// DISASMDSO-NEXT: 1038: 10 62 00 91 add x16, x16, #24
// DISASMDSO-NEXT: 103c: 20 02 1f d6 br x17
// bar at plt
-// Page(0x20D0) - Page(0x1040) = 0x2000 - 0x1000 = 0x1000 = 4096
-// DISASMDSO-NEXT: 1040: 10 00 00 b0 adrp x16, #4096
-// 0x20D0 & 0xFFF = 0xD0 = 208
-// DISASMDSO-NEXT: 1044: 11 6a 40 f9 ldr x17, [x16, #208]
-// DISASMDSO-NEXT: 1048: 10 42 03 91 add x16, x16, #208
+// Page(0x3020) - Page(0x1040) = 0x3000 - 0x1000 = 0x2000 = 8192
+// DISASMDSO-NEXT: 1040: 10 00 00 d0 adrp x16, #8192
+// 0x3020 & 0xFFF = 0x20 = 32
+// DISASMDSO-NEXT: 1044: 11 12 40 f9 ldr x17, [x16, #32]
+// DISASMDSO-NEXT: 1048: 10 82 00 91 add x16, x16, #32
// DISASMDSO-NEXT: 104c: 20 02 1f d6 br x17
// weak at plt
-// Page(0x20D8) - Page(0x1050) = 0x2000 - 0x1000 = 0x1000 = 4096
-// DISASMDSO-NEXT: 1050: 10 00 00 b0 adrp x16, #4096
-// 0x20D8 & 0xFFF = 0xD8 = 216
-// DISASMDSO-NEXT: 1054: 11 6e 40 f9 ldr x17, [x16, #216]
-// DISASMDSO-NEXT: 1058: 10 62 03 91 add x16, x16, #216
+// Page(0x3028) - Page(0x1050) = 0x3000 - 0x1000 = 0x2000 = 8192
+// DISASMDSO-NEXT: 1050: 10 00 00 d0 adrp x16, #8192
+// 0x3028 & 0xFFF = 0x28 = 40
+// DISASMDSO-NEXT: 1054: 11 16 40 f9 ldr x17, [x16, #40]
+// DISASMDSO-NEXT: 1058: 10 a2 00 91 add x16, x16, #40
// DISASMDSO-NEXT: 105c: 20 02 1f d6 br x17
// CHECKEXE: Name: .plt
// CHECKEXE-NEXT: Type: SHT_PROGBITS
// CHECKEXE-NEXT: Flags [
// CHECKEXE-NEXT: SHF_ALLOC
// CHECKEXE-NEXT: SHF_EXECINSTR
// CHECKEXE-NEXT: ]
// CHECKEXE-NEXT: Address: 0x11010
// CHECKEXE-NEXT: Offset:
// CHECKEXE-NEXT: Size: 64
// CHECKEXE-NEXT: Link:
// CHECKEXE-NEXT: Info:
// CHECKEXE-NEXT: AddressAlignment: 16
// CHECKEXE: Name: .got.plt
// CHECKEXE-NEXT: Type: SHT_PROGBITS
// CHECKEXE-NEXT: Flags [
// CHECKEXE-NEXT: SHF_ALLOC
// CHECKEXE-NEXT: SHF_WRITE
// CHECKEXE-NEXT: ]
-// CHECKEXE-NEXT: Address: 0x120B0
+// CHECKEXE-NEXT: Address: 0x13000
// CHECKEXE-NEXT: Offset:
// CHECKEXE-NEXT: Size: 40
// CHECKEXE-NEXT: Link:
// CHECKEXE-NEXT: Info:
// CHECKEXE-NEXT: AddressAlignment: 8
// CHECKEXE: Relocations [
// CHECKEXE-NEXT: Section ({{.*}}) .rela.plt {
-// &(.got.plt[3]) = 0x120B0 + 3 * 8 = 0x120C8
-// CHECKEXE-NEXT: 0x120C8 R_AARCH64_JUMP_SLOT bar 0x0
+// &(.got.plt[3]) = 0x13000 + 3 * 8 = 0x13018
+// CHECKEXE-NEXT: 0x13018 R_AARCH64_JUMP_SLOT bar 0x0
-// &(.got.plt[4]) = 0x120B0 + 4 * 8 = 0x120D0
-// CHECKEXE-NEXT: 0x120D0 R_AARCH64_JUMP_SLOT weak 0x0
+// &(.got.plt[4]) = 0x13000 + 4 * 8 = 0x13020
+// CHECKEXE-NEXT: 0x13020 R_AARCH64_JUMP_SLOT weak 0x0
// CHECKEXE-NEXT: }
// CHECKEXE-NEXT: ]
// DUMPEXE: Contents of section .got.plt:
// .got.plt[0..2] = 0 (reserved)
// .got.plt[3..4] = .plt = 0x11010
-// DUMPEXE-NEXT: 120b0 00000000 00000000 00000000 00000000 ................
-// DUMPEXE-NEXT: 120c0 00000000 00000000 10100100 00000000 ................
-// DUMPEXE-NEXT: 120d0 10100100 00000000 ........
+// DUMPEXE-NEXT: 13000 00000000 00000000 00000000 00000000 ................
+// DUMPEXE-NEXT: 13010 00000000 00000000 10100100 00000000 ................
+// DUMPEXE-NEXT: 13020 10100100 00000000 ........
// DISASMEXE: _start:
// 0x1100c - 0x11000 = 0xc = 12
// DISASMEXE-NEXT: 11000: 03 00 00 14 b #12
// 0x11030 - 0x11004 = 0x2c = 44
// DISASMEXE-NEXT: 11004: 0b 00 00 14 b #44
// 0x11040 - 0x11008 = 0x38 = 56
// DISASMEXE-NEXT: 11008: 0e 00 00 14 b #56
// DISASMEXE: foo:
// DISASMEXE-NEXT: 1100c: 1f 20 03 d5 nop
// DISASMEXE: Disassembly of section .plt:
// DISASMEXE-NEXT: .plt:
// DISASMEXE-NEXT: 11010: f0 7b bf a9 stp x16, x30, [sp, #-16]!
// &(.got.plt[2]) = 0x120B0 + 2 * 8 = 0x120C0
-// Page(0x120C0) - Page(0x11014) = 0x12000 - 0x11000 = 0x1000 = 4096
-// DISASMEXE-NEXT: 11014: 10 00 00 b0 adrp x16, #4096
+// Page(0x13010) - Page(0x11014) = 0x13000 - 0x11000 = 0x1000 = 8192
+// DISASMEXE-NEXT: 11014: 10 00 00 d0 adrp x16, #8192
// 0x120c0 & 0xFFF = 0xC0 = 192
-// DISASMEXE-NEXT: 11018: 11 62 40 f9 ldr x17, [x16, #192]
-// DISASMEXE-NEXT: 1101c: 10 02 03 91 add x16, x16, #192
+// DISASMEXE-NEXT: 11018: 11 0a 40 f9 ldr x17, [x16, #16]
+// DISASMEXE-NEXT: 1101c: 10 42 00 91 add x16, x16, #16
// DISASMEXE-NEXT: 11020: 20 02 1f d6 br x17
// DISASMEXE-NEXT: 11024: 1f 20 03 d5 nop
// DISASMEXE-NEXT: 11028: 1f 20 03 d5 nop
// DISASMEXE-NEXT: 1102c: 1f 20 03 d5 nop
// bar at plt
-// Page(0x120C8) - Page(0x11030) = 0x12000 - 0x11000 = 0x1000 = 4096
-// DISASMEXE-NEXT: 11030: 10 00 00 b0 adrp x16, #4096
+// Page(0x13018) - Page(0x11030) = 0x12000 - 0x11000 = 0x1000 = 8192
+// DISASMEXE-NEXT: 11030: 10 00 00 d0 adrp x16, #8192
// 0x120C8 & 0xFFF = 0xC8 = 200
-// DISASMEXE-NEXT: 11034: 11 66 40 f9 ldr x17, [x16, #200]
-// DISASMEXE-NEXT: 11038: 10 22 03 91 add x16, x16, #200
+// DISASMEXE-NEXT: 11034: 11 0e 40 f9 ldr x17, [x16, #24]
+// DISASMEXE-NEXT: 11038: 10 62 00 91 add x16, x16, #24
// DISASMEXE-NEXT: 1103c: 20 02 1f d6 br x17
// weak at plt
-// Page(0x120D0) - Page(0x11040) = 0x12000 - 0x11000 = 0x1000 = 4096
-// DISASMEXE-NEXT: 11040: 10 00 00 b0 adrp x16, #4096
+// Page(0x13020) - Page(0x11040) = 0x12000 - 0x11000 = 0x1000 = 8192
+// DISASMEXE-NEXT: 11040: 10 00 00 d0 adrp x16, #8192
// 0x120D0 & 0xFFF = 0xD0 = 208
-// DISASMEXE-NEXT: 11044: 11 6a 40 f9 ldr x17, [x16, #208]
-// DISASMEXE-NEXT: 11048: 10 42 03 91 add x16, x16, #208
+// DISASMEXE-NEXT: 11044: 11 12 40 f9 ldr x17, [x16, #32]
+// DISASMEXE-NEXT: 11048: 10 82 00 91 add x16, x16, #32
// DISASMEXE-NEXT: 1104c: 20 02 1f d6 br x17
.global _start,foo,bar
.weak weak
_start:
b foo
b bar
b weak
.section .text2,"ax", at progbits
foo:
nop
diff --git a/test/ELF/plt-i686.s b/test/ELF/plt-i686.s
index 7f50967..4947e0e 100644
--- a/test/ELF/plt-i686.s
+++ b/test/ELF/plt-i686.s
@@ -1,158 +1,158 @@
// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o
// RUN: ld.lld -shared %t2.o -o %t2.so
// RUN: ld.lld %t.o %t2.so -o %t
// RUN: llvm-readobj -s -r %t | FileCheck --check-prefix=CHECK %s
// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
// RUN: ld.lld -shared %t.o %t2.so -o %t
// RUN: llvm-readobj -s -r %t | FileCheck --check-prefix=CHECKSHARED %s
// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASMSHARED %s
// REQUIRES: x86
// CHECK: Name: .plt
// CHECK-NEXT: Type: SHT_PROGBITS
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_EXECINSTR
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x11020
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 48
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
// CHECK-NEXT: AddressAlignment: 16
// CHECK: Name: .got.plt
// CHECK-NEXT: Type: SHT_PROGBITS
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
-// CHECK-NEXT: Address: 0x12058
-// CHECK-NEXT: Offset: 0x2058
+// CHECK-NEXT: Address: 0x13000
+// CHECK-NEXT: Offset: 0x3000
// CHECK-NEXT: Size: 20
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
// CHECK-NEXT: AddressAlignment: 4
// CHECK-NEXT: EntrySize: 0
-// 0x12058 + got.plt.reserved(12) = 0x12064
-// 0x12058 + got.plt.reserved(12) + 4 = 0x12068
+// 0x13000 + got.plt.reserved(12) = 0x1300C
+// 0x13000 + got.plt.reserved(12) + 4 = 0x13010
// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rel.plt {
-// CHECK-NEXT: 0x12064 R_386_JUMP_SLOT bar 0x0
-// CHECK-NEXT: 0x12068 R_386_JUMP_SLOT zed 0x0
+// CHECK-NEXT: 0x1300C R_386_JUMP_SLOT bar 0x0
+// CHECK-NEXT: 0x13010 R_386_JUMP_SLOT zed 0x0
// CHECK-NEXT: }
// CHECK-NEXT: ]
// Unfortunately FileCheck can't do math, so we have to check for explicit
// values:
// 16 is the size of PLT[0]
// (0x11010 + 16) - (0x11000 + 1) - 4 = 27
// (0x11010 + 16) - (0x11005 + 1) - 4 = 22
// (0x11020 + 16) - (0x1100a + 1) - 4 = 33
// DISASM: local:
// DISASM-NEXT: 11000: {{.*}}
// DISASM-NEXT: 11002: {{.*}}
// DISASM: _start:
// 0x11013 + 5 - 24 = 0x11000
// DISASM-NEXT: 11004: e9 27 00 00 00 jmp 39
// DISASM-NEXT: 11009: e9 22 00 00 00 jmp 34
// DISASM-NEXT: 1100e: e9 2d 00 00 00 jmp 45
// DISASM-NEXT: 11013: e9 e8 ff ff ff jmp -24
// 0x11010 - 0x1102b - 5 = -32
// 0x11010 - 0x1103b - 5 = -48
-// 73820 = 0x1205C = .got.plt (0x12058) + 4
-// 73824 = 0x12060 = .got.plt (0x12058) + 8
-// 73828 = 0x12064 = .got.plt (0x12058) + got.plt.reserved(12)
-// 73832 = 0x12068 = .got.plt (0x12058) + got.plt.reserved(12) + 4
+// 77828 = 0x13004 = .got.plt (0x13000) + 4
+// 77832 = 0x13008 = .got.plt (0x13000) + 8
+// 77836 = 0x1300C = .got.plt (0x13000) + got.plt.reserved(12)
+// 77840 = 0x13010 = .got.plt (0x13000) + got.plt.reserved(12) + 4
// DISASM: Disassembly of section .plt:
// DISASM-NEXT: .plt:
-// DISASM-NEXT: 11020: ff 35 5c 20 01 00 pushl 73820
-// DISASM-NEXT: 11026: ff 25 60 20 01 00 jmpl *73824
+// DISASM-NEXT: 11020: ff 35 04 30 01 00 pushl 77828
+// DISASM-NEXT: 11026: ff 25 08 30 01 00 jmpl *77832
// DISASM-NEXT: 1102c: 90 nop
// DISASM-NEXT: 1102d: 90 nop
// DISASM-NEXT: 1102e: 90 nop
// DISASM-NEXT: 1102f: 90 nop
-// DISASM-NEXT: 11030: ff 25 64 20 01 00 jmpl *73828
+// DISASM-NEXT: 11030: ff 25 0c 30 01 00 jmpl *77836
// DISASM-NEXT: 11036: 68 00 00 00 00 pushl $0
// DISASM-NEXT: 1103b: e9 e0 ff ff ff jmp -32 <.plt>
-// DISASM-NEXT: 11040: ff 25 68 20 01 00 jmpl *73832
+// DISASM-NEXT: 11040: ff 25 10 30 01 00 jmpl *77840
// DISASM-NEXT: 11046: 68 08 00 00 00 pushl $8
// DISASM-NEXT: 1104b: e9 d0 ff ff ff jmp -48 <.plt>
// CHECKSHARED: Name: .plt
// CHECKSHARED-NEXT: Type: SHT_PROGBITS
// CHECKSHARED-NEXT: Flags [
// CHECKSHARED-NEXT: SHF_ALLOC
// CHECKSHARED-NEXT: SHF_EXECINSTR
// CHECKSHARED-NEXT: ]
// CHECKSHARED-NEXT: Address: 0x1020
// CHECKSHARED-NEXT: Offset: 0x1020
// CHECKSHARED-NEXT: Size: 48
// CHECKSHARED-NEXT: Link: 0
// CHECKSHARED-NEXT: Info: 0
// CHECKSHARED-NEXT: AddressAlignment: 16
// CHECKSHARED-NEXT: EntrySize: 0
// CHECKSHARED-NEXT: }
// CHECKSHARED: Name: .got.plt
// CHECKSHARED-NEXT: Type: SHT_PROGBITS
// CHECKSHARED-NEXT: Flags [
// CHECKSHARED-NEXT: SHF_ALLOC
// CHECKSHARED-NEXT: SHF_WRITE
// CHECKSHARED-NEXT: ]
-// CHECKSHARED-NEXT: Address: 0x2058
-// CHECKSHARED-NEXT: Offset: 0x2058
+// CHECKSHARED-NEXT: Address: 0x3000
+// CHECKSHARED-NEXT: Offset: 0x3000
// CHECKSHARED-NEXT: Size: 20
// CHECKSHARED-NEXT: Link: 0
// CHECKSHARED-NEXT: Info: 0
// CHECKSHARED-NEXT: AddressAlignment: 4
// CHECKSHARED-NEXT: EntrySize: 0
// CHECKSHARED-NEXT: }
-// 0x2058 + got.plt.reserved(12) = 0x2064
-// 0x2058 + got.plt.reserved(12) + 4 = 0x2068
+// 0x3000 + got.plt.reserved(12) = 0x300C
+// 0x3000 + got.plt.reserved(12) + 4 = 0x3010
// CHECKSHARED: Relocations [
// CHECKSHARED-NEXT: Section ({{.*}}) .rel.plt {
-// CHECKSHARED-NEXT: 0x2064 R_386_JUMP_SLOT bar 0x0
-// CHECKSHARED-NEXT: 0x2068 R_386_JUMP_SLOT zed 0x0
+// CHECKSHARED-NEXT: 0x300C R_386_JUMP_SLOT bar 0x0
+// CHECKSHARED-NEXT: 0x3010 R_386_JUMP_SLOT zed 0x0
// CHECKSHARED-NEXT: }
// CHECKSHARED-NEXT: ]
// DISASMSHARED: local:
// DISASMSHARED-NEXT: 1000: {{.*}}
// DISASMSHARED-NEXT: 1002: {{.*}}
// DISASMSHARED: _start:
// 0x1013 + 5 - 24 = 0x1000
// DISASMSHARED-NEXT: 1004: e9 27 00 00 00 jmp 39
// DISASMSHARED-NEXT: 1009: e9 22 00 00 00 jmp 34
// DISASMSHARED-NEXT: 100e: e9 2d 00 00 00 jmp 45
// DISASMSHARED-NEXT: 1013: e9 e8 ff ff ff jmp -24
// DISASMSHARED-NEXT: Disassembly of section .plt:
// DISASMSHARED-NEXT: .plt:
// DISASMSHARED-NEXT: 1020: ff b3 04 00 00 00 pushl 4(%ebx)
// DISASMSHARED-NEXT: 1026: ff a3 08 00 00 00 jmpl *8(%ebx)
// DISASMSHARED-NEXT: 102c: 90 nop
// DISASMSHARED-NEXT: 102d: 90 nop
// DISASMSHARED-NEXT: 102e: 90 nop
// DISASMSHARED-NEXT: 102f: 90 nop
// DISASMSHARED-NEXT: 1030: ff a3 0c 00 00 00 jmpl *12(%ebx)
// DISASMSHARED-NEXT: 1036: 68 00 00 00 00 pushl $0
// DISASMSHARED-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt>
// DISASMSHARED-NEXT: 1040: ff a3 10 00 00 00 jmpl *16(%ebx)
// DISASMSHARED-NEXT: 1046: 68 08 00 00 00 pushl $8
// DISASMSHARED-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt>
local:
.long 0
.global _start
_start:
jmp bar at PLT
jmp bar at PLT
jmp zed at PLT
jmp local at plt
diff --git a/test/ELF/plt.s b/test/ELF/plt.s
index 0159091..1183d32 100644
--- a/test/ELF/plt.s
+++ b/test/ELF/plt.s
@@ -1,119 +1,119 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
// RUN: ld.lld -shared %t2.o -o %t2.so
// RUN: ld.lld -shared %t.o %t2.so -o %t
// RUN: ld.lld %t.o %t2.so -o %t3
// RUN: llvm-readobj -s -r %t | FileCheck %s
// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
// RUN: llvm-readobj -s -r %t3 | FileCheck --check-prefix=CHECK2 %s
// RUN: llvm-objdump -d %t3 | FileCheck --check-prefix=DISASM2 %s
// REQUIRES: x86
// CHECK: Name: .plt
// CHECK-NEXT: Type: SHT_PROGBITS
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_EXECINSTR
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x1020
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 64
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
// CHECK-NEXT: AddressAlignment: 16
// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rela.plt {
-// CHECK-NEXT: 0x20C8 R_X86_64_JUMP_SLOT bar 0x0
-// CHECK-NEXT: 0x20D0 R_X86_64_JUMP_SLOT zed 0x0
-// CHECK-NEXT: 0x20D8 R_X86_64_JUMP_SLOT _start 0x0
+// CHECK-NEXT: 0x3018 R_X86_64_JUMP_SLOT bar 0x0
+// CHECK-NEXT: 0x3020 R_X86_64_JUMP_SLOT zed 0x0
+// CHECK-NEXT: 0x3028 R_X86_64_JUMP_SLOT _start 0x0
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK2: Name: .plt
// CHECK2-NEXT: Type: SHT_PROGBITS
// CHECK2-NEXT: Flags [
// CHECK2-NEXT: SHF_ALLOC
// CHECK2-NEXT: SHF_EXECINSTR
// CHECK2-NEXT: ]
// CHECK2-NEXT: Address: 0x11020
// CHECK2-NEXT: Offset:
// CHECK2-NEXT: Size: 48
// CHECK2-NEXT: Link: 0
// CHECK2-NEXT: Info: 0
// CHECK2-NEXT: AddressAlignment: 16
// CHECK2: Relocations [
// CHECK2-NEXT: Section ({{.*}}) .rela.plt {
-// CHECK2-NEXT: 0x120C8 R_X86_64_JUMP_SLOT bar 0x0
-// CHECK2-NEXT: 0x120D0 R_X86_64_JUMP_SLOT zed 0x0
+// CHECK2-NEXT: 0x13018 R_X86_64_JUMP_SLOT bar 0x0
+// CHECK2-NEXT: 0x13020 R_X86_64_JUMP_SLOT zed 0x0
// CHECK2-NEXT: }
// CHECK2-NEXT: ]
// Unfortunately FileCheck can't do math, so we have to check for explicit
// values:
// 0x1030 - (0x1000 + 5) = 43
// 0x1030 - (0x1005 + 5) = 38
// 0x1040 - (0x100a + 5) = 49
// 0x1048 - (0x100a + 5) = 60
// DISASM: _start:
// DISASM-NEXT: 1000: e9 {{.*}} jmp 43
// DISASM-NEXT: 1005: e9 {{.*}} jmp 38
// DISASM-NEXT: 100a: e9 {{.*}} jmp 49
// DISASM-NEXT: 100f: e9 {{.*}} jmp 60
-// 0x20C8 - 0x1036 = 4242
-// 0x20D0 - 0x1046 = 4234
-// 0x20D8 - 0x1056 = 4226
+// 0x3018 - 0x1036 = 8162
+// 0x3020 - 0x1046 = 4234
+// 0x3028 - 0x1056 = 4226
// DISASM: Disassembly of section .plt:
// DISASM-NEXT: .plt:
-// DISASM-NEXT: 1020: ff 35 92 10 00 00 pushq 4242(%rip)
-// DISASM-NEXT: 1026: ff 25 94 10 00 00 jmpq *4244(%rip)
+// DISASM-NEXT: 1020: ff 35 e2 1f 00 00 pushq 8162(%rip)
+// DISASM-NEXT: 1026: ff 25 e4 1f 00 00 jmpq *8164(%rip)
// DISASM-NEXT: 102c: 0f 1f 40 00 nopl (%rax)
-// DISASM-NEXT: 1030: ff 25 92 10 00 00 jmpq *4242(%rip)
+// DISASM-NEXT: 1030: ff 25 e2 1f 00 00 jmpq *8162(%rip)
// DISASM-NEXT: 1036: 68 00 00 00 00 pushq $0
// DISASM-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt>
-// DISASM-NEXT: 1040: ff 25 8a 10 00 00 jmpq *4234(%rip)
+// DISASM-NEXT: 1040: ff 25 da 1f 00 00 jmpq *8154(%rip)
// DISASM-NEXT: 1046: 68 01 00 00 00 pushq $1
// DISASM-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt>
-// DISASM-NEXT: 1050: ff 25 82 10 00 00 jmpq *4226(%rip)
+// DISASM-NEXT: 1050: ff 25 d2 1f 00 00 jmpq *8146(%rip)
// DISASM-NEXT: 1056: 68 02 00 00 00 pushq $2
// DISASM-NEXT: 105b: e9 c0 ff ff ff jmp -64 <.plt>
// 0x11030 - (0x11000 + 1) - 4 = 43
// 0x11030 - (0x11005 + 1) - 4 = 38
// 0x11040 - (0x1100a + 1) - 4 = 49
// 0x11000 - (0x1100f + 1) - 4 = -20
// DISASM2: _start:
// DISASM2-NEXT: 11000: e9 {{.*}} jmp 43
// DISASM2-NEXT: 11005: e9 {{.*}} jmp 38
// DISASM2-NEXT: 1100a: e9 {{.*}} jmp 49
// DISASM2-NEXT: 1100f: e9 {{.*}} jmp -20
-// 0x120C8 - 0x11036 = 4242
-// 0x120D0 - 0x11046 = 4234
+// 0x13018 - 0x11036 = 4242
+// 0x13020 - 0x11046 = 4234
// DISASM2: Disassembly of section .plt:
// DISASM2-NEXT: .plt:
-// DISASM2-NEXT: 11020: ff 35 92 10 00 00 pushq 4242(%rip)
-// DISASM2-NEXT: 11026: ff 25 94 10 00 00 jmpq *4244(%rip)
+// DISASM2-NEXT: 11020: ff 35 e2 1f 00 00 pushq 8162(%rip)
+// DISASM2-NEXT: 11026: ff 25 e4 1f 00 00 jmpq *8164(%rip)
// DISASM2-NEXT: 1102c: 0f 1f 40 00 nopl (%rax)
-// DISASM2-NEXT: 11030: ff 25 92 10 00 00 jmpq *4242(%rip)
+// DISASM2-NEXT: 11030: ff 25 e2 1f 00 00 jmpq *8162(%rip)
// DISASM2-NEXT: 11036: 68 00 00 00 00 pushq $0
// DISASM2-NEXT: 1103b: e9 e0 ff ff ff jmp -32 <.plt>
-// DISASM2-NEXT: 11040: ff 25 8a 10 00 00 jmpq *4234(%rip)
+// DISASM2-NEXT: 11040: ff 25 da 1f 00 00 jmpq *8154(%rip)
// DISASM2-NEXT: 11046: 68 01 00 00 00 pushq $1
// DISASM2-NEXT: 1104b: e9 d0 ff ff ff jmp -48 <.plt>
// DISASM2-NEXT-NOT: 110C0
.global _start
_start:
jmp bar at PLT
jmp bar at PLT
jmp zed at PLT
jmp _start at plt
diff --git a/test/ELF/ppc64-shared-rel-toc.s b/test/ELF/ppc64-shared-rel-toc.s
index aa8654a..f5cd459 100644
--- a/test/ELF/ppc64-shared-rel-toc.s
+++ b/test/ELF/ppc64-shared-rel-toc.s
@@ -1,27 +1,27 @@
// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
// RUN: ld.lld -shared %t.o -o %t.so
// RUN: llvm-readobj -t -r -dyn-symbols %t.so | FileCheck %s
// REQUIRES: ppc
// When we create the TOC reference in the shared library, make sure that the
// R_PPC64_RELATIVE relocation uses the correct (non-zero) offset.
.globl foo
.align 2
.type foo, at function
.section .opd,"aw", at progbits
foo: # @foo
.align 3
.quad .Lfunc_begin0
.quad .TOC. at tocbase
.quad 0
.text
.Lfunc_begin0:
blr
-// CHECK: 0x20090 R_PPC64_RELATIVE - 0x10000
-// CHECK: 0x20098 R_PPC64_RELATIVE - 0x8000
+// CHECK: 0x30000 R_PPC64_RELATIVE - 0x10000
+// CHECK: 0x30008 R_PPC64_RELATIVE - 0x8000
// CHECK: Name: foo
-// CHECK-NEXT: Value: 0x20090
+// CHECK-NEXT: Value: 0x30000
diff --git a/test/ELF/relocation-copy-i686.s b/test/ELF/relocation-copy-i686.s
index b537edf..d61f847 100644
--- a/test/ELF/relocation-copy-i686.s
+++ b/test/ELF/relocation-copy-i686.s
@@ -1,63 +1,63 @@
// REQUIRES: x86
// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/relocation-copy.s -o %t2.o
// RUN: ld.lld -shared %t2.o -o %t.so
// RUN: ld.lld -e main %t.o %t.so -o %t3
// RUN: llvm-readobj -s -r --expand-relocs %t3 | FileCheck %s
// RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s
.text
.globl main
.align 16, 0x90
.type main, at function
main:
movl $5, x
movl $7, y
movl $9, z
// CHECK: Name: .bss
// CHECK-NEXT: Type: SHT_NOBITS
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
-// CHECK-NEXT: Address: 0x12050
-// CHECK-NEXT: Offset: 0x2050
+// CHECK-NEXT: Address: 0x13000
+// CHECK-NEXT: Offset: 0x3000
// CHECK-NEXT: Size: 24
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
// CHECK-NEXT: AddressAlignment: 16
// CHECK-NEXT: EntrySize: 0
// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rel.dyn {
// CHECK-NEXT: Relocation {
// CHECK-NEXT: Offset:
// CHECK-NEXT: Type: R_386_COPY
// CHECK-NEXT: Symbol: x
// CHECK-NEXT: Addend: 0x0
// CHECK-NEXT: }
// CHECK-NEXT: Relocation {
// CHECK-NEXT: Offset:
// CHECK-NEXT: Type: R_386_COPY
// CHECK-NEXT: Symbol: y
// CHECK-NEXT: Addend: 0x0
// CHECK-NEXT: }
// CHECK-NEXT: Relocation {
// CHECK-NEXT: Offset:
// CHECK-NEXT: Type: R_386_COPY
// CHECK-NEXT: Symbol: z
// CHECK-NEXT: Addend: 0x0
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
-// 73808 = 0x12050
+// 77824 = 0x13000
// 16 is alignment here
-// 73824 = 0x12050 + 16
-// 73828 = 0x12050 + 16 + 4
+// 77840 = 0x13000 + 16
+// 77844 = 0x13000 + 16 + 4
// CODE: Disassembly of section .text:
// CODE-NEXT: main:
-// CODE-NEXT: 11000: c7 05 50 20 01 00 05 00 00 00 movl $5, 73808
-// CODE-NEXT: 1100a: c7 05 60 20 01 00 07 00 00 00 movl $7, 73824
-// CODE-NEXT: 11014: c7 05 64 20 01 00 09 00 00 00 movl $9, 73828
+// CODE-NEXT: 11000: c7 05 00 30 01 00 05 00 00 00 movl $5, 77824
+// CODE-NEXT: 1100a: c7 05 10 30 01 00 07 00 00 00 movl $7, 77840
+// CODE-NEXT: 11014: c7 05 14 30 01 00 09 00 00 00 movl $9, 77844
diff --git a/test/ELF/relocation-copy.s b/test/ELF/relocation-copy.s
index 17b3a64..85cbf67 100644
--- a/test/ELF/relocation-copy.s
+++ b/test/ELF/relocation-copy.s
@@ -1,63 +1,63 @@
// REQUIRES: x86
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy.s -o %t2.o
// RUN: ld.lld -shared %t2.o -o %t.so
// RUN: ld.lld -e main %t.o %t.so -o %t3
// RUN: llvm-readobj -s -r --expand-relocs %t3 | FileCheck %s
// RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s
.text
.globl main
.align 16, 0x90
.type main, at function
main:
movl $5, x
movl $7, y
movl $9, z
// CHECK: Name: .bss
// CHECK-NEXT: Type: SHT_NOBITS (0x8)
// CHECK-NEXT: Flags [ (0x3)
// CHECK-NEXT: SHF_ALLOC (0x2)
// CHECK-NEXT: SHF_WRITE (0x1)
// CHECK-NEXT: ]
-// CHECK-NEXT: Address: 0x120A0
-// CHECK-NEXT: Offset: 0x20A0
+// CHECK-NEXT: Address: 0x13000
+// CHECK-NEXT: Offset: 0x3000
// CHECK-NEXT: Size: 24
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
// CHECK-NEXT: AddressAlignment: 16
// CHECK-NEXT: EntrySize: 0
// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
// CHECK-NEXT: Relocation {
// CHECK-NEXT: Offset:
// CHECK-NEXT: Type: R_X86_64_COPY
// CHECK-NEXT: Symbol: x
// CHECK-NEXT: Addend: 0x0
// CHECK-NEXT: }
// CHECK-NEXT: Relocation {
// CHECK-NEXT: Offset:
// CHECK-NEXT: Type: R_X86_64_COPY
// CHECK-NEXT: Symbol: y
// CHECK-NEXT: Addend: 0x0
// CHECK-NEXT: }
// CHECK-NEXT: Relocation {
// CHECK-NEXT: Offset:
// CHECK-NEXT: Type: R_X86_64_COPY
// CHECK-NEXT: Symbol: z
// CHECK-NEXT: Addend: 0x0
// CHECK-NEXT: }
// CHECK-NEXT: }
// CHECK-NEXT: ]
-// 73888 = 0x120A0
+// 77824 = 0x13000
// 16 is alignment here
-// 73904 = 0x120A0 + 16
-// 73908 = 0x120A0 + 16 + 4
+// 77840 = 0x13000 + 16
+// 77844 = 0x13000 + 16 + 4
// CODE: Disassembly of section .text:
// CODE-NEXT: main:
-// CODE-NEXT: 11000: c7 04 25 a0 20 01 00 05 00 00 00 movl $5, 73888
-// CODE-NEXT: 1100b: c7 04 25 b0 20 01 00 07 00 00 00 movl $7, 73904
-// CODE-NEXT: 11016: c7 04 25 b4 20 01 00 09 00 00 00 movl $9, 73908
+// CODE-NEXT: 11000: c7 04 25 00 30 01 00 05 00 00 00 movl $5, 77824
+// CODE-NEXT: 1100b: c7 04 25 10 30 01 00 07 00 00 00 movl $7, 77840
+// CODE-NEXT: 11016: c7 04 25 14 30 01 00 09 00 00 00 movl $9, 77844
diff --git a/test/ELF/relocation.s b/test/ELF/relocation.s
index 9d4c03b..a6dd1d1 100644
--- a/test/ELF/relocation.s
+++ b/test/ELF/relocation.s
@@ -1,117 +1,117 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t2
// RUN: ld.lld %t2 -o %t2.so -shared
// RUN: ld.lld %t %t2.so -o %t3
// RUN: llvm-readobj -s %t3 | FileCheck --check-prefix=SEC %s
// RUN: llvm-objdump -s -d %t3 | FileCheck %s
// REQUIRES: x86
// SEC: Name: .plt
// SEC-NEXT: Type: SHT_PROGBITS
// SEC-NEXT: Flags [
// SEC-NEXT: SHF_ALLOC
// SEC-NEXT: SHF_EXECINSTR
// SEC-NEXT: ]
// SEC-NEXT: Address: 0x11030
// SEC-NEXT: Offset: 0x1030
// SEC-NEXT: Size: 32
// SEC: Name: .got
// SEC-NEXT: Type: SHT_PROGBITS
// SEC-NEXT: Flags [
// SEC-NEXT: SHF_ALLOC
// SEC-NEXT: SHF_WRITE
// SEC-NEXT: ]
// SEC-NEXT: Address: 0x120E0
// SEC-NEXT: Offset:
// SEC-NEXT: Size: 8
// SEC-NEXT: Link: 0
// SEC-NEXT: Info: 0
// SEC-NEXT: AddressAlignment: 8
// SEC-NEXT: EntrySize: 0
// SEC-NEXT: }
// SEC: Name: .got.plt
// SEC-NEXT: Type: SHT_PROGBITS
// SEC-NEXT: Flags [
// SEC-NEXT: SHF_ALLOC
// SEC-NEXT: SHF_WRITE
// SEC-NEXT: ]
-// SEC-NEXT: Address: 0x120E8
-// SEC-NEXT: Offset: 0x20E8
+// SEC-NEXT: Address: 0x13000
+// SEC-NEXT: Offset: 0x3000
// SEC-NEXT: Size: 32
// SEC-NEXT: Link: 0
// SEC-NEXT: Info: 0
// SEC-NEXT: AddressAlignment: 8
// SEC-NEXT: EntrySize: 0
// SEC-NEXT: }
.section .text,"ax", at progbits,unique,1
.global _start
_start:
call lulz
.section .text,"ax", at progbits,unique,2
.zero 4
.global lulz
lulz:
nop
// CHECK: Disassembly of section .text:
// CHECK-NEXT: _start:
// CHECK-NEXT: 11000: e8 04 00 00 00 callq 4
// CHECK-NEXT: 11005:
// CHECK: lulz:
// CHECK-NEXT: 11009: 90 nop
.section .text2,"ax", at progbits
.global R_X86_64_32
R_X86_64_32:
movl $R_X86_64_32, %edx
// FIXME: this would be far more self evident if llvm-objdump printed
// constants in hex.
// CHECK: Disassembly of section .text2:
// CHECK-NEXT: R_X86_64_32:
// CHECK-NEXT: 1100a: {{.*}} movl $69642, %edx
.section .R_X86_64_32S,"ax", at progbits
.global R_X86_64_32S
R_X86_64_32S:
movq lulz - 0x100000, %rdx
// CHECK: Disassembly of section .R_X86_64_32S:
// CHECK-NEXT: R_X86_64_32S:
// CHECK-NEXT: {{.*}}: {{.*}} movq -978935, %rdx
.section .R_X86_64_PC32,"ax", at progbits
.global R_X86_64_PC32
R_X86_64_PC32:
call bar
movl $bar, %eax
//16 is a size of PLT[0]
// 0x11030 + 16 - (0x11017 + 5) = 20
// CHECK: Disassembly of section .R_X86_64_PC32:
// CHECK-NEXT: R_X86_64_PC32:
// CHECK-NEXT: 11017: {{.*}} callq 36
// CHECK-NEXT: 1101c: {{.*}} movl $69696, %eax
.section .R_X86_64_64,"a", at progbits
.global R_X86_64_64
R_X86_64_64:
.quad R_X86_64_64
// CHECK: Contents of section .R_X86_64_64:
// CHECK-NEXT: 101c8 c8010100 00000000
.section .R_X86_64_GOTPCREL,"a", at progbits
.global R_X86_64_GOTPCREL
R_X86_64_GOTPCREL:
.long zed at gotpcrel
// 0x120E8 - 0x101D8 = 7952
// 7952 = 0x101f0000 in little endian
// CHECK: Contents of section .R_X86_64_GOTPCREL
// CHECK-NEXT: 101d0 101f0000
diff --git a/test/ELF/relro.s b/test/ELF/relro.s
index 43b0d34..7a225a2 100644
--- a/test/ELF/relro.s
+++ b/test/ELF/relro.s
@@ -1,243 +1,242 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
// RUN: ld.lld -shared %t2.o -o %t2.so
// RUN: ld.lld %t.o %t2.so -z now -z relro -o %t
// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck --check-prefix=FULLRELRO %s
// RUN: ld.lld %t.o %t2.so -z relro -o %t
// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck --check-prefix=PARTRELRO %s
// RUN: ld.lld %t.o %t2.so -z norelro -o %t
// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck --check-prefix=NORELRO %s
// REQUIRES: x86
// FULLRELRO: Section {
// FULLRELRO: Index: 9
// FULLRELRO-NEXT: Name: .got
// FULLRELRO-NEXT: Type: SHT_PROGBITS
// FULLRELRO-NEXT: Flags [
// FULLRELRO-NEXT: SHF_ALLOC
// FULLRELRO-NEXT: SHF_WRITE
// FULLRELRO-NEXT: ]
// FULLRELRO-NEXT: Address: 0x12100
// FULLRELRO-NEXT: Offset: 0x2100
// FULLRELRO-NEXT: Size: 8
// FULLRELRO-NEXT: Link: 0
// FULLRELRO-NEXT: Info: 0
// FULLRELRO-NEXT: AddressAlignment: 8
// FULLRELRO-NEXT: EntrySize: 0
// FULLRELRO-NEXT: SectionData (
// FULLRELRO-NEXT: 0000: 00000000 00000000
// FULLRELRO-NEXT: )
// FULLRELRO-NEXT: }
// FULLRELRO-NEXT: Section {
// FULLRELRO-NEXT: Index: 10
// FULLRELRO-NEXT: Name: .got.plt
// FULLRELRO-NEXT: Type: SHT_PROGBITS
// FULLRELRO-NEXT: Flags [
// FULLRELRO-NEXT: SHF_ALLOC
// FULLRELRO-NEXT: SHF_WRITE
// FULLRELRO-NEXT: ]
// FULLRELRO-NEXT: Address: 0x12108
// FULLRELRO-NEXT: Offset: 0x2108
// FULLRELRO-NEXT: Size: 32
// FULLRELRO-NEXT: Link: 0
// FULLRELRO-NEXT: Info: 0
// FULLRELRO-NEXT: AddressAlignment: 8
// FULLRELRO-NEXT: EntrySize: 0
// FULLRELRO-NEXT: SectionData (
// FULLRELRO-NEXT: 0000:
// FULLRELRO-NEXT: 0010:
// FULLRELRO-NEXT: )
// FULLRELRO-NEXT: }
// FULLRELRO-NEXT: Section {
// FULLRELRO-NEXT: Index: 11
// FULLRELRO-NEXT: Name: .data
// FULLRELRO-NEXT: Type: SHT_PROGBITS
// FULLRELRO-NEXT: Flags [
// FULLRELRO-NEXT: SHF_ALLOC
// FULLRELRO-NEXT: SHF_WRITE
// FULLRELRO-NEXT: ]
-// FULLRELRO-NEXT: Address: 0x12128
-// FULLRELRO-NEXT: Offset: 0x2128
+// FULLRELRO-NEXT: Address: 0x13000
+// FULLRELRO-NEXT: Offset: 0x3000
// FULLRELRO-NEXT: Size: 12
// FULLRELRO-NEXT: Link: 0
// FULLRELRO-NEXT: Info: 0
// FULLRELRO-NEXT: AddressAlignment:
// FULLRELRO-NEXT: EntrySize: 0
// FULLRELRO-NEXT: SectionData (
// FULLRELRO-NEXT: 0000:
// FULLRELRO-NEXT: )
// FULLRELRO-NEXT: }
// FULLRELRO-NEXT: Section {
// FULLRELRO-NEXT: Index: 12
// FULLRELRO-NEXT: Name: .foo
// FULLRELRO-NEXT: Type: SHT_PROGBITS
// FULLRELRO-NEXT: Flags [
// FULLRELRO-NEXT: SHF_ALLOC
// FULLRELRO-NEXT: SHF_WRITE
// FULLRELRO-NEXT: ]
-// FULLRELRO-NEXT: Address: 0x12134
-// FULLRELRO-NEXT: Offset: 0x2134
+// FULLRELRO-NEXT: Address: 0x1300C
+// FULLRELRO-NEXT: Offset: 0x300C
// FULLRELRO-NEXT: Size: 0
// FULLRELRO-NEXT: Link: 0
// FULLRELRO-NEXT: Info: 0
// FULLRELRO-NEXT: AddressAlignment:
// FULLRELRO-NEXT: EntrySize: 0
// FULLRELRO-NEXT: SectionData (
// FULLRELRO-NEXT: )
// FULLRELRO-NEXT: }
// 308 - sizeof(.data)(12) = 296
// FULLRELRO: ProgramHeaders [
// FULLRELRO: Type: PT_LOAD
// FULLRELRO: Offset: 0x2000
// FULLRELRO-NEXT: VirtualAddress: [[RWADDR:.*]]
// FULLRELRO-NEXT: PhysicalAddress:
-// FULLRELRO-NEXT: FileSize: 308
-// FULLRELRO-NEXT: MemSize: 308
+// FULLRELRO-NEXT: FileSize: 4108
+// FULLRELRO-NEXT: MemSize: 4108
// FULLRELRO-NEXT: Flags [
// FULLRELRO-NEXT: PF_R
// FULLRELRO-NEXT: PF_W
// FULLRELRO-NEXT: ]
// FULLRELRO-NEXT: Alignment: 4096
// FULLRELRO-NEXT:}
// FULLRELRO: Type: PT_GNU_RELRO
// FULLRELRO-NEXT: Offset: 0x
// FULLRELRO-NEXT: VirtualAddress: [[RWADDR]]
// FULLRELRO-NEXT: PhysicalAddress:
// FULLRELRO-NEXT: FileSize: 296
// FULLRELRO-NEXT: MemSize: 296
// FULLRELRO-NEXT: Flags [
// FULLRELRO-NEXT: PF_R
// FULLRELRO-NEXT: ]
// FULLRELRO-NEXT: Alignment: 1
// FULLRELRO-NEXT:}
// PARTRELRO: Section {
// PARTRELRO: Index: 9
// PARTRELRO-NEXT: Name: .got
// PARTRELRO-NEXT: Type: SHT_PROGBITS
// PARTRELRO-NEXT: Flags [
// PARTRELRO-NEXT: SHF_ALLOC
// PARTRELRO-NEXT: SHF_WRITE
// PARTRELRO-NEXT: ]
// PARTRELRO-NEXT: Address: 0x120E0
// PARTRELRO-NEXT: Offset: 0x20E0
// PARTRELRO-NEXT: Size: 8
// PARTRELRO-NEXT: Link: 0
// PARTRELRO-NEXT: Info: 0
// PARTRELRO-NEXT: AddressAlignment: 8
// PARTRELRO-NEXT: EntrySize: 0
// PARTRELRO-NEXT: SectionData (
// PARTRELRO-NEXT: 0000:
// PARTRELRO-NEXT: )
// PARTRELRO-NEXT: }
// PARTRELRO-NEXT: Section {
// PARTRELRO-NEXT: Index: 10
// PARTRELRO-NEXT: Name: .data
// PARTRELRO-NEXT: Type: SHT_PROGBITS
// PARTRELRO-NEXT: Flags [
// PARTRELRO-NEXT: SHF_ALLOC
// PARTRELRO-NEXT: SHF_WRITE
// PARTRELRO-NEXT: ]
-// PARTRELRO-NEXT: Address: 0x120E8
-// PARTRELRO-NEXT: Offset: 0x20E8
+// PARTRELRO-NEXT: Address: 0x13000
+// PARTRELRO-NEXT: Offset: 0x3000
// PARTRELRO-NEXT: Size: 12
// PARTRELRO-NEXT: Link: 0
// PARTRELRO-NEXT: Info: 0
// PARTRELRO-NEXT: AddressAlignment: 1
// PARTRELRO-NEXT: EntrySize: 0
// PARTRELRO-NEXT: SectionData (
// PARTRELRO-NEXT: 0000:
// PARTRELRO-NEXT: )
// PARTRELRO-NEXT: }
// PARTRELRO-NEXT: Section {
// PARTRELRO-NEXT: Index: 11
// PARTRELRO-NEXT: Name: .foo
// PARTRELRO-NEXT: Type: SHT_PROGBITS
// PARTRELRO-NEXT: Flags [
// PARTRELRO-NEXT: SHF_ALLOC
// PARTRELRO-NEXT: SHF_WRITE
// PARTRELRO-NEXT: ]
-// PARTRELRO-NEXT: Address: 0x120F4
-// PARTRELRO-NEXT: Offset: 0x20F4
+// PARTRELRO-NEXT: Address: 0x1300C
+// PARTRELRO-NEXT: Offset: 0x300C
// PARTRELRO-NEXT: Size: 0
// PARTRELRO-NEXT: Link: 0
// PARTRELRO-NEXT: Info: 0
// PARTRELRO-NEXT: AddressAlignment: 1
// PARTRELRO-NEXT: EntrySize: 0
// PARTRELRO-NEXT: SectionData (
// PARTRELRO-NEXT: )
// PARTRELRO-NEXT: }
// PARTRELRO-NEXT: Section {
// PARTRELRO-NEXT: Index: 12
// PARTRELRO-NEXT: Name: .got.plt
// PARTRELRO-NEXT: Type: SHT_PROGBITS
// PARTRELRO-NEXT: Flags [
// PARTRELRO-NEXT: SHF_ALLOC
// PARTRELRO-NEXT: SHF_WRITE
// PARTRELRO-NEXT: ]
-// PARTRELRO-NEXT: Address: 0x120F8
-// PARTRELRO-NEXT: Offset: 0x20F8
+// PARTRELRO-NEXT: Address: 0x13010
+// PARTRELRO-NEXT: Offset: 0x3010
// PARTRELRO-NEXT: Size: 32
// PARTRELRO-NEXT: Link: 0
// PARTRELRO-NEXT: Info: 0
// PARTRELRO-NEXT: AddressAlignment: 8
// PARTRELRO-NEXT: EntrySize: 0
// PARTRELRO-NEXT: SectionData (
// PARTRELRO-NEXT: 0000:
// PARTRELRO-NEXT: 0010:
// PARTRELRO-NEXT: )
// PARTRELRO-NEXT: }
// PARTRELRO-NEXT: Section {
// PARTRELRO-NEXT: Index: 13
// PARTRELRO-NEXT: Name: .bss
// PARTRELRO-NEXT: Type: SHT_NOBITS
// PARTRELRO-NEXT: Flags [
// PARTRELRO-NEXT: SHF_ALLOC
// PARTRELRO-NEXT: SHF_WRITE
// PARTRELRO-NEXT: ]
-// PARTRELRO-NEXT: Address: 0x12118
-// PARTRELRO-NEXT: Offset: 0x2118
+// PARTRELRO-NEXT: Address: 0x13030
+// PARTRELRO-NEXT: Offset: 0x3030
// PARTRELRO-NEXT: Size: 0
// PARTRELRO-NEXT: Link: 0
// PARTRELRO-NEXT: Info: 0
// PARTRELRO-NEXT: AddressAlignment: 1
// PARTRELRO-NEXT: EntrySize: 0
// PARTRELRO-NEXT: }
-// 232 + sizeof(.data)(12) + align(4) + sizeof(.got.plt)(32) = 280
// PARTRELRO: ProgramHeader {
// PARTRELRO: Type: PT_LOAD
// PARTRELRO: Offset: 0x2000
// PARTRELRO-NEXT: VirtualAddress: [[RWADDR:.*]]
// PARTRELRO-NEXT: PhysicalAddress:
-// PARTRELRO-NEXT: FileSize: 280
-// PARTRELRO-NEXT: MemSize: 280
+// PARTRELRO-NEXT: FileSize: 4144
+// PARTRELRO-NEXT: MemSize: 4144
// PARTRELRO-NEXT: Flags [
// PARTRELRO-NEXT: PF_R (0x4)
// PARTRELRO-NEXT: PF_W (0x2)
// PARTRELRO-NEXT: ]
// PARTRELRO-NEXT: Alignment: 4096
// PARTRELRO: Type: PT_GNU_RELRO
// PARTRELRO-NEXT: Offset: 0x2000
// PARTRELRO-NEXT: VirtualAddress: [[RWADDR]]
// PARTRELRO-NEXT: PhysicalAddress:
// PARTRELRO-NEXT: FileSize: 232
// PARTRELRO-NEXT: MemSize: 232
// PARTRELRO-NEXT: Flags [
// PARTRELRO-NEXT: PF_R
// PARTRELRO-NEXT: ]
// PARTRELRO-NEXT: Alignment: 1
// NORELRO: ProgramHeaders [
// NORELRO-NOT: PT_GNU_RELRO
.global _start
_start:
.long bar
jmp *bar at GOTPCREL(%rip)
.section .data,"aw"
.quad 0
.zero 4
.section .foo,"aw"
.section .bss,"", at nobits
diff --git a/test/ELF/tls-opt-gdie.s b/test/ELF/tls-opt-gdie.s
index 2b59ed7..a6c6868 100644
--- a/test/ELF/tls-opt-gdie.s
+++ b/test/ELF/tls-opt-gdie.s
@@ -1,55 +1,55 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-opt-gdie.s -o %tso.o
// RUN: ld.lld -shared %tso.o -o %t.so
// RUN: ld.lld %t.o %t.so -o %t1
// RUN: llvm-readobj -s -r %t1 | FileCheck --check-prefix=RELOC %s
// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
//RELOC: Section {
//RELOC: Index: 9
//RELOC-NEXT: Name: .got
//RELOC-NEXT: Type: SHT_PROGBITS
//RELOC-NEXT: Flags [
//RELOC-NEXT: SHF_ALLOC
//RELOC-NEXT: SHF_WRITE
//RELOC-NEXT: ]
//RELOC-NEXT: Address: 0x120E0
//RELOC-NEXT: Offset: 0x20E0
//RELOC-NEXT: Size: 16
//RELOC-NEXT: Link: 0
//RELOC-NEXT: Info: 0
//RELOC-NEXT: AddressAlignment: 8
//RELOC-NEXT: EntrySize: 0
//RELOC-NEXT: }
//RELOC: Relocations [
//RELOC-NEXT: Section (4) .rela.dyn {
//RELOC-NEXT: 0x120E0 R_X86_64_TPOFF64 tlsshared0 0x0
//RELOC-NEXT: 0x120E8 R_X86_64_TPOFF64 tlsshared1 0x0
//RELOC-NEXT: }
//RELOC-NEXT: Section (5) .rela.plt {
-//RELOC-NEXT: 0x12108 R_X86_64_JUMP_SLOT __tls_get_addr 0x0
+//RELOC-NEXT: 0x13018 R_X86_64_JUMP_SLOT __tls_get_addr 0x0
//RELOC-NEXT: }
//RELOC-NEXT: ]
//0x11009 + (4304 + 7) = 0x120E0
//0x11019 + (4296 + 7) = 0x120E8
// DISASM: Disassembly of section .text:
// DISASM-NEXT: _start:
// DISASM-NEXT: 11000: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax
// DISASM-NEXT: 11009: 48 03 05 d0 10 00 00 addq 4304(%rip), %rax
// DISASM-NEXT: 11010: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax
// DISASM-NEXT: 11019: 48 03 05 c8 10 00 00 addq 4296(%rip), %rax
.section .text
.globl _start
_start:
.byte 0x66
leaq tlsshared0 at tlsgd(%rip),%rdi
.word 0x6666
rex64
call __tls_get_addr at plt
.byte 0x66
leaq tlsshared1 at tlsgd(%rip),%rdi
.word 0x6666
rex64
call __tls_get_addr at plt
More information about the llvm-commits
mailing list