2015-07-25 05:03:07 +08:00
|
|
|
//===- Writer.cpp ---------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Linker
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2015-09-05 06:48:30 +08:00
|
|
|
#include "Writer.h"
|
2015-08-06 07:51:50 +08:00
|
|
|
#include "Config.h"
|
2015-09-22 05:38:08 +08:00
|
|
|
#include "OutputSections.h"
|
2015-08-06 07:24:46 +08:00
|
|
|
#include "SymbolTable.h"
|
2015-09-23 02:19:46 +08:00
|
|
|
#include "Target.h"
|
2015-08-12 08:00:24 +08:00
|
|
|
|
2015-10-13 04:51:48 +08:00
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
2015-08-06 07:24:46 +08:00
|
|
|
#include "llvm/Support/FileOutputBuffer.h"
|
2015-10-16 01:11:03 +08:00
|
|
|
#include "llvm/Support/StringSaver.h"
|
2015-07-25 05:03:07 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace llvm::ELF;
|
|
|
|
using namespace llvm::object;
|
|
|
|
|
|
|
|
using namespace lld;
|
|
|
|
using namespace lld::elf2;
|
|
|
|
|
2015-08-06 07:24:46 +08:00
|
|
|
namespace {
|
|
|
|
// The writer writes a SymbolTable result to a file.
|
|
|
|
template <class ELFT> class Writer {
|
|
|
|
public:
|
2015-09-09 05:57:31 +08:00
|
|
|
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;
|
2015-09-17 04:45:57 +08:00
|
|
|
typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
|
2015-09-16 23:54:15 +08:00
|
|
|
typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela;
|
2015-10-10 05:07:25 +08:00
|
|
|
Writer(SymbolTable<ELFT> &S) : Symtab(S) {}
|
2015-08-06 07:24:46 +08:00
|
|
|
void run();
|
|
|
|
|
|
|
|
private:
|
2015-10-09 07:49:30 +08:00
|
|
|
void copyLocalSymbols();
|
2015-08-06 07:24:46 +08:00
|
|
|
void createSections();
|
2015-09-17 22:02:10 +08:00
|
|
|
template <bool isRela>
|
2015-09-22 01:47:00 +08:00
|
|
|
void scanRelocs(const InputSection<ELFT> &C,
|
2015-09-17 22:02:10 +08:00
|
|
|
iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels);
|
2015-09-22 01:47:00 +08:00
|
|
|
void scanRelocs(const InputSection<ELFT> &C);
|
2015-08-06 07:24:46 +08:00
|
|
|
void assignAddresses();
|
|
|
|
void openFile(StringRef OutputPath);
|
|
|
|
void writeHeader();
|
|
|
|
void writeSections();
|
2015-09-12 02:49:42 +08:00
|
|
|
bool needsInterpSection() const {
|
2015-10-08 05:25:39 +08:00
|
|
|
return !Symtab.getSharedFiles().empty() && !Config->DynamicLinker.empty();
|
2015-09-12 02:49:42 +08:00
|
|
|
}
|
2015-10-07 04:39:09 +08:00
|
|
|
bool isOutputDynamic() const {
|
2015-10-08 05:25:39 +08:00
|
|
|
return !Symtab.getSharedFiles().empty() || Config->Shared;
|
2015-09-12 06:42:45 +08:00
|
|
|
}
|
2015-10-24 06:44:37 +08:00
|
|
|
uintX_t getEntryAddr() const;
|
2015-10-24 05:45:59 +08:00
|
|
|
int getPhdrsNum() const;
|
2015-08-06 07:24:46 +08:00
|
|
|
|
2015-11-04 05:35:14 +08:00
|
|
|
OutputSection<ELFT> *getBSS();
|
|
|
|
void addCommonSymbols(std::vector<DefinedCommon<ELFT> *> &Syms);
|
|
|
|
void addSharedCopySymbols(std::vector<SharedSymbol<ELFT> *> &Syms);
|
|
|
|
|
2015-08-06 07:24:46 +08:00
|
|
|
std::unique_ptr<llvm::FileOutputBuffer> Buffer;
|
2015-09-18 03:58:07 +08:00
|
|
|
|
2015-10-15 20:33:04 +08:00
|
|
|
SpecificBumpPtrAllocator<OutputSection<ELFT>> SecAlloc;
|
2015-10-20 05:00:02 +08:00
|
|
|
SpecificBumpPtrAllocator<MergeOutputSection<ELFT>> MSecAlloc;
|
2015-10-16 01:11:03 +08:00
|
|
|
BumpPtrAllocator Alloc;
|
2015-10-16 06:27:29 +08:00
|
|
|
std::vector<OutputSectionBase<ELFT> *> OutputSections;
|
2015-09-09 01:39:39 +08:00
|
|
|
unsigned getNumSections() const { return OutputSections.size() + 1; }
|
2015-08-06 07:24:46 +08:00
|
|
|
|
2015-10-16 06:27:29 +08:00
|
|
|
void addStartStopSymbols(OutputSectionBase<ELFT> *Sec);
|
2015-10-12 03:45:58 +08:00
|
|
|
void setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags, uintX_t FileOff,
|
2015-10-24 05:45:59 +08:00
|
|
|
uintX_t VA, uintX_t Size, uintX_t Align);
|
2015-10-16 06:27:29 +08:00
|
|
|
void copyPhdr(Elf_Phdr *PH, OutputSectionBase<ELFT> *From);
|
2015-10-11 06:34:30 +08:00
|
|
|
|
2015-10-10 05:07:25 +08:00
|
|
|
SymbolTable<ELFT> &Symtab;
|
2015-10-11 07:59:57 +08:00
|
|
|
std::vector<Elf_Phdr> Phdrs;
|
2015-09-18 03:58:07 +08:00
|
|
|
|
2015-08-12 07:14:13 +08:00
|
|
|
uintX_t FileSize;
|
2015-08-06 07:24:46 +08:00
|
|
|
uintX_t SectionHeaderOff;
|
|
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
|
2015-10-10 05:07:25 +08:00
|
|
|
template <class ELFT> void lld::elf2::writeResult(SymbolTable<ELFT> *Symtab) {
|
2015-10-08 03:18:16 +08:00
|
|
|
// Initialize output sections that are handled by Writer specially.
|
|
|
|
// Don't reorder because the order of initialization matters.
|
2015-10-16 06:27:29 +08:00
|
|
|
InterpSection<ELFT> Interp;
|
2015-10-08 03:18:16 +08:00
|
|
|
Out<ELFT>::Interp = &Interp;
|
2015-10-21 01:21:35 +08:00
|
|
|
StringTableSection<ELFT> ShStrTab(".shstrtab", false);
|
|
|
|
Out<ELFT>::ShStrTab = &ShStrTab;
|
|
|
|
StringTableSection<ELFT> StrTab(".strtab", false);
|
2015-10-24 16:52:46 +08:00
|
|
|
if (!Config->StripAll)
|
|
|
|
Out<ELFT>::StrTab = &StrTab;
|
2015-10-21 01:21:35 +08:00
|
|
|
StringTableSection<ELFT> DynStrTab(".dynstr", true);
|
2015-10-08 03:18:16 +08:00
|
|
|
Out<ELFT>::DynStrTab = &DynStrTab;
|
|
|
|
GotSection<ELFT> Got;
|
|
|
|
Out<ELFT>::Got = &Got;
|
2015-10-20 16:54:27 +08:00
|
|
|
GotPltSection<ELFT> GotPlt;
|
|
|
|
if (Target->supportsLazyRelocations())
|
|
|
|
Out<ELFT>::GotPlt = &GotPlt;
|
2015-10-08 03:18:16 +08:00
|
|
|
PltSection<ELFT> Plt;
|
|
|
|
Out<ELFT>::Plt = &Plt;
|
2015-10-24 16:52:46 +08:00
|
|
|
std::unique_ptr<SymbolTableSection<ELFT>> SymTab;
|
|
|
|
if (!Config->StripAll) {
|
|
|
|
SymTab.reset(new SymbolTableSection<ELFT>(*Symtab, *Out<ELFT>::StrTab));
|
|
|
|
Out<ELFT>::SymTab = SymTab.get();
|
|
|
|
}
|
2015-10-08 03:18:16 +08:00
|
|
|
SymbolTableSection<ELFT> DynSymTab(*Symtab, *Out<ELFT>::DynStrTab);
|
|
|
|
Out<ELFT>::DynSymTab = &DynSymTab;
|
|
|
|
HashTableSection<ELFT> HashTab;
|
2015-10-22 16:21:35 +08:00
|
|
|
if (Config->SysvHash)
|
|
|
|
Out<ELFT>::HashTab = &HashTab;
|
|
|
|
GnuHashTableSection<ELFT> GnuHashTab;
|
|
|
|
if (Config->GnuHash)
|
|
|
|
Out<ELFT>::GnuHashTab = &GnuHashTab;
|
2015-10-20 16:54:27 +08:00
|
|
|
bool IsRela = Symtab->shouldUseRela();
|
|
|
|
RelocationSection<ELFT> RelaDyn(IsRela ? ".rela.dyn" : ".rel.dyn", IsRela);
|
2015-10-08 03:18:16 +08:00
|
|
|
Out<ELFT>::RelaDyn = &RelaDyn;
|
2015-10-20 16:54:27 +08:00
|
|
|
RelocationSection<ELFT> RelaPlt(IsRela ? ".rela.plt" : ".rel.plt", IsRela);
|
|
|
|
if (Target->supportsLazyRelocations())
|
|
|
|
Out<ELFT>::RelaPlt = &RelaPlt;
|
2015-10-08 03:18:16 +08:00
|
|
|
DynamicSection<ELFT> Dynamic(*Symtab);
|
|
|
|
Out<ELFT>::Dynamic = &Dynamic;
|
|
|
|
|
2015-10-08 05:25:39 +08:00
|
|
|
Writer<ELFT>(*Symtab).run();
|
2015-10-08 03:18:16 +08:00
|
|
|
}
|
|
|
|
|
2015-07-25 05:03:07 +08:00
|
|
|
// The main function of the writer.
|
2015-08-06 07:24:46 +08:00
|
|
|
template <class ELFT> void Writer<ELFT>::run() {
|
2015-10-09 07:49:30 +08:00
|
|
|
if (!Config->DiscardAll)
|
|
|
|
copyLocalSymbols();
|
2015-07-25 05:03:07 +08:00
|
|
|
createSections();
|
|
|
|
assignAddresses();
|
2015-08-06 07:51:50 +08:00
|
|
|
openFile(Config->OutputFile);
|
2015-07-25 05:03:07 +08:00
|
|
|
writeHeader();
|
|
|
|
writeSections();
|
|
|
|
error(Buffer->commit());
|
|
|
|
}
|
|
|
|
|
2015-08-14 01:04:50 +08:00
|
|
|
namespace {
|
|
|
|
template <bool Is64Bits> struct SectionKey {
|
|
|
|
typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t;
|
|
|
|
StringRef Name;
|
2015-10-03 05:13:19 +08:00
|
|
|
uint32_t Type;
|
|
|
|
uintX_t Flags;
|
2015-10-20 05:00:02 +08:00
|
|
|
uintX_t EntSize;
|
2015-08-14 01:04:50 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
namespace llvm {
|
|
|
|
template <bool Is64Bits> struct DenseMapInfo<SectionKey<Is64Bits>> {
|
|
|
|
static SectionKey<Is64Bits> getEmptyKey() {
|
2015-10-20 05:00:02 +08:00
|
|
|
return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getEmptyKey(), 0, 0,
|
|
|
|
0};
|
2015-08-14 01:04:50 +08:00
|
|
|
}
|
|
|
|
static SectionKey<Is64Bits> getTombstoneKey() {
|
|
|
|
return SectionKey<Is64Bits>{DenseMapInfo<StringRef>::getTombstoneKey(), 0,
|
2015-10-20 05:00:02 +08:00
|
|
|
0, 0};
|
2015-08-14 01:04:50 +08:00
|
|
|
}
|
|
|
|
static unsigned getHashValue(const SectionKey<Is64Bits> &Val) {
|
2015-10-20 05:00:02 +08:00
|
|
|
return hash_combine(Val.Name, Val.Type, Val.Flags, Val.EntSize);
|
2015-08-14 01:04:50 +08:00
|
|
|
}
|
|
|
|
static bool isEqual(const SectionKey<Is64Bits> &LHS,
|
|
|
|
const SectionKey<Is64Bits> &RHS) {
|
|
|
|
return DenseMapInfo<StringRef>::isEqual(LHS.Name, RHS.Name) &&
|
2015-10-20 05:00:02 +08:00
|
|
|
LHS.Type == RHS.Type && LHS.Flags == RHS.Flags &&
|
|
|
|
LHS.EntSize == RHS.EntSize;
|
2015-08-14 01:04:50 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2015-09-16 23:54:15 +08:00
|
|
|
// 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.
|
2015-09-17 22:02:10 +08:00
|
|
|
template <class ELFT>
|
|
|
|
template <bool isRela>
|
|
|
|
void Writer<ELFT>::scanRelocs(
|
2015-09-22 01:47:00 +08:00
|
|
|
const InputSection<ELFT> &C,
|
2015-09-17 22:02:10 +08:00
|
|
|
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) {
|
2015-10-17 06:51:43 +08:00
|
|
|
uint32_t SymIndex = RI.getSymbol(Config->Mips64EL);
|
2015-09-18 22:40:19 +08:00
|
|
|
SymbolBody *Body = File.getSymbolBody(SymIndex);
|
2015-10-17 06:51:43 +08:00
|
|
|
uint32_t Type = RI.getType(Config->Mips64EL);
|
2015-10-12 04:59:12 +08:00
|
|
|
|
|
|
|
// 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();
|
2015-10-15 02:42:16 +08:00
|
|
|
bool NeedsGot = false;
|
2015-10-20 16:54:27 +08:00
|
|
|
bool NeedsPlt = false;
|
2015-10-06 03:30:12 +08:00
|
|
|
if (Body) {
|
2015-10-29 00:48:58 +08:00
|
|
|
if (auto *E = dyn_cast<SharedSymbol<ELFT>>(Body)) {
|
2015-11-03 22:34:11 +08:00
|
|
|
if (E->needsCopy())
|
2015-10-29 00:48:58 +08:00
|
|
|
continue;
|
2015-11-03 22:34:11 +08:00
|
|
|
if (Target->relocNeedsCopy(Type, *Body))
|
|
|
|
E->OffsetInBSS = 0;
|
2015-10-29 00:48:58 +08:00
|
|
|
}
|
2015-10-20 16:54:27 +08:00
|
|
|
NeedsPlt = Target->relocNeedsPlt(Type, *Body);
|
|
|
|
if (NeedsPlt) {
|
2015-10-06 03:30:12 +08:00
|
|
|
if (Body->isInPlt())
|
|
|
|
continue;
|
2015-10-08 03:18:16 +08:00
|
|
|
Out<ELFT>::Plt->addEntry(Body);
|
2015-10-14 00:59:30 +08:00
|
|
|
}
|
2015-10-15 02:42:16 +08:00
|
|
|
NeedsGot = Target->relocNeedsGot(Type, *Body);
|
|
|
|
if (NeedsGot) {
|
2015-10-20 16:54:27 +08:00
|
|
|
if (NeedsPlt && Target->supportsLazyRelocations()) {
|
|
|
|
Out<ELFT>::GotPlt->addEntry(Body);
|
|
|
|
} else {
|
|
|
|
if (Body->isInGot())
|
|
|
|
continue;
|
|
|
|
Out<ELFT>::Got->addEntry(Body);
|
|
|
|
}
|
2015-10-06 03:30:12 +08:00
|
|
|
}
|
|
|
|
}
|
2015-10-12 04:59:12 +08:00
|
|
|
|
2015-11-06 15:43:03 +08:00
|
|
|
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;
|
|
|
|
}
|
2015-10-15 02:42:16 +08:00
|
|
|
bool CBP = canBePreempted(Body, NeedsGot);
|
2015-10-12 04:59:12 +08:00
|
|
|
if (!CBP && (!Config->Shared || Target->isRelRelative(Type)))
|
|
|
|
continue;
|
|
|
|
if (CBP)
|
2015-10-07 07:56:53 +08:00
|
|
|
Body->setUsedInDynamicReloc();
|
2015-10-20 16:54:27 +08:00
|
|
|
if (NeedsPlt && Target->supportsLazyRelocations())
|
|
|
|
Out<ELFT>::RelaPlt->addReloc({C, RI});
|
|
|
|
else
|
|
|
|
Out<ELFT>::RelaDyn->addReloc({C, RI});
|
2015-09-17 22:02:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-16 23:54:15 +08:00
|
|
|
template <class ELFT>
|
2015-09-22 01:47:00 +08:00
|
|
|
void Writer<ELFT>::scanRelocs(const InputSection<ELFT> &C) {
|
2015-09-24 23:11:50 +08:00
|
|
|
ObjectFile<ELFT> *File = C.getFile();
|
|
|
|
ELFFile<ELFT> &EObj = File->getObj();
|
2015-09-16 23:54:15 +08:00
|
|
|
|
|
|
|
if (!(C.getSectionHdr()->sh_flags & SHF_ALLOC))
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (const Elf_Shdr *RelSec : C.RelocSections) {
|
2015-09-17 22:02:10 +08:00
|
|
|
if (RelSec->sh_type == SHT_RELA)
|
2015-09-24 23:11:50 +08:00
|
|
|
scanRelocs(C, EObj.relas(RelSec));
|
2015-09-17 22:02:10 +08:00
|
|
|
else
|
2015-09-24 23:11:50 +08:00
|
|
|
scanRelocs(C, EObj.rels(RelSec));
|
2015-09-16 23:54:15 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-23 22:37:01 +08:00
|
|
|
template <class ELFT>
|
2015-10-10 05:07:25 +08:00
|
|
|
static void reportUndefined(const SymbolTable<ELFT> &S, const SymbolBody &Sym) {
|
2015-09-23 22:37:01 +08:00
|
|
|
typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
|
|
|
|
typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
|
|
|
|
|
2015-10-02 04:14:45 +08:00
|
|
|
if (Config->Shared && !Config->NoUndefined)
|
2015-10-02 01:24:24 +08:00
|
|
|
return;
|
|
|
|
|
2015-09-23 22:37:01 +08:00
|
|
|
const Elf_Sym &SymE = cast<ELFSymbolBody<ELFT>>(Sym).Sym;
|
2015-10-12 09:55:32 +08:00
|
|
|
ELFFileBase<ELFT> *SymFile = nullptr;
|
2015-09-23 22:37:01 +08:00
|
|
|
|
2015-10-10 05:07:25 +08:00
|
|
|
for (const std::unique_ptr<ObjectFile<ELFT>> &File : S.getObjectFiles()) {
|
|
|
|
Elf_Sym_Range Syms = File->getObj().symbols(File->getSymbolTable());
|
2015-09-23 22:37:01 +08:00
|
|
|
if (&SymE > Syms.begin() && &SymE < Syms.end())
|
2015-10-10 05:07:25 +08:00
|
|
|
SymFile = File.get();
|
2015-09-23 22:37:01 +08:00
|
|
|
}
|
2015-09-26 03:24:57 +08:00
|
|
|
|
|
|
|
std::string Message = "undefined symbol: " + Sym.getName().str();
|
2015-09-23 22:37:01 +08:00
|
|
|
if (SymFile)
|
2015-09-26 03:24:57 +08:00
|
|
|
Message += " in " + SymFile->getName().str();
|
|
|
|
if (Config->NoInhibitExec)
|
|
|
|
warning(Message);
|
2015-09-23 22:37:01 +08:00
|
|
|
else
|
2015-09-26 03:24:57 +08:00
|
|
|
error(Message);
|
2015-09-23 22:37:01 +08:00
|
|
|
}
|
|
|
|
|
2015-10-09 07:49:30 +08:00
|
|
|
// 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() {
|
2015-10-10 05:07:25 +08:00
|
|
|
for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
|
|
|
|
for (const Elf_Sym &Sym : F->getLocalSymbols()) {
|
|
|
|
ErrorOr<StringRef> SymNameOrErr = Sym.getName(F->getStringTable());
|
2015-10-09 07:49:30 +08:00
|
|
|
error(SymNameOrErr);
|
|
|
|
StringRef SymName = *SymNameOrErr;
|
2015-10-10 05:07:25 +08:00
|
|
|
if (!shouldKeepInSymtab<ELFT>(*F, SymName, Sym))
|
2015-10-10 03:25:07 +08:00
|
|
|
continue;
|
2015-10-24 16:52:46 +08:00
|
|
|
if (Out<ELFT>::SymTab)
|
|
|
|
Out<ELFT>::SymTab->addLocalSymbol(SymName);
|
2015-10-09 07:49:30 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-13 04:51:48 +08:00
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
2015-10-09 07:49:30 +08:00
|
|
|
// Output section ordering is determined by this function.
|
|
|
|
template <class ELFT>
|
2015-10-16 06:27:29 +08:00
|
|
|
static bool compareOutputSections(OutputSectionBase<ELFT> *A,
|
|
|
|
OutputSectionBase<ELFT> *B) {
|
2015-10-09 07:49:30 +08:00
|
|
|
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;
|
|
|
|
|
2015-10-14 01:57:46 +08:00
|
|
|
// If we got here we know that both A and B are in the same PT_LOAD.
|
2015-10-17 07:11:07 +08:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
2015-10-14 02:55:01 +08:00
|
|
|
// The next requirement we have is to put nobits sections last. The
|
2015-10-09 07:49:30 +08:00
|
|
|
// 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.
|
2015-10-14 03:27:12 +08:00
|
|
|
bool AIsNoBits = A->getType() == SHT_NOBITS;
|
|
|
|
bool BIsNoBits = B->getType() == SHT_NOBITS;
|
|
|
|
if (AIsNoBits != BIsNoBits)
|
|
|
|
return BIsNoBits;
|
2015-10-13 04:51:48 +08:00
|
|
|
|
2015-10-14 03:07:29 +08:00
|
|
|
// 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;
|
2015-10-09 07:49:30 +08:00
|
|
|
}
|
|
|
|
|
2015-11-04 05:35:14 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-10-09 07:49:30 +08:00
|
|
|
// 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>
|
2015-11-04 05:35:14 +08:00
|
|
|
void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon<ELFT> *> &Syms) {
|
2015-10-09 07:49:30 +08:00
|
|
|
typedef typename ELFFile<ELFT>::uintX_t uintX_t;
|
|
|
|
typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
|
|
|
|
|
2015-11-04 05:35:14 +08:00
|
|
|
if (Syms.empty())
|
|
|
|
return;
|
|
|
|
|
2015-10-09 07:49:30 +08:00
|
|
|
// 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;
|
|
|
|
});
|
|
|
|
|
2015-11-04 05:35:14 +08:00
|
|
|
uintX_t Off = getBSS()->getSize();
|
2015-10-09 07:49:30 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2015-10-29 00:48:58 +08:00
|
|
|
template <class ELFT>
|
2015-11-04 05:35:14 +08:00
|
|
|
void Writer<ELFT>::addSharedCopySymbols(
|
|
|
|
std::vector<SharedSymbol<ELFT> *> &Syms) {
|
2015-10-29 00:48:58 +08:00
|
|
|
typedef typename ELFFile<ELFT>::uintX_t uintX_t;
|
|
|
|
typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
|
2015-11-03 22:13:40 +08:00
|
|
|
typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
|
2015-10-29 00:48:58 +08:00
|
|
|
|
2015-11-04 05:35:14 +08:00
|
|
|
if (Syms.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
uintX_t Off = getBSS()->getSize();
|
2015-10-29 00:48:58 +08:00
|
|
|
for (SharedSymbol<ELFT> *C : Syms) {
|
|
|
|
const Elf_Sym &Sym = C->Sym;
|
2015-11-03 22:13:40 +08:00
|
|
|
const Elf_Shdr *Sec = C->File->getSection(Sym);
|
|
|
|
uintX_t SecAlign = Sec->sh_addralign;
|
|
|
|
uintX_t Align = Sym.st_value % SecAlign;
|
|
|
|
if (Align == 0)
|
|
|
|
Align = SecAlign;
|
|
|
|
Out<ELFT>::Bss->updateAlign(Align);
|
|
|
|
Off = RoundUpToAlignment(Off, Align);
|
2015-10-29 00:48:58 +08:00
|
|
|
C->OffsetInBSS = Off;
|
|
|
|
Off += Sym.st_size;
|
|
|
|
}
|
|
|
|
Out<ELFT>::Bss->setSize(Off);
|
|
|
|
}
|
|
|
|
|
2015-10-15 03:21:25 +08:00
|
|
|
static StringRef getOutputName(StringRef S) {
|
|
|
|
if (S.startswith(".text."))
|
|
|
|
return ".text";
|
|
|
|
if (S.startswith(".rodata."))
|
|
|
|
return ".rodata";
|
|
|
|
if (S.startswith(".data."))
|
|
|
|
return ".data";
|
|
|
|
if (S.startswith(".bss."))
|
|
|
|
return ".bss";
|
|
|
|
return S;
|
|
|
|
}
|
|
|
|
|
2015-07-25 05:03:07 +08:00
|
|
|
// Create output section objects and add them to OutputSections.
|
|
|
|
template <class ELFT> void Writer<ELFT>::createSections() {
|
2015-10-11 07:25:39 +08:00
|
|
|
// .interp needs to be on the first page in the output file.
|
|
|
|
if (needsInterpSection())
|
|
|
|
OutputSections.push_back(Out<ELFT>::Interp);
|
|
|
|
|
2015-10-20 05:00:02 +08:00
|
|
|
SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSectionBase<ELFT> *> Map;
|
2015-09-24 02:25:05 +08:00
|
|
|
|
2015-10-16 06:27:29 +08:00
|
|
|
std::vector<OutputSectionBase<ELFT> *> RegularSections;
|
2015-10-16 01:11:03 +08:00
|
|
|
|
2015-10-10 05:07:25 +08:00
|
|
|
for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
|
2015-10-20 05:00:02 +08:00
|
|
|
for (InputSectionBase<ELFT> *C : F->getSections()) {
|
ELF2: Implement --gc-sections.
Section garbage collection is a feature to remove unused sections
from outputs. Unused sections are sections that cannot be reachable
from known GC-root symbols or sections. Naturally the feature is
implemented as a mark-sweep garbage collector.
In this patch, I added Live bit to InputSectionBase. If and only
if Live bit is on, the section will be written to the output.
Starting from GC-root symbols or sections, a new function, markLive(),
visits all reachable sections and sets their Live bits. Writer then
ignores sections whose Live bit is off, so that such sections are
excluded from the output.
This change has small negative impact on performance if you use
the feature because making sections means more work. The time to
link Clang changes from 0.356s to 0.386s, or +8%.
It reduces Clang size from 57,764,984 bytes to 55,296,600 bytes.
That is 4.3% reduction.
http://reviews.llvm.org/D13950
llvm-svn: 251043
2015-10-23 02:49:53 +08:00
|
|
|
if (!C || !C->isLive() || C == &InputSection<ELFT>::Discarded)
|
2015-09-16 23:54:15 +08:00
|
|
|
continue;
|
|
|
|
const Elf_Shdr *H = C->getSectionHdr();
|
2015-10-10 03:25:07 +08:00
|
|
|
uintX_t OutFlags = H->sh_flags & ~SHF_GROUP;
|
2015-10-20 05:00:02 +08:00
|
|
|
// 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.
|
|
|
|
auto *IS = dyn_cast<InputSection<ELFT>>(C);
|
|
|
|
uintX_t EntSize = IS ? 0 : H->sh_entsize;
|
2015-10-15 03:21:25 +08:00
|
|
|
SectionKey<ELFT::Is64Bits> Key{getOutputName(C->getSectionName()),
|
2015-10-20 05:00:02 +08:00
|
|
|
H->sh_type, OutFlags, EntSize};
|
|
|
|
OutputSectionBase<ELFT> *&Sec = Map[Key];
|
2015-09-25 23:08:44 +08:00
|
|
|
if (!Sec) {
|
2015-10-20 05:00:02 +08:00
|
|
|
if (IS)
|
|
|
|
Sec = new (SecAlloc.Allocate())
|
|
|
|
OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
|
|
|
|
else
|
|
|
|
Sec = new (MSecAlloc.Allocate())
|
|
|
|
MergeOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
|
2015-09-25 23:08:44 +08:00
|
|
|
OutputSections.push_back(Sec);
|
2015-10-16 01:11:03 +08:00
|
|
|
RegularSections.push_back(Sec);
|
2015-09-25 23:08:44 +08:00
|
|
|
}
|
2015-10-20 05:00:02 +08:00
|
|
|
if (IS)
|
|
|
|
static_cast<OutputSection<ELFT> *>(Sec)->addSection(IS);
|
|
|
|
else
|
|
|
|
static_cast<MergeOutputSection<ELFT> *>(Sec)
|
|
|
|
->addSection(cast<MergeInputSection<ELFT>>(C));
|
2015-09-16 23:54:15 +08:00
|
|
|
}
|
2015-09-01 08:16:38 +08:00
|
|
|
}
|
|
|
|
|
2015-11-04 05:35:14 +08:00
|
|
|
Out<ELFT>::Bss = static_cast<OutputSection<ELFT> *>(
|
|
|
|
Map[{".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE, 0}]);
|
|
|
|
|
2015-10-20 05:00:02 +08:00
|
|
|
Out<ELFT>::Dynamic->PreInitArraySec = Map.lookup(
|
|
|
|
{".preinit_array", SHT_PREINIT_ARRAY, SHF_WRITE | SHF_ALLOC, 0});
|
2015-10-08 03:18:16 +08:00
|
|
|
Out<ELFT>::Dynamic->InitArraySec =
|
2015-10-20 05:00:02 +08:00
|
|
|
Map.lookup({".init_array", SHT_INIT_ARRAY, SHF_WRITE | SHF_ALLOC, 0});
|
2015-10-08 03:18:16 +08:00
|
|
|
Out<ELFT>::Dynamic->FiniArraySec =
|
2015-10-20 05:00:02 +08:00
|
|
|
Map.lookup({".fini_array", SHT_FINI_ARRAY, SHF_WRITE | SHF_ALLOC, 0});
|
2015-10-03 03:37:55 +08:00
|
|
|
|
2015-10-08 05:25:39 +08:00
|
|
|
auto AddStartEnd = [&](StringRef Start, StringRef End,
|
2015-10-16 06:27:29 +08:00
|
|
|
OutputSectionBase<ELFT> *OS) {
|
2015-10-06 09:16:17 +08:00
|
|
|
if (OS) {
|
2015-10-10 05:07:25 +08:00
|
|
|
Symtab.addSyntheticSym(Start, *OS, 0);
|
|
|
|
Symtab.addSyntheticSym(End, *OS, OS->getSize());
|
2015-10-19 23:21:42 +08:00
|
|
|
} else {
|
|
|
|
Symtab.addIgnoredSym(Start);
|
|
|
|
Symtab.addIgnoredSym(End);
|
2015-10-06 09:16:17 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-10-07 03:57:05 +08:00
|
|
|
AddStartEnd("__preinit_array_start", "__preinit_array_end",
|
2015-10-08 03:18:16 +08:00
|
|
|
Out<ELFT>::Dynamic->PreInitArraySec);
|
2015-10-07 03:57:05 +08:00
|
|
|
AddStartEnd("__init_array_start", "__init_array_end",
|
2015-10-08 03:18:16 +08:00
|
|
|
Out<ELFT>::Dynamic->InitArraySec);
|
2015-10-07 03:57:05 +08:00
|
|
|
AddStartEnd("__fini_array_start", "__fini_array_end",
|
2015-10-08 03:18:16 +08:00
|
|
|
Out<ELFT>::Dynamic->FiniArraySec);
|
2015-09-26 02:56:53 +08:00
|
|
|
|
2015-10-19 23:21:42 +08:00
|
|
|
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.addIgnoredSym("__tls_get_addr");
|
|
|
|
|
|
|
|
// 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())
|
2015-10-20 05:00:02 +08:00
|
|
|
for (InputSectionBase<ELFT> *B : F->getSections())
|
|
|
|
if (auto *S = dyn_cast_or_null<InputSection<ELFT>>(B))
|
|
|
|
if (S != &InputSection<ELFT>::Discarded)
|
ELF2: Implement --gc-sections.
Section garbage collection is a feature to remove unused sections
from outputs. Unused sections are sections that cannot be reachable
from known GC-root symbols or sections. Naturally the feature is
implemented as a mark-sweep garbage collector.
In this patch, I added Live bit to InputSectionBase. If and only
if Live bit is on, the section will be written to the output.
Starting from GC-root symbols or sections, a new function, markLive(),
visits all reachable sections and sets their Live bits. Writer then
ignores sections whose Live bit is off, so that such sections are
excluded from the output.
This change has small negative impact on performance if you use
the feature because making sections means more work. The time to
link Clang changes from 0.356s to 0.386s, or +8%.
It reduces Clang size from 57,764,984 bytes to 55,296,600 bytes.
That is 4.3% reduction.
http://reviews.llvm.org/D13950
llvm-svn: 251043
2015-10-23 02:49:53 +08:00
|
|
|
if (S->isLive())
|
|
|
|
scanRelocs(*S);
|
2015-10-19 23:21:42 +08:00
|
|
|
|
2015-09-23 07:38:23 +08:00
|
|
|
std::vector<DefinedCommon<ELFT> *> CommonSymbols;
|
2015-10-29 00:48:58 +08:00
|
|
|
std::vector<SharedSymbol<ELFT> *> SharedCopySymbols;
|
2015-09-23 07:38:23 +08:00
|
|
|
for (auto &P : Symtab.getSymbols()) {
|
|
|
|
SymbolBody *Body = P.second->Body;
|
2015-10-16 04:55:20 +08:00
|
|
|
if (auto *U = dyn_cast<Undefined<ELFT>>(Body))
|
2015-10-05 17:43:57 +08:00
|
|
|
if (!U->isWeak() && !U->canKeepUndefined())
|
|
|
|
reportUndefined<ELFT>(Symtab, *Body);
|
2015-09-23 07:38:23 +08:00
|
|
|
|
|
|
|
if (auto *C = dyn_cast<DefinedCommon<ELFT>>(Body))
|
|
|
|
CommonSymbols.push_back(C);
|
2015-10-29 00:48:58 +08:00
|
|
|
if (auto *SC = dyn_cast<SharedSymbol<ELFT>>(Body))
|
2015-11-03 22:34:11 +08:00
|
|
|
if (SC->needsCopy())
|
2015-10-29 00:48:58 +08:00
|
|
|
SharedCopySymbols.push_back(SC);
|
|
|
|
|
2015-10-05 23:24:04 +08:00
|
|
|
if (!includeInSymtab<ELFT>(*Body))
|
2015-09-23 07:38:23 +08:00
|
|
|
continue;
|
2015-10-24 16:52:46 +08:00
|
|
|
if (Out<ELFT>::SymTab)
|
|
|
|
Out<ELFT>::SymTab->addSymbol(Body);
|
2015-09-23 07:38:23 +08:00
|
|
|
|
2015-10-13 07:39:23 +08:00
|
|
|
if (isOutputDynamic() && includeInDynamicSymtab(*Body))
|
2015-10-21 05:47:58 +08:00
|
|
|
Out<ELFT>::DynSymTab->addSymbol(Body);
|
2015-09-23 07:38:23 +08:00
|
|
|
}
|
2015-10-09 07:49:30 +08:00
|
|
|
addCommonSymbols(CommonSymbols);
|
2015-10-29 00:48:58 +08:00
|
|
|
addSharedCopySymbols(SharedCopySymbols);
|
2015-07-25 05:03:07 +08:00
|
|
|
|
2015-10-16 05:50:30 +08:00
|
|
|
// This order is not the same as the final output order
|
|
|
|
// because we sort the sections using their attributes below.
|
2015-10-24 16:52:46 +08:00
|
|
|
if (Out<ELFT>::SymTab)
|
|
|
|
OutputSections.push_back(Out<ELFT>::SymTab);
|
2015-10-21 01:21:35 +08:00
|
|
|
OutputSections.push_back(Out<ELFT>::ShStrTab);
|
2015-10-24 16:52:46 +08:00
|
|
|
if (Out<ELFT>::StrTab)
|
|
|
|
OutputSections.push_back(Out<ELFT>::StrTab);
|
2015-10-13 07:39:23 +08:00
|
|
|
if (isOutputDynamic()) {
|
2015-10-08 03:18:16 +08:00
|
|
|
OutputSections.push_back(Out<ELFT>::DynSymTab);
|
2015-10-22 16:21:35 +08:00
|
|
|
if (Out<ELFT>::GnuHashTab)
|
|
|
|
OutputSections.push_back(Out<ELFT>::GnuHashTab);
|
|
|
|
if (Out<ELFT>::HashTab)
|
|
|
|
OutputSections.push_back(Out<ELFT>::HashTab);
|
2015-10-08 03:18:16 +08:00
|
|
|
OutputSections.push_back(Out<ELFT>::Dynamic);
|
|
|
|
OutputSections.push_back(Out<ELFT>::DynStrTab);
|
|
|
|
if (Out<ELFT>::RelaDyn->hasRelocs())
|
|
|
|
OutputSections.push_back(Out<ELFT>::RelaDyn);
|
2015-10-20 16:54:27 +08:00
|
|
|
if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs())
|
|
|
|
OutputSections.push_back(Out<ELFT>::RelaPlt);
|
2015-09-09 23:33:08 +08:00
|
|
|
}
|
2015-10-08 03:18:16 +08:00
|
|
|
if (!Out<ELFT>::Got->empty())
|
|
|
|
OutputSections.push_back(Out<ELFT>::Got);
|
2015-10-20 16:54:27 +08:00
|
|
|
if (Out<ELFT>::GotPlt && !Out<ELFT>::GotPlt->empty())
|
|
|
|
OutputSections.push_back(Out<ELFT>::GotPlt);
|
2015-10-08 03:18:16 +08:00
|
|
|
if (!Out<ELFT>::Plt->empty())
|
|
|
|
OutputSections.push_back(Out<ELFT>::Plt);
|
2015-09-09 03:43:27 +08:00
|
|
|
|
2015-10-09 07:49:30 +08:00
|
|
|
std::stable_sort(OutputSections.begin(), OutputSections.end(),
|
|
|
|
compareOutputSections<ELFT>);
|
2015-09-25 11:48:25 +08:00
|
|
|
|
2015-09-09 02:08:57 +08:00
|
|
|
for (unsigned I = 0, N = OutputSections.size(); I < N; ++I)
|
2015-10-16 04:55:22 +08:00
|
|
|
OutputSections[I]->SectionIndex = I + 1;
|
2015-10-02 05:15:02 +08:00
|
|
|
|
2015-10-16 06:27:29 +08:00
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
2015-10-21 01:21:35 +08:00
|
|
|
Out<ELFT>::ShStrTab->add(Sec->getName());
|
2015-10-16 05:50:30 +08:00
|
|
|
|
2015-11-02 18:46:14 +08:00
|
|
|
// 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.
|
2015-10-08 03:18:16 +08:00
|
|
|
Out<ELFT>::Dynamic->finalize();
|
2015-11-02 18:46:14 +08:00
|
|
|
if (isOutputDynamic())
|
|
|
|
Out<ELFT>::DynSymTab->finalize();
|
2015-10-10 00:03:53 +08:00
|
|
|
|
2015-10-16 05:50:30 +08:00
|
|
|
// Fill other section headers.
|
2015-10-16 06:27:29 +08:00
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
2015-10-10 00:03:53 +08:00
|
|
|
Sec->finalize();
|
[ELF2/PPC64] Resolve local-call relocations using the correct function-descriptor values
Under PPC64 ELF v1 ABI, the symbols associated with each function name don't
point directly to the code in the .text section (or similar), but rather to a
function descriptor structure in a special data section named .opd. The
elements in the .opd structure include a pointer to the actual code, and a the
relevant TOC base value. Both of these are themselves set by relocations.
When we have a local call, we need the relevant relocation to refer directly to
the target code, not to the function-descriptor in the .opd section. Only when
we have a .plt stub do we care about the address of the .opd function
descriptor itself.
So we make a few changes here:
1. Always write .opd first, so that its relocated data values are available
for later use when writing the text sections. Record a pointer to the .opd
structure, and its corresponding buffer.
2. When processing a relative branch relocation under ppc64, if the
destination points into the .opd section, read the code pointer out of the
function descriptor structure and use that instead.
This this, I can link, and run, a dynamically-compiled "hello world"
application on big-Endian PPC64/Linux (ELF v1 ABI) using lld.
llvm-svn: 250122
2015-10-13 07:16:53 +08:00
|
|
|
|
|
|
|
// 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.
|
2015-10-20 05:00:02 +08:00
|
|
|
Out<ELFT>::Opd = Map.lookup({".opd", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, 0});
|
2015-08-13 23:23:46 +08:00
|
|
|
}
|
|
|
|
|
2015-10-16 01:11:03 +08:00
|
|
|
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>
|
2015-10-16 06:27:29 +08:00
|
|
|
void Writer<ELFT>::addStartStopSymbols(OutputSectionBase<ELFT> *Sec) {
|
2015-10-16 01:11:03 +08:00
|
|
|
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.addSyntheticSym(Start, *Sec, 0);
|
|
|
|
if (Symtab.isUndefined(Stop))
|
|
|
|
Symtab.addSyntheticSym(Stop, *Sec, Sec->getSize());
|
|
|
|
}
|
|
|
|
|
2015-10-16 06:27:29 +08:00
|
|
|
template <class ELFT> static bool needsPhdr(OutputSectionBase<ELFT> *Sec) {
|
2015-09-18 03:58:07 +08:00
|
|
|
return Sec->getFlags() & SHF_ALLOC;
|
2015-09-10 04:48:09 +08:00
|
|
|
}
|
|
|
|
|
2015-10-25 02:22:59 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-10-24 05:45:59 +08:00
|
|
|
// Visits all sections to create PHDRs and to assign incremental,
|
|
|
|
// non-overlapping addresses to output sections.
|
2015-07-25 05:03:07 +08:00
|
|
|
template <class ELFT> void Writer<ELFT>::assignAddresses() {
|
2015-11-10 16:39:27 +08:00
|
|
|
uintX_t VA = Target->getVAStart() + sizeof(Elf_Ehdr);
|
2015-10-11 06:34:30 +08:00
|
|
|
uintX_t FileOff = sizeof(Elf_Ehdr);
|
2015-09-10 04:48:09 +08:00
|
|
|
|
2015-10-24 05:45:59 +08:00
|
|
|
// 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();
|
2015-10-11 07:59:57 +08:00
|
|
|
|
2015-10-24 05:45:59 +08:00
|
|
|
// 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;
|
2015-08-13 23:23:46 +08:00
|
|
|
|
2015-10-24 05:45:59 +08:00
|
|
|
// PT_INTERP must be the second entry if exists.
|
|
|
|
int PhdrIdx = 0;
|
2015-10-11 07:59:57 +08:00
|
|
|
Elf_Phdr *Interp = nullptr;
|
2015-10-24 05:45:59 +08:00
|
|
|
if (needsInterpSection())
|
|
|
|
Interp = &Phdrs[++PhdrIdx];
|
2015-09-12 02:49:42 +08:00
|
|
|
|
2015-10-24 05:45:59 +08:00
|
|
|
// Add the first PT_LOAD segment for regular output sections.
|
2015-11-10 16:39:27 +08:00
|
|
|
setPhdr(&Phdrs[++PhdrIdx], PT_LOAD, PF_R, 0, Target->getVAStart(), FileOff,
|
2015-10-24 05:45:59 +08:00
|
|
|
Target->getPageSize());
|
2015-09-10 23:41:34 +08:00
|
|
|
|
2015-11-04 06:43:11 +08:00
|
|
|
Elf_Phdr TlsPhdr{};
|
2015-11-03 08:34:39 +08:00
|
|
|
uintX_t ThreadBSSOffset = 0;
|
2015-10-24 05:45:59 +08:00
|
|
|
// Create phdrs as we assign VAs and file offsets to all output sections.
|
2015-10-16 06:27:29 +08:00
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
|
2015-11-04 07:19:42 +08:00
|
|
|
if (needsPhdr<ELFT>(Sec)) {
|
|
|
|
uintX_t Flags = toPhdrFlags(Sec->getFlags());
|
|
|
|
if (Phdrs[PhdrIdx].p_flags != Flags) {
|
|
|
|
// Flags changed. Create a new PT_LOAD.
|
2015-11-04 06:08:08 +08:00
|
|
|
VA = RoundUpToAlignment(VA, Target->getPageSize());
|
|
|
|
FileOff = RoundUpToAlignment(FileOff, Target->getPageSize());
|
|
|
|
Elf_Phdr *PH = &Phdrs[++PhdrIdx];
|
|
|
|
setPhdr(PH, PT_LOAD, Flags, FileOff, VA, 0, Target->getPageSize());
|
2015-09-18 03:58:07 +08:00
|
|
|
}
|
2015-09-10 04:48:09 +08:00
|
|
|
|
2015-11-04 07:19:42 +08:00
|
|
|
if (Sec->getFlags() & SHF_TLS) {
|
2015-11-07 06:14:44 +08:00
|
|
|
if (!TlsPhdr.p_vaddr)
|
2015-11-04 07:19:42 +08:00
|
|
|
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());
|
2015-11-03 23:46:15 +08:00
|
|
|
} else {
|
2015-11-04 07:19:42 +08:00
|
|
|
VA = RoundUpToAlignment(VA, Sec->getAlign());
|
|
|
|
Sec->setVA(VA);
|
2015-11-03 08:34:39 +08:00
|
|
|
VA += Sec->getSize();
|
|
|
|
}
|
2015-08-13 23:31:17 +08:00
|
|
|
}
|
2015-11-03 08:34:39 +08:00
|
|
|
|
2015-10-24 05:45:59 +08:00
|
|
|
FileOff = RoundUpToAlignment(FileOff, Sec->getAlign());
|
2015-07-25 05:03:07 +08:00
|
|
|
Sec->setFileOffset(FileOff);
|
2015-09-01 04:23:57 +08:00
|
|
|
if (Sec->getType() != SHT_NOBITS)
|
2015-10-24 05:45:59 +08:00
|
|
|
FileOff += Sec->getSize();
|
2015-11-04 07:19:42 +08:00
|
|
|
if (needsPhdr<ELFT>(Sec)) {
|
|
|
|
Elf_Phdr *Cur = &Phdrs[PhdrIdx];
|
|
|
|
Cur->p_filesz = FileOff - Cur->p_offset;
|
|
|
|
Cur->p_memsz = VA - Cur->p_vaddr;
|
|
|
|
}
|
2015-07-25 05:03:07 +08:00
|
|
|
}
|
2015-08-12 08:00:24 +08:00
|
|
|
|
2015-11-05 10:00:35 +08:00
|
|
|
if (TlsPhdr.p_vaddr) {
|
2015-11-07 06:14:44 +08:00
|
|
|
// 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);
|
2015-11-03 08:34:39 +08:00
|
|
|
Phdrs[++PhdrIdx] = TlsPhdr;
|
2015-11-07 06:14:44 +08:00
|
|
|
Out<ELFT>::TlsPhdr = &Phdrs[PhdrIdx];
|
2015-11-05 10:00:35 +08:00
|
|
|
}
|
2015-11-03 08:34:39 +08:00
|
|
|
|
2015-10-24 05:45:59 +08:00
|
|
|
// Add an entry for .dynamic.
|
2015-10-13 07:39:23 +08:00
|
|
|
if (isOutputDynamic()) {
|
2015-10-24 05:45:59 +08:00
|
|
|
Elf_Phdr *PH = &Phdrs[++PhdrIdx];
|
2015-10-11 07:59:57 +08:00
|
|
|
PH->p_type = PT_DYNAMIC;
|
2015-10-12 03:45:58 +08:00
|
|
|
copyPhdr(PH, Out<ELFT>::Dynamic);
|
2015-10-11 06:34:30 +08:00
|
|
|
}
|
2015-08-12 09:45:28 +08:00
|
|
|
|
2015-10-24 05:45:59 +08:00
|
|
|
// 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);
|
2015-10-11 07:25:39 +08:00
|
|
|
}
|
|
|
|
|
2015-07-29 08:30:10 +08:00
|
|
|
// Add space for section headers.
|
2015-10-24 05:45:59 +08:00
|
|
|
SectionHeaderOff = RoundUpToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4);
|
|
|
|
FileSize = SectionHeaderOff + getNumSections() * sizeof(Elf_Shdr);
|
2015-11-06 15:43:03 +08:00
|
|
|
|
|
|
|
// 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>();
|
2015-10-24 05:45:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the number of PHDR entries.
|
|
|
|
template <class ELFT> int Writer<ELFT>::getPhdrsNum() const {
|
2015-11-03 08:34:39 +08:00
|
|
|
bool Tls = false;
|
2015-10-24 05:45:59 +08:00
|
|
|
int I = 2; // 2 for PT_PHDR and the first PT_LOAD
|
|
|
|
if (needsInterpSection())
|
|
|
|
++I;
|
|
|
|
if (isOutputDynamic())
|
|
|
|
++I;
|
|
|
|
uintX_t Last = PF_R;
|
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
|
2015-11-04 06:08:08 +08:00
|
|
|
if (!needsPhdr<ELFT>(Sec))
|
2015-10-24 05:45:59 +08:00
|
|
|
continue;
|
2015-11-03 08:34:39 +08:00
|
|
|
if (Sec->getFlags() & SHF_TLS)
|
|
|
|
Tls = true;
|
2015-10-24 05:45:59 +08:00
|
|
|
uintX_t Flags = toPhdrFlags(Sec->getFlags());
|
|
|
|
if (Last != Flags) {
|
|
|
|
Last = Flags;
|
|
|
|
++I;
|
|
|
|
}
|
|
|
|
}
|
2015-11-03 08:34:39 +08:00
|
|
|
if (Tls)
|
|
|
|
++I;
|
2015-10-24 05:45:59 +08:00
|
|
|
return I;
|
2015-07-25 05:03:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class ELFT> void Writer<ELFT>::writeHeader() {
|
|
|
|
uint8_t *Buf = Buffer->getBufferStart();
|
2015-10-24 06:44:39 +08:00
|
|
|
memcpy(Buf, "\177ELF", 4);
|
|
|
|
|
2015-10-25 01:57:40 +08:00
|
|
|
// Write the ELF header.
|
2015-09-09 05:57:31 +08:00
|
|
|
auto *EHdr = reinterpret_cast<Elf_Ehdr *>(Buf);
|
2015-08-05 23:08:40 +08:00
|
|
|
EHdr->e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
|
|
|
|
EHdr->e_ident[EI_DATA] = ELFT::TargetEndianness == llvm::support::little
|
|
|
|
? ELFDATA2LSB
|
|
|
|
: ELFDATA2MSB;
|
2015-07-25 05:03:07 +08:00
|
|
|
EHdr->e_ident[EI_VERSION] = EV_CURRENT;
|
2015-09-25 09:59:13 +08:00
|
|
|
|
2015-10-12 19:52:31 +08:00
|
|
|
auto &FirstObj = cast<ELFFileBase<ELFT>>(*Config->FirstElf);
|
2015-09-25 09:59:13 +08:00
|
|
|
EHdr->e_ident[EI_OSABI] = FirstObj.getOSABI();
|
2015-07-25 05:03:07 +08:00
|
|
|
|
2015-09-12 06:42:45 +08:00
|
|
|
EHdr->e_type = Config->Shared ? ET_DYN : ET_EXEC;
|
2015-09-04 04:03:54 +08:00
|
|
|
EHdr->e_machine = FirstObj.getEMachine();
|
2015-07-25 05:03:07 +08:00
|
|
|
EHdr->e_version = EV_CURRENT;
|
2015-10-24 06:44:37 +08:00
|
|
|
EHdr->e_entry = getEntryAddr();
|
2015-10-11 06:36:36 +08:00
|
|
|
EHdr->e_phoff = sizeof(Elf_Ehdr);
|
2015-07-29 08:30:10 +08:00
|
|
|
EHdr->e_shoff = SectionHeaderOff;
|
2015-09-09 05:57:31 +08:00
|
|
|
EHdr->e_ehsize = sizeof(Elf_Ehdr);
|
|
|
|
EHdr->e_phentsize = sizeof(Elf_Phdr);
|
2015-10-11 06:34:30 +08:00
|
|
|
EHdr->e_phnum = Phdrs.size();
|
2015-09-09 05:57:31 +08:00
|
|
|
EHdr->e_shentsize = sizeof(Elf_Shdr);
|
2015-09-09 01:39:39 +08:00
|
|
|
EHdr->e_shnum = getNumSections();
|
2015-10-21 01:21:35 +08:00
|
|
|
EHdr->e_shstrndx = Out<ELFT>::ShStrTab->SectionIndex;
|
2015-10-25 01:57:40 +08:00
|
|
|
|
|
|
|
// Write the program header table.
|
2015-10-11 08:10:36 +08:00
|
|
|
memcpy(Buf + EHdr->e_phoff, &Phdrs[0], Phdrs.size() * sizeof(Phdrs[0]));
|
2015-09-09 06:55:28 +08:00
|
|
|
|
2015-10-25 01:57:40 +08:00
|
|
|
// Write the section header table. Note that the first table entry is null.
|
2015-09-09 05:57:31 +08:00
|
|
|
auto SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);
|
2015-10-25 01:57:39 +08:00
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
2015-10-25 01:57:40 +08:00
|
|
|
Sec->writeHeaderTo(++SHdrs);
|
2015-07-25 05:03:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class ELFT> void Writer<ELFT>::openFile(StringRef Path) {
|
2015-08-13 08:31:46 +08:00
|
|
|
ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
|
|
|
|
FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable);
|
|
|
|
error(BufferOrErr, Twine("failed to open ") + Path);
|
|
|
|
Buffer = std::move(*BufferOrErr);
|
2015-07-25 05:03:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Write section contents to a mmap'ed file.
|
|
|
|
template <class ELFT> void Writer<ELFT>::writeSections() {
|
|
|
|
uint8_t *Buf = Buffer->getBufferStart();
|
[ELF2/PPC64] Resolve local-call relocations using the correct function-descriptor values
Under PPC64 ELF v1 ABI, the symbols associated with each function name don't
point directly to the code in the .text section (or similar), but rather to a
function descriptor structure in a special data section named .opd. The
elements in the .opd structure include a pointer to the actual code, and a the
relevant TOC base value. Both of these are themselves set by relocations.
When we have a local call, we need the relevant relocation to refer directly to
the target code, not to the function-descriptor in the .opd section. Only when
we have a .plt stub do we care about the address of the .opd function
descriptor itself.
So we make a few changes here:
1. Always write .opd first, so that its relocated data values are available
for later use when writing the text sections. Record a pointer to the .opd
structure, and its corresponding buffer.
2. When processing a relative branch relocation under ppc64, if the
destination points into the .opd section, read the code pointer out of the
function descriptor structure and use that instead.
This this, I can link, and run, a dynamically-compiled "hello world"
application on big-Endian PPC64/Linux (ELF v1 ABI) using lld.
llvm-svn: 250122
2015-10-13 07:16:53 +08:00
|
|
|
|
|
|
|
// PPC64 needs to process relocations in the .opd section before processing
|
|
|
|
// relocations in code-containing sections.
|
2015-10-16 06:27:29 +08:00
|
|
|
if (OutputSectionBase<ELFT> *Sec = Out<ELFT>::Opd) {
|
2015-10-13 22:45:51 +08:00
|
|
|
Out<ELFT>::OpdBuf = Buf + Sec->getFileOff();
|
|
|
|
Sec->writeTo(Buf + Sec->getFileOff());
|
|
|
|
}
|
[ELF2/PPC64] Resolve local-call relocations using the correct function-descriptor values
Under PPC64 ELF v1 ABI, the symbols associated with each function name don't
point directly to the code in the .text section (or similar), but rather to a
function descriptor structure in a special data section named .opd. The
elements in the .opd structure include a pointer to the actual code, and a the
relevant TOC base value. Both of these are themselves set by relocations.
When we have a local call, we need the relevant relocation to refer directly to
the target code, not to the function-descriptor in the .opd section. Only when
we have a .plt stub do we care about the address of the .opd function
descriptor itself.
So we make a few changes here:
1. Always write .opd first, so that its relocated data values are available
for later use when writing the text sections. Record a pointer to the .opd
structure, and its corresponding buffer.
2. When processing a relative branch relocation under ppc64, if the
destination points into the .opd section, read the code pointer out of the
function descriptor structure and use that instead.
This this, I can link, and run, a dynamically-compiled "hello world"
application on big-Endian PPC64/Linux (ELF v1 ABI) using lld.
llvm-svn: 250122
2015-10-13 07:16:53 +08:00
|
|
|
|
2015-10-16 06:27:29 +08:00
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
2015-10-13 22:45:51 +08:00
|
|
|
if (Sec != Out<ELFT>::Opd)
|
[ELF2/PPC64] Resolve local-call relocations using the correct function-descriptor values
Under PPC64 ELF v1 ABI, the symbols associated with each function name don't
point directly to the code in the .text section (or similar), but rather to a
function descriptor structure in a special data section named .opd. The
elements in the .opd structure include a pointer to the actual code, and a the
relevant TOC base value. Both of these are themselves set by relocations.
When we have a local call, we need the relevant relocation to refer directly to
the target code, not to the function-descriptor in the .opd section. Only when
we have a .plt stub do we care about the address of the .opd function
descriptor itself.
So we make a few changes here:
1. Always write .opd first, so that its relocated data values are available
for later use when writing the text sections. Record a pointer to the .opd
structure, and its corresponding buffer.
2. When processing a relative branch relocation under ppc64, if the
destination points into the .opd section, read the code pointer out of the
function descriptor structure and use that instead.
This this, I can link, and run, a dynamically-compiled "hello world"
application on big-Endian PPC64/Linux (ELF v1 ABI) using lld.
llvm-svn: 250122
2015-10-13 07:16:53 +08:00
|
|
|
Sec->writeTo(Buf + Sec->getFileOff());
|
2015-07-25 05:03:07 +08:00
|
|
|
}
|
2015-10-10 05:07:25 +08:00
|
|
|
|
2015-10-11 06:34:30 +08:00
|
|
|
template <class ELFT>
|
2015-10-24 06:44:37 +08:00
|
|
|
typename ELFFile<ELFT>::uintX_t Writer<ELFT>::getEntryAddr() const {
|
|
|
|
if (Config->EntrySym) {
|
|
|
|
if (auto *E = dyn_cast<ELFSymbolBody<ELFT>>(Config->EntrySym->repl()))
|
|
|
|
return getSymVA<ELFT>(*E);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (Config->EntryAddr != uint64_t(-1))
|
|
|
|
return Config->EntryAddr;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class ELFT>
|
2015-10-12 03:45:58 +08:00
|
|
|
void Writer<ELFT>::setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags,
|
2015-10-24 05:45:59 +08:00
|
|
|
uintX_t FileOff, uintX_t VA, uintX_t Size,
|
|
|
|
uintX_t Align) {
|
2015-10-11 06:34:30 +08:00
|
|
|
PH->p_type = Type;
|
|
|
|
PH->p_flags = Flags;
|
|
|
|
PH->p_offset = FileOff;
|
|
|
|
PH->p_vaddr = VA;
|
|
|
|
PH->p_paddr = VA;
|
2015-10-24 05:45:59 +08:00
|
|
|
PH->p_filesz = Size;
|
|
|
|
PH->p_memsz = Size;
|
2015-10-11 06:34:30 +08:00
|
|
|
PH->p_align = Align;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class ELFT>
|
2015-10-16 06:27:29 +08:00
|
|
|
void Writer<ELFT>::copyPhdr(Elf_Phdr *PH, OutputSectionBase<ELFT> *From) {
|
2015-10-11 06:34:30 +08:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2015-10-10 05:07:25 +08:00
|
|
|
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);
|