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"
|
2016-02-12 05:17:59 +08:00
|
|
|
#include "LinkerScript.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
|
|
|
|
2016-02-11 06:43:13 +08:00
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
2015-11-12 17:52:08 +08:00
|
|
|
#include "llvm/ADT/StringMap.h"
|
2015-10-13 04:51:48 +08:00
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
2016-04-13 09:40:19 +08:00
|
|
|
#include "llvm/Support/Endian.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"
|
2016-02-06 08:06:26 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2015-07-25 05:03:07 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace llvm::ELF;
|
|
|
|
using namespace llvm::object;
|
2016-04-13 09:40:19 +08:00
|
|
|
using namespace llvm::support::endian;
|
2015-07-25 05:03:07 +08:00
|
|
|
|
|
|
|
using namespace lld;
|
2016-02-28 08:25:54 +08:00
|
|
|
using namespace lld::elf;
|
2015-07-25 05:03:07 +08:00
|
|
|
|
2015-08-06 07:24:46 +08:00
|
|
|
namespace {
|
|
|
|
// The writer writes a SymbolTable result to a file.
|
|
|
|
template <class ELFT> class Writer {
|
|
|
|
public:
|
2016-03-15 07:16:09 +08:00
|
|
|
typedef typename ELFT::uint uintX_t;
|
|
|
|
typedef typename ELFT::Shdr Elf_Shdr;
|
|
|
|
typedef typename ELFT::Ehdr Elf_Ehdr;
|
|
|
|
typedef typename ELFT::Phdr Elf_Phdr;
|
|
|
|
typedef typename ELFT::Sym Elf_Sym;
|
|
|
|
typedef typename ELFT::SymRange Elf_Sym_Range;
|
|
|
|
typedef typename ELFT::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:
|
2016-02-11 06:43:13 +08:00
|
|
|
// This describes a program header entry.
|
|
|
|
// Each contains type, access flags and range of output sections that will be
|
|
|
|
// placed in it.
|
|
|
|
struct Phdr {
|
|
|
|
Phdr(unsigned Type, unsigned Flags) {
|
|
|
|
H.p_type = Type;
|
|
|
|
H.p_flags = Flags;
|
|
|
|
}
|
|
|
|
Elf_Phdr H = {};
|
|
|
|
OutputSectionBase<ELFT> *First = nullptr;
|
|
|
|
OutputSectionBase<ELFT> *Last = nullptr;
|
|
|
|
};
|
|
|
|
|
2015-10-09 07:49:30 +08:00
|
|
|
void copyLocalSymbols();
|
2015-12-26 15:50:39 +08:00
|
|
|
void addReservedSymbols();
|
2016-04-02 01:24:19 +08:00
|
|
|
void createSections();
|
2015-12-26 15:50:41 +08:00
|
|
|
void addPredefinedSections();
|
2016-02-26 03:34:37 +08:00
|
|
|
bool needsGot();
|
2015-12-25 15:38:58 +08:00
|
|
|
|
2016-03-13 13:06:50 +08:00
|
|
|
template <class RelTy>
|
2016-04-05 22:47:28 +08:00
|
|
|
void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels);
|
2015-12-25 15:38:58 +08:00
|
|
|
|
2015-11-11 23:29:50 +08:00
|
|
|
void scanRelocs(InputSection<ELFT> &C);
|
2015-11-12 03:54:14 +08:00
|
|
|
void scanRelocs(InputSectionBase<ELFT> &S, const Elf_Shdr &RelSec);
|
2016-05-13 05:51:16 +08:00
|
|
|
RelExpr adjustExpr(SymbolBody &S, bool IsWrite, RelExpr Expr, uint32_t Type);
|
2016-02-11 06:43:13 +08:00
|
|
|
void createPhdrs();
|
2015-08-06 07:24:46 +08:00
|
|
|
void assignAddresses();
|
2016-04-02 01:07:17 +08:00
|
|
|
void assignFileOffsets();
|
|
|
|
void setPhdrs();
|
2016-04-06 15:20:45 +08:00
|
|
|
void fixHeaders();
|
2016-03-31 03:41:51 +08:00
|
|
|
void fixSectionAlignments();
|
2015-12-26 18:52:26 +08:00
|
|
|
void fixAbsoluteSymbols();
|
2016-04-02 01:24:19 +08:00
|
|
|
void openFile();
|
2015-08-06 07:24:46 +08:00
|
|
|
void writeHeader();
|
|
|
|
void writeSections();
|
ELF: Implement --build-id.
This patch implements --build-id. After the linker creates an output file
in the memory buffer, it computes the FNV1 hash of the resulting file
and set the hash to the .note section as a build-id.
GNU ld and gold have the same feature, but their default choice of the
hash function is different. Their default is SHA1.
We made a deliberate choice to not use a secure hash function for the
sake of performance. Computing a secure hash is slow -- for example,
MD5 throughput is usually 400 MB/s or so. SHA1 is slower than that.
As a result, if you pass --build-id to gold, then the linker becomes about
10% slower than that without the option. We observed a similar degradation
in an experimental implementation of build-id for LLD. On the other hand,
we observed only 1-2% performance degradation with the FNV hash.
Since build-id is not for digital certificate or anything, we think that
a very small probability of collision is acceptable.
We considered using other signals such as using input file timestamps as
inputs to a secure hash function. But such signals would have an issue
with build reproducibility (if you build a binary from the same source
tree using the same toolchain, the build id should become the same.)
GNU linkers accepts --build-id=<style> option where style is one of
"MD5", "SHA1", or an arbitrary hex string. That option is out of scope
of this patch.
http://reviews.llvm.org/D18091
llvm-svn: 263292
2016-03-12 04:51:53 +08:00
|
|
|
void writeBuildId();
|
2015-11-12 17:52:08 +08:00
|
|
|
bool isDiscarded(InputSectionBase<ELFT> *IS) const;
|
2016-02-13 05:47:28 +08:00
|
|
|
StringRef getOutputSectionName(InputSectionBase<ELFT> *S) const;
|
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 {
|
2016-03-17 13:57:33 +08:00
|
|
|
return !Symtab.getSharedFiles().empty() || Config->Pic;
|
2015-09-12 06:42:45 +08:00
|
|
|
}
|
2016-04-01 05:26:23 +08:00
|
|
|
template <class RelTy>
|
|
|
|
void scanRelocsForThunks(const elf::ObjectFile<ELFT> &File,
|
2016-04-05 22:47:28 +08:00
|
|
|
ArrayRef<RelTy> Rels);
|
2015-08-06 07:24:46 +08:00
|
|
|
|
2016-03-13 12:11:53 +08:00
|
|
|
void ensureBss();
|
2015-12-25 00:23:37 +08:00
|
|
|
void addCommonSymbols(std::vector<DefinedCommon *> &Syms);
|
2016-04-05 06:29:24 +08:00
|
|
|
void addCopyRelSymbol(SharedSymbol<ELFT> *Sym);
|
2015-11-04 05:35:14 +08:00
|
|
|
|
2015-08-06 07:24:46 +08:00
|
|
|
std::unique_ptr<llvm::FileOutputBuffer> Buffer;
|
2015-09-18 03:58:07 +08:00
|
|
|
|
2015-10-16 01:11:03 +08:00
|
|
|
BumpPtrAllocator Alloc;
|
2015-10-16 06:27:29 +08:00
|
|
|
std::vector<OutputSectionBase<ELFT> *> OutputSections;
|
2015-12-26 15:01:26 +08:00
|
|
|
std::vector<std::unique_ptr<OutputSectionBase<ELFT>>> OwningSections;
|
2016-02-11 06:43:13 +08:00
|
|
|
|
2015-12-26 17:47:57 +08:00
|
|
|
void addRelIpltSymbols();
|
2015-12-26 17:48:00 +08:00
|
|
|
void addStartEndSymbols();
|
2015-10-16 06:27:29 +08:00
|
|
|
void addStartStopSymbols(OutputSectionBase<ELFT> *Sec);
|
2015-10-11 06:34:30 +08:00
|
|
|
|
2015-10-10 05:07:25 +08:00
|
|
|
SymbolTable<ELFT> &Symtab;
|
2016-02-11 06:43:13 +08:00
|
|
|
std::vector<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;
|
2015-11-12 17:52:08 +08:00
|
|
|
|
2016-01-23 09:49:37 +08:00
|
|
|
// Flag to force GOT to be in output if we have relocations
|
|
|
|
// that relies on its address.
|
|
|
|
bool HasGotOffRel = false;
|
2015-08-06 07:24:46 +08:00
|
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
|
2016-02-28 08:25:54 +08:00
|
|
|
template <class ELFT> void elf::writeResult(SymbolTable<ELFT> *Symtab) {
|
2016-03-15 07:16:09 +08:00
|
|
|
typedef typename ELFT::uint uintX_t;
|
2016-04-02 01:30:52 +08:00
|
|
|
typedef typename ELFT::Ehdr Elf_Ehdr;
|
2016-02-11 06:43:13 +08:00
|
|
|
|
2016-02-06 02:41:40 +08:00
|
|
|
// Create singleton output sections.
|
|
|
|
DynamicSection<ELFT> Dynamic(*Symtab);
|
|
|
|
EhFrameHeader<ELFT> EhFrameHdr;
|
2015-10-08 03:18:16 +08:00
|
|
|
GotSection<ELFT> Got;
|
2016-02-06 02:41:40 +08:00
|
|
|
InterpSection<ELFT> Interp;
|
2015-10-08 03:18:16 +08:00
|
|
|
PltSection<ELFT> Plt;
|
2016-05-10 23:47:57 +08:00
|
|
|
RelocationSection<ELFT> RelaDyn(Config->Rela ? ".rela.dyn" : ".rel.dyn",
|
|
|
|
Config->ZCombreloc);
|
2016-02-06 02:41:40 +08:00
|
|
|
StringTableSection<ELFT> DynStrTab(".dynstr", true);
|
|
|
|
StringTableSection<ELFT> ShStrTab(".shstrtab", false);
|
|
|
|
SymbolTableSection<ELFT> DynSymTab(*Symtab, DynStrTab);
|
2016-04-28 04:22:31 +08:00
|
|
|
VersionTableSection<ELFT> VerSym;
|
|
|
|
VersionNeedSection<ELFT> VerNeed;
|
2016-02-06 02:41:40 +08:00
|
|
|
|
2016-02-11 06:43:13 +08:00
|
|
|
OutputSectionBase<ELFT> ElfHeader("", 0, SHF_ALLOC);
|
2016-04-02 01:30:52 +08:00
|
|
|
ElfHeader.setSize(sizeof(Elf_Ehdr));
|
2016-02-11 06:43:13 +08:00
|
|
|
OutputSectionBase<ELFT> ProgramHeaders("", 0, SHF_ALLOC);
|
|
|
|
ProgramHeaders.updateAlign(sizeof(uintX_t));
|
|
|
|
|
2016-02-06 02:41:40 +08:00
|
|
|
// Instantiate optional output sections if they are needed.
|
ELF: Implement --build-id.
This patch implements --build-id. After the linker creates an output file
in the memory buffer, it computes the FNV1 hash of the resulting file
and set the hash to the .note section as a build-id.
GNU ld and gold have the same feature, but their default choice of the
hash function is different. Their default is SHA1.
We made a deliberate choice to not use a secure hash function for the
sake of performance. Computing a secure hash is slow -- for example,
MD5 throughput is usually 400 MB/s or so. SHA1 is slower than that.
As a result, if you pass --build-id to gold, then the linker becomes about
10% slower than that without the option. We observed a similar degradation
in an experimental implementation of build-id for LLD. On the other hand,
we observed only 1-2% performance degradation with the FNV hash.
Since build-id is not for digital certificate or anything, we think that
a very small probability of collision is acceptable.
We considered using other signals such as using input file timestamps as
inputs to a secure hash function. But such signals would have an issue
with build reproducibility (if you build a binary from the same source
tree using the same toolchain, the build id should become the same.)
GNU linkers accepts --build-id=<style> option where style is one of
"MD5", "SHA1", or an arbitrary hex string. That option is out of scope
of this patch.
http://reviews.llvm.org/D18091
llvm-svn: 263292
2016-03-12 04:51:53 +08:00
|
|
|
std::unique_ptr<BuildIdSection<ELFT>> BuildId;
|
2016-02-06 02:41:40 +08:00
|
|
|
std::unique_ptr<GnuHashTableSection<ELFT>> GnuHashTab;
|
|
|
|
std::unique_ptr<GotPltSection<ELFT>> GotPlt;
|
|
|
|
std::unique_ptr<HashTableSection<ELFT>> HashTab;
|
|
|
|
std::unique_ptr<RelocationSection<ELFT>> RelaPlt;
|
|
|
|
std::unique_ptr<StringTableSection<ELFT>> StrTab;
|
|
|
|
std::unique_ptr<SymbolTableSection<ELFT>> SymTabSec;
|
2016-02-26 07:54:49 +08:00
|
|
|
std::unique_ptr<OutputSection<ELFT>> MipsRldMap;
|
2016-02-06 02:41:40 +08:00
|
|
|
|
2016-04-08 06:49:21 +08:00
|
|
|
if (Config->BuildId == BuildIdKind::Fnv1)
|
|
|
|
BuildId.reset(new BuildIdFnv1<ELFT>);
|
|
|
|
else if (Config->BuildId == BuildIdKind::Md5)
|
|
|
|
BuildId.reset(new BuildIdMd5<ELFT>);
|
2016-04-08 07:51:56 +08:00
|
|
|
else if (Config->BuildId == BuildIdKind::Sha1)
|
|
|
|
BuildId.reset(new BuildIdSha1<ELFT>);
|
2016-04-08 06:49:21 +08:00
|
|
|
|
2016-02-06 02:41:40 +08:00
|
|
|
if (Config->GnuHash)
|
|
|
|
GnuHashTab.reset(new GnuHashTableSection<ELFT>);
|
|
|
|
if (Config->SysvHash)
|
|
|
|
HashTab.reset(new HashTableSection<ELFT>);
|
|
|
|
if (Target->UseLazyBinding) {
|
2016-03-14 04:10:20 +08:00
|
|
|
StringRef S = Config->Rela ? ".rela.plt" : ".rel.plt";
|
2016-02-06 02:41:40 +08:00
|
|
|
GotPlt.reset(new GotPltSection<ELFT>);
|
2016-05-10 23:47:57 +08:00
|
|
|
RelaPlt.reset(new RelocationSection<ELFT>(S, false /*Sort*/));
|
2016-02-06 02:41:40 +08:00
|
|
|
}
|
2015-10-24 16:52:46 +08:00
|
|
|
if (!Config->StripAll) {
|
2016-02-06 02:41:40 +08:00
|
|
|
StrTab.reset(new StringTableSection<ELFT>(".strtab", false));
|
|
|
|
SymTabSec.reset(new SymbolTableSection<ELFT>(*Symtab, *StrTab));
|
2015-10-24 16:52:46 +08:00
|
|
|
}
|
2016-02-26 07:54:49 +08:00
|
|
|
if (Config->EMachine == EM_MIPS && !Config->Shared) {
|
|
|
|
// 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
|
|
|
|
MipsRldMap.reset(new OutputSection<ELFT>(".rld_map", SHT_PROGBITS,
|
|
|
|
SHF_ALLOC | SHF_WRITE));
|
|
|
|
MipsRldMap->setSize(sizeof(uintX_t));
|
|
|
|
MipsRldMap->updateAlign(sizeof(uintX_t));
|
|
|
|
}
|
2016-02-06 02:41:40 +08:00
|
|
|
|
ELF: Implement --build-id.
This patch implements --build-id. After the linker creates an output file
in the memory buffer, it computes the FNV1 hash of the resulting file
and set the hash to the .note section as a build-id.
GNU ld and gold have the same feature, but their default choice of the
hash function is different. Their default is SHA1.
We made a deliberate choice to not use a secure hash function for the
sake of performance. Computing a secure hash is slow -- for example,
MD5 throughput is usually 400 MB/s or so. SHA1 is slower than that.
As a result, if you pass --build-id to gold, then the linker becomes about
10% slower than that without the option. We observed a similar degradation
in an experimental implementation of build-id for LLD. On the other hand,
we observed only 1-2% performance degradation with the FNV hash.
Since build-id is not for digital certificate or anything, we think that
a very small probability of collision is acceptable.
We considered using other signals such as using input file timestamps as
inputs to a secure hash function. But such signals would have an issue
with build reproducibility (if you build a binary from the same source
tree using the same toolchain, the build id should become the same.)
GNU linkers accepts --build-id=<style> option where style is one of
"MD5", "SHA1", or an arbitrary hex string. That option is out of scope
of this patch.
http://reviews.llvm.org/D18091
llvm-svn: 263292
2016-03-12 04:51:53 +08:00
|
|
|
Out<ELFT>::BuildId = BuildId.get();
|
2016-02-06 02:41:40 +08:00
|
|
|
Out<ELFT>::DynStrTab = &DynStrTab;
|
2015-10-08 03:18:16 +08:00
|
|
|
Out<ELFT>::DynSymTab = &DynSymTab;
|
|
|
|
Out<ELFT>::Dynamic = &Dynamic;
|
2016-01-15 21:34:52 +08:00
|
|
|
Out<ELFT>::EhFrameHdr = &EhFrameHdr;
|
2016-02-06 02:41:40 +08:00
|
|
|
Out<ELFT>::GnuHashTab = GnuHashTab.get();
|
|
|
|
Out<ELFT>::Got = &Got;
|
|
|
|
Out<ELFT>::GotPlt = GotPlt.get();
|
|
|
|
Out<ELFT>::HashTab = HashTab.get();
|
|
|
|
Out<ELFT>::Interp = &Interp;
|
|
|
|
Out<ELFT>::Plt = &Plt;
|
|
|
|
Out<ELFT>::RelaDyn = &RelaDyn;
|
|
|
|
Out<ELFT>::RelaPlt = RelaPlt.get();
|
|
|
|
Out<ELFT>::ShStrTab = &ShStrTab;
|
|
|
|
Out<ELFT>::StrTab = StrTab.get();
|
|
|
|
Out<ELFT>::SymTab = SymTabSec.get();
|
2016-04-28 04:22:31 +08:00
|
|
|
Out<ELFT>::VerSym = &VerSym;
|
|
|
|
Out<ELFT>::VerNeed = &VerNeed;
|
2016-02-06 02:41:40 +08:00
|
|
|
Out<ELFT>::Bss = nullptr;
|
2016-02-26 07:54:49 +08:00
|
|
|
Out<ELFT>::MipsRldMap = MipsRldMap.get();
|
2016-02-06 02:41:40 +08:00
|
|
|
Out<ELFT>::Opd = nullptr;
|
|
|
|
Out<ELFT>::OpdBuf = nullptr;
|
|
|
|
Out<ELFT>::TlsPhdr = nullptr;
|
2016-02-11 06:43:13 +08:00
|
|
|
Out<ELFT>::ElfHeader = &ElfHeader;
|
|
|
|
Out<ELFT>::ProgramHeaders = &ProgramHeaders;
|
2015-10-08 03:18:16 +08:00
|
|
|
|
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-12-26 15:50:39 +08:00
|
|
|
addReservedSymbols();
|
2016-04-02 01:24:19 +08:00
|
|
|
createSections();
|
|
|
|
if (HasError)
|
2016-01-29 06:56:29 +08:00
|
|
|
return;
|
2016-04-02 01:07:17 +08:00
|
|
|
|
|
|
|
if (Config->Relocatable) {
|
|
|
|
assignFileOffsets();
|
|
|
|
} else {
|
2016-02-25 16:23:37 +08:00
|
|
|
createPhdrs();
|
2016-04-06 15:20:45 +08:00
|
|
|
fixHeaders();
|
2016-04-21 04:13:41 +08:00
|
|
|
if (ScriptConfig->DoLayout) {
|
|
|
|
Script<ELFT>::X->assignAddresses(OutputSections);
|
2016-04-16 18:10:32 +08:00
|
|
|
} else {
|
|
|
|
fixSectionAlignments();
|
|
|
|
assignAddresses();
|
|
|
|
}
|
2016-04-02 01:07:17 +08:00
|
|
|
assignFileOffsets();
|
|
|
|
setPhdrs();
|
2016-04-02 01:11:42 +08:00
|
|
|
fixAbsoluteSymbols();
|
2016-02-25 16:23:37 +08:00
|
|
|
}
|
2016-04-02 01:07:17 +08:00
|
|
|
|
2016-04-02 01:24:19 +08:00
|
|
|
openFile();
|
|
|
|
if (HasError)
|
2016-02-03 06:48:04 +08:00
|
|
|
return;
|
2015-07-25 05:03:07 +08:00
|
|
|
writeHeader();
|
|
|
|
writeSections();
|
ELF: Implement --build-id.
This patch implements --build-id. After the linker creates an output file
in the memory buffer, it computes the FNV1 hash of the resulting file
and set the hash to the .note section as a build-id.
GNU ld and gold have the same feature, but their default choice of the
hash function is different. Their default is SHA1.
We made a deliberate choice to not use a secure hash function for the
sake of performance. Computing a secure hash is slow -- for example,
MD5 throughput is usually 400 MB/s or so. SHA1 is slower than that.
As a result, if you pass --build-id to gold, then the linker becomes about
10% slower than that without the option. We observed a similar degradation
in an experimental implementation of build-id for LLD. On the other hand,
we observed only 1-2% performance degradation with the FNV hash.
Since build-id is not for digital certificate or anything, we think that
a very small probability of collision is acceptable.
We considered using other signals such as using input file timestamps as
inputs to a secure hash function. But such signals would have an issue
with build reproducibility (if you build a binary from the same source
tree using the same toolchain, the build id should become the same.)
GNU linkers accepts --build-id=<style> option where style is one of
"MD5", "SHA1", or an arbitrary hex string. That option is out of scope
of this patch.
http://reviews.llvm.org/D18091
llvm-svn: 263292
2016-03-12 04:51:53 +08:00
|
|
|
writeBuildId();
|
2016-02-02 07:28:21 +08:00
|
|
|
if (HasError)
|
|
|
|
return;
|
2016-03-04 06:24:39 +08:00
|
|
|
check(Buffer->commit());
|
2015-07-25 05:03:07 +08:00
|
|
|
}
|
|
|
|
|
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;
|
2016-02-19 22:17:40 +08:00
|
|
|
uintX_t Alignment;
|
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) {
|
2016-02-19 22:17:40 +08:00
|
|
|
return hash_combine(Val.Name, Val.Type, Val.Flags, Val.Alignment);
|
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 &&
|
2016-02-19 22:17:40 +08:00
|
|
|
LHS.Alignment == RHS.Alignment;
|
2015-08-14 01:04:50 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2016-03-22 21:24:29 +08:00
|
|
|
// Returns the number of relocations processed.
|
2016-04-13 09:40:19 +08:00
|
|
|
template <class ELFT>
|
2016-03-22 21:24:29 +08:00
|
|
|
static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body,
|
2016-04-13 09:40:19 +08:00
|
|
|
InputSectionBase<ELFT> &C,
|
|
|
|
typename ELFT::uint Offset,
|
|
|
|
typename ELFT::uint Addend, RelExpr Expr) {
|
|
|
|
if (!(C.getSectionHdr()->sh_flags & SHF_ALLOC))
|
|
|
|
return 0;
|
|
|
|
|
2016-04-20 22:52:18 +08:00
|
|
|
if (!Body.isTls())
|
|
|
|
return 0;
|
|
|
|
|
2016-04-07 23:20:56 +08:00
|
|
|
typedef typename ELFT::uint uintX_t;
|
2016-04-18 09:34:20 +08:00
|
|
|
if (Expr == R_TLSLD_PC || Expr == R_TLSLD) {
|
2016-04-20 23:01:42 +08:00
|
|
|
// Local-Dynamic relocs can be relaxed to Local-Exec.
|
|
|
|
if (!Config->Shared) {
|
2016-04-13 09:40:19 +08:00
|
|
|
C.Relocations.push_back(
|
|
|
|
{R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Body});
|
2016-04-02 08:19:22 +08:00
|
|
|
return 2;
|
2016-04-13 09:40:19 +08:00
|
|
|
}
|
2016-02-05 08:10:02 +08:00
|
|
|
if (Out<ELFT>::Got->addTlsIndex())
|
2016-04-07 23:20:56 +08:00
|
|
|
Out<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel, Out<ELFT>::Got,
|
|
|
|
Out<ELFT>::Got->getTlsIndexOff(), false,
|
|
|
|
nullptr, 0});
|
2016-04-13 09:40:19 +08:00
|
|
|
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
|
2016-03-22 21:24:29 +08:00
|
|
|
return 1;
|
2016-01-21 17:14:22 +08:00
|
|
|
}
|
|
|
|
|
2016-04-20 23:01:42 +08:00
|
|
|
// Local-Dynamic relocs can be relaxed to Local-Exec.
|
|
|
|
if (Target->isTlsLocalDynamicRel(Type) && !Config->Shared) {
|
2016-04-13 09:40:19 +08:00
|
|
|
C.Relocations.push_back(
|
|
|
|
{R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Body});
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-01-29 10:33:45 +08:00
|
|
|
if (Target->isTlsGlobalDynamicRel(Type)) {
|
2016-04-20 23:01:42 +08:00
|
|
|
if (Config->Shared) {
|
2016-02-23 03:57:55 +08:00
|
|
|
if (Out<ELFT>::Got->addDynTlsEntry(Body)) {
|
2016-04-07 23:20:56 +08:00
|
|
|
uintX_t Off = Out<ELFT>::Got->getGlobalDynOffset(Body);
|
2016-02-23 03:57:55 +08:00
|
|
|
Out<ELFT>::RelaDyn->addReloc(
|
2016-04-07 23:20:56 +08:00
|
|
|
{Target->TlsModuleIndexRel, Out<ELFT>::Got, Off, false, &Body, 0});
|
|
|
|
Out<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, Out<ELFT>::Got,
|
|
|
|
Off + (uintX_t)sizeof(uintX_t), false,
|
|
|
|
&Body, 0});
|
2016-02-23 03:57:55 +08:00
|
|
|
}
|
2016-04-13 09:40:19 +08:00
|
|
|
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
|
2016-03-22 21:24:29 +08:00
|
|
|
return 1;
|
2016-01-21 17:14:22 +08:00
|
|
|
}
|
2016-04-13 09:40:19 +08:00
|
|
|
|
2016-04-20 23:01:42 +08:00
|
|
|
// Global-Dynamic relocs can be relaxed to Initial-Exec or Local-Exec
|
|
|
|
// depending on the symbol being locally defined or not.
|
2016-04-13 09:40:19 +08:00
|
|
|
if (Body.isPreemptible()) {
|
2016-04-18 09:29:15 +08:00
|
|
|
Expr =
|
|
|
|
Expr == R_TLSGD_PC ? R_RELAX_TLS_GD_TO_IE_PC : R_RELAX_TLS_GD_TO_IE;
|
2016-04-13 09:40:19 +08:00
|
|
|
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
|
|
|
|
if (!Body.isInGot()) {
|
|
|
|
Out<ELFT>::Got->addEntry(Body);
|
|
|
|
Out<ELFT>::RelaDyn->addReloc({Target->TlsGotRel, Out<ELFT>::Got,
|
|
|
|
Body.getGotOffset<ELFT>(), false, &Body,
|
|
|
|
0});
|
|
|
|
}
|
2016-04-02 07:36:56 +08:00
|
|
|
return 2;
|
2016-04-01 20:54:27 +08:00
|
|
|
}
|
2016-04-13 09:40:19 +08:00
|
|
|
C.Relocations.push_back(
|
|
|
|
{R_RELAX_TLS_GD_TO_LE, Type, Offset, Addend, &Body});
|
|
|
|
return Target->TlsGdToLeSkip;
|
|
|
|
}
|
2016-04-20 23:01:42 +08:00
|
|
|
|
|
|
|
// Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally
|
|
|
|
// defined.
|
|
|
|
if (Target->isTlsInitialExecRel(Type) && !Config->Shared &&
|
|
|
|
!Body.isPreemptible()) {
|
2016-04-13 09:40:19 +08:00
|
|
|
C.Relocations.push_back(
|
|
|
|
{R_RELAX_TLS_IE_TO_LE, Type, Offset, Addend, &Body});
|
|
|
|
return 1;
|
2016-01-21 17:14:22 +08:00
|
|
|
}
|
2016-03-22 21:24:29 +08:00
|
|
|
return 0;
|
2016-01-21 17:14:22 +08:00
|
|
|
}
|
|
|
|
|
2016-04-01 05:26:23 +08:00
|
|
|
// Some targets might require creation of thunks for relocations. Now we
|
|
|
|
// support only MIPS which requires LA25 thunk to call PIC code from non-PIC
|
|
|
|
// one. Scan relocations to find each one requires thunk.
|
|
|
|
template <class ELFT>
|
|
|
|
template <class RelTy>
|
|
|
|
void Writer<ELFT>::scanRelocsForThunks(const elf::ObjectFile<ELFT> &File,
|
2016-04-05 22:47:28 +08:00
|
|
|
ArrayRef<RelTy> Rels) {
|
2016-04-01 05:26:23 +08:00
|
|
|
for (const RelTy &RI : Rels) {
|
|
|
|
uint32_t Type = RI.getType(Config->Mips64EL);
|
2016-04-27 07:52:44 +08:00
|
|
|
SymbolBody &Body = File.getRelocTargetSym(RI);
|
2016-04-01 05:26:23 +08:00
|
|
|
if (Body.hasThunk() || !Target->needsThunk(Type, File, Body))
|
|
|
|
continue;
|
|
|
|
auto *D = cast<DefinedRegular<ELFT>>(&Body);
|
|
|
|
auto *S = cast<InputSection<ELFT>>(D->Section);
|
|
|
|
S->addThunk(Body);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-13 09:40:19 +08:00
|
|
|
template <endianness E> static int16_t readSignedLo16(const uint8_t *Loc) {
|
|
|
|
return read32<E>(Loc) & 0xffff;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class RelTy>
|
|
|
|
static uint32_t getMipsPairType(const RelTy *Rel, const SymbolBody &Sym) {
|
|
|
|
switch (Rel->getType(Config->Mips64EL)) {
|
|
|
|
case R_MIPS_HI16:
|
|
|
|
return R_MIPS_LO16;
|
|
|
|
case R_MIPS_GOT16:
|
|
|
|
return Sym.isLocal() ? R_MIPS_LO16 : R_MIPS_NONE;
|
|
|
|
case R_MIPS_PCHI16:
|
|
|
|
return R_MIPS_PCLO16;
|
|
|
|
case R_MICROMIPS_HI16:
|
|
|
|
return R_MICROMIPS_LO16;
|
|
|
|
default:
|
|
|
|
return R_MIPS_NONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class ELFT, class RelTy>
|
|
|
|
static int32_t findMipsPairedAddend(const uint8_t *Buf, const uint8_t *BufLoc,
|
|
|
|
SymbolBody &Sym, const RelTy *Rel,
|
|
|
|
const RelTy *End) {
|
|
|
|
uint32_t SymIndex = Rel->getSymbol(Config->Mips64EL);
|
|
|
|
uint32_t Type = getMipsPairType(Rel, Sym);
|
|
|
|
|
|
|
|
// Some MIPS relocations use addend calculated from addend of the relocation
|
|
|
|
// itself and addend of paired relocation. ABI requires to compute such
|
|
|
|
// combined addend in case of REL relocation record format only.
|
|
|
|
// See p. 4-17 at ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
|
|
|
|
if (RelTy::IsRela || Type == R_MIPS_NONE)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (const RelTy *RI = Rel; RI != End; ++RI) {
|
|
|
|
if (RI->getType(Config->Mips64EL) != Type)
|
|
|
|
continue;
|
|
|
|
if (RI->getSymbol(Config->Mips64EL) != SymIndex)
|
|
|
|
continue;
|
|
|
|
const endianness E = ELFT::TargetEndianness;
|
|
|
|
return ((read32<E>(BufLoc) & 0xffff) << 16) +
|
|
|
|
readSignedLo16<E>(Buf + RI->r_offset);
|
|
|
|
}
|
|
|
|
unsigned OldType = Rel->getType(Config->Mips64EL);
|
|
|
|
StringRef OldName = getELFRelocationTypeName(Config->EMachine, OldType);
|
|
|
|
StringRef NewName = getELFRelocationTypeName(Config->EMachine, Type);
|
|
|
|
warning("can't find matching " + NewName + " relocation for " + OldName);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-04-15 20:22:22 +08:00
|
|
|
// True if non-preemptable symbol always has the same value regardless of where
|
|
|
|
// the DSO is loaded.
|
|
|
|
template <class ELFT> static bool isAbsolute(const SymbolBody &Body) {
|
ELF: New symbol table design.
This patch implements a new design for the symbol table that stores
SymbolBodies within a memory region of the Symbol object. Symbols are mutated
by constructing SymbolBodies in place over existing SymbolBodies, rather
than by mutating pointers. As mentioned in the initial proposal [1], this
memory layout helps reduce the cache miss rate by improving memory locality.
Performance numbers:
old(s) new(s)
Without debug info:
chrome 7.178 6.432 (-11.5%)
LLVMgold.so 0.505 0.502 (-0.5%)
clang 0.954 0.827 (-15.4%)
llvm-as 0.052 0.045 (-15.5%)
With debug info:
scylla 5.695 5.613 (-1.5%)
clang 14.396 14.143 (-1.8%)
Performance counter results show that the fewer required indirections is
indeed the cause of the improved performance. For example, when linking
chrome, stalled cycles decreases from 14,556,444,002 to 12,959,238,310, and
instructions per cycle increases from 0.78 to 0.83. We are also executing
many fewer instructions (15,516,401,933 down to 15,002,434,310), probably
because we spend less time allocating SymbolBodies.
The new mechanism by which symbols are added to the symbol table is by calling
add* functions on the SymbolTable.
In this patch, I handle local symbols by storing them inside "unparented"
SymbolBodies. This is suboptimal, but if we do want to try to avoid allocating
these SymbolBodies, we can probably do that separately.
I also removed a few members from the SymbolBody class that were only being
used to pass information from the input file to the symbol table.
This patch implements the new design for the ELF linker only. I intend to
prepare a similar patch for the COFF linker.
[1] http://lists.llvm.org/pipermail/llvm-dev/2016-April/098832.html
Differential Revision: http://reviews.llvm.org/D19752
llvm-svn: 268178
2016-05-01 12:55:03 +08:00
|
|
|
if (Body.isUndefined())
|
|
|
|
return !Body.isLocal() && Body.symbol()->isWeak();
|
2016-04-15 20:22:22 +08:00
|
|
|
if (const auto *DR = dyn_cast<DefinedRegular<ELFT>>(&Body))
|
|
|
|
return DR->Section == nullptr; // Absolute symbol.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-04-22 01:30:24 +08:00
|
|
|
static bool needsPlt(RelExpr Expr) {
|
|
|
|
return Expr == R_PLT_PC || Expr == R_PPC_PLT_OPD || Expr == R_PLT;
|
|
|
|
}
|
|
|
|
|
2016-05-06 05:19:38 +08:00
|
|
|
// True if this expression is of the form Sym - X, where X is a position in the
|
|
|
|
// file (PC, or GOT for example).
|
|
|
|
static bool isRelExpr(RelExpr Expr) {
|
|
|
|
return Expr == R_PC || Expr == R_GOTREL || Expr == R_PAGE_PC;
|
|
|
|
}
|
|
|
|
|
2016-04-27 20:47:30 +08:00
|
|
|
template <class ELFT>
|
2016-05-05 05:28:56 +08:00
|
|
|
static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type,
|
|
|
|
const SymbolBody &Body) {
|
2016-05-05 05:40:07 +08:00
|
|
|
// These expressions always compute a constant
|
|
|
|
if (E == R_SIZE || E == R_GOT_FROM_END || E == R_GOT_OFF || E == R_MIPS_GOT ||
|
|
|
|
E == R_MIPS_GOT_LOCAL || E == R_GOT_PAGE_PC || E == R_GOT_PC ||
|
|
|
|
E == R_PLT_PC || E == R_TLSGD_PC || E == R_TLSGD || E == R_PPC_PLT_OPD)
|
2016-04-27 20:47:30 +08:00
|
|
|
return true;
|
|
|
|
|
2016-05-05 05:40:07 +08:00
|
|
|
// These never do, except if the entire file is position dependent or if
|
|
|
|
// only the low bits are used.
|
|
|
|
if (E == R_GOT || E == R_PLT)
|
|
|
|
return Target->usesOnlyLowPageBits(Type) || !Config->Pic;
|
2016-04-27 20:47:30 +08:00
|
|
|
|
2016-05-05 05:40:07 +08:00
|
|
|
if (Body.isPreemptible())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!Config->Pic)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
bool AbsVal = isAbsolute<ELFT>(Body) || Body.isTls();
|
2016-05-06 05:19:38 +08:00
|
|
|
bool RelE = isRelExpr(E);
|
2016-04-27 20:47:30 +08:00
|
|
|
if (AbsVal && !RelE)
|
|
|
|
return true;
|
|
|
|
if (!AbsVal && RelE)
|
|
|
|
return true;
|
|
|
|
|
2016-05-03 09:21:08 +08:00
|
|
|
// Relative relocation to an absolute value. This is normally unrepresentable,
|
|
|
|
// but if the relocation refers to a weak undefined symbol, we allow it to
|
|
|
|
// resolve to the image base. This is a little strange, but it allows us to
|
|
|
|
// link function calls to such symbols. Normally such a call will be guarded
|
|
|
|
// with a comparison, which will load a zero from the GOT.
|
|
|
|
if (AbsVal && RelE) {
|
|
|
|
if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak())
|
|
|
|
return true;
|
|
|
|
StringRef S = getELFRelocationTypeName(Config->EMachine, Type);
|
|
|
|
error("relocation " + S + " cannot refer to absolute symbol " +
|
|
|
|
Body.getName());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-04-28 22:34:39 +08:00
|
|
|
return Target->usesOnlyLowPageBits(Type);
|
2016-04-27 20:47:30 +08:00
|
|
|
}
|
|
|
|
|
2016-04-30 09:15:17 +08:00
|
|
|
static RelExpr toPlt(RelExpr Expr) {
|
|
|
|
if (Expr == R_PPC_OPD)
|
|
|
|
return R_PPC_PLT_OPD;
|
|
|
|
if (Expr == R_PC)
|
|
|
|
return R_PLT_PC;
|
|
|
|
if (Expr == R_ABS)
|
|
|
|
return R_PLT;
|
|
|
|
return Expr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static RelExpr fromPlt(RelExpr Expr) {
|
|
|
|
// We decided not to use a plt. Optimize a reference to the plt to a
|
|
|
|
// reference to the symbol itself.
|
|
|
|
if (Expr == R_PLT_PC)
|
|
|
|
return R_PC;
|
|
|
|
if (Expr == R_PPC_PLT_OPD)
|
|
|
|
return R_PPC_OPD;
|
|
|
|
if (Expr == R_PLT)
|
|
|
|
return R_ABS;
|
|
|
|
return Expr;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class ELFT>
|
2016-05-13 05:51:16 +08:00
|
|
|
RelExpr Writer<ELFT>::adjustExpr(SymbolBody &Body, bool IsWrite, RelExpr Expr,
|
2016-04-30 09:15:17 +08:00
|
|
|
uint32_t Type) {
|
|
|
|
bool Preemptible = Body.isPreemptible();
|
2016-05-05 05:40:07 +08:00
|
|
|
if (Body.isGnuIFunc())
|
|
|
|
Expr = toPlt(Expr);
|
|
|
|
else if (needsPlt(Expr) && !Preemptible)
|
|
|
|
Expr = fromPlt(Expr);
|
2016-04-30 09:15:17 +08:00
|
|
|
|
2016-05-05 05:40:07 +08:00
|
|
|
if (IsWrite || isStaticLinkTimeConstant<ELFT>(Expr, Type, Body))
|
2016-05-05 05:09:24 +08:00
|
|
|
return Expr;
|
|
|
|
|
|
|
|
// This relocation would require the dynamic linker to write a value to read
|
|
|
|
// only memory. We can hack around it if we are producing an executable and
|
|
|
|
// the refered symbol can be preemepted to refer to the executable.
|
2016-05-06 05:19:38 +08:00
|
|
|
if (Config->Shared || (Config->Pic && !isRelExpr(Expr))) {
|
2016-05-05 05:09:24 +08:00
|
|
|
StringRef S = getELFRelocationTypeName(Config->EMachine, Type);
|
|
|
|
error("relocation " + S + " cannot be used when making a shared "
|
|
|
|
"object; recompile with -fPIC.");
|
|
|
|
return Expr;
|
|
|
|
}
|
|
|
|
if (Body.getVisibility() != STV_DEFAULT) {
|
|
|
|
error("Cannot preempt symbol");
|
|
|
|
return Expr;
|
|
|
|
}
|
|
|
|
if (Body.isObject()) {
|
|
|
|
// Produce a copy relocation.
|
|
|
|
auto *B = cast<SharedSymbol<ELFT>>(&Body);
|
|
|
|
if (!B->needsCopy())
|
|
|
|
addCopyRelSymbol(B);
|
|
|
|
return Expr;
|
2016-04-30 09:15:17 +08:00
|
|
|
}
|
2016-05-05 05:09:24 +08:00
|
|
|
if (Body.isFunc()) {
|
|
|
|
// This handles a non PIC program call to function in a shared library. In
|
|
|
|
// an ideal world, we could just report an error saying the relocation can
|
|
|
|
// overflow at runtime. In the real world with glibc, crt1.o has a
|
|
|
|
// R_X86_64_PC32 pointing to libc.so.
|
|
|
|
//
|
|
|
|
// The general idea on how to handle such cases is to create a PLT entry and
|
|
|
|
// use that as the function value.
|
|
|
|
//
|
|
|
|
// For the static linking part, we just return a plt expr and everything
|
|
|
|
// else will use the the PLT entry as the address.
|
|
|
|
//
|
|
|
|
// The remaining problem is making sure pointer equality still works. We
|
|
|
|
// need the help of the dynamic linker for that. We let it know that we have
|
|
|
|
// a direct reference to a so symbol by creating an undefined symbol with a
|
|
|
|
// non zero st_value. Seeing that, the dynamic linker resolves the symbol to
|
|
|
|
// the value of the symbol we created. This is true even for got entries, so
|
|
|
|
// pointer equality is maintained. To avoid an infinite loop, the only entry
|
|
|
|
// that points to the real function is a dedicated got entry used by the
|
|
|
|
// plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT,
|
|
|
|
// R_386_JMP_SLOT, etc).
|
|
|
|
Body.NeedsCopyOrPltAddr = true;
|
|
|
|
return toPlt(Expr);
|
|
|
|
}
|
|
|
|
error("Symbol is missing type");
|
|
|
|
|
2016-04-30 09:15:17 +08:00
|
|
|
return Expr;
|
|
|
|
}
|
|
|
|
|
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.
|
2016-02-02 23:45:37 +08:00
|
|
|
// This would have some drawbacks. For example, we would only know if .rela.dyn
|
|
|
|
// is needed after applying relocations. If it is, it will go after rw and rx
|
|
|
|
// sections. Given that it is ro, we will need an extra PT_LOAD. This
|
|
|
|
// complicates things for the dynamic linker and means we would have to reserve
|
|
|
|
// space for the extra PT_LOAD even if we end up not using it.
|
2015-09-17 22:02:10 +08:00
|
|
|
template <class ELFT>
|
2016-03-13 13:06:50 +08:00
|
|
|
template <class RelTy>
|
2016-04-05 22:47:28 +08:00
|
|
|
void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
|
2016-04-14 09:48:11 +08:00
|
|
|
uintX_t Flags = C.getSectionHdr()->sh_flags;
|
|
|
|
bool IsWrite = Flags & SHF_WRITE;
|
2016-04-13 09:40:19 +08:00
|
|
|
|
|
|
|
auto AddDyn = [=](const DynamicReloc<ELFT> &Reloc) {
|
2016-04-29 02:42:04 +08:00
|
|
|
Out<ELFT>::RelaDyn->addReloc(Reloc);
|
2016-04-13 09:40:19 +08:00
|
|
|
};
|
|
|
|
|
2016-03-12 02:56:05 +08:00
|
|
|
const elf::ObjectFile<ELFT> &File = *C.getFile();
|
2016-04-13 09:40:19 +08:00
|
|
|
ArrayRef<uint8_t> SectionData = C.getSectionData();
|
|
|
|
const uint8_t *Buf = SectionData.begin();
|
2016-03-22 21:24:29 +08:00
|
|
|
for (auto I = Rels.begin(), E = Rels.end(); I != E; ++I) {
|
|
|
|
const RelTy &RI = *I;
|
2016-04-27 07:52:44 +08:00
|
|
|
SymbolBody &Body = File.getRelocTargetSym(RI);
|
2015-10-17 06:51:43 +08:00
|
|
|
uint32_t Type = RI.getType(Config->Mips64EL);
|
2015-10-12 04:59:12 +08:00
|
|
|
|
2016-05-04 22:44:22 +08:00
|
|
|
RelExpr Expr = Target->getRelExpr(Type, Body);
|
2016-01-15 04:42:09 +08:00
|
|
|
// Ignore "hint" relocation because it is for optional code optimization.
|
2016-05-04 22:44:22 +08:00
|
|
|
if (Expr == R_HINT)
|
2016-01-15 04:42:09 +08:00
|
|
|
continue;
|
|
|
|
|
2016-04-07 22:22:09 +08:00
|
|
|
uintX_t Offset = C.getOffset(RI.r_offset);
|
|
|
|
if (Offset == (uintX_t)-1)
|
|
|
|
continue;
|
|
|
|
|
2016-05-06 03:41:49 +08:00
|
|
|
bool Preemptible = Body.isPreemptible();
|
2016-05-13 05:51:16 +08:00
|
|
|
Expr = adjustExpr(Body, IsWrite, Expr, Type);
|
2016-04-30 09:15:17 +08:00
|
|
|
if (HasError)
|
|
|
|
continue;
|
|
|
|
|
2016-04-18 20:31:37 +08:00
|
|
|
// This relocation does not require got entry, but it is relative to got and
|
|
|
|
// needs it to be created. Here we request for that.
|
2016-04-27 20:21:27 +08:00
|
|
|
if (Expr == R_GOTONLY_PC || Expr == R_GOTREL || Expr == R_PPC_TOC)
|
2016-04-18 20:31:37 +08:00
|
|
|
HasGotOffRel = true;
|
|
|
|
|
2016-04-13 09:40:19 +08:00
|
|
|
uintX_t Addend = getAddend<ELFT>(RI);
|
|
|
|
const uint8_t *BufLoc = Buf + RI.r_offset;
|
|
|
|
if (!RelTy::IsRela)
|
|
|
|
Addend += Target->getImplicitAddend(BufLoc, Type);
|
2016-04-15 05:10:05 +08:00
|
|
|
if (Config->EMachine == EM_MIPS) {
|
2016-04-13 09:40:19 +08:00
|
|
|
Addend += findMipsPairedAddend<ELFT>(Buf, BufLoc, Body, &RI, E);
|
2016-04-15 05:10:05 +08:00
|
|
|
if (Type == R_MIPS_LO16 && Expr == R_PC)
|
|
|
|
// R_MIPS_LO16 expression has R_PC type iif the target is _gp_disp
|
|
|
|
// symbol. In that case we should use the following formula for
|
2016-05-02 17:49:03 +08:00
|
|
|
// calculation "AHL + GP - P + 4". Let's add 4 right here.
|
2016-04-15 05:10:05 +08:00
|
|
|
// For details see p. 4-19 at
|
|
|
|
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
|
|
|
|
Addend += 4;
|
|
|
|
}
|
2016-04-13 09:40:19 +08:00
|
|
|
|
|
|
|
if (unsigned Processed =
|
|
|
|
handleTlsRelocation<ELFT>(Type, Body, C, Offset, Addend, Expr)) {
|
2016-03-22 21:24:29 +08:00
|
|
|
I += (Processed - 1);
|
2015-11-14 00:28:53 +08:00
|
|
|
continue;
|
2016-03-22 21:24:29 +08:00
|
|
|
}
|
2015-11-14 00:28:53 +08:00
|
|
|
|
2016-05-05 05:28:56 +08:00
|
|
|
if (Expr == R_GOT && !isStaticLinkTimeConstant<ELFT>(Expr, Type, Body) &&
|
2016-04-27 20:47:30 +08:00
|
|
|
Config->Shared)
|
2016-04-13 09:40:19 +08:00
|
|
|
AddDyn({Target->RelativeRel, C.OutSec, Offset, true, &Body,
|
|
|
|
getAddend<ELFT>(RI)});
|
2015-12-17 17:32:21 +08:00
|
|
|
|
2016-02-02 15:07:34 +08:00
|
|
|
// If a relocation needs PLT, we create a PLT and a GOT slot
|
|
|
|
// for the symbol.
|
2016-04-30 09:15:17 +08:00
|
|
|
if (needsPlt(Expr)) {
|
|
|
|
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
|
2016-04-13 09:40:19 +08:00
|
|
|
|
2016-03-11 20:06:30 +08:00
|
|
|
if (Body.isInPlt())
|
2016-02-02 15:07:34 +08:00
|
|
|
continue;
|
|
|
|
Out<ELFT>::Plt->addEntry(Body);
|
2016-02-02 13:55:28 +08:00
|
|
|
|
2016-04-01 22:14:48 +08:00
|
|
|
uint32_t Rel;
|
2016-04-04 22:04:16 +08:00
|
|
|
if (Body.isGnuIFunc())
|
2016-04-01 22:14:48 +08:00
|
|
|
Rel = Preemptible ? Target->PltRel : Target->IRelativeRel;
|
|
|
|
else
|
|
|
|
Rel = Target->UseLazyBinding ? Target->PltRel : Target->GotRel;
|
|
|
|
|
2016-02-02 15:07:34 +08:00
|
|
|
if (Target->UseLazyBinding) {
|
|
|
|
Out<ELFT>::GotPlt->addEntry(Body);
|
2016-04-29 02:42:04 +08:00
|
|
|
Out<ELFT>::RelaPlt->addReloc({Rel, Out<ELFT>::GotPlt,
|
|
|
|
Body.getGotPltOffset<ELFT>(),
|
|
|
|
!Preemptible, &Body, 0});
|
2016-02-02 15:07:34 +08:00
|
|
|
} else {
|
2016-03-11 20:06:30 +08:00
|
|
|
if (Body.isInGot())
|
2015-10-06 03:30:12 +08:00
|
|
|
continue;
|
2016-02-02 15:07:34 +08:00
|
|
|
Out<ELFT>::Got->addEntry(Body);
|
2016-04-13 09:40:19 +08:00
|
|
|
AddDyn({Rel, Out<ELFT>::Got, Body.getGotOffset<ELFT>(), !Preemptible,
|
|
|
|
&Body, 0});
|
2015-10-14 00:59:30 +08:00
|
|
|
}
|
2016-02-02 15:07:34 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-05-13 05:51:16 +08:00
|
|
|
if (Target->needsThunk(Type, File, Body)) {
|
|
|
|
C.Relocations.push_back({R_THUNK, Type, Offset, Addend, &Body});
|
2016-04-13 09:40:19 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-02-02 15:07:35 +08:00
|
|
|
// If a relocation needs GOT, we create a GOT slot for the symbol.
|
2016-04-21 01:30:22 +08:00
|
|
|
if (refersToGotEntry(Expr)) {
|
2016-04-20 06:46:03 +08:00
|
|
|
if (Config->EMachine == EM_MIPS && Expr == R_GOT_OFF)
|
|
|
|
Addend -= MipsGPOffset;
|
2016-05-04 23:51:23 +08:00
|
|
|
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
|
2016-03-11 20:06:30 +08:00
|
|
|
if (Body.isInGot())
|
2016-02-02 15:07:35 +08:00
|
|
|
continue;
|
|
|
|
Out<ELFT>::Got->addEntry(Body);
|
2016-02-02 15:07:34 +08:00
|
|
|
|
2016-03-22 16:36:48 +08:00
|
|
|
if (Config->EMachine == EM_MIPS)
|
2016-02-02 15:07:35 +08:00
|
|
|
// 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
|
|
|
|
continue;
|
|
|
|
|
2016-04-15 20:44:43 +08:00
|
|
|
if (Preemptible || (Config->Pic && !isAbsolute<ELFT>(Body))) {
|
2016-02-05 05:33:05 +08:00
|
|
|
uint32_t DynType;
|
2016-04-04 22:04:16 +08:00
|
|
|
if (Body.isTls())
|
2016-03-12 02:33:48 +08:00
|
|
|
DynType = Target->TlsGotRel;
|
2016-03-14 03:48:18 +08:00
|
|
|
else if (Preemptible)
|
2016-03-12 02:33:48 +08:00
|
|
|
DynType = Target->GotRel;
|
2016-02-05 05:33:05 +08:00
|
|
|
else
|
|
|
|
DynType = Target->RelativeRel;
|
2016-04-13 09:40:19 +08:00
|
|
|
AddDyn({DynType, Out<ELFT>::Got, Body.getGotOffset<ELFT>(),
|
|
|
|
!Preemptible, &Body, 0});
|
2016-02-05 05:33:05 +08:00
|
|
|
}
|
2016-02-02 15:07:35 +08:00
|
|
|
continue;
|
2015-10-06 03:30:12 +08:00
|
|
|
}
|
2015-10-12 04:59:12 +08:00
|
|
|
|
2016-05-06 03:41:49 +08:00
|
|
|
if (Body.isPreemptible()) {
|
2016-02-05 05:33:05 +08:00
|
|
|
// We don't know anything about the finaly symbol. Just ask the dynamic
|
|
|
|
// linker to handle the relocation for us.
|
2016-04-13 09:40:19 +08:00
|
|
|
AddDyn({Target->getDynRel(Type), C.OutSec, Offset, false, &Body, Addend});
|
2016-04-21 05:40:33 +08:00
|
|
|
// MIPS ABI turns using of GOT and dynamic relocations inside out.
|
|
|
|
// While regular ABI uses dynamic relocations to fill up GOT entries
|
|
|
|
// MIPS ABI requires dynamic linker to fills up GOT entries using
|
|
|
|
// specially sorted dynamic symbol table. This affects even dynamic
|
|
|
|
// relocations against symbols which do not require GOT entries
|
|
|
|
// creation explicitly, i.e. do not have any GOT-relocations. So if
|
|
|
|
// a preemptible symbol has a dynamic relocation we anyway have
|
|
|
|
// to create a GOT entry for it.
|
|
|
|
// If a non-preemptible symbol has a dynamic relocation against it,
|
|
|
|
// dynamic linker takes it st_value, adds offset and writes down
|
|
|
|
// result of the dynamic relocation. In case of preemptible symbol
|
|
|
|
// dynamic linker performs symbol resolution, writes the symbol value
|
|
|
|
// to the GOT entry and reads the GOT entry when it needs to perform
|
|
|
|
// a dynamic relocation.
|
|
|
|
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf p.4-19
|
|
|
|
if (Config->EMachine == EM_MIPS && !Body.isInGot())
|
|
|
|
Out<ELFT>::Got->addEntry(Body);
|
2016-04-13 09:40:19 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-02-05 05:33:05 +08:00
|
|
|
// We know that this is the final symbol. If the program being produced
|
|
|
|
// is position independent, the final value is still not known.
|
|
|
|
// If the relocation depends on the symbol value (not the size or distances
|
|
|
|
// in the output), we still need some help from the dynamic linker.
|
|
|
|
// We can however do better than just copying the incoming relocation. We
|
|
|
|
// can process some of it and and just ask the dynamic linker to add the
|
|
|
|
// load address.
|
2016-05-05 05:28:56 +08:00
|
|
|
if (!Config->Pic || isStaticLinkTimeConstant<ELFT>(Expr, Type, Body)) {
|
2016-05-06 23:02:50 +08:00
|
|
|
if (Config->EMachine == EM_MIPS && Expr == R_GOTREL) {
|
|
|
|
Addend -= MipsGPOffset;
|
|
|
|
if (Body.isLocal())
|
|
|
|
Addend += File.getMipsGp0();
|
|
|
|
}
|
2016-04-13 09:40:19 +08:00
|
|
|
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
|
2016-02-05 05:33:05 +08:00
|
|
|
continue;
|
|
|
|
}
|
2016-04-13 09:40:19 +08:00
|
|
|
|
2016-04-27 19:54:07 +08:00
|
|
|
if (Config->EMachine == EM_PPC64 && Type == R_PPC64_TOC)
|
|
|
|
Addend += getPPC64TocBase();
|
2016-04-13 09:40:19 +08:00
|
|
|
AddDyn({Target->RelativeRel, C.OutSec, Offset, true, &Body, Addend});
|
2016-04-27 19:54:07 +08:00
|
|
|
C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
|
2015-09-17 22:02:10 +08:00
|
|
|
}
|
2016-04-01 05:26:23 +08:00
|
|
|
|
|
|
|
// Scan relocations for necessary thunks.
|
|
|
|
if (Config->EMachine == EM_MIPS)
|
|
|
|
scanRelocsForThunks(File, Rels);
|
2015-09-17 22:02:10 +08:00
|
|
|
}
|
|
|
|
|
2015-11-11 23:29:50 +08:00
|
|
|
template <class ELFT> void Writer<ELFT>::scanRelocs(InputSection<ELFT> &C) {
|
2016-04-28 11:04:15 +08:00
|
|
|
// Scan all relocations. Each relocation goes through a series
|
|
|
|
// of tests to determine if it needs special treatment, such as
|
|
|
|
// creating GOT, PLT, copy relocations, etc.
|
2016-04-29 02:42:04 +08:00
|
|
|
// Note that relocations for non-alloc sections are directly
|
|
|
|
// processed by InputSection::relocateNative.
|
|
|
|
if (C.getSectionHdr()->sh_flags & SHF_ALLOC)
|
|
|
|
for (const Elf_Shdr *RelSec : C.RelocSections)
|
|
|
|
scanRelocs(C, *RelSec);
|
2015-11-12 03:54:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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));
|
2015-09-16 23:54:15 +08:00
|
|
|
}
|
|
|
|
|
2015-09-23 22:37:01 +08:00
|
|
|
template <class ELFT>
|
2016-01-06 04:01:29 +08:00
|
|
|
static void reportUndefined(SymbolTable<ELFT> &Symtab, SymbolBody *Sym) {
|
2016-04-24 10:31:04 +08:00
|
|
|
if (!Config->NoUndefined) {
|
|
|
|
if (Config->Relocatable)
|
|
|
|
return;
|
2016-05-11 21:48:41 +08:00
|
|
|
if (Config->Shared && !Config->ZDefs)
|
ELF: New symbol table design.
This patch implements a new design for the symbol table that stores
SymbolBodies within a memory region of the Symbol object. Symbols are mutated
by constructing SymbolBodies in place over existing SymbolBodies, rather
than by mutating pointers. As mentioned in the initial proposal [1], this
memory layout helps reduce the cache miss rate by improving memory locality.
Performance numbers:
old(s) new(s)
Without debug info:
chrome 7.178 6.432 (-11.5%)
LLVMgold.so 0.505 0.502 (-0.5%)
clang 0.954 0.827 (-15.4%)
llvm-as 0.052 0.045 (-15.5%)
With debug info:
scylla 5.695 5.613 (-1.5%)
clang 14.396 14.143 (-1.8%)
Performance counter results show that the fewer required indirections is
indeed the cause of the improved performance. For example, when linking
chrome, stalled cycles decreases from 14,556,444,002 to 12,959,238,310, and
instructions per cycle increases from 0.78 to 0.83. We are also executing
many fewer instructions (15,516,401,933 down to 15,002,434,310), probably
because we spend less time allocating SymbolBodies.
The new mechanism by which symbols are added to the symbol table is by calling
add* functions on the SymbolTable.
In this patch, I handle local symbols by storing them inside "unparented"
SymbolBodies. This is suboptimal, but if we do want to try to avoid allocating
these SymbolBodies, we can probably do that separately.
I also removed a few members from the SymbolBody class that were only being
used to pass information from the input file to the symbol table.
This patch implements the new design for the ELF linker only. I intend to
prepare a similar patch for the COFF linker.
[1] http://lists.llvm.org/pipermail/llvm-dev/2016-April/098832.html
Differential Revision: http://reviews.llvm.org/D19752
llvm-svn: 268178
2016-05-01 12:55:03 +08:00
|
|
|
if (Sym->symbol()->Visibility == STV_DEFAULT)
|
2016-04-24 10:31:04 +08:00
|
|
|
return;
|
|
|
|
}
|
2015-10-02 01:24:24 +08:00
|
|
|
|
2016-03-11 22:43:02 +08:00
|
|
|
std::string Msg = "undefined symbol: " + Sym->getName().str();
|
2016-05-03 09:48:25 +08:00
|
|
|
if (InputFile *File = Sym->getSourceFile<ELFT>())
|
2016-05-10 05:40:06 +08:00
|
|
|
Msg += " in " + getFilename(File);
|
2016-03-08 12:06:29 +08:00
|
|
|
if (Config->NoinhibitExec)
|
2016-01-06 04:01:29 +08:00
|
|
|
warning(Msg);
|
2015-09-23 22:37:01 +08:00
|
|
|
else
|
2016-01-29 06:56:29 +08:00
|
|
|
error(Msg);
|
2015-09-23 22:37:01 +08:00
|
|
|
}
|
|
|
|
|
2016-01-28 02:04:26 +08:00
|
|
|
template <class ELFT>
|
2016-04-04 22:04:16 +08:00
|
|
|
static bool shouldKeepInSymtab(InputSectionBase<ELFT> *Sec, StringRef SymName,
|
|
|
|
const SymbolBody &B) {
|
|
|
|
if (B.isFile())
|
2016-01-28 02:04:26 +08:00
|
|
|
return false;
|
|
|
|
|
2016-03-03 15:49:35 +08:00
|
|
|
// We keep sections in symtab for relocatable output.
|
2016-04-04 22:04:16 +08:00
|
|
|
if (B.isSection())
|
2016-03-03 15:49:35 +08:00
|
|
|
return Config->Relocatable;
|
|
|
|
|
2016-01-28 02:04:26 +08:00
|
|
|
// If sym references a section in a discarded group, don't keep it.
|
2016-04-04 22:04:16 +08:00
|
|
|
if (Sec == &InputSection<ELFT>::Discarded)
|
2016-01-28 02:04:26 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (Config->DiscardNone)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// In ELF assembly .L symbols are normally discarded by the assembler.
|
|
|
|
// If the assembler fails to do so, the linker discards them if
|
|
|
|
// * --discard-locals is used.
|
|
|
|
// * The symbol is in a SHF_MERGE section, which is normally the reason for
|
|
|
|
// the assembler keeping the .L symbol.
|
|
|
|
if (!SymName.startswith(".L") && !SymName.empty())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (Config->DiscardLocals)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return !(Sec->getSectionHdr()->sh_flags & SHF_MERGE);
|
|
|
|
}
|
|
|
|
|
2016-05-06 00:40:28 +08:00
|
|
|
template <class ELFT> static bool includeInSymtab(const SymbolBody &B) {
|
|
|
|
if (!B.isLocal() && !B.symbol()->IsUsedInRegularObj)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (auto *D = dyn_cast<DefinedRegular<ELFT>>(&B)) {
|
|
|
|
// Always include absolute symbols.
|
|
|
|
if (!D->Section)
|
|
|
|
return true;
|
|
|
|
// Exclude symbols pointing to garbage-collected sections.
|
|
|
|
if (!D->Section->Live)
|
|
|
|
return false;
|
|
|
|
if (auto *S = dyn_cast<MergeInputSection<ELFT>>(D->Section))
|
|
|
|
if (S->getRangeAndSize(D->Value).first->second ==
|
|
|
|
MergeInputSection<ELFT>::PieceDead)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2016-05-06 00:38:46 +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() {
|
2016-01-21 11:07:38 +08:00
|
|
|
if (!Out<ELFT>::SymTab)
|
|
|
|
return;
|
2016-03-12 00:41:23 +08:00
|
|
|
for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
|
|
|
|
Symtab.getObjectFiles()) {
|
2016-04-04 22:04:16 +08:00
|
|
|
const char *StrTab = F->getStringTable().data();
|
2016-03-11 20:06:30 +08:00
|
|
|
for (SymbolBody *B : F->getLocalSymbols()) {
|
2016-04-04 22:04:16 +08:00
|
|
|
auto *DR = dyn_cast<DefinedRegular<ELFT>>(B);
|
|
|
|
// No reason to keep local undefined symbol in symtab.
|
|
|
|
if (!DR)
|
|
|
|
continue;
|
2016-05-06 00:38:46 +08:00
|
|
|
if (!includeInSymtab<ELFT>(*B))
|
|
|
|
continue;
|
2016-04-04 22:04:16 +08:00
|
|
|
StringRef SymName(StrTab + B->getNameOffset());
|
|
|
|
InputSectionBase<ELFT> *Sec = DR->Section;
|
|
|
|
if (!shouldKeepInSymtab<ELFT>(Sec, SymName, *B))
|
2015-10-10 03:25:07 +08:00
|
|
|
continue;
|
2016-01-29 09:24:25 +08:00
|
|
|
++Out<ELFT>::SymTab->NumLocals;
|
2016-03-03 15:49:35 +08:00
|
|
|
if (Config->Relocatable)
|
2016-03-14 04:18:12 +08:00
|
|
|
B->DynsymIndex = Out<ELFT>::SymTab->NumLocals;
|
2016-04-04 22:04:16 +08:00
|
|
|
F->KeptLocalSyms.push_back(
|
|
|
|
std::make_pair(DR, Out<ELFT>::SymTab->StrTabSec.addString(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)
|
2016-04-14 21:23:02 +08:00
|
|
|
.Case(".tocbss", 0)
|
|
|
|
.Case(".branch_lt", 2)
|
|
|
|
.Case(".toc", 3)
|
|
|
|
.Case(".toc1", 4)
|
|
|
|
.Case(".opd", 5)
|
|
|
|
.Default(1);
|
2015-10-13 04:51:48 +08:00
|
|
|
}
|
|
|
|
|
2015-11-24 18:15:50 +08:00
|
|
|
template <class ELFT> static bool isRelroSection(OutputSectionBase<ELFT> *Sec) {
|
2016-02-11 06:43:13 +08:00
|
|
|
if (!Config->ZRelro)
|
|
|
|
return false;
|
2016-04-27 11:04:56 +08:00
|
|
|
typename ELFT::uint Flags = Sec->getFlags();
|
2015-11-24 18:15:50 +08:00
|
|
|
if (!(Flags & SHF_ALLOC) || !(Flags & SHF_WRITE))
|
|
|
|
return false;
|
2015-12-11 03:13:08 +08:00
|
|
|
if (Flags & SHF_TLS)
|
|
|
|
return true;
|
2015-11-24 18:15:50 +08:00
|
|
|
uint32_t Type = Sec->getType();
|
2015-12-11 03:13:08 +08:00
|
|
|
if (Type == SHT_INIT_ARRAY || Type == SHT_FINI_ARRAY ||
|
|
|
|
Type == SHT_PREINIT_ARRAY)
|
2015-11-24 18:15:50 +08:00
|
|
|
return true;
|
|
|
|
if (Sec == Out<ELFT>::GotPlt)
|
|
|
|
return Config->ZNow;
|
|
|
|
if (Sec == Out<ELFT>::Dynamic || Sec == Out<ELFT>::Got)
|
|
|
|
return true;
|
2015-12-11 03:19:04 +08:00
|
|
|
StringRef S = Sec->getName();
|
|
|
|
return S == ".data.rel.ro" || S == ".ctors" || S == ".dtors" || S == ".jcr" ||
|
|
|
|
S == ".eh_frame";
|
2015-11-24 18:15:50 +08:00
|
|
|
}
|
|
|
|
|
2015-10-09 07:49:30 +08:00
|
|
|
// Output section ordering is determined by this function.
|
|
|
|
template <class ELFT>
|
2016-02-12 05:17:59 +08:00
|
|
|
static bool compareSections(OutputSectionBase<ELFT> *A,
|
|
|
|
OutputSectionBase<ELFT> *B) {
|
2016-03-15 07:16:09 +08:00
|
|
|
typedef typename ELFT::uint uintX_t;
|
2015-10-09 07:49:30 +08:00
|
|
|
|
2016-04-21 04:13:41 +08:00
|
|
|
int Comp = Script<ELFT>::X->compareSections(A->getName(), B->getName());
|
2016-02-12 05:17:59 +08:00
|
|
|
if (Comp != 0)
|
|
|
|
return Comp < 0;
|
|
|
|
|
2015-10-09 07:49:30 +08:00
|
|
|
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.
|
2015-12-17 08:12:03 +08:00
|
|
|
bool AIsTls = AFlags & SHF_TLS;
|
|
|
|
bool BIsTls = BFlags & SHF_TLS;
|
|
|
|
if (AIsTls != BIsTls)
|
|
|
|
return AIsTls;
|
2015-10-17 07:11:07 +08:00
|
|
|
|
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-11-24 18:15:50 +08:00
|
|
|
// We place RelRo section before plain r/w ones.
|
|
|
|
bool AIsRelRo = isRelroSection(A);
|
|
|
|
bool BIsRelRo = isRelroSection(B);
|
|
|
|
if (AIsRelRo != BIsRelRo)
|
|
|
|
return AIsRelRo;
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2016-03-13 12:11:53 +08:00
|
|
|
// The .bss section does not exist if no input file has a .bss section.
|
|
|
|
// This function creates one if that's the case.
|
|
|
|
template <class ELFT> void Writer<ELFT>::ensureBss() {
|
|
|
|
if (Out<ELFT>::Bss)
|
|
|
|
return;
|
|
|
|
Out<ELFT>::Bss =
|
|
|
|
new OutputSection<ELFT>(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
|
|
|
|
OwningSections.emplace_back(Out<ELFT>::Bss);
|
|
|
|
OutputSections.push_back(Out<ELFT>::Bss);
|
2015-11-04 05:35:14 +08:00
|
|
|
}
|
|
|
|
|
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-12-25 00:23:37 +08:00
|
|
|
void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon *> &Syms) {
|
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.
|
2015-12-25 00:23:37 +08:00
|
|
|
std::stable_sort(Syms.begin(), Syms.end(),
|
|
|
|
[](const DefinedCommon *A, const DefinedCommon *B) {
|
2016-03-11 02:58:53 +08:00
|
|
|
return A->Alignment > B->Alignment;
|
2015-12-25 00:23:37 +08:00
|
|
|
});
|
2015-10-09 07:49:30 +08:00
|
|
|
|
2016-03-13 12:11:53 +08:00
|
|
|
ensureBss();
|
|
|
|
uintX_t Off = Out<ELFT>::Bss->getSize();
|
2015-12-25 00:23:37 +08:00
|
|
|
for (DefinedCommon *C : Syms) {
|
2016-03-11 02:58:53 +08:00
|
|
|
Off = alignTo(Off, C->Alignment);
|
|
|
|
Out<ELFT>::Bss->updateAlign(C->Alignment);
|
2016-01-06 00:35:43 +08:00
|
|
|
C->OffsetInBss = Off;
|
2015-12-25 00:23:37 +08:00
|
|
|
Off += C->Size;
|
2015-10-09 07:49:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Out<ELFT>::Bss->setSize(Off);
|
|
|
|
}
|
|
|
|
|
2016-03-15 06:41:08 +08:00
|
|
|
template <class ELFT> static uint32_t getAlignment(SharedSymbol<ELFT> *SS) {
|
|
|
|
typedef typename ELFFile<ELFT>::uintX_t uintX_t;
|
|
|
|
|
|
|
|
uintX_t SecAlign = SS->File->getSection(SS->Sym)->sh_addralign;
|
|
|
|
uintX_t SymValue = SS->Sym.st_value;
|
2016-04-14 21:23:02 +08:00
|
|
|
int TrailingZeros =
|
|
|
|
std::min(countTrailingZeros(SecAlign), countTrailingZeros(SymValue));
|
2016-03-13 12:05:42 +08:00
|
|
|
return 1 << TrailingZeros;
|
|
|
|
}
|
|
|
|
|
2016-04-05 06:29:24 +08:00
|
|
|
// Reserve space in .bss for copy relocation.
|
2015-10-29 00:48:58 +08:00
|
|
|
template <class ELFT>
|
2016-04-05 06:29:24 +08:00
|
|
|
void Writer<ELFT>::addCopyRelSymbol(SharedSymbol<ELFT> *SS) {
|
2016-03-13 12:11:53 +08:00
|
|
|
ensureBss();
|
2016-04-05 06:29:24 +08:00
|
|
|
uintX_t Align = getAlignment(SS);
|
2016-04-14 21:56:28 +08:00
|
|
|
uintX_t Off = alignTo(Out<ELFT>::Bss->getSize(), Align);
|
2016-04-05 06:29:24 +08:00
|
|
|
Out<ELFT>::Bss->setSize(Off + SS->template getSize<ELFT>());
|
|
|
|
Out<ELFT>::Bss->updateAlign(Align);
|
|
|
|
uintX_t Shndx = SS->Sym.st_shndx;
|
|
|
|
uintX_t Value = SS->Sym.st_value;
|
ELF: New symbol table design.
This patch implements a new design for the symbol table that stores
SymbolBodies within a memory region of the Symbol object. Symbols are mutated
by constructing SymbolBodies in place over existing SymbolBodies, rather
than by mutating pointers. As mentioned in the initial proposal [1], this
memory layout helps reduce the cache miss rate by improving memory locality.
Performance numbers:
old(s) new(s)
Without debug info:
chrome 7.178 6.432 (-11.5%)
LLVMgold.so 0.505 0.502 (-0.5%)
clang 0.954 0.827 (-15.4%)
llvm-as 0.052 0.045 (-15.5%)
With debug info:
scylla 5.695 5.613 (-1.5%)
clang 14.396 14.143 (-1.8%)
Performance counter results show that the fewer required indirections is
indeed the cause of the improved performance. For example, when linking
chrome, stalled cycles decreases from 14,556,444,002 to 12,959,238,310, and
instructions per cycle increases from 0.78 to 0.83. We are also executing
many fewer instructions (15,516,401,933 down to 15,002,434,310), probably
because we spend less time allocating SymbolBodies.
The new mechanism by which symbols are added to the symbol table is by calling
add* functions on the SymbolTable.
In this patch, I handle local symbols by storing them inside "unparented"
SymbolBodies. This is suboptimal, but if we do want to try to avoid allocating
these SymbolBodies, we can probably do that separately.
I also removed a few members from the SymbolBody class that were only being
used to pass information from the input file to the symbol table.
This patch implements the new design for the ELF linker only. I intend to
prepare a similar patch for the COFF linker.
[1] http://lists.llvm.org/pipermail/llvm-dev/2016-April/098832.html
Differential Revision: http://reviews.llvm.org/D19752
llvm-svn: 268178
2016-05-01 12:55:03 +08:00
|
|
|
// Look through the DSO's dynamic symbol table for aliases and create a
|
|
|
|
// dynamic symbol for each one. This causes the copy relocation to correctly
|
|
|
|
// interpose any aliases.
|
|
|
|
for (const Elf_Sym &S : SS->File->getElfSymbols(true)) {
|
|
|
|
if (S.st_shndx != Shndx || S.st_value != Value)
|
|
|
|
continue;
|
|
|
|
auto *Alias = dyn_cast_or_null<SharedSymbol<ELFT>>(
|
|
|
|
Symtab.find(check(S.getName(SS->File->getStringTable()))));
|
|
|
|
if (!Alias)
|
2016-04-05 06:29:24 +08:00
|
|
|
continue;
|
ELF: New symbol table design.
This patch implements a new design for the symbol table that stores
SymbolBodies within a memory region of the Symbol object. Symbols are mutated
by constructing SymbolBodies in place over existing SymbolBodies, rather
than by mutating pointers. As mentioned in the initial proposal [1], this
memory layout helps reduce the cache miss rate by improving memory locality.
Performance numbers:
old(s) new(s)
Without debug info:
chrome 7.178 6.432 (-11.5%)
LLVMgold.so 0.505 0.502 (-0.5%)
clang 0.954 0.827 (-15.4%)
llvm-as 0.052 0.045 (-15.5%)
With debug info:
scylla 5.695 5.613 (-1.5%)
clang 14.396 14.143 (-1.8%)
Performance counter results show that the fewer required indirections is
indeed the cause of the improved performance. For example, when linking
chrome, stalled cycles decreases from 14,556,444,002 to 12,959,238,310, and
instructions per cycle increases from 0.78 to 0.83. We are also executing
many fewer instructions (15,516,401,933 down to 15,002,434,310), probably
because we spend less time allocating SymbolBodies.
The new mechanism by which symbols are added to the symbol table is by calling
add* functions on the SymbolTable.
In this patch, I handle local symbols by storing them inside "unparented"
SymbolBodies. This is suboptimal, but if we do want to try to avoid allocating
these SymbolBodies, we can probably do that separately.
I also removed a few members from the SymbolBody class that were only being
used to pass information from the input file to the symbol table.
This patch implements the new design for the ELF linker only. I intend to
prepare a similar patch for the COFF linker.
[1] http://lists.llvm.org/pipermail/llvm-dev/2016-April/098832.html
Differential Revision: http://reviews.llvm.org/D19752
llvm-svn: 268178
2016-05-01 12:55:03 +08:00
|
|
|
Alias->OffsetInBss = Off;
|
|
|
|
Alias->NeedsCopyOrPltAddr = true;
|
|
|
|
Alias->symbol()->IsUsedInRegularObj = true;
|
2015-10-29 00:48:58 +08:00
|
|
|
}
|
2016-04-07 22:34:15 +08:00
|
|
|
Out<ELFT>::RelaDyn->addReloc(
|
|
|
|
{Target->CopyRel, Out<ELFT>::Bss, SS->OffsetInBss, false, SS, 0});
|
2015-10-29 00:48:58 +08:00
|
|
|
}
|
|
|
|
|
2015-11-12 17:52:08 +08:00
|
|
|
template <class ELFT>
|
2016-02-13 05:47:28 +08:00
|
|
|
StringRef Writer<ELFT>::getOutputSectionName(InputSectionBase<ELFT> *S) const {
|
2016-04-21 04:13:41 +08:00
|
|
|
StringRef Dest = Script<ELFT>::X->getOutputSection(S);
|
2016-02-13 05:47:28 +08:00
|
|
|
if (!Dest.empty())
|
|
|
|
return Dest;
|
2015-11-12 17:52:08 +08:00
|
|
|
|
2016-02-13 05:47:28 +08:00
|
|
|
StringRef Name = S->getSectionName();
|
2016-02-17 00:05:27 +08:00
|
|
|
for (StringRef V : {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.",
|
|
|
|
".init_array.", ".fini_array.", ".ctors.", ".dtors.",
|
2016-02-17 00:12:06 +08:00
|
|
|
".tbss.", ".gcc_except_table.", ".tdata."})
|
2016-02-13 05:47:28 +08:00
|
|
|
if (Name.startswith(V))
|
2016-02-11 09:07:18 +08:00
|
|
|
return V.drop_back();
|
2016-02-13 05:47:28 +08:00
|
|
|
return Name;
|
2015-10-15 03:21:25 +08:00
|
|
|
}
|
|
|
|
|
2015-12-10 17:12:18 +08:00
|
|
|
template <class ELFT>
|
|
|
|
void reportDiscarded(InputSectionBase<ELFT> *IS,
|
2016-03-12 00:32:46 +08:00
|
|
|
const std::unique_ptr<elf::ObjectFile<ELFT>> &File) {
|
2016-02-24 08:23:15 +08:00
|
|
|
if (!Config->PrintGcSections || !IS || IS->Live)
|
2015-12-10 17:12:18 +08:00
|
|
|
return;
|
|
|
|
llvm::errs() << "removing unused section from '" << IS->getSectionName()
|
|
|
|
<< "' in file '" << File->getName() << "'\n";
|
|
|
|
}
|
|
|
|
|
2015-11-12 17:52:08 +08:00
|
|
|
template <class ELFT>
|
2016-02-12 05:17:59 +08:00
|
|
|
bool Writer<ELFT>::isDiscarded(InputSectionBase<ELFT> *S) const {
|
2016-04-04 22:04:16 +08:00
|
|
|
return !S || S == &InputSection<ELFT>::Discarded || !S->Live ||
|
2016-04-21 04:13:41 +08:00
|
|
|
Script<ELFT>::X->isDiscarded(S);
|
2015-11-12 17:52:08 +08:00
|
|
|
}
|
|
|
|
|
2016-04-12 21:26:51 +08:00
|
|
|
template <class ELFT>
|
ELF: New symbol table design.
This patch implements a new design for the symbol table that stores
SymbolBodies within a memory region of the Symbol object. Symbols are mutated
by constructing SymbolBodies in place over existing SymbolBodies, rather
than by mutating pointers. As mentioned in the initial proposal [1], this
memory layout helps reduce the cache miss rate by improving memory locality.
Performance numbers:
old(s) new(s)
Without debug info:
chrome 7.178 6.432 (-11.5%)
LLVMgold.so 0.505 0.502 (-0.5%)
clang 0.954 0.827 (-15.4%)
llvm-as 0.052 0.045 (-15.5%)
With debug info:
scylla 5.695 5.613 (-1.5%)
clang 14.396 14.143 (-1.8%)
Performance counter results show that the fewer required indirections is
indeed the cause of the improved performance. For example, when linking
chrome, stalled cycles decreases from 14,556,444,002 to 12,959,238,310, and
instructions per cycle increases from 0.78 to 0.83. We are also executing
many fewer instructions (15,516,401,933 down to 15,002,434,310), probably
because we spend less time allocating SymbolBodies.
The new mechanism by which symbols are added to the symbol table is by calling
add* functions on the SymbolTable.
In this patch, I handle local symbols by storing them inside "unparented"
SymbolBodies. This is suboptimal, but if we do want to try to avoid allocating
these SymbolBodies, we can probably do that separately.
I also removed a few members from the SymbolBody class that were only being
used to pass information from the input file to the symbol table.
This patch implements the new design for the ELF linker only. I intend to
prepare a similar patch for the COFF linker.
[1] http://lists.llvm.org/pipermail/llvm-dev/2016-April/098832.html
Differential Revision: http://reviews.llvm.org/D19752
llvm-svn: 268178
2016-05-01 12:55:03 +08:00
|
|
|
static Symbol *addOptionalSynthetic(SymbolTable<ELFT> &Table, StringRef Name,
|
2016-05-03 09:21:08 +08:00
|
|
|
OutputSectionBase<ELFT> *Sec,
|
ELF: New symbol table design.
This patch implements a new design for the symbol table that stores
SymbolBodies within a memory region of the Symbol object. Symbols are mutated
by constructing SymbolBodies in place over existing SymbolBodies, rather
than by mutating pointers. As mentioned in the initial proposal [1], this
memory layout helps reduce the cache miss rate by improving memory locality.
Performance numbers:
old(s) new(s)
Without debug info:
chrome 7.178 6.432 (-11.5%)
LLVMgold.so 0.505 0.502 (-0.5%)
clang 0.954 0.827 (-15.4%)
llvm-as 0.052 0.045 (-15.5%)
With debug info:
scylla 5.695 5.613 (-1.5%)
clang 14.396 14.143 (-1.8%)
Performance counter results show that the fewer required indirections is
indeed the cause of the improved performance. For example, when linking
chrome, stalled cycles decreases from 14,556,444,002 to 12,959,238,310, and
instructions per cycle increases from 0.78 to 0.83. We are also executing
many fewer instructions (15,516,401,933 down to 15,002,434,310), probably
because we spend less time allocating SymbolBodies.
The new mechanism by which symbols are added to the symbol table is by calling
add* functions on the SymbolTable.
In this patch, I handle local symbols by storing them inside "unparented"
SymbolBodies. This is suboptimal, but if we do want to try to avoid allocating
these SymbolBodies, we can probably do that separately.
I also removed a few members from the SymbolBody class that were only being
used to pass information from the input file to the symbol table.
This patch implements the new design for the ELF linker only. I intend to
prepare a similar patch for the COFF linker.
[1] http://lists.llvm.org/pipermail/llvm-dev/2016-April/098832.html
Differential Revision: http://reviews.llvm.org/D19752
llvm-svn: 268178
2016-05-01 12:55:03 +08:00
|
|
|
typename ELFT::uint Val) {
|
2016-05-09 23:25:54 +08:00
|
|
|
SymbolBody *S = Table.find(Name);
|
|
|
|
if (!S)
|
2016-04-12 21:26:51 +08:00
|
|
|
return nullptr;
|
2016-05-09 23:25:54 +08:00
|
|
|
if (!S->isUndefined() && !S->isShared())
|
|
|
|
return S->symbol();
|
2016-04-14 00:57:28 +08:00
|
|
|
return Table.addSynthetic(Name, Sec, Val);
|
2016-04-12 21:26:51 +08:00
|
|
|
}
|
|
|
|
|
2015-12-26 17:47:57 +08:00
|
|
|
// The beginning and the ending of .rel[a].plt section are marked
|
|
|
|
// with __rel[a]_iplt_{start,end} symbols if it is a statically linked
|
|
|
|
// executable. The runtime needs these symbols in order to resolve
|
|
|
|
// all IRELATIVE relocs on startup. For dynamic executables, we don't
|
|
|
|
// need these symbols, since IRELATIVE relocs are resolved through GOT
|
|
|
|
// and PLT. For details, see http://www.airs.com/blog/archives/403.
|
2016-04-14 21:23:02 +08:00
|
|
|
template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
|
2015-12-26 17:47:57 +08:00
|
|
|
if (isOutputDynamic() || !Out<ELFT>::RelaPlt)
|
2015-12-21 18:12:06 +08:00
|
|
|
return;
|
2016-03-14 04:10:20 +08:00
|
|
|
StringRef S = Config->Rela ? "__rela_iplt_start" : "__rel_iplt_start";
|
2016-05-03 09:21:08 +08:00
|
|
|
addOptionalSynthetic(Symtab, S, Out<ELFT>::RelaPlt, 0);
|
2015-12-26 17:47:57 +08:00
|
|
|
|
2016-03-14 04:10:20 +08:00
|
|
|
S = Config->Rela ? "__rela_iplt_end" : "__rel_iplt_end";
|
2016-05-03 09:21:08 +08:00
|
|
|
addOptionalSynthetic(Symtab, S, Out<ELFT>::RelaPlt,
|
ELF: New symbol table design.
This patch implements a new design for the symbol table that stores
SymbolBodies within a memory region of the Symbol object. Symbols are mutated
by constructing SymbolBodies in place over existing SymbolBodies, rather
than by mutating pointers. As mentioned in the initial proposal [1], this
memory layout helps reduce the cache miss rate by improving memory locality.
Performance numbers:
old(s) new(s)
Without debug info:
chrome 7.178 6.432 (-11.5%)
LLVMgold.so 0.505 0.502 (-0.5%)
clang 0.954 0.827 (-15.4%)
llvm-as 0.052 0.045 (-15.5%)
With debug info:
scylla 5.695 5.613 (-1.5%)
clang 14.396 14.143 (-1.8%)
Performance counter results show that the fewer required indirections is
indeed the cause of the improved performance. For example, when linking
chrome, stalled cycles decreases from 14,556,444,002 to 12,959,238,310, and
instructions per cycle increases from 0.78 to 0.83. We are also executing
many fewer instructions (15,516,401,933 down to 15,002,434,310), probably
because we spend less time allocating SymbolBodies.
The new mechanism by which symbols are added to the symbol table is by calling
add* functions on the SymbolTable.
In this patch, I handle local symbols by storing them inside "unparented"
SymbolBodies. This is suboptimal, but if we do want to try to avoid allocating
these SymbolBodies, we can probably do that separately.
I also removed a few members from the SymbolBody class that were only being
used to pass information from the input file to the symbol table.
This patch implements the new design for the ELF linker only. I intend to
prepare a similar patch for the COFF linker.
[1] http://lists.llvm.org/pipermail/llvm-dev/2016-April/098832.html
Differential Revision: http://reviews.llvm.org/D19752
llvm-svn: 268178
2016-05-01 12:55:03 +08:00
|
|
|
DefinedSynthetic<ELFT>::SectionEnd);
|
2015-12-21 18:12:06 +08:00
|
|
|
}
|
|
|
|
|
2015-12-26 15:01:28 +08:00
|
|
|
// This class knows how to create an output section for a given
|
|
|
|
// input section. Output section type is determined by various
|
|
|
|
// factors, including input section's sh_flags, sh_type and
|
|
|
|
// linker scripts.
|
|
|
|
namespace {
|
|
|
|
template <class ELFT> class OutputSectionFactory {
|
2016-03-15 07:16:09 +08:00
|
|
|
typedef typename ELFT::Shdr Elf_Shdr;
|
|
|
|
typedef typename ELFT::uint uintX_t;
|
2015-12-26 15:01:28 +08:00
|
|
|
|
|
|
|
public:
|
|
|
|
std::pair<OutputSectionBase<ELFT> *, bool> create(InputSectionBase<ELFT> *C,
|
|
|
|
StringRef OutsecName);
|
|
|
|
|
2016-04-14 22:07:54 +08:00
|
|
|
OutputSectionBase<ELFT> *lookup(StringRef Name, uint32_t Type,
|
|
|
|
uintX_t Flags) {
|
2016-04-14 22:24:23 +08:00
|
|
|
return Map.lookup({Name, Type, Flags, 0});
|
2016-04-14 22:07:54 +08:00
|
|
|
}
|
2015-12-26 15:01:28 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
SectionKey<ELFT::Is64Bits> createKey(InputSectionBase<ELFT> *C,
|
|
|
|
StringRef OutsecName);
|
|
|
|
|
|
|
|
SmallDenseMap<SectionKey<ELFT::Is64Bits>, OutputSectionBase<ELFT> *> Map;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class ELFT>
|
|
|
|
std::pair<OutputSectionBase<ELFT> *, bool>
|
|
|
|
OutputSectionFactory<ELFT>::create(InputSectionBase<ELFT> *C,
|
|
|
|
StringRef OutsecName) {
|
|
|
|
SectionKey<ELFT::Is64Bits> Key = createKey(C, OutsecName);
|
|
|
|
OutputSectionBase<ELFT> *&Sec = Map[Key];
|
|
|
|
if (Sec)
|
|
|
|
return {Sec, false};
|
|
|
|
|
2015-12-25 15:38:58 +08:00
|
|
|
switch (C->SectionKind) {
|
|
|
|
case InputSectionBase<ELFT>::Regular:
|
2016-01-12 07:50:55 +08:00
|
|
|
Sec = new OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
|
|
|
|
break;
|
2015-12-25 15:38:58 +08:00
|
|
|
case InputSectionBase<ELFT>::EHFrame:
|
2016-01-12 07:50:55 +08:00
|
|
|
Sec = new EHOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
|
|
|
|
break;
|
2015-12-25 15:38:58 +08:00
|
|
|
case InputSectionBase<ELFT>::Merge:
|
2016-02-19 22:17:40 +08:00
|
|
|
Sec = new MergeOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags,
|
|
|
|
Key.Alignment);
|
2016-01-12 07:50:55 +08:00
|
|
|
break;
|
2015-12-25 15:38:58 +08:00
|
|
|
case InputSectionBase<ELFT>::MipsReginfo:
|
2016-01-12 07:50:55 +08:00
|
|
|
Sec = new MipsReginfoOutputSection<ELFT>();
|
|
|
|
break;
|
2016-05-04 18:07:38 +08:00
|
|
|
case InputSectionBase<ELFT>::MipsOptions:
|
|
|
|
Sec = new MipsOptionsOutputSection<ELFT>();
|
|
|
|
break;
|
2015-12-25 15:38:58 +08:00
|
|
|
}
|
2016-01-12 07:50:55 +08:00
|
|
|
return {Sec, true};
|
2015-12-25 15:38:58 +08:00
|
|
|
}
|
|
|
|
|
2015-12-26 15:01:28 +08:00
|
|
|
template <class ELFT>
|
|
|
|
SectionKey<ELFT::Is64Bits>
|
|
|
|
OutputSectionFactory<ELFT>::createKey(InputSectionBase<ELFT> *C,
|
|
|
|
StringRef OutsecName) {
|
|
|
|
const Elf_Shdr *H = C->getSectionHdr();
|
2015-12-26 15:13:38 +08:00
|
|
|
uintX_t Flags = H->sh_flags & ~SHF_GROUP;
|
2015-12-26 15:01:28 +08:00
|
|
|
|
2016-02-19 22:17:40 +08:00
|
|
|
// For SHF_MERGE we create different output sections for each alignment.
|
|
|
|
// This makes each output section simple and keeps a single level mapping from
|
|
|
|
// input to output.
|
|
|
|
uintX_t Alignment = 0;
|
2016-04-14 21:00:03 +08:00
|
|
|
if (isa<MergeInputSection<ELFT>>(C))
|
|
|
|
Alignment = std::max(H->sh_addralign, H->sh_entsize);
|
2015-12-26 15:13:38 +08:00
|
|
|
|
2016-04-28 21:38:10 +08:00
|
|
|
// GNU as can give .eh_frame section type SHT_PROGBITS or SHT_X86_64_UNWIND
|
2015-12-26 15:13:38 +08:00
|
|
|
// depending on the construct. We want to canonicalize it so that
|
|
|
|
// there is only one .eh_frame in the end.
|
|
|
|
uint32_t Type = H->sh_type;
|
|
|
|
if (Type == SHT_PROGBITS && Config->EMachine == EM_X86_64 &&
|
|
|
|
isa<EHInputSection<ELFT>>(C))
|
|
|
|
Type = SHT_X86_64_UNWIND;
|
|
|
|
|
2016-02-19 22:17:40 +08:00
|
|
|
return SectionKey<ELFT::Is64Bits>{OutsecName, Type, Flags, Alignment};
|
2015-12-26 15:01:28 +08:00
|
|
|
}
|
|
|
|
|
2015-12-26 15:50:39 +08:00
|
|
|
// The linker is expected to define some symbols depending on
|
|
|
|
// the linking result. This function defines such symbols.
|
|
|
|
template <class ELFT> void Writer<ELFT>::addReservedSymbols() {
|
2016-04-04 22:04:16 +08:00
|
|
|
if (Config->EMachine == EM_MIPS) {
|
2016-04-12 10:24:43 +08:00
|
|
|
// Define _gp for MIPS. st_value of _gp symbol will be updated by Writer
|
|
|
|
// so that it points to an absolute address which is relative to GOT.
|
|
|
|
// See "Global Data Symbols" in Chapter 6 in the following document:
|
|
|
|
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
|
2016-05-03 09:21:08 +08:00
|
|
|
Symtab.addSynthetic("_gp", Out<ELFT>::Got, MipsGPOffset);
|
2016-04-12 10:24:43 +08:00
|
|
|
|
2016-04-04 22:04:16 +08:00
|
|
|
// On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
|
|
|
|
// start of function and 'gp' pointer into GOT.
|
2016-05-04 02:03:45 +08:00
|
|
|
Symbol *Sym =
|
|
|
|
addOptionalSynthetic(Symtab, "_gp_disp", Out<ELFT>::Got, MipsGPOffset);
|
|
|
|
if (Sym)
|
|
|
|
ElfSym<ELFT>::MipsGpDisp = Sym->body();
|
|
|
|
|
2016-04-04 22:04:16 +08:00
|
|
|
// The __gnu_local_gp is a magic symbol equal to the current value of 'gp'
|
|
|
|
// pointer. This symbol is used in the code generated by .cpload pseudo-op
|
|
|
|
// in case of using -mno-shared option.
|
|
|
|
// https://sourceware.org/ml/binutils/2004-12/msg00094.html
|
2016-05-03 09:21:08 +08:00
|
|
|
addOptionalSynthetic(Symtab, "__gnu_local_gp", Out<ELFT>::Got,
|
ELF: New symbol table design.
This patch implements a new design for the symbol table that stores
SymbolBodies within a memory region of the Symbol object. Symbols are mutated
by constructing SymbolBodies in place over existing SymbolBodies, rather
than by mutating pointers. As mentioned in the initial proposal [1], this
memory layout helps reduce the cache miss rate by improving memory locality.
Performance numbers:
old(s) new(s)
Without debug info:
chrome 7.178 6.432 (-11.5%)
LLVMgold.so 0.505 0.502 (-0.5%)
clang 0.954 0.827 (-15.4%)
llvm-as 0.052 0.045 (-15.5%)
With debug info:
scylla 5.695 5.613 (-1.5%)
clang 14.396 14.143 (-1.8%)
Performance counter results show that the fewer required indirections is
indeed the cause of the improved performance. For example, when linking
chrome, stalled cycles decreases from 14,556,444,002 to 12,959,238,310, and
instructions per cycle increases from 0.78 to 0.83. We are also executing
many fewer instructions (15,516,401,933 down to 15,002,434,310), probably
because we spend less time allocating SymbolBodies.
The new mechanism by which symbols are added to the symbol table is by calling
add* functions on the SymbolTable.
In this patch, I handle local symbols by storing them inside "unparented"
SymbolBodies. This is suboptimal, but if we do want to try to avoid allocating
these SymbolBodies, we can probably do that separately.
I also removed a few members from the SymbolBody class that were only being
used to pass information from the input file to the symbol table.
This patch implements the new design for the ELF linker only. I intend to
prepare a similar patch for the COFF linker.
[1] http://lists.llvm.org/pipermail/llvm-dev/2016-April/098832.html
Differential Revision: http://reviews.llvm.org/D19752
llvm-svn: 268178
2016-05-01 12:55:03 +08:00
|
|
|
MipsGPOffset);
|
2016-04-04 22:04:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol
|
|
|
|
// is magical and is used to produce a R_386_GOTPC relocation.
|
|
|
|
// The R_386_GOTPC relocation value doesn't actually depend on the
|
|
|
|
// symbol value, so it could use an index of STN_UNDEF which, according
|
|
|
|
// to the spec, means the symbol value is 0.
|
|
|
|
// Unfortunately both gas and MC keep the _GLOBAL_OFFSET_TABLE_ symbol in
|
|
|
|
// the object file.
|
|
|
|
// The situation is even stranger on x86_64 where the assembly doesn't
|
|
|
|
// need the magical symbol, but gas still puts _GLOBAL_OFFSET_TABLE_ as
|
|
|
|
// an undefined symbol in the .o files.
|
|
|
|
// Given that the symbol is effectively unused, we just create a dummy
|
|
|
|
// hidden one to avoid the undefined symbol error.
|
|
|
|
if (!Config->Relocatable)
|
|
|
|
Symtab.addIgnored("_GLOBAL_OFFSET_TABLE_");
|
|
|
|
|
2015-12-26 15:50:39 +08:00
|
|
|
// __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");
|
|
|
|
|
2016-04-22 04:50:15 +08:00
|
|
|
auto Define = [this](StringRef S, DefinedRegular<ELFT> *&Sym1,
|
|
|
|
DefinedRegular<ELFT> *&Sym2) {
|
|
|
|
Sym1 = Symtab.addIgnored(S, STV_DEFAULT);
|
2016-02-27 00:38:39 +08:00
|
|
|
|
|
|
|
// The name without the underscore is not a reserved name,
|
|
|
|
// so it is defined only when there is a reference against it.
|
2016-02-27 00:49:54 +08:00
|
|
|
assert(S.startswith("_"));
|
2016-02-27 00:38:39 +08:00
|
|
|
S = S.substr(1);
|
|
|
|
if (SymbolBody *B = Symtab.find(S))
|
2016-02-26 22:36:36 +08:00
|
|
|
if (B->isUndefined())
|
2016-04-22 04:50:15 +08:00
|
|
|
Sym2 = Symtab.addAbsolute(S, STV_DEFAULT);
|
2016-02-26 22:36:36 +08:00
|
|
|
};
|
|
|
|
|
2016-04-22 04:50:15 +08:00
|
|
|
Define("_end", ElfSym<ELFT>::End, ElfSym<ELFT>::End2);
|
|
|
|
Define("_etext", ElfSym<ELFT>::Etext, ElfSym<ELFT>::Etext2);
|
|
|
|
Define("_edata", ElfSym<ELFT>::Edata, ElfSym<ELFT>::Edata2);
|
2015-12-26 15:50:39 +08:00
|
|
|
}
|
|
|
|
|
2016-02-11 07:20:42 +08:00
|
|
|
// Sort input sections by section name suffixes for
|
|
|
|
// __attribute__((init_priority(N))).
|
2016-02-12 07:41:38 +08:00
|
|
|
template <class ELFT> static void sortInitFini(OutputSectionBase<ELFT> *S) {
|
2016-02-11 07:20:42 +08:00
|
|
|
if (S)
|
2016-02-12 07:41:38 +08:00
|
|
|
reinterpret_cast<OutputSection<ELFT> *>(S)->sortInitFini();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort input sections by the special rule for .ctors and .dtors.
|
|
|
|
template <class ELFT> static void sortCtorsDtors(OutputSectionBase<ELFT> *S) {
|
|
|
|
if (S)
|
|
|
|
reinterpret_cast<OutputSection<ELFT> *>(S)->sortCtorsDtors();
|
2016-02-11 07:20:42 +08:00
|
|
|
}
|
|
|
|
|
2015-07-25 05:03:07 +08:00
|
|
|
// Create output section objects and add them to OutputSections.
|
2016-04-02 01:24:19 +08:00
|
|
|
template <class ELFT> void Writer<ELFT>::createSections() {
|
2015-12-26 18:22:16 +08:00
|
|
|
// Add .interp first because some loaders want to see that section
|
|
|
|
// on the first page of the executable file when loaded into memory.
|
2015-10-11 07:25:39 +08:00
|
|
|
if (needsInterpSection())
|
|
|
|
OutputSections.push_back(Out<ELFT>::Interp);
|
|
|
|
|
2016-03-13 09:54:48 +08:00
|
|
|
// A core file does not usually contain unmodified segments except
|
|
|
|
// the first page of the executable. Add the build ID section now
|
|
|
|
// so that the section is included in the first page.
|
|
|
|
if (Out<ELFT>::BuildId)
|
|
|
|
OutputSections.push_back(Out<ELFT>::BuildId);
|
|
|
|
|
2015-12-26 18:22:16 +08:00
|
|
|
// Create output sections for input object file sections.
|
2015-10-16 06:27:29 +08:00
|
|
|
std::vector<OutputSectionBase<ELFT> *> RegularSections;
|
2015-12-26 15:01:28 +08:00
|
|
|
OutputSectionFactory<ELFT> Factory;
|
2016-03-12 00:41:23 +08:00
|
|
|
for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
|
|
|
|
Symtab.getObjectFiles()) {
|
2015-10-20 05:00:02 +08:00
|
|
|
for (InputSectionBase<ELFT> *C : F->getSections()) {
|
2015-12-10 17:12:18 +08:00
|
|
|
if (isDiscarded(C)) {
|
|
|
|
reportDiscarded(C, F);
|
2015-09-16 23:54:15 +08:00
|
|
|
continue;
|
2015-12-10 17:12:18 +08:00
|
|
|
}
|
2015-12-26 15:01:28 +08:00
|
|
|
OutputSectionBase<ELFT> *Sec;
|
|
|
|
bool IsNew;
|
2016-02-13 05:47:28 +08:00
|
|
|
std::tie(Sec, IsNew) = Factory.create(C, getOutputSectionName(C));
|
2015-12-26 15:01:28 +08:00
|
|
|
if (IsNew) {
|
2015-12-26 15:01:26 +08:00
|
|
|
OwningSections.emplace_back(Sec);
|
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-12-26 13:51:07 +08:00
|
|
|
Sec->addSection(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> *>(
|
2015-12-26 15:01:28 +08:00
|
|
|
Factory.lookup(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE));
|
2015-11-04 05:35:14 +08:00
|
|
|
|
2015-12-26 15:50:41 +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.
|
|
|
|
Out<ELFT>::Opd = Factory.lookup(".opd", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC);
|
|
|
|
|
2015-12-26 15:01:28 +08:00
|
|
|
Out<ELFT>::Dynamic->PreInitArraySec = Factory.lookup(
|
|
|
|
".preinit_array", SHT_PREINIT_ARRAY, SHF_WRITE | SHF_ALLOC);
|
2015-10-08 03:18:16 +08:00
|
|
|
Out<ELFT>::Dynamic->InitArraySec =
|
2015-12-26 15:01:28 +08:00
|
|
|
Factory.lookup(".init_array", SHT_INIT_ARRAY, SHF_WRITE | SHF_ALLOC);
|
2015-10-08 03:18:16 +08:00
|
|
|
Out<ELFT>::Dynamic->FiniArraySec =
|
2015-12-26 15:01:28 +08:00
|
|
|
Factory.lookup(".fini_array", SHT_FINI_ARRAY, SHF_WRITE | SHF_ALLOC);
|
2015-10-03 03:37:55 +08:00
|
|
|
|
2016-02-11 07:20:42 +08:00
|
|
|
// Sort section contents for __attribute__((init_priority(N)).
|
2016-02-12 07:41:38 +08:00
|
|
|
sortInitFini(Out<ELFT>::Dynamic->InitArraySec);
|
|
|
|
sortInitFini(Out<ELFT>::Dynamic->FiniArraySec);
|
|
|
|
sortCtorsDtors(Factory.lookup(".ctors", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC));
|
|
|
|
sortCtorsDtors(Factory.lookup(".dtors", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC));
|
2016-02-11 07:20:42 +08:00
|
|
|
|
2015-12-26 17:48:00 +08:00
|
|
|
// The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop
|
|
|
|
// symbols for sections, so that the runtime can get the start and end
|
|
|
|
// addresses of each section by section name. Add such symbols.
|
2016-03-02 03:12:35 +08:00
|
|
|
if (!Config->Relocatable) {
|
|
|
|
addStartEndSymbols();
|
|
|
|
for (OutputSectionBase<ELFT> *Sec : RegularSections)
|
|
|
|
addStartStopSymbols(Sec);
|
|
|
|
}
|
2016-03-05 02:34:14 +08:00
|
|
|
|
|
|
|
// Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type.
|
|
|
|
// It should be okay as no one seems to care about the type.
|
|
|
|
// Even the author of gold doesn't remember why gold behaves that way.
|
|
|
|
// https://sourceware.org/ml/binutils/2002-03/msg00360.html
|
2016-03-02 00:23:13 +08:00
|
|
|
if (isOutputDynamic())
|
2016-05-03 09:21:08 +08:00
|
|
|
Symtab.addSynthetic("_DYNAMIC", Out<ELFT>::Dynamic, 0);
|
2015-10-19 23:21:42 +08:00
|
|
|
|
2016-02-05 05:33:05 +08:00
|
|
|
// Define __rel[a]_iplt_{start,end} symbols if needed.
|
|
|
|
addRelIpltSymbols();
|
|
|
|
|
2016-04-07 22:22:09 +08:00
|
|
|
if (Out<ELFT>::EhFrameHdr->Sec)
|
|
|
|
Out<ELFT>::EhFrameHdr->Sec->finalize();
|
|
|
|
|
2015-10-19 23:21:42 +08:00
|
|
|
// Scan relocations. This must be done after every symbol is declared so that
|
|
|
|
// we can correctly decide if a dynamic relocation is needed.
|
2016-04-07 23:50:23 +08:00
|
|
|
// Check size() each time to guard against .bss being created.
|
|
|
|
for (unsigned I = 0; I < OutputSections.size(); ++I) {
|
|
|
|
OutputSectionBase<ELFT> *Sec = OutputSections[I];
|
2016-04-07 22:22:09 +08:00
|
|
|
Sec->forEachInputSection([&](InputSectionBase<ELFT> *S) {
|
|
|
|
if (auto *IS = dyn_cast<InputSection<ELFT>>(S)) {
|
|
|
|
// Set OutSecOff so that scanRelocs can use it.
|
|
|
|
uintX_t Off = alignTo(Sec->getSize(), S->Align);
|
|
|
|
IS->OutSecOff = Off;
|
|
|
|
|
|
|
|
scanRelocs(*IS);
|
|
|
|
|
|
|
|
// Now that scan relocs possibly changed the size, update the offset.
|
|
|
|
Sec->setSize(Off + S->getSize());
|
|
|
|
} else if (auto *EH = dyn_cast<EHInputSection<ELFT>>(S)) {
|
|
|
|
if (EH->RelocSection)
|
|
|
|
scanRelocs(*EH, *EH->RelocSection);
|
|
|
|
}
|
|
|
|
});
|
2015-11-12 03:54:14 +08:00
|
|
|
}
|
2015-10-19 23:21:42 +08:00
|
|
|
|
2015-12-26 18:22:16 +08:00
|
|
|
// Now that we have defined all possible symbols including linker-
|
|
|
|
// synthesized ones. Visit all symbols to give the finishing touches.
|
2015-12-25 00:23:37 +08:00
|
|
|
std::vector<DefinedCommon *> CommonSymbols;
|
2016-04-15 04:42:43 +08:00
|
|
|
for (Symbol *S : Symtab.getSymbols()) {
|
ELF: New symbol table design.
This patch implements a new design for the symbol table that stores
SymbolBodies within a memory region of the Symbol object. Symbols are mutated
by constructing SymbolBodies in place over existing SymbolBodies, rather
than by mutating pointers. As mentioned in the initial proposal [1], this
memory layout helps reduce the cache miss rate by improving memory locality.
Performance numbers:
old(s) new(s)
Without debug info:
chrome 7.178 6.432 (-11.5%)
LLVMgold.so 0.505 0.502 (-0.5%)
clang 0.954 0.827 (-15.4%)
llvm-as 0.052 0.045 (-15.5%)
With debug info:
scylla 5.695 5.613 (-1.5%)
clang 14.396 14.143 (-1.8%)
Performance counter results show that the fewer required indirections is
indeed the cause of the improved performance. For example, when linking
chrome, stalled cycles decreases from 14,556,444,002 to 12,959,238,310, and
instructions per cycle increases from 0.78 to 0.83. We are also executing
many fewer instructions (15,516,401,933 down to 15,002,434,310), probably
because we spend less time allocating SymbolBodies.
The new mechanism by which symbols are added to the symbol table is by calling
add* functions on the SymbolTable.
In this patch, I handle local symbols by storing them inside "unparented"
SymbolBodies. This is suboptimal, but if we do want to try to avoid allocating
these SymbolBodies, we can probably do that separately.
I also removed a few members from the SymbolBody class that were only being
used to pass information from the input file to the symbol table.
This patch implements the new design for the ELF linker only. I intend to
prepare a similar patch for the COFF linker.
[1] http://lists.llvm.org/pipermail/llvm-dev/2016-April/098832.html
Differential Revision: http://reviews.llvm.org/D19752
llvm-svn: 268178
2016-05-01 12:55:03 +08:00
|
|
|
SymbolBody *Body = S->body();
|
2016-04-26 21:56:26 +08:00
|
|
|
|
|
|
|
// Set "used" bit for --as-needed.
|
|
|
|
if (S->IsUsedInRegularObj && !S->isWeak())
|
|
|
|
if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(Body))
|
|
|
|
SS->File->IsUsed = true;
|
|
|
|
|
2016-05-06 01:13:49 +08:00
|
|
|
// We only report undefined symbols in regular objects. This means that we
|
|
|
|
// will accept an undefined reference in bitcode if it can be optimized out.
|
|
|
|
if (S->IsUsedInRegularObj && Body->isUndefined() && !S->isWeak())
|
2016-04-27 08:05:03 +08:00
|
|
|
reportUndefined<ELFT>(Symtab, Body);
|
2015-09-23 07:38:23 +08:00
|
|
|
|
2015-12-25 00:23:37 +08:00
|
|
|
if (auto *C = dyn_cast<DefinedCommon>(Body))
|
2015-09-23 07:38:23 +08:00
|
|
|
CommonSymbols.push_back(C);
|
2015-10-29 00:48:58 +08:00
|
|
|
|
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
|
|
|
|
2016-04-28 04:22:31 +08:00
|
|
|
if (isOutputDynamic() && S->includeInDynsym()) {
|
2015-10-21 05:47:58 +08:00
|
|
|
Out<ELFT>::DynSymTab->addSymbol(Body);
|
2016-04-28 04:22:31 +08:00
|
|
|
if (auto *SS = dyn_cast<SharedSymbol<ELFT>>(Body))
|
|
|
|
Out<ELFT>::VerNeed->addSymbol(SS);
|
|
|
|
}
|
2015-09-23 07:38:23 +08:00
|
|
|
}
|
2016-01-29 06:56:29 +08:00
|
|
|
|
|
|
|
// Do not proceed if there was an undefined symbol.
|
|
|
|
if (HasError)
|
2016-04-02 01:24:19 +08:00
|
|
|
return;
|
2016-01-29 06:56:29 +08:00
|
|
|
|
2015-10-09 07:49:30 +08:00
|
|
|
addCommonSymbols(CommonSymbols);
|
2015-07-25 05:03:07 +08:00
|
|
|
|
2015-12-26 15:50:41 +08:00
|
|
|
// So far we have added sections from input object files.
|
|
|
|
// This function adds linker-created Out<ELFT>::* sections.
|
|
|
|
addPredefinedSections();
|
|
|
|
|
|
|
|
std::stable_sort(OutputSections.begin(), OutputSections.end(),
|
|
|
|
compareSections<ELFT>);
|
|
|
|
|
2016-04-06 15:20:45 +08:00
|
|
|
unsigned I = 1;
|
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
|
|
|
|
Sec->SectionIndex = I++;
|
2016-01-29 09:24:25 +08:00
|
|
|
Sec->setSHName(Out<ELFT>::ShStrTab->addString(Sec->getName()));
|
2016-04-06 15:20:45 +08:00
|
|
|
}
|
2015-12-26 15:50:41 +08:00
|
|
|
|
|
|
|
// Finalizers fix each section's size.
|
2016-01-26 05:32:04 +08:00
|
|
|
// .dynsym is finalized early since that may fill up .gnu.hash.
|
2015-12-26 15:50:41 +08:00
|
|
|
if (isOutputDynamic())
|
|
|
|
Out<ELFT>::DynSymTab->finalize();
|
|
|
|
|
2016-02-02 17:07:47 +08:00
|
|
|
// Fill other section headers. The dynamic table is finalized
|
|
|
|
// at the end because some tags like RELSZ depend on result
|
|
|
|
// of finalizing other sections. The dynamic string table is
|
|
|
|
// finalized once the .dynamic finalizer has added a few last
|
|
|
|
// strings. See DynamicSection::finalize()
|
2015-12-26 15:50:41 +08:00
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
2016-02-02 17:07:47 +08:00
|
|
|
if (Sec != Out<ELFT>::DynStrTab && Sec != Out<ELFT>::Dynamic)
|
2016-01-26 05:32:04 +08:00
|
|
|
Sec->finalize();
|
2016-02-02 17:07:47 +08:00
|
|
|
|
|
|
|
if (isOutputDynamic())
|
|
|
|
Out<ELFT>::Dynamic->finalize();
|
2015-12-26 15:50:41 +08:00
|
|
|
}
|
|
|
|
|
2016-02-26 03:34:37 +08:00
|
|
|
template <class ELFT> bool Writer<ELFT>::needsGot() {
|
|
|
|
if (!Out<ELFT>::Got->empty())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// We add the .got section to the result for dynamic MIPS target because
|
|
|
|
// its address and properties are mentioned in the .dynamic section.
|
2016-04-12 21:21:13 +08:00
|
|
|
if (Config->EMachine == EM_MIPS)
|
2016-02-26 03:34:37 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
// If we have a relocation that is relative to GOT (such as GOTOFFREL),
|
|
|
|
// we need to emit a GOT even if it's empty.
|
|
|
|
return HasGotOffRel;
|
|
|
|
}
|
|
|
|
|
2015-12-26 15:50:41 +08:00
|
|
|
// This function add Out<ELFT>::* sections to OutputSections.
|
|
|
|
template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
|
2015-12-26 18:34:33 +08:00
|
|
|
auto Add = [&](OutputSectionBase<ELFT> *C) {
|
|
|
|
if (C)
|
|
|
|
OutputSections.push_back(C);
|
|
|
|
};
|
|
|
|
|
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-12-26 18:34:33 +08:00
|
|
|
Add(Out<ELFT>::SymTab);
|
|
|
|
Add(Out<ELFT>::ShStrTab);
|
|
|
|
Add(Out<ELFT>::StrTab);
|
2015-10-13 07:39:23 +08:00
|
|
|
if (isOutputDynamic()) {
|
2015-12-26 18:34:33 +08:00
|
|
|
Add(Out<ELFT>::DynSymTab);
|
2016-04-28 04:22:31 +08:00
|
|
|
if (Out<ELFT>::VerNeed->getNeedNum() != 0) {
|
|
|
|
Add(Out<ELFT>::VerSym);
|
|
|
|
Add(Out<ELFT>::VerNeed);
|
|
|
|
}
|
2015-12-26 18:34:33 +08:00
|
|
|
Add(Out<ELFT>::GnuHashTab);
|
|
|
|
Add(Out<ELFT>::HashTab);
|
|
|
|
Add(Out<ELFT>::Dynamic);
|
|
|
|
Add(Out<ELFT>::DynStrTab);
|
2015-10-08 03:18:16 +08:00
|
|
|
if (Out<ELFT>::RelaDyn->hasRelocs())
|
2015-12-26 18:34:33 +08:00
|
|
|
Add(Out<ELFT>::RelaDyn);
|
2016-02-26 07:54:49 +08:00
|
|
|
Add(Out<ELFT>::MipsRldMap);
|
2015-09-09 23:33:08 +08:00
|
|
|
}
|
2015-11-12 12:39:49 +08:00
|
|
|
|
2015-12-21 18:12:06 +08:00
|
|
|
// 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()) {
|
2015-12-26 18:34:33 +08:00
|
|
|
Add(Out<ELFT>::RelaPlt);
|
2015-12-21 18:12:06 +08:00
|
|
|
Out<ELFT>::RelaPlt->Static = !isOutputDynamic();
|
|
|
|
}
|
|
|
|
|
2016-02-26 03:34:37 +08:00
|
|
|
if (needsGot())
|
2015-12-26 18:34:33 +08:00
|
|
|
Add(Out<ELFT>::Got);
|
2015-10-20 16:54:27 +08:00
|
|
|
if (Out<ELFT>::GotPlt && !Out<ELFT>::GotPlt->empty())
|
2015-12-26 18:34:33 +08:00
|
|
|
Add(Out<ELFT>::GotPlt);
|
2015-10-08 03:18:16 +08:00
|
|
|
if (!Out<ELFT>::Plt->empty())
|
2015-12-26 18:34:33 +08:00
|
|
|
Add(Out<ELFT>::Plt);
|
2016-01-15 21:34:52 +08:00
|
|
|
if (Out<ELFT>::EhFrameHdr->Live)
|
|
|
|
Add(Out<ELFT>::EhFrameHdr);
|
2015-08-13 23:23:46 +08:00
|
|
|
}
|
|
|
|
|
2015-12-26 17:48:00 +08:00
|
|
|
// The linker is expected to define SECNAME_start and SECNAME_end
|
|
|
|
// symbols for a few sections. This function defines them.
|
|
|
|
template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
|
|
|
|
auto Define = [&](StringRef Start, StringRef End,
|
|
|
|
OutputSectionBase<ELFT> *OS) {
|
|
|
|
if (OS) {
|
2016-05-03 09:21:08 +08:00
|
|
|
this->Symtab.addSynthetic(Start, OS, 0);
|
|
|
|
this->Symtab.addSynthetic(End, OS, DefinedSynthetic<ELFT>::SectionEnd);
|
2015-12-26 17:48:00 +08:00
|
|
|
} else {
|
2016-05-03 09:21:08 +08:00
|
|
|
addOptionalSynthetic(this->Symtab, Start,
|
|
|
|
(OutputSectionBase<ELFT> *)nullptr, 0);
|
|
|
|
addOptionalSynthetic(this->Symtab, End,
|
|
|
|
(OutputSectionBase<ELFT> *)nullptr, 0);
|
2015-12-26 17:48:00 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Define("__preinit_array_start", "__preinit_array_end",
|
|
|
|
Out<ELFT>::Dynamic->PreInitArraySec);
|
|
|
|
Define("__init_array_start", "__init_array_end",
|
|
|
|
Out<ELFT>::Dynamic->InitArraySec);
|
|
|
|
Define("__fini_array_start", "__fini_array_end",
|
|
|
|
Out<ELFT>::Dynamic->FiniArraySec);
|
|
|
|
}
|
|
|
|
|
2015-10-16 01:11:03 +08:00
|
|
|
// 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);
|
2016-01-06 04:35:16 +08:00
|
|
|
if (SymbolBody *B = Symtab.find(Start))
|
|
|
|
if (B->isUndefined())
|
2016-05-03 09:21:08 +08:00
|
|
|
Symtab.addSynthetic(Start, Sec, 0);
|
2016-01-06 04:35:16 +08:00
|
|
|
if (SymbolBody *B = Symtab.find(Stop))
|
|
|
|
if (B->isUndefined())
|
2016-05-03 09:21:08 +08:00
|
|
|
Symtab.addSynthetic(Stop, Sec, DefinedSynthetic<ELFT>::SectionEnd);
|
2015-10-16 01:11:03 +08:00
|
|
|
}
|
|
|
|
|
2016-02-11 07:29:38 +08:00
|
|
|
template <class ELFT> static bool needsPtLoad(OutputSectionBase<ELFT> *Sec) {
|
|
|
|
if (!(Sec->getFlags() & SHF_ALLOC))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is
|
|
|
|
// responsible for allocating space for them, not the PT_LOAD that
|
|
|
|
// contains the TLS initialization image.
|
|
|
|
if (Sec->getFlags() & SHF_TLS && Sec->getType() == SHT_NOBITS)
|
|
|
|
return false;
|
|
|
|
return true;
|
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;
|
|
|
|
}
|
|
|
|
|
2016-02-11 06:43:13 +08:00
|
|
|
// Decide which program headers to create and which sections to include in each
|
|
|
|
// one.
|
|
|
|
template <class ELFT> void Writer<ELFT>::createPhdrs() {
|
|
|
|
auto AddHdr = [this](unsigned Type, unsigned Flags) {
|
|
|
|
return &*Phdrs.emplace(Phdrs.end(), Type, Flags);
|
|
|
|
};
|
2015-09-10 04:48:09 +08:00
|
|
|
|
2016-02-11 06:43:13 +08:00
|
|
|
auto AddSec = [](Phdr &Hdr, OutputSectionBase<ELFT> *Sec) {
|
|
|
|
Hdr.Last = Sec;
|
|
|
|
if (!Hdr.First)
|
|
|
|
Hdr.First = Sec;
|
|
|
|
Hdr.H.p_align = std::max<uintX_t>(Hdr.H.p_align, Sec->getAlign());
|
|
|
|
};
|
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.
|
2016-02-11 06:43:13 +08:00
|
|
|
Phdr &Hdr = *AddHdr(PT_PHDR, PF_R);
|
|
|
|
AddSec(Hdr, Out<ELFT>::ProgramHeaders);
|
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.
|
2016-02-11 06:43:13 +08:00
|
|
|
if (needsInterpSection()) {
|
|
|
|
Phdr &Hdr = *AddHdr(PT_INTERP, toPhdrFlags(Out<ELFT>::Interp->getFlags()));
|
|
|
|
AddSec(Hdr, Out<ELFT>::Interp);
|
|
|
|
}
|
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.
|
2016-02-11 06:43:13 +08:00
|
|
|
uintX_t Flags = PF_R;
|
|
|
|
Phdr *Load = AddHdr(PT_LOAD, Flags);
|
|
|
|
AddSec(*Load, Out<ELFT>::ElfHeader);
|
2016-04-06 15:20:45 +08:00
|
|
|
AddSec(*Load, Out<ELFT>::ProgramHeaders);
|
2015-09-10 23:41:34 +08:00
|
|
|
|
2016-02-11 06:43:13 +08:00
|
|
|
Phdr TlsHdr(PT_TLS, PF_R);
|
|
|
|
Phdr RelRo(PT_GNU_RELRO, PF_R);
|
2016-03-01 21:23:29 +08:00
|
|
|
Phdr Note(PT_NOTE, PF_R);
|
2015-10-16 06:27:29 +08:00
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
|
2016-02-11 07:29:38 +08:00
|
|
|
if (!(Sec->getFlags() & SHF_ALLOC))
|
2016-02-11 06:43:13 +08:00
|
|
|
break;
|
|
|
|
|
2016-02-11 07:29:38 +08:00
|
|
|
// If we meet TLS section then we create TLS header
|
|
|
|
// and put all TLS sections inside for futher use when
|
|
|
|
// assign addresses.
|
|
|
|
if (Sec->getFlags() & SHF_TLS)
|
|
|
|
AddSec(TlsHdr, Sec);
|
|
|
|
|
|
|
|
if (!needsPtLoad<ELFT>(Sec))
|
|
|
|
continue;
|
|
|
|
|
2016-02-11 06:43:13 +08:00
|
|
|
// If flags changed then we want new load segment.
|
|
|
|
uintX_t NewFlags = toPhdrFlags(Sec->getFlags());
|
|
|
|
if (Flags != NewFlags) {
|
2016-03-10 05:37:22 +08:00
|
|
|
Load = AddHdr(PT_LOAD, NewFlags);
|
2016-02-11 06:43:13 +08:00
|
|
|
Flags = NewFlags;
|
2015-08-13 23:31:17 +08:00
|
|
|
}
|
2015-08-12 08:00:24 +08:00
|
|
|
|
2016-02-11 06:43:13 +08:00
|
|
|
AddSec(*Load, Sec);
|
|
|
|
|
|
|
|
if (isRelroSection(Sec))
|
|
|
|
AddSec(RelRo, Sec);
|
2016-03-01 21:23:29 +08:00
|
|
|
if (Sec->getType() == SHT_NOTE)
|
|
|
|
AddSec(Note, Sec);
|
2015-11-05 10:00:35 +08:00
|
|
|
}
|
2015-11-03 08:34:39 +08:00
|
|
|
|
2016-02-11 06:43:13 +08:00
|
|
|
// Add the TLS segment unless it's empty.
|
|
|
|
if (TlsHdr.First)
|
|
|
|
Phdrs.push_back(std::move(TlsHdr));
|
|
|
|
|
2015-10-24 05:45:59 +08:00
|
|
|
// Add an entry for .dynamic.
|
2015-10-13 07:39:23 +08:00
|
|
|
if (isOutputDynamic()) {
|
2016-02-11 06:43:13 +08:00
|
|
|
Phdr &H = *AddHdr(PT_DYNAMIC, toPhdrFlags(Out<ELFT>::Dynamic->getFlags()));
|
|
|
|
AddSec(H, Out<ELFT>::Dynamic);
|
2015-10-11 06:34:30 +08:00
|
|
|
}
|
2015-08-12 09:45:28 +08:00
|
|
|
|
2016-02-11 06:43:13 +08:00
|
|
|
// PT_GNU_RELRO includes all sections that should be marked as
|
|
|
|
// read-only by dynamic linker after proccessing relocations.
|
|
|
|
if (RelRo.First)
|
|
|
|
Phdrs.push_back(std::move(RelRo));
|
2015-11-24 18:15:50 +08:00
|
|
|
|
2016-02-11 06:43:13 +08:00
|
|
|
// PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr.
|
2016-01-15 21:34:52 +08:00
|
|
|
if (Out<ELFT>::EhFrameHdr->Live) {
|
2016-02-11 06:43:13 +08:00
|
|
|
Phdr &Hdr = *AddHdr(PT_GNU_EH_FRAME,
|
|
|
|
toPhdrFlags(Out<ELFT>::EhFrameHdr->getFlags()));
|
|
|
|
AddSec(Hdr, Out<ELFT>::EhFrameHdr);
|
2016-01-15 21:34:52 +08:00
|
|
|
}
|
|
|
|
|
2015-11-22 06:19:32 +08:00
|
|
|
// PT_GNU_STACK is a special section to tell the loader to make the
|
|
|
|
// pages for the stack non-executable.
|
2016-02-11 06:43:13 +08:00
|
|
|
if (!Config->ZExecStack)
|
|
|
|
AddHdr(PT_GNU_STACK, PF_R | PF_W);
|
2016-03-01 21:23:29 +08:00
|
|
|
|
|
|
|
if (Note.First)
|
|
|
|
Phdrs.push_back(std::move(Note));
|
2016-04-02 01:30:52 +08:00
|
|
|
|
|
|
|
Out<ELFT>::ProgramHeaders->setSize(sizeof(Elf_Phdr) * Phdrs.size());
|
2016-02-11 06:43:13 +08:00
|
|
|
}
|
|
|
|
|
2016-03-31 03:41:51 +08:00
|
|
|
// The first section of each PT_LOAD and the first section after PT_GNU_RELRO
|
|
|
|
// have to be page aligned so that the dynamic linker can set the permissions.
|
|
|
|
template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
|
|
|
|
for (const Phdr &P : Phdrs)
|
|
|
|
if (P.H.p_type == PT_LOAD)
|
|
|
|
P.First->PageAlign = true;
|
|
|
|
|
|
|
|
for (const Phdr &P : Phdrs) {
|
|
|
|
if (P.H.p_type != PT_GNU_RELRO)
|
|
|
|
continue;
|
|
|
|
// Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we
|
|
|
|
// have to align it to a page.
|
|
|
|
auto End = OutputSections.end();
|
|
|
|
auto I = std::find(OutputSections.begin(), End, P.Last);
|
|
|
|
if (I == End || (I + 1) == End)
|
|
|
|
continue;
|
|
|
|
OutputSectionBase<ELFT> *Sec = *(I + 1);
|
|
|
|
if (needsPtLoad(Sec))
|
|
|
|
Sec->PageAlign = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-06 15:20:45 +08:00
|
|
|
// We should set file offsets and VAs for elf header and program headers
|
|
|
|
// sections. These are special, we do not include them into output sections
|
|
|
|
// list, but have them to simplify the code.
|
|
|
|
template <class ELFT> void Writer<ELFT>::fixHeaders() {
|
2016-04-21 04:13:41 +08:00
|
|
|
uintX_t BaseVA = ScriptConfig->DoLayout ? 0 : Target->getVAStart();
|
2016-04-16 18:10:32 +08:00
|
|
|
Out<ELFT>::ElfHeader->setVA(BaseVA);
|
2016-04-06 15:20:45 +08:00
|
|
|
Out<ELFT>::ElfHeader->setFileOffset(0);
|
|
|
|
uintX_t Off = Out<ELFT>::ElfHeader->getSize();
|
2016-04-16 18:10:32 +08:00
|
|
|
Out<ELFT>::ProgramHeaders->setVA(Off + BaseVA);
|
2016-04-06 15:20:45 +08:00
|
|
|
Out<ELFT>::ProgramHeaders->setFileOffset(Off);
|
|
|
|
}
|
|
|
|
|
2016-04-02 01:07:17 +08:00
|
|
|
// Assign VAs (addresses at run-time) to output sections.
|
2016-02-11 06:43:13 +08:00
|
|
|
template <class ELFT> void Writer<ELFT>::assignAddresses() {
|
2016-04-06 15:20:45 +08:00
|
|
|
uintX_t VA = Target->getVAStart() + Out<ELFT>::ElfHeader->getSize() +
|
|
|
|
Out<ELFT>::ProgramHeaders->getSize();
|
2016-02-11 06:43:13 +08:00
|
|
|
|
2016-04-06 15:20:45 +08:00
|
|
|
uintX_t ThreadBssOffset = 0;
|
2016-02-11 06:43:13 +08:00
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
|
|
|
|
uintX_t Align = Sec->getAlign();
|
2016-03-31 03:41:51 +08:00
|
|
|
if (Sec->PageAlign)
|
2016-02-11 06:43:13 +08:00
|
|
|
Align = std::max<uintX_t>(Align, Target->PageSize);
|
|
|
|
|
|
|
|
// We only assign VAs to allocated sections.
|
2016-02-11 07:29:38 +08:00
|
|
|
if (needsPtLoad<ELFT>(Sec)) {
|
|
|
|
VA = alignTo(VA, Align);
|
|
|
|
Sec->setVA(VA);
|
|
|
|
VA += Sec->getSize();
|
|
|
|
} else if (Sec->getFlags() & SHF_TLS && Sec->getType() == SHT_NOBITS) {
|
|
|
|
uintX_t TVA = VA + ThreadBssOffset;
|
|
|
|
TVA = alignTo(TVA, Align);
|
|
|
|
Sec->setVA(TVA);
|
|
|
|
ThreadBssOffset = TVA - VA + Sec->getSize();
|
2016-02-11 06:43:13 +08:00
|
|
|
}
|
2015-10-11 07:25:39 +08:00
|
|
|
}
|
2016-04-02 01:07:17 +08:00
|
|
|
}
|
2015-10-11 07:25:39 +08:00
|
|
|
|
2016-04-27 17:16:28 +08:00
|
|
|
// Adjusts the file alignment for a given output section and returns
|
|
|
|
// its new file offset. The file offset must be the same with its
|
|
|
|
// virtual address (modulo the page size) so that the loader can load
|
|
|
|
// executables without any address adjustment.
|
|
|
|
template <class ELFT, class uintX_t>
|
|
|
|
static uintX_t getFileAlignment(uintX_t Off, OutputSectionBase<ELFT> *Sec) {
|
|
|
|
uintX_t Align = Sec->getAlign();
|
|
|
|
if (Sec->PageAlign)
|
|
|
|
Align = std::max<uintX_t>(Align, Target->PageSize);
|
|
|
|
Off = alignTo(Off, Align);
|
|
|
|
|
|
|
|
// Relocatable output does not have program headers
|
|
|
|
// and does not need any other offset adjusting.
|
|
|
|
if (Config->Relocatable || !(Sec->getFlags() & SHF_ALLOC))
|
|
|
|
return Off;
|
|
|
|
return alignTo(Off, Target->PageSize, Sec->getVA());
|
|
|
|
}
|
|
|
|
|
2016-04-02 01:07:17 +08:00
|
|
|
// Assign file offsets to output sections.
|
|
|
|
template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
|
2016-04-06 15:20:45 +08:00
|
|
|
uintX_t Off =
|
|
|
|
Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
|
|
|
|
|
2016-04-02 01:07:17 +08:00
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
|
|
|
|
if (Sec->getType() == SHT_NOBITS) {
|
|
|
|
Sec->setFileOffset(Off);
|
|
|
|
continue;
|
|
|
|
}
|
2016-04-27 17:16:28 +08:00
|
|
|
|
|
|
|
Off = getFileAlignment<ELFT>(Off, Sec);
|
2016-04-02 01:07:17 +08:00
|
|
|
Sec->setFileOffset(Off);
|
|
|
|
Off += Sec->getSize();
|
|
|
|
}
|
|
|
|
SectionHeaderOff = alignTo(Off, sizeof(uintX_t));
|
2016-04-06 15:20:45 +08:00
|
|
|
FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr);
|
2016-04-01 18:49:14 +08:00
|
|
|
}
|
|
|
|
|
2016-04-02 01:07:17 +08:00
|
|
|
// Finalize the program headers. We call this function after we assign
|
|
|
|
// file offsets and VAs to all sections.
|
|
|
|
template <class ELFT> void Writer<ELFT>::setPhdrs() {
|
2016-04-02 06:42:04 +08:00
|
|
|
for (Phdr &P : Phdrs) {
|
|
|
|
Elf_Phdr &H = P.H;
|
|
|
|
OutputSectionBase<ELFT> *First = P.First;
|
|
|
|
OutputSectionBase<ELFT> *Last = P.Last;
|
|
|
|
if (First) {
|
|
|
|
H.p_filesz = Last->getFileOff() - First->getFileOff();
|
2016-02-11 06:43:13 +08:00
|
|
|
if (Last->getType() != SHT_NOBITS)
|
|
|
|
H.p_filesz += Last->getSize();
|
2016-04-02 06:42:04 +08:00
|
|
|
H.p_memsz = Last->getVA() + Last->getSize() - First->getVA();
|
|
|
|
H.p_offset = First->getFileOff();
|
|
|
|
H.p_vaddr = First->getVA();
|
2016-02-11 06:43:13 +08:00
|
|
|
}
|
2016-03-01 16:46:03 +08:00
|
|
|
if (H.p_type == PT_LOAD)
|
2016-02-11 06:43:13 +08:00
|
|
|
H.p_align = Target->PageSize;
|
2016-03-01 16:46:03 +08:00
|
|
|
else if (H.p_type == PT_GNU_RELRO)
|
2016-02-11 06:43:13 +08:00
|
|
|
H.p_align = 1;
|
|
|
|
H.p_paddr = H.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.
|
2016-03-01 16:46:03 +08:00
|
|
|
if (H.p_type == PT_TLS) {
|
2016-02-11 06:43:13 +08:00
|
|
|
Out<ELFT>::TlsPhdr = &H;
|
|
|
|
H.p_memsz = alignTo(H.p_memsz, H.p_align);
|
2015-10-24 05:45:59 +08:00
|
|
|
}
|
|
|
|
}
|
2015-07-25 05:03:07 +08:00
|
|
|
}
|
|
|
|
|
2016-04-29 18:39:17 +08:00
|
|
|
static uint32_t getMipsEFlags(bool Is64Bits) {
|
2015-12-19 13:51:49 +08:00
|
|
|
// FIXME: In fact ELF flags depends on ELF flags of input object files
|
2016-01-12 14:24:02 +08:00
|
|
|
// and selected emulation. For now just use hard coded values.
|
2016-04-29 18:39:17 +08:00
|
|
|
if (Is64Bits)
|
|
|
|
return EF_MIPS_CPIC | EF_MIPS_PIC | EF_MIPS_ARCH_64R2;
|
|
|
|
|
|
|
|
uint32_t V = EF_MIPS_CPIC | EF_MIPS_ABI_O32 | EF_MIPS_ARCH_32R2;
|
2015-12-19 13:51:49 +08:00
|
|
|
if (Config->Shared)
|
|
|
|
V |= EF_MIPS_PIC;
|
|
|
|
return V;
|
|
|
|
}
|
|
|
|
|
2016-03-15 07:16:09 +08:00
|
|
|
template <class ELFT> static typename ELFT::uint getEntryAddr() {
|
2016-04-15 22:41:56 +08:00
|
|
|
if (Symbol *S = Config->EntrySym)
|
ELF: New symbol table design.
This patch implements a new design for the symbol table that stores
SymbolBodies within a memory region of the Symbol object. Symbols are mutated
by constructing SymbolBodies in place over existing SymbolBodies, rather
than by mutating pointers. As mentioned in the initial proposal [1], this
memory layout helps reduce the cache miss rate by improving memory locality.
Performance numbers:
old(s) new(s)
Without debug info:
chrome 7.178 6.432 (-11.5%)
LLVMgold.so 0.505 0.502 (-0.5%)
clang 0.954 0.827 (-15.4%)
llvm-as 0.052 0.045 (-15.5%)
With debug info:
scylla 5.695 5.613 (-1.5%)
clang 14.396 14.143 (-1.8%)
Performance counter results show that the fewer required indirections is
indeed the cause of the improved performance. For example, when linking
chrome, stalled cycles decreases from 14,556,444,002 to 12,959,238,310, and
instructions per cycle increases from 0.78 to 0.83. We are also executing
many fewer instructions (15,516,401,933 down to 15,002,434,310), probably
because we spend less time allocating SymbolBodies.
The new mechanism by which symbols are added to the symbol table is by calling
add* functions on the SymbolTable.
In this patch, I handle local symbols by storing them inside "unparented"
SymbolBodies. This is suboptimal, but if we do want to try to avoid allocating
these SymbolBodies, we can probably do that separately.
I also removed a few members from the SymbolBody class that were only being
used to pass information from the input file to the symbol table.
This patch implements the new design for the ELF linker only. I intend to
prepare a similar patch for the COFF linker.
[1] http://lists.llvm.org/pipermail/llvm-dev/2016-April/098832.html
Differential Revision: http://reviews.llvm.org/D19752
llvm-svn: 268178
2016-05-01 12:55:03 +08:00
|
|
|
return S->body()->getVA<ELFT>();
|
2015-12-24 16:37:34 +08:00
|
|
|
if (Config->EntryAddr != uint64_t(-1))
|
|
|
|
return Config->EntryAddr;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-02-26 03:28:37 +08:00
|
|
|
template <class ELFT> static uint8_t getELFEncoding() {
|
|
|
|
if (ELFT::TargetEndianness == llvm::support::little)
|
|
|
|
return ELFDATA2LSB;
|
|
|
|
return ELFDATA2MSB;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint16_t getELFType() {
|
2016-03-17 13:57:33 +08:00
|
|
|
if (Config->Pic)
|
2016-02-26 03:28:37 +08:00
|
|
|
return ET_DYN;
|
|
|
|
if (Config->Relocatable)
|
|
|
|
return ET_REL;
|
|
|
|
return ET_EXEC;
|
|
|
|
}
|
|
|
|
|
2015-12-26 18:52:26 +08:00
|
|
|
// This function is called after we have assigned address and size
|
|
|
|
// to each section. This function fixes some predefined absolute
|
|
|
|
// symbol values that depend on section address and size.
|
|
|
|
template <class ELFT> void Writer<ELFT>::fixAbsoluteSymbols() {
|
2016-04-22 04:50:15 +08:00
|
|
|
auto Set = [](DefinedRegular<ELFT> *&S1, DefinedRegular<ELFT> *&S2,
|
|
|
|
uintX_t V) {
|
|
|
|
if (S1)
|
|
|
|
S1->Value = V;
|
|
|
|
if (S2)
|
|
|
|
S2->Value = V;
|
|
|
|
};
|
|
|
|
|
2016-03-02 03:18:07 +08:00
|
|
|
// _etext is the first location after the last read-only loadable segment.
|
|
|
|
// _edata is the first location after the last read-write loadable segment.
|
2016-04-01 18:23:32 +08:00
|
|
|
// _end is the first location after the uninitialized data region.
|
2016-04-02 06:42:04 +08:00
|
|
|
for (Phdr &P : Phdrs) {
|
|
|
|
Elf_Phdr &H = P.H;
|
|
|
|
if (H.p_type != PT_LOAD)
|
2016-02-26 22:36:36 +08:00
|
|
|
continue;
|
2016-04-22 04:50:15 +08:00
|
|
|
Set(ElfSym<ELFT>::End, ElfSym<ELFT>::End2, H.p_vaddr + H.p_memsz);
|
2016-04-14 22:37:59 +08:00
|
|
|
|
|
|
|
uintX_t Val = H.p_vaddr + H.p_filesz;
|
|
|
|
if (H.p_flags & PF_W)
|
2016-04-22 04:50:15 +08:00
|
|
|
Set(ElfSym<ELFT>::Edata, ElfSym<ELFT>::Edata2, Val);
|
2016-04-14 22:37:59 +08:00
|
|
|
else
|
2016-04-22 04:50:15 +08:00
|
|
|
Set(ElfSym<ELFT>::Etext, ElfSym<ELFT>::Etext2, Val);
|
2016-02-26 22:36:36 +08:00
|
|
|
}
|
2015-12-26 18:52:26 +08:00
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
2016-02-26 03:28:37 +08:00
|
|
|
auto &FirstObj = cast<ELFFileBase<ELFT>>(*Config->FirstElf);
|
|
|
|
|
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;
|
2016-02-26 03:28:37 +08:00
|
|
|
EHdr->e_ident[EI_DATA] = getELFEncoding<ELFT>();
|
2015-07-25 05:03:07 +08:00
|
|
|
EHdr->e_ident[EI_VERSION] = EV_CURRENT;
|
2015-09-25 09:59:13 +08:00
|
|
|
EHdr->e_ident[EI_OSABI] = FirstObj.getOSABI();
|
2016-02-26 03:28:37 +08:00
|
|
|
EHdr->e_type = getELFType();
|
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-12-24 16:37:34 +08:00
|
|
|
EHdr->e_entry = getEntryAddr<ELFT>();
|
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);
|
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);
|
2016-04-06 15:20:45 +08:00
|
|
|
EHdr->e_shnum = OutputSections.size() + 1;
|
2015-10-21 01:21:35 +08:00
|
|
|
EHdr->e_shstrndx = Out<ELFT>::ShStrTab->SectionIndex;
|
2015-10-25 01:57:40 +08:00
|
|
|
|
2016-03-14 03:29:17 +08:00
|
|
|
if (Config->EMachine == EM_MIPS)
|
2016-04-29 18:39:17 +08:00
|
|
|
EHdr->e_flags = getMipsEFlags(ELFT::Is64Bits);
|
2016-03-14 03:29:17 +08:00
|
|
|
|
2016-02-25 16:23:37 +08:00
|
|
|
if (!Config->Relocatable) {
|
|
|
|
EHdr->e_phoff = sizeof(Elf_Ehdr);
|
|
|
|
EHdr->e_phentsize = sizeof(Elf_Phdr);
|
|
|
|
}
|
|
|
|
|
2015-10-25 01:57:40 +08:00
|
|
|
// Write the program header table.
|
2016-02-11 06:43:13 +08:00
|
|
|
auto *HBuf = reinterpret_cast<Elf_Phdr *>(Buf + EHdr->e_phoff);
|
|
|
|
for (Phdr &P : Phdrs)
|
|
|
|
*HBuf++ = P.H;
|
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.
|
2016-02-26 07:58:21 +08:00
|
|
|
auto *SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);
|
2016-04-06 15:20:45 +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
|
|
|
}
|
|
|
|
|
2016-04-02 01:24:19 +08:00
|
|
|
template <class ELFT> void Writer<ELFT>::openFile() {
|
2015-08-13 08:31:46 +08:00
|
|
|
ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
|
2016-02-03 06:48:04 +08:00
|
|
|
FileOutputBuffer::create(Config->OutputFile, FileSize,
|
|
|
|
FileOutputBuffer::F_executable);
|
2016-04-02 01:24:19 +08:00
|
|
|
if (BufferOrErr)
|
|
|
|
Buffer = std::move(*BufferOrErr);
|
|
|
|
else
|
2016-03-13 12:25:41 +08:00
|
|
|
error(BufferOrErr, "failed to open " + Config->OutputFile);
|
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)
|
2016-02-02 05:52:00 +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
|
|
|
|
ELF: Implement --build-id.
This patch implements --build-id. After the linker creates an output file
in the memory buffer, it computes the FNV1 hash of the resulting file
and set the hash to the .note section as a build-id.
GNU ld and gold have the same feature, but their default choice of the
hash function is different. Their default is SHA1.
We made a deliberate choice to not use a secure hash function for the
sake of performance. Computing a secure hash is slow -- for example,
MD5 throughput is usually 400 MB/s or so. SHA1 is slower than that.
As a result, if you pass --build-id to gold, then the linker becomes about
10% slower than that without the option. We observed a similar degradation
in an experimental implementation of build-id for LLD. On the other hand,
we observed only 1-2% performance degradation with the FNV hash.
Since build-id is not for digital certificate or anything, we think that
a very small probability of collision is acceptable.
We considered using other signals such as using input file timestamps as
inputs to a secure hash function. But such signals would have an issue
with build reproducibility (if you build a binary from the same source
tree using the same toolchain, the build id should become the same.)
GNU linkers accepts --build-id=<style> option where style is one of
"MD5", "SHA1", or an arbitrary hex string. That option is out of scope
of this patch.
http://reviews.llvm.org/D18091
llvm-svn: 263292
2016-03-12 04:51:53 +08:00
|
|
|
template <class ELFT> void Writer<ELFT>::writeBuildId() {
|
|
|
|
BuildIdSection<ELFT> *S = Out<ELFT>::BuildId;
|
|
|
|
if (!S)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Compute a hash of all sections except .debug_* sections.
|
|
|
|
// We skip debug sections because they tend to be very large
|
|
|
|
// and their contents are very likely to be the same as long as
|
|
|
|
// other sections are the same.
|
|
|
|
uint8_t *Start = Buffer->getBufferStart();
|
|
|
|
uint8_t *Last = Start;
|
2016-05-03 07:35:59 +08:00
|
|
|
std::vector<ArrayRef<uint8_t>> Regions;
|
ELF: Implement --build-id.
This patch implements --build-id. After the linker creates an output file
in the memory buffer, it computes the FNV1 hash of the resulting file
and set the hash to the .note section as a build-id.
GNU ld and gold have the same feature, but their default choice of the
hash function is different. Their default is SHA1.
We made a deliberate choice to not use a secure hash function for the
sake of performance. Computing a secure hash is slow -- for example,
MD5 throughput is usually 400 MB/s or so. SHA1 is slower than that.
As a result, if you pass --build-id to gold, then the linker becomes about
10% slower than that without the option. We observed a similar degradation
in an experimental implementation of build-id for LLD. On the other hand,
we observed only 1-2% performance degradation with the FNV hash.
Since build-id is not for digital certificate or anything, we think that
a very small probability of collision is acceptable.
We considered using other signals such as using input file timestamps as
inputs to a secure hash function. But such signals would have an issue
with build reproducibility (if you build a binary from the same source
tree using the same toolchain, the build id should become the same.)
GNU linkers accepts --build-id=<style> option where style is one of
"MD5", "SHA1", or an arbitrary hex string. That option is out of scope
of this patch.
http://reviews.llvm.org/D18091
llvm-svn: 263292
2016-03-12 04:51:53 +08:00
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
|
|
|
|
uint8_t *End = Start + Sec->getFileOff();
|
|
|
|
if (!Sec->getName().startswith(".debug_"))
|
2016-05-03 07:35:59 +08:00
|
|
|
Regions.push_back({Last, End});
|
ELF: Implement --build-id.
This patch implements --build-id. After the linker creates an output file
in the memory buffer, it computes the FNV1 hash of the resulting file
and set the hash to the .note section as a build-id.
GNU ld and gold have the same feature, but their default choice of the
hash function is different. Their default is SHA1.
We made a deliberate choice to not use a secure hash function for the
sake of performance. Computing a secure hash is slow -- for example,
MD5 throughput is usually 400 MB/s or so. SHA1 is slower than that.
As a result, if you pass --build-id to gold, then the linker becomes about
10% slower than that without the option. We observed a similar degradation
in an experimental implementation of build-id for LLD. On the other hand,
we observed only 1-2% performance degradation with the FNV hash.
Since build-id is not for digital certificate or anything, we think that
a very small probability of collision is acceptable.
We considered using other signals such as using input file timestamps as
inputs to a secure hash function. But such signals would have an issue
with build reproducibility (if you build a binary from the same source
tree using the same toolchain, the build id should become the same.)
GNU linkers accepts --build-id=<style> option where style is one of
"MD5", "SHA1", or an arbitrary hex string. That option is out of scope
of this patch.
http://reviews.llvm.org/D18091
llvm-svn: 263292
2016-03-12 04:51:53 +08:00
|
|
|
Last = End;
|
|
|
|
}
|
2016-05-03 07:35:59 +08:00
|
|
|
Regions.push_back({Last, Start + FileSize});
|
|
|
|
S->writeBuildId(Regions);
|
ELF: Implement --build-id.
This patch implements --build-id. After the linker creates an output file
in the memory buffer, it computes the FNV1 hash of the resulting file
and set the hash to the .note section as a build-id.
GNU ld and gold have the same feature, but their default choice of the
hash function is different. Their default is SHA1.
We made a deliberate choice to not use a secure hash function for the
sake of performance. Computing a secure hash is slow -- for example,
MD5 throughput is usually 400 MB/s or so. SHA1 is slower than that.
As a result, if you pass --build-id to gold, then the linker becomes about
10% slower than that without the option. We observed a similar degradation
in an experimental implementation of build-id for LLD. On the other hand,
we observed only 1-2% performance degradation with the FNV hash.
Since build-id is not for digital certificate or anything, we think that
a very small probability of collision is acceptable.
We considered using other signals such as using input file timestamps as
inputs to a secure hash function. But such signals would have an issue
with build reproducibility (if you build a binary from the same source
tree using the same toolchain, the build id should become the same.)
GNU linkers accepts --build-id=<style> option where style is one of
"MD5", "SHA1", or an arbitrary hex string. That option is out of scope
of this patch.
http://reviews.llvm.org/D18091
llvm-svn: 263292
2016-03-12 04:51:53 +08:00
|
|
|
}
|
|
|
|
|
2016-02-28 08:25:54 +08:00
|
|
|
template void elf::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab);
|
|
|
|
template void elf::writeResult<ELF32BE>(SymbolTable<ELF32BE> *Symtab);
|
|
|
|
template void elf::writeResult<ELF64LE>(SymbolTable<ELF64LE> *Symtab);
|
|
|
|
template void elf::writeResult<ELF64BE>(SymbolTable<ELF64BE> *Symtab);
|