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"
|
2016-05-25 04:24:43 +08:00
|
|
|
#include "Relocations.h"
|
2016-06-29 17:08:02 +08:00
|
|
|
#include "Strings.h"
|
2015-08-06 07:24:46 +08:00
|
|
|
#include "SymbolTable.h"
|
2015-09-23 02:19:46 +08:00
|
|
|
#include "Target.h"
|
2015-08-12 08:00:24 +08:00
|
|
|
|
2015-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"
|
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;
|
|
|
|
|
|
|
|
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-08-06 07:24:46 +08:00
|
|
|
void run();
|
|
|
|
|
|
|
|
private:
|
2016-07-19 20:33:46 +08:00
|
|
|
typedef PhdrEntry<ELFT> Phdr;
|
2016-02-11 06:43:13 +08:00
|
|
|
|
2015-10-09 07:49:30 +08:00
|
|
|
void copyLocalSymbols();
|
2015-12-26 15:50:39 +08:00
|
|
|
void addReservedSymbols();
|
2016-07-30 00:18:47 +08:00
|
|
|
void createSections();
|
2016-07-21 01:58:07 +08:00
|
|
|
void forEachRelSec(
|
|
|
|
std::function<void(InputSectionBase<ELFT> &, const typename ELFT::Shdr &)>
|
|
|
|
Fn);
|
2016-07-20 22:43:20 +08:00
|
|
|
void finalizeSections();
|
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-07-21 03:36:39 +08:00
|
|
|
std::vector<Phdr> createPhdrs();
|
2015-08-06 07:24:46 +08:00
|
|
|
void assignAddresses();
|
2016-04-02 01:07:17 +08:00
|
|
|
void assignFileOffsets();
|
2016-08-25 17:05:47 +08:00
|
|
|
void assignFileOffsetsBinary();
|
2016-04-02 01:07:17 +08:00
|
|
|
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();
|
2016-08-25 17:05:47 +08:00
|
|
|
void writeSectionsBinary();
|
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-08-06 07:24:46 +08:00
|
|
|
|
2016-07-17 02:55:47 +08:00
|
|
|
std::unique_ptr<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;
|
2016-07-20 22:43:20 +08:00
|
|
|
OutputSectionFactory<ELFT> Factory;
|
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);
|
2016-08-09 09:35:38 +08:00
|
|
|
OutputSectionBase<ELFT> *findSection(StringRef Name);
|
2015-10-11 06:34:30 +08:00
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
|
2016-07-12 16:50:42 +08:00
|
|
|
template <class ELFT>
|
|
|
|
StringRef elf::getOutputSectionName(InputSectionBase<ELFT> *S) {
|
|
|
|
StringRef Name = S->getSectionName();
|
|
|
|
for (StringRef V : {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.",
|
|
|
|
".init_array.", ".fini_array.", ".ctors.", ".dtors.",
|
2016-08-24 17:08:54 +08:00
|
|
|
".tbss.", ".gcc_except_table.", ".tdata.", ".ARM.exidx."})
|
2016-07-12 16:50:42 +08:00
|
|
|
if (Name.startswith(V))
|
|
|
|
return V.drop_back();
|
|
|
|
return Name;
|
|
|
|
}
|
|
|
|
|
2016-07-26 06:26:28 +08:00
|
|
|
template <class ELFT> void elf::reportDiscarded(InputSectionBase<ELFT> *IS) {
|
2016-07-12 16:50:42 +08:00
|
|
|
if (!Config->PrintGcSections || !IS || IS->Live)
|
|
|
|
return;
|
|
|
|
errs() << "removing unused section from '" << IS->getSectionName()
|
2016-07-26 06:26:28 +08:00
|
|
|
<< "' in file '" << IS->getFile()->getName() << "'\n";
|
2016-07-12 16:50:42 +08:00
|
|
|
}
|
|
|
|
|
2016-07-21 19:01:23 +08:00
|
|
|
template <class ELFT> static bool needsInterpSection() {
|
|
|
|
return !Symtab<ELFT>::X->getSharedFiles().empty() &&
|
2016-08-16 14:40:58 +08:00
|
|
|
!Config->DynamicLinker.empty() &&
|
|
|
|
!Script<ELFT>::X->ignoreInterpSection();
|
2016-07-21 19:01:23 +08:00
|
|
|
}
|
|
|
|
|
2016-08-09 11:38:23 +08:00
|
|
|
template <class ELFT> void elf::writeResult() {
|
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.
|
2016-05-24 11:16:51 +08:00
|
|
|
OutputSection<ELFT> Bss(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
|
2016-05-24 12:25:47 +08:00
|
|
|
DynamicSection<ELFT> Dynamic;
|
2016-05-24 00:24:16 +08:00
|
|
|
EhOutputSection<ELFT> EhFrame;
|
2015-10-08 03:18:16 +08:00
|
|
|
GotSection<ELFT> Got;
|
|
|
|
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> ShStrTab(".shstrtab", false);
|
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);
|
2016-06-17 09:18:46 +08:00
|
|
|
ProgramHeaders.updateAlignment(sizeof(uintX_t));
|
2016-02-11 06:43:13 +08:00
|
|
|
|
2016-02-06 02:41:40 +08:00
|
|
|
// Instantiate optional output sections if they are needed.
|
2016-07-21 19:01:23 +08:00
|
|
|
std::unique_ptr<InterpSection<ELFT>> Interp;
|
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-08-09 12:42:01 +08:00
|
|
|
std::unique_ptr<StringTableSection<ELFT>> DynStrTab;
|
|
|
|
std::unique_ptr<SymbolTableSection<ELFT>> DynSymTab;
|
2016-05-24 00:24:16 +08:00
|
|
|
std::unique_ptr<EhFrameHeader<ELFT>> EhFrameHdr;
|
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-06-20 19:55:12 +08:00
|
|
|
std::unique_ptr<VersionDefinitionSection<ELFT>> VerDef;
|
2016-02-06 02:41:40 +08:00
|
|
|
|
2016-07-21 19:01:23 +08:00
|
|
|
if (needsInterpSection<ELFT>())
|
|
|
|
Interp.reset(new InterpSection<ELFT>);
|
|
|
|
|
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-05-14 05:55:56 +08:00
|
|
|
else if (Config->BuildId == BuildIdKind::Hexstring)
|
|
|
|
BuildId.reset(new BuildIdHexstring<ELFT>);
|
2016-04-08 06:49:21 +08:00
|
|
|
|
2016-08-09 12:42:01 +08:00
|
|
|
if (!Symtab<ELFT>::X->getSharedFiles().empty() || Config->Pic) {
|
|
|
|
DynStrTab.reset(new StringTableSection<ELFT>(".dynstr", true));
|
|
|
|
DynSymTab.reset(new SymbolTableSection<ELFT>(*DynStrTab));
|
|
|
|
}
|
|
|
|
|
2016-05-24 00:24:16 +08:00
|
|
|
if (Config->EhFrameHdr)
|
|
|
|
EhFrameHdr.reset(new EhFrameHeader<ELFT>);
|
|
|
|
|
2016-02-06 02:41:40 +08:00
|
|
|
if (Config->GnuHash)
|
|
|
|
GnuHashTab.reset(new GnuHashTableSection<ELFT>);
|
|
|
|
if (Config->SysvHash)
|
|
|
|
HashTab.reset(new HashTableSection<ELFT>);
|
2016-05-19 05:03:36 +08:00
|
|
|
StringRef S = Config->Rela ? ".rela.plt" : ".rel.plt";
|
|
|
|
GotPlt.reset(new GotPltSection<ELFT>);
|
|
|
|
RelaPlt.reset(new RelocationSection<ELFT>(S, false /*Sort*/));
|
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));
|
2016-05-24 12:25:47 +08:00
|
|
|
SymTabSec.reset(new SymbolTableSection<ELFT>(*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));
|
2016-06-17 09:18:46 +08:00
|
|
|
MipsRldMap->updateAlignment(sizeof(uintX_t));
|
2016-02-26 07:54:49 +08:00
|
|
|
}
|
2016-07-16 12:09:27 +08:00
|
|
|
if (!Config->VersionDefinitions.empty())
|
2016-06-20 19:55:12 +08:00
|
|
|
VerDef.reset(new VersionDefinitionSection<ELFT>());
|
2016-02-06 02:41:40 +08:00
|
|
|
|
2016-05-24 11:16:51 +08:00
|
|
|
Out<ELFT>::Bss = &Bss;
|
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-08-09 12:42:01 +08:00
|
|
|
Out<ELFT>::DynStrTab = DynStrTab.get();
|
|
|
|
Out<ELFT>::DynSymTab = DynSymTab.get();
|
2015-10-08 03:18:16 +08:00
|
|
|
Out<ELFT>::Dynamic = &Dynamic;
|
2016-05-24 00:24:16 +08:00
|
|
|
Out<ELFT>::EhFrame = &EhFrame;
|
|
|
|
Out<ELFT>::EhFrameHdr = EhFrameHdr.get();
|
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();
|
2016-07-21 19:01:23 +08:00
|
|
|
Out<ELFT>::Interp = Interp.get();
|
2016-02-06 02:41:40 +08:00
|
|
|
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-06-20 19:55:12 +08:00
|
|
|
Out<ELFT>::VerDef = VerDef.get();
|
2016-04-28 04:22:31 +08:00
|
|
|
Out<ELFT>::VerSym = &VerSym;
|
|
|
|
Out<ELFT>::VerNeed = &VerNeed;
|
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
|
|
|
|
2016-08-09 12:25:20 +08:00
|
|
|
Out<ELFT>::PreinitArray = nullptr;
|
|
|
|
Out<ELFT>::InitArray = nullptr;
|
|
|
|
Out<ELFT>::FiniArray = nullptr;
|
|
|
|
|
2016-08-09 11:38:23 +08:00
|
|
|
Writer<ELFT>().run();
|
2016-08-12 09:10:17 +08:00
|
|
|
Out<ELFT>::Pool.clear();
|
2015-10-08 03:18:16 +08:00
|
|
|
}
|
|
|
|
|
2016-07-29 11:39:44 +08:00
|
|
|
template <class ELFT>
|
|
|
|
static std::vector<DefinedCommon<ELFT> *> getCommonSymbols() {
|
|
|
|
std::vector<DefinedCommon<ELFT> *> V;
|
|
|
|
for (Symbol *S : Symtab<ELFT>::X->getSymbols())
|
|
|
|
if (auto *B = dyn_cast<DefinedCommon<ELFT>>(S->body()))
|
|
|
|
V.push_back(B);
|
|
|
|
return V;
|
|
|
|
}
|
|
|
|
|
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-07-20 22:43:20 +08:00
|
|
|
|
2016-08-11 15:56:43 +08:00
|
|
|
if (Target->NeedsThunks)
|
|
|
|
forEachRelSec(createThunks<ELFT>);
|
|
|
|
|
2016-07-29 11:39:44 +08:00
|
|
|
CommonInputSection<ELFT> Common(getCommonSymbols<ELFT>());
|
2016-07-29 05:05:04 +08:00
|
|
|
CommonInputSection<ELFT>::X = &Common;
|
|
|
|
|
2016-08-04 20:13:05 +08:00
|
|
|
Script<ELFT>::X->OutputSections = &OutputSections;
|
2016-07-30 00:18:47 +08:00
|
|
|
if (ScriptConfig->HasContents)
|
2016-08-04 20:13:05 +08:00
|
|
|
Script<ELFT>::X->createSections(Factory);
|
2016-07-30 00:18:47 +08:00
|
|
|
else
|
|
|
|
createSections();
|
|
|
|
|
2016-07-20 22:43:20 +08:00
|
|
|
finalizeSections();
|
2016-04-02 01:24:19 +08:00
|
|
|
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-08-04 20:13:05 +08:00
|
|
|
Phdrs = Script<ELFT>::X->hasPhdrsCommands() ? Script<ELFT>::X->createPhdrs()
|
|
|
|
: createPhdrs();
|
2016-04-06 15:20:45 +08:00
|
|
|
fixHeaders();
|
2016-07-29 11:31:09 +08:00
|
|
|
if (ScriptConfig->HasContents) {
|
2016-08-04 20:13:05 +08:00
|
|
|
Script<ELFT>::X->assignAddresses();
|
2016-04-16 18:10:32 +08:00
|
|
|
} else {
|
|
|
|
fixSectionAlignments();
|
|
|
|
assignAddresses();
|
|
|
|
}
|
2016-08-25 17:05:47 +08:00
|
|
|
|
|
|
|
if (!Config->OFormatBinary)
|
|
|
|
assignFileOffsets();
|
|
|
|
else
|
|
|
|
assignFileOffsetsBinary();
|
|
|
|
|
2016-04-02 01:07:17 +08:00
|
|
|
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;
|
2016-08-25 17:05:47 +08:00
|
|
|
if (!Config->OFormatBinary) {
|
|
|
|
writeHeader();
|
|
|
|
writeSections();
|
|
|
|
} else {
|
|
|
|
writeSectionsBinary();
|
|
|
|
}
|
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-07-15 10:01:03 +08:00
|
|
|
if (auto EC = Buffer->commit())
|
|
|
|
error(EC, "failed to write to the output file");
|
2015-07-25 05:03:07 +08:00
|
|
|
}
|
|
|
|
|
2016-08-09 11:38:23 +08:00
|
|
|
template <class ELFT> static void reportUndefined(SymbolBody *Sym) {
|
2016-06-29 20:35:04 +08:00
|
|
|
if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (Config->Shared && Sym->symbol()->Visibility == STV_DEFAULT &&
|
|
|
|
Config->UnresolvedSymbols != UnresolvedPolicy::NoUndef)
|
|
|
|
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-07-17 11:11:46 +08:00
|
|
|
if (Sym->File)
|
|
|
|
Msg += " in " + getFilename(Sym->File);
|
2016-06-29 20:35:04 +08:00
|
|
|
if (Config->UnresolvedSymbols == UnresolvedPolicy::Warn)
|
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))
|
2016-05-22 08:41:38 +08:00
|
|
|
if (!S->getSectionPiece(D->Value)->Live)
|
2016-05-06 00:40:28 +08:00
|
|
|
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 :
|
2016-08-09 11:38:23 +08:00
|
|
|
Symtab<ELFT>::X->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
|
|
|
}
|
|
|
|
|
2016-07-19 17:25:43 +08:00
|
|
|
template <class ELFT> bool elf::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-07-20 22:43:20 +08:00
|
|
|
template <class ELFT> static bool isDiscarded(InputSectionBase<ELFT> *S) {
|
|
|
|
return !S || S == &InputSection<ELFT>::Discarded || !S->Live;
|
|
|
|
}
|
|
|
|
|
2016-07-19 17:25:43 +08:00
|
|
|
// Program header entry
|
|
|
|
template<class ELFT>
|
2016-07-19 20:33:46 +08:00
|
|
|
PhdrEntry<ELFT>::PhdrEntry(unsigned Type, unsigned Flags) {
|
2016-07-19 17:25:43 +08:00
|
|
|
H.p_type = Type;
|
|
|
|
H.p_flags = Flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class ELFT>
|
2016-07-21 03:36:41 +08:00
|
|
|
void PhdrEntry<ELFT>::add(OutputSectionBase<ELFT> *Sec) {
|
2016-07-19 17:25:43 +08:00
|
|
|
Last = Sec;
|
|
|
|
if (!First)
|
|
|
|
First = Sec;
|
|
|
|
H.p_align = std::max<typename ELFT::uint>(H.p_align, Sec->getAlignment());
|
|
|
|
}
|
|
|
|
|
2016-04-12 21:26:51 +08:00
|
|
|
template <class ELFT>
|
2016-08-09 11:38:23 +08:00
|
|
|
static Symbol *addOptionalSynthetic(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-08-09 11:38:23 +08:00
|
|
|
SymbolBody *S = Symtab<ELFT>::X->find(Name);
|
2016-05-09 23:25:54 +08:00
|
|
|
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-08-19 23:36:32 +08:00
|
|
|
return Symtab<ELFT>::X->addSynthetic(Name, Sec, Val, STV_HIDDEN);
|
2016-04-12 21:26:51 +08:00
|
|
|
}
|
|
|
|
|
2016-08-15 15:24:20 +08:00
|
|
|
template <class ELFT>
|
|
|
|
static void addSynthetic(StringRef Name, OutputSectionBase<ELFT> *Sec,
|
2016-08-22 12:55:41 +08:00
|
|
|
typename ELFT::uint Val) {
|
2016-08-15 15:24:20 +08:00
|
|
|
SymbolBody *S = Symtab<ELFT>::X->find(Name);
|
|
|
|
if (!S || S->isUndefined() || S->isShared())
|
2016-08-19 23:36:32 +08:00
|
|
|
Symtab<ELFT>::X->addSynthetic(Name, Sec, Val, STV_HIDDEN);
|
2016-08-15 15:24:20 +08:00
|
|
|
}
|
2016-08-22 12:55:41 +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() {
|
2016-08-09 12:42:01 +08:00
|
|
|
if (Out<ELFT>::DynSymTab || !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-08-09 11:38:23 +08:00
|
|
|
addOptionalSynthetic(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-08-09 11:38:23 +08:00
|
|
|
addOptionalSynthetic(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: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-07-27 05:11:30 +08:00
|
|
|
if (Config->EMachine == EM_MIPS && !Config->Relocatable) {
|
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-08-19 23:36:32 +08:00
|
|
|
Symtab<ELFT>::X->addSynthetic("_gp", Out<ELFT>::Got, MipsGPOffset,
|
|
|
|
STV_HIDDEN);
|
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 =
|
2016-08-09 11:38:23 +08:00
|
|
|
addOptionalSynthetic("_gp_disp", Out<ELFT>::Got, MipsGPOffset);
|
2016-05-04 02:03:45 +08:00
|
|
|
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-08-09 11:38:23 +08:00
|
|
|
addOptionalSynthetic("__gnu_local_gp", Out<ELFT>::Got, 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)
|
2016-08-09 11:38:23 +08:00
|
|
|
Symtab<ELFT>::X->addIgnored("_GLOBAL_OFFSET_TABLE_");
|
2016-04-04 22:04:16 +08:00
|
|
|
|
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.
|
2016-08-09 12:42:01 +08:00
|
|
|
if (!Out<ELFT>::DynSymTab)
|
2016-08-09 11:38:23 +08:00
|
|
|
Symtab<ELFT>::X->addIgnored("__tls_get_addr");
|
2015-12-26 15:50:39 +08:00
|
|
|
|
2016-08-08 16:42:48 +08:00
|
|
|
// If linker script do layout we do not need to create any standart symbols.
|
|
|
|
if (ScriptConfig->HasContents)
|
|
|
|
return;
|
|
|
|
|
2016-08-23 02:44:04 +08:00
|
|
|
ElfSym<ELFT>::EhdrStart = Symtab<ELFT>::X->addIgnored("__ehdr_start");
|
|
|
|
|
2016-04-22 04:50:15 +08:00
|
|
|
auto Define = [this](StringRef S, DefinedRegular<ELFT> *&Sym1,
|
|
|
|
DefinedRegular<ELFT> *&Sym2) {
|
2016-08-09 11:38:23 +08:00
|
|
|
Sym1 = Symtab<ELFT>::X->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);
|
2016-08-09 11:38:23 +08:00
|
|
|
if (SymbolBody *B = Symtab<ELFT>::X->find(S))
|
2016-02-26 22:36:36 +08:00
|
|
|
if (B->isUndefined())
|
2016-08-09 11:38:23 +08:00
|
|
|
Sym2 = Symtab<ELFT>::X->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
|
|
|
}
|
|
|
|
|
2016-07-21 01:58:07 +08:00
|
|
|
template <class ELFT>
|
|
|
|
void Writer<ELFT>::forEachRelSec(
|
|
|
|
std::function<void(InputSectionBase<ELFT> &, const typename ELFT::Shdr &)>
|
|
|
|
Fn) {
|
|
|
|
for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
|
2016-08-09 11:38:23 +08:00
|
|
|
Symtab<ELFT>::X->getObjectFiles()) {
|
2016-07-21 01:58:07 +08:00
|
|
|
for (InputSectionBase<ELFT> *C : F->getSections()) {
|
|
|
|
if (isDiscarded(C))
|
|
|
|
continue;
|
|
|
|
// 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.
|
|
|
|
// Note that relocations for non-alloc sections are directly
|
|
|
|
// processed by InputSection::relocateNonAlloc.
|
|
|
|
if (!(C->getSectionHdr()->sh_flags & SHF_ALLOC))
|
|
|
|
continue;
|
|
|
|
if (auto *S = dyn_cast<InputSection<ELFT>>(C)) {
|
|
|
|
for (const Elf_Shdr *RelSec : S->RelocSections)
|
|
|
|
Fn(*S, *RelSec);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (auto *S = dyn_cast<EhInputSection<ELFT>>(C))
|
|
|
|
if (S->RelocSection)
|
|
|
|
Fn(*S, *S->RelocSection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-30 00:18:47 +08:00
|
|
|
template <class ELFT> void Writer<ELFT>::createSections() {
|
2016-03-12 00:41:23 +08:00
|
|
|
for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
|
2016-08-09 11:38:23 +08:00
|
|
|
Symtab<ELFT>::X->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)) {
|
2016-07-26 06:26:28 +08:00
|
|
|
reportDiscarded(C);
|
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));
|
2016-07-20 22:43:20 +08:00
|
|
|
if (IsNew)
|
2016-07-30 00:18:47 +08:00
|
|
|
OutputSections.push_back(Sec);
|
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
|
|
|
}
|
2016-08-11 15:56:43 +08:00
|
|
|
|
|
|
|
sortInitFini(findSection(".init_array"));
|
|
|
|
sortInitFini(findSection(".fini_array"));
|
|
|
|
sortCtorsDtors(findSection(".ctors"));
|
|
|
|
sortCtorsDtors(findSection(".dtors"));
|
|
|
|
|
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
|
|
|
Sec->assignOffsets();
|
2016-07-20 22:43:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create output section objects and add them to OutputSections.
|
|
|
|
template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
2016-08-09 12:25:20 +08:00
|
|
|
Out<ELFT>::PreinitArray = findSection(".preinit_array");
|
|
|
|
Out<ELFT>::InitArray = findSection(".init_array");
|
|
|
|
Out<ELFT>::FiniArray = findSection(".fini_array");
|
2015-10-03 03:37:55 +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();
|
2016-08-09 09:35:39 +08:00
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
2016-03-02 03:12:35 +08:00
|
|
|
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-08-09 12:42:01 +08:00
|
|
|
if (Out<ELFT>::DynSymTab)
|
2016-08-19 23:36:32 +08:00
|
|
|
Symtab<ELFT>::X->addSynthetic("_DYNAMIC", Out<ELFT>::Dynamic, 0,
|
|
|
|
STV_HIDDEN);
|
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-05-24 00:24:16 +08:00
|
|
|
if (!Out<ELFT>::EhFrame->empty()) {
|
|
|
|
OutputSections.push_back(Out<ELFT>::EhFrame);
|
|
|
|
Out<ELFT>::EhFrame->finalize();
|
|
|
|
}
|
2016-04-07 22:22:09 +08:00
|
|
|
|
2016-07-21 01:58:07 +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.
|
|
|
|
forEachRelSec(scanRelocations<ELFT>);
|
|
|
|
|
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.
|
2016-08-09 11:38:23 +08:00
|
|
|
for (Symbol *S : Symtab<ELFT>::X->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
|
|
|
|
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-08-09 11:38:23 +08:00
|
|
|
reportUndefined<ELFT>(Body);
|
2015-09-23 07:38:23 +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-08-09 12:42:01 +08:00
|
|
|
if (Out<ELFT>::DynSymTab && 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))
|
2016-07-17 11:11:46 +08:00
|
|
|
if (SS->file()->isNeeded())
|
2016-06-10 02:01:35 +08:00
|
|
|
Out<ELFT>::VerNeed->addSymbol(SS);
|
2016-04-28 04:22:31 +08:00
|
|
|
}
|
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
|
|
|
|
2016-07-29 03:24:13 +08:00
|
|
|
// If linker script processor hasn't added common symbol section yet,
|
|
|
|
// then add it to .bss now.
|
2016-07-29 05:05:04 +08:00
|
|
|
if (!CommonInputSection<ELFT>::X->OutSec) {
|
|
|
|
Out<ELFT>::Bss->addSection(CommonInputSection<ELFT>::X);
|
2016-07-29 03:24:13 +08:00
|
|
|
Out<ELFT>::Bss->assignOffsets();
|
|
|
|
}
|
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.
|
2016-08-09 12:42:01 +08:00
|
|
|
if (Out<ELFT>::DynSymTab)
|
2015-12-26 15:50:41 +08:00
|
|
|
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
|
|
|
|
2016-08-09 12:42:01 +08:00
|
|
|
if (Out<ELFT>::DynSymTab)
|
2016-02-02 17:07:47 +08:00
|
|
|
Out<ELFT>::Dynamic->finalize();
|
Avoid doing binary search.
MergedInputSection::getOffset is the busiest function in LLD if string
merging is enabled and input files have lots of mergeable sections.
It is usually the case when creating executable with debug info,
so it is pretty common.
The reason why it is slow is because it has to do faily complex
computations. For non-mergeable sections, section contents are
contiguous in output, so in order to compute an output offset,
we only have to add the output section's base address to an input
offset. But for mergeable strings, section contents are split for
merging, so they are not contigous. We've got to do some lookups.
We used to do binary search on the list of section pieces.
It is slow because I think it's hostile to branch prediction.
This patch replaces it with hash table lookup. Seems it's working
pretty well. Below is "perf stat -r10" output when linking clang
with debug info. In this case this patch speeds up about 4%.
Before:
6584.153205 task-clock (msec) # 1.001 CPUs utilized ( +- 0.09% )
238 context-switches # 0.036 K/sec ( +- 6.59% )
0 cpu-migrations # 0.000 K/sec ( +- 50.92% )
1,067,675 page-faults # 0.162 M/sec ( +- 0.15% )
18,369,931,470 cycles # 2.790 GHz ( +- 0.09% )
9,640,680,143 stalled-cycles-frontend # 52.48% frontend cycles idle ( +- 0.18% )
<not supported> stalled-cycles-backend
21,206,747,787 instructions # 1.15 insns per cycle
# 0.45 stalled cycles per insn ( +- 0.04% )
3,817,398,032 branches # 579.786 M/sec ( +- 0.04% )
132,787,249 branch-misses # 3.48% of all branches ( +- 0.02% )
6.579106511 seconds time elapsed ( +- 0.09% )
After:
6312.317533 task-clock (msec) # 1.001 CPUs utilized ( +- 0.19% )
221 context-switches # 0.035 K/sec ( +- 4.11% )
1 cpu-migrations # 0.000 K/sec ( +- 45.21% )
1,280,775 page-faults # 0.203 M/sec ( +- 0.37% )
17,611,539,150 cycles # 2.790 GHz ( +- 0.19% )
10,285,148,569 stalled-cycles-frontend # 58.40% frontend cycles idle ( +- 0.30% )
<not supported> stalled-cycles-backend
18,794,779,900 instructions # 1.07 insns per cycle
# 0.55 stalled cycles per insn ( +- 0.03% )
3,287,450,865 branches # 520.799 M/sec ( +- 0.03% )
72,259,605 branch-misses # 2.20% of all branches ( +- 0.01% )
6.307411828 seconds time elapsed ( +- 0.19% )
Differential Revision: http://reviews.llvm.org/D20645
llvm-svn: 270999
2016-05-27 22:39:13 +08:00
|
|
|
|
|
|
|
// Now that all output offsets are fixed. Finalize mergeable sections
|
|
|
|
// to fix their maps from input offsets to output offsets.
|
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
|
|
|
Sec->finalizePieces();
|
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-07-27 05:11:30 +08:00
|
|
|
if (Config->EMachine == EM_MIPS && !Config->Relocatable)
|
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.
|
2016-05-24 11:36:07 +08:00
|
|
|
return Out<ELFT>::Got->HasGotOffRel;
|
2016-02-26 03:34:37 +08:00
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
};
|
|
|
|
|
2016-07-13 22:26:31 +08:00
|
|
|
// A core file does not usually contain unmodified segments except
|
|
|
|
// the first page of the executable. Add the build ID section to beginning of
|
|
|
|
// the file so that the section is included in the first page.
|
|
|
|
if (Out<ELFT>::BuildId)
|
|
|
|
OutputSections.insert(OutputSections.begin(), Out<ELFT>::BuildId);
|
|
|
|
|
|
|
|
// Add .interp at first because some loaders want to see that section
|
|
|
|
// on the first page of the executable file when loaded into memory.
|
2016-07-21 19:01:23 +08:00
|
|
|
if (Out<ELFT>::Interp)
|
2016-07-13 22:26:31 +08:00
|
|
|
OutputSections.insert(OutputSections.begin(), Out<ELFT>::Interp);
|
|
|
|
|
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);
|
2016-08-09 12:42:01 +08:00
|
|
|
if (Out<ELFT>::DynSymTab) {
|
2015-12-26 18:34:33 +08:00
|
|
|
Add(Out<ELFT>::DynSymTab);
|
2016-06-20 19:55:12 +08:00
|
|
|
|
|
|
|
bool HasVerNeed = Out<ELFT>::VerNeed->getNeedNum() != 0;
|
|
|
|
if (Out<ELFT>::VerDef || HasVerNeed)
|
2016-04-28 04:22:31 +08:00
|
|
|
Add(Out<ELFT>::VerSym);
|
2016-06-20 21:22:54 +08:00
|
|
|
Add(Out<ELFT>::VerDef);
|
2016-06-20 19:55:12 +08:00
|
|
|
if (HasVerNeed)
|
2016-04-28 04:22:31 +08:00
|
|
|
Add(Out<ELFT>::VerNeed);
|
2016-06-20 19:55:12 +08:00
|
|
|
|
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.
|
2016-08-09 12:31:21 +08:00
|
|
|
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
|
|
|
|
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-05-24 00:24:16 +08:00
|
|
|
if (!Out<ELFT>::EhFrame->empty())
|
2016-01-15 21:34:52 +08:00
|
|
|
Add(Out<ELFT>::EhFrameHdr);
|
2016-05-24 11:16:51 +08:00
|
|
|
if (Out<ELFT>::Bss->getSize() > 0)
|
|
|
|
Add(Out<ELFT>::Bss);
|
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-08-15 15:24:20 +08:00
|
|
|
addSynthetic(Start, OS, 0);
|
|
|
|
addSynthetic(End, OS, DefinedSynthetic<ELFT>::SectionEnd);
|
2015-12-26 17:48:00 +08:00
|
|
|
} else {
|
2016-08-09 11:38:23 +08:00
|
|
|
addOptionalSynthetic(Start, (OutputSectionBase<ELFT> *)nullptr, 0);
|
|
|
|
addOptionalSynthetic(End, (OutputSectionBase<ELFT> *)nullptr, 0);
|
2015-12-26 17:48:00 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Define("__preinit_array_start", "__preinit_array_end",
|
2016-08-09 12:25:20 +08:00
|
|
|
Out<ELFT>::PreinitArray);
|
|
|
|
Define("__init_array_start", "__init_array_end", Out<ELFT>::InitArray);
|
|
|
|
Define("__fini_array_start", "__fini_array_end", Out<ELFT>::FiniArray);
|
2015-12-26 17:48:00 +08:00
|
|
|
}
|
|
|
|
|
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-08-09 11:38:23 +08:00
|
|
|
if (SymbolBody *B = Symtab<ELFT>::X->find(Start))
|
2016-01-06 04:35:16 +08:00
|
|
|
if (B->isUndefined())
|
2016-08-19 23:36:32 +08:00
|
|
|
Symtab<ELFT>::X->addSynthetic(Start, Sec, 0, B->getVisibility());
|
2016-08-09 11:38:23 +08:00
|
|
|
if (SymbolBody *B = Symtab<ELFT>::X->find(Stop))
|
2016-01-06 04:35:16 +08:00
|
|
|
if (B->isUndefined())
|
2016-08-19 23:36:32 +08:00
|
|
|
Symtab<ELFT>::X->addSynthetic(
|
|
|
|
Stop, Sec, DefinedSynthetic<ELFT>::SectionEnd, B->getVisibility());
|
2015-10-16 01:11:03 +08:00
|
|
|
}
|
|
|
|
|
2016-08-09 09:35:38 +08:00
|
|
|
template <class ELFT>
|
|
|
|
OutputSectionBase<ELFT> *Writer<ELFT>::findSection(StringRef Name) {
|
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
|
|
|
if (Sec->getName() == Name)
|
|
|
|
return Sec;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2016-07-27 01:35:42 +08:00
|
|
|
template <class ELFT> static bool needsPtLoad(OutputSectionBase<ELFT> *Sec) {
|
2016-02-11 07:29:38 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2016-02-11 06:43:13 +08:00
|
|
|
// Decide which program headers to create and which sections to include in each
|
|
|
|
// one.
|
2016-07-21 03:36:39 +08:00
|
|
|
template <class ELFT>
|
|
|
|
std::vector<PhdrEntry<ELFT>> Writer<ELFT>::createPhdrs() {
|
|
|
|
std::vector<Phdr> Ret;
|
|
|
|
|
|
|
|
auto AddHdr = [&](unsigned Type, unsigned Flags) -> Phdr * {
|
|
|
|
Ret.emplace_back(Type, Flags);
|
|
|
|
return &Ret.back();
|
2016-02-11 06:43:13 +08:00
|
|
|
};
|
2015-09-10 04:48:09 +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);
|
2016-07-21 03:36:41 +08:00
|
|
|
Hdr.add(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-07-21 19:01:23 +08:00
|
|
|
if (Out<ELFT>::Interp) {
|
2016-07-27 22:10:56 +08:00
|
|
|
Phdr &Hdr = *AddHdr(PT_INTERP, Out<ELFT>::Interp->getPhdrFlags());
|
2016-07-21 03:36:41 +08:00
|
|
|
Hdr.add(Out<ELFT>::Interp);
|
2016-02-11 06:43:13 +08:00
|
|
|
}
|
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);
|
2016-07-21 03:36:41 +08:00
|
|
|
Load->add(Out<ELFT>::ElfHeader);
|
|
|
|
Load->add(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)
|
2016-07-21 03:36:41 +08:00
|
|
|
TlsHdr.add(Sec);
|
2016-02-11 07:29:38 +08:00
|
|
|
|
2016-07-27 01:35:42 +08:00
|
|
|
if (!needsPtLoad(Sec))
|
2016-02-11 07:29:38 +08:00
|
|
|
continue;
|
|
|
|
|
2016-08-17 15:44:19 +08:00
|
|
|
// Segments are contiguous memory regions that has the same attributes
|
|
|
|
// (e.g. executable or writable). There is one phdr for each segment.
|
|
|
|
// Therefore, we need to create a new phdr when the next section has
|
|
|
|
// different flags or is loaded at a discontiguous address using AT linker
|
|
|
|
// script command.
|
2016-07-27 22:10:56 +08:00
|
|
|
uintX_t NewFlags = Sec->getPhdrFlags();
|
2016-08-17 15:44:19 +08:00
|
|
|
if (Script<ELFT>::X->getLma(Sec->getName()) || 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-07-21 03:36:41 +08:00
|
|
|
Load->add(Sec);
|
2016-02-11 06:43:13 +08:00
|
|
|
|
|
|
|
if (isRelroSection(Sec))
|
2016-07-21 03:36:41 +08:00
|
|
|
RelRo.add(Sec);
|
2016-03-01 21:23:29 +08:00
|
|
|
if (Sec->getType() == SHT_NOTE)
|
2016-07-21 03:36:41 +08:00
|
|
|
Note.add(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)
|
2016-07-21 03:36:39 +08:00
|
|
|
Ret.push_back(std::move(TlsHdr));
|
2016-02-11 06:43:13 +08:00
|
|
|
|
2015-10-24 05:45:59 +08:00
|
|
|
// Add an entry for .dynamic.
|
2016-08-09 12:42:01 +08:00
|
|
|
if (Out<ELFT>::DynSymTab) {
|
2016-07-27 22:10:56 +08:00
|
|
|
Phdr &H = *AddHdr(PT_DYNAMIC, Out<ELFT>::Dynamic->getPhdrFlags());
|
2016-07-21 03:36:41 +08:00
|
|
|
H.add(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)
|
2016-07-21 03:36:39 +08:00
|
|
|
Ret.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-05-24 00:24:16 +08:00
|
|
|
if (!Out<ELFT>::EhFrame->empty() && Out<ELFT>::EhFrameHdr) {
|
2016-07-27 22:10:56 +08:00
|
|
|
Phdr &Hdr = *AddHdr(PT_GNU_EH_FRAME, Out<ELFT>::EhFrameHdr->getPhdrFlags());
|
2016-07-21 03:36:41 +08:00
|
|
|
Hdr.add(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-08-18 07:59:58 +08:00
|
|
|
if (!Config->ZExecStack) {
|
|
|
|
Phdr &Hdr = *AddHdr(PT_GNU_STACK, PF_R | PF_W);
|
|
|
|
if (Config->ZStackSize != uint64_t(-1))
|
|
|
|
Hdr.H.p_memsz = Config->ZStackSize;
|
|
|
|
}
|
2016-03-01 21:23:29 +08:00
|
|
|
|
|
|
|
if (Note.First)
|
2016-07-21 03:36:39 +08:00
|
|
|
Ret.push_back(std::move(Note));
|
|
|
|
return Ret;
|
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-07-29 11:31:09 +08:00
|
|
|
uintX_t BaseVA = ScriptConfig->HasContents ? 0 : Config->ImageBase;
|
2016-07-01 18:42:25 +08:00
|
|
|
Out<ELFT>::ElfHeader->setVA(BaseVA);
|
2016-04-06 15:20:45 +08:00
|
|
|
uintX_t Off = Out<ELFT>::ElfHeader->getSize();
|
2016-07-01 18:42:25 +08:00
|
|
|
Out<ELFT>::ProgramHeaders->setVA(Off + BaseVA);
|
2016-07-19 17:25:43 +08:00
|
|
|
Out<ELFT>::ProgramHeaders->setSize(sizeof(Elf_Phdr) * Phdrs.size());
|
2016-04-06 15:20:45 +08:00
|
|
|
}
|
|
|
|
|
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-08-25 17:05:47 +08:00
|
|
|
uintX_t VA = Config->ImageBase;
|
|
|
|
if (!Config->OFormatBinary)
|
|
|
|
VA +=
|
|
|
|
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) {
|
2016-06-17 09:18:46 +08:00
|
|
|
uintX_t Alignment = Sec->getAlignment();
|
2016-03-31 03:41:51 +08:00
|
|
|
if (Sec->PageAlign)
|
2016-06-17 09:18:46 +08:00
|
|
|
Alignment = std::max<uintX_t>(Alignment, Target->PageSize);
|
2016-02-11 06:43:13 +08:00
|
|
|
|
|
|
|
// We only assign VAs to allocated sections.
|
2016-07-27 01:35:42 +08:00
|
|
|
if (needsPtLoad(Sec)) {
|
2016-06-17 09:18:46 +08:00
|
|
|
VA = alignTo(VA, Alignment);
|
2016-02-11 07:29:38 +08:00
|
|
|
Sec->setVA(VA);
|
|
|
|
VA += Sec->getSize();
|
|
|
|
} else if (Sec->getFlags() & SHF_TLS && Sec->getType() == SHT_NOBITS) {
|
|
|
|
uintX_t TVA = VA + ThreadBssOffset;
|
2016-06-17 09:18:46 +08:00
|
|
|
TVA = alignTo(TVA, Alignment);
|
2016-02-11 07:29:38 +08:00
|
|
|
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) {
|
2016-06-17 09:18:46 +08:00
|
|
|
uintX_t Alignment = Sec->getAlignment();
|
2016-04-27 17:16:28 +08:00
|
|
|
if (Sec->PageAlign)
|
2016-06-17 09:18:46 +08:00
|
|
|
Alignment = std::max<uintX_t>(Alignment, Target->PageSize);
|
|
|
|
Off = alignTo(Off, Alignment);
|
2016-04-27 17:16:28 +08:00
|
|
|
|
|
|
|
// 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-08-25 17:05:47 +08:00
|
|
|
template <class ELFT, class uintX_t>
|
|
|
|
void setOffset(OutputSectionBase<ELFT> *Sec, uintX_t &Off) {
|
|
|
|
if (Sec->getType() == SHT_NOBITS) {
|
|
|
|
Sec->setFileOffset(Off);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Off = getFileAlignment<ELFT>(Off, Sec);
|
|
|
|
Sec->setFileOffset(Off);
|
|
|
|
Off += Sec->getSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() {
|
|
|
|
uintX_t Off = 0;
|
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
|
|
|
if (Sec->getFlags() & SHF_ALLOC)
|
|
|
|
setOffset(Sec, Off);
|
|
|
|
FileSize = alignTo(Off, sizeof(uintX_t));
|
|
|
|
}
|
|
|
|
|
2016-04-02 01:07:17 +08:00
|
|
|
// Assign file offsets to output sections.
|
|
|
|
template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
|
2016-07-01 18:27:36 +08:00
|
|
|
uintX_t Off = 0;
|
2016-08-25 17:05:47 +08:00
|
|
|
setOffset(Out<ELFT>::ElfHeader, Off);
|
|
|
|
setOffset(Out<ELFT>::ProgramHeaders, Off);
|
2016-04-06 15:20:45 +08:00
|
|
|
|
2016-07-01 18:27:36 +08:00
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
2016-08-25 17:05:47 +08:00
|
|
|
setOffset(Sec, Off);
|
2016-07-01 18:27:36 +08:00
|
|
|
|
2016-04-02 01:07:17 +08:00
|
|
|
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;
|
2016-08-17 15:44:19 +08:00
|
|
|
|
2016-02-11 06:43:13 +08:00
|
|
|
H.p_paddr = H.p_vaddr;
|
2016-08-17 15:44:19 +08:00
|
|
|
if (H.p_type == PT_LOAD && First)
|
|
|
|
if (Expr LmaExpr = Script<ELFT>::X->getLma(First->getName()))
|
|
|
|
H.p_paddr = LmaExpr(H.p_vaddr);
|
2016-02-11 06:43:13 +08:00
|
|
|
|
|
|
|
// The TLS pointer goes after PT_TLS. At least glibc will align it,
|
|
|
|
// so round up the size to make sure the offsets are correct.
|
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;
|
2016-07-30 03:24:27 +08:00
|
|
|
if (H.p_memsz)
|
|
|
|
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-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-08-23 02:44:04 +08:00
|
|
|
// __ehdr_start is the location of program headers.
|
|
|
|
if (ElfSym<ELFT>::EhdrStart)
|
|
|
|
ElfSym<ELFT>::EhdrStart->Value = Out<ELFT>::ProgramHeaders->getVA();
|
|
|
|
|
2016-06-20 21:30:37 +08:00
|
|
|
auto Set = [](DefinedRegular<ELFT> *S1, DefinedRegular<ELFT> *S2, uintX_t V) {
|
2016-04-22 04:50:15 +08:00
|
|
|
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();
|
2016-06-29 09:30:50 +08:00
|
|
|
EHdr->e_machine = FirstObj.EMachine;
|
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-07-21 04:30:41 +08:00
|
|
|
EHdr->e_flags = getMipsEFlags<ELFT>();
|
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-07-15 09:38:54 +08:00
|
|
|
if (auto EC = BufferOrErr.getError())
|
|
|
|
error(EC, "failed to open " + Config->OutputFile);
|
2016-04-02 01:24:19 +08:00
|
|
|
else
|
2016-07-15 09:38:54 +08:00
|
|
|
Buffer = std::move(*BufferOrErr);
|
2015-07-25 05:03:07 +08:00
|
|
|
}
|
|
|
|
|
2016-08-25 17:05:47 +08:00
|
|
|
template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
|
|
|
|
uint8_t *Buf = Buffer->getBufferStart();
|
|
|
|
for (OutputSectionBase<ELFT> *Sec : OutputSections)
|
|
|
|
if (Sec->getFlags() & SHF_ALLOC)
|
|
|
|
Sec->writeTo(Buf + Sec->getFileOff());
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2016-08-09 09:35:37 +08:00
|
|
|
// PPC64 needs to process relocations in the .opd section
|
|
|
|
// before processing relocations in code-containing sections.
|
2016-08-09 09:35:38 +08:00
|
|
|
Out<ELFT>::Opd = findSection(".opd");
|
2016-08-09 09:35:37 +08:00
|
|
|
if (Out<ELFT>::Opd) {
|
|
|
|
Out<ELFT>::OpdBuf = Buf + Out<ELFT>::Opd->getFileOff();
|
|
|
|
Out<ELFT>::Opd->writeTo(Buf + Out<ELFT>::Opd->getFileOff());
|
2015-10-13 22:45:51 +08:00
|
|
|
}
|
[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() {
|
2016-07-16 12:19:29 +08:00
|
|
|
if (!Out<ELFT>::BuildId)
|
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
|
|
|
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});
|
2016-07-16 12:19:29 +08:00
|
|
|
Out<ELFT>::BuildId->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-08-09 11:38:23 +08:00
|
|
|
template void elf::writeResult<ELF32LE>();
|
|
|
|
template void elf::writeResult<ELF32BE>();
|
|
|
|
template void elf::writeResult<ELF64LE>();
|
|
|
|
template void elf::writeResult<ELF64BE>();
|
2016-07-19 17:25:43 +08:00
|
|
|
|
2016-07-19 20:33:46 +08:00
|
|
|
template struct elf::PhdrEntry<ELF32LE>;
|
|
|
|
template struct elf::PhdrEntry<ELF32BE>;
|
|
|
|
template struct elf::PhdrEntry<ELF64LE>;
|
|
|
|
template struct elf::PhdrEntry<ELF64BE>;
|
2016-07-19 17:25:43 +08:00
|
|
|
|
|
|
|
template bool elf::isRelroSection<ELF32LE>(OutputSectionBase<ELF32LE> *);
|
|
|
|
template bool elf::isRelroSection<ELF32BE>(OutputSectionBase<ELF32BE> *);
|
|
|
|
template bool elf::isRelroSection<ELF64LE>(OutputSectionBase<ELF64LE> *);
|
|
|
|
template bool elf::isRelroSection<ELF64BE>(OutputSectionBase<ELF64BE> *);
|
|
|
|
|
2016-07-20 23:42:34 +08:00
|
|
|
template StringRef elf::getOutputSectionName<ELF32LE>(InputSectionBase<ELF32LE> *);
|
|
|
|
template StringRef elf::getOutputSectionName<ELF32BE>(InputSectionBase<ELF32BE> *);
|
|
|
|
template StringRef elf::getOutputSectionName<ELF64LE>(InputSectionBase<ELF64LE> *);
|
|
|
|
template StringRef elf::getOutputSectionName<ELF64BE>(InputSectionBase<ELF64BE> *);
|
2016-07-21 02:47:33 +08:00
|
|
|
|
2016-07-26 06:26:28 +08:00
|
|
|
template void elf::reportDiscarded<ELF32LE>(InputSectionBase<ELF32LE> *);
|
|
|
|
template void elf::reportDiscarded<ELF32BE>(InputSectionBase<ELF32BE> *);
|
|
|
|
template void elf::reportDiscarded<ELF64LE>(InputSectionBase<ELF64LE> *);
|
|
|
|
template void elf::reportDiscarded<ELF64BE>(InputSectionBase<ELF64BE> *);
|