2015-08-14 22:12:54 +08:00
|
|
|
//===- InputFiles.h ---------------------------------------------*- C++ -*-===//
|
2015-07-25 05:03:07 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2015-07-25 05:03:07 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLD_ELF_INPUT_FILES_H
|
|
|
|
#define LLD_ELF_INPUT_FILES_H
|
|
|
|
|
2015-10-07 17:13:03 +08:00
|
|
|
#include "Config.h"
|
[lld] unified COFF and ELF error handling on new Common/ErrorHandler
Summary:
The COFF linker and the ELF linker have long had similar but separate
Error.h and Error.cpp files to implement error handling. This change
introduces new error handling code in Common/ErrorHandler.h, changes the
COFF and ELF linkers to use it, and removes the old, separate
implementations.
Reviewers: ruiu
Reviewed By: ruiu
Subscribers: smeenai, jyknight, emaste, sdardis, nemanjai, nhaehnle, mgorny, javed.absar, kbarton, fedor.sergeev, llvm-commits
Differential Revision: https://reviews.llvm.org/D39259
llvm-svn: 316624
2017-10-26 06:28:38 +08:00
|
|
|
#include "lld/Common/ErrorHandler.h"
|
2017-10-03 05:00:41 +08:00
|
|
|
#include "lld/Common/LLVM.h"
|
|
|
|
#include "lld/Common/Reproduce.h"
|
2017-05-26 05:53:02 +08:00
|
|
|
#include "llvm/ADT/CachedHashString.h"
|
2015-09-05 06:28:10 +08:00
|
|
|
#include "llvm/ADT/DenseSet.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2016-03-12 02:46:51 +08:00
|
|
|
#include "llvm/IR/Comdat.h"
|
2015-09-05 06:28:10 +08:00
|
|
|
#include "llvm/Object/Archive.h"
|
2015-07-25 05:03:07 +08:00
|
|
|
#include "llvm/Object/ELF.h"
|
2016-03-12 02:46:51 +08:00
|
|
|
#include "llvm/Object/IRObjectFile.h"
|
2017-07-21 19:26:08 +08:00
|
|
|
#include "llvm/Support/Threading.h"
|
2016-04-28 04:22:31 +08:00
|
|
|
#include <map>
|
|
|
|
|
2016-09-29 08:40:08 +08:00
|
|
|
namespace llvm {
|
2019-11-15 06:16:21 +08:00
|
|
|
struct DILineInfo;
|
2017-01-09 09:42:02 +08:00
|
|
|
class TarWriter;
|
2016-09-29 08:40:08 +08:00
|
|
|
namespace lto {
|
|
|
|
class InputFile;
|
|
|
|
}
|
2017-07-18 19:55:35 +08:00
|
|
|
} // namespace llvm
|
2016-09-29 08:40:08 +08:00
|
|
|
|
2015-07-25 05:03:07 +08:00
|
|
|
namespace lld {
|
2019-11-15 06:16:21 +08:00
|
|
|
class DWARFCache;
|
2017-01-06 18:04:08 +08:00
|
|
|
|
2017-11-28 06:49:16 +08:00
|
|
|
// Returns "<internal>", "foo.a(bar.o)" or "baz.o".
|
2017-01-06 18:04:08 +08:00
|
|
|
std::string toString(const elf::InputFile *f);
|
|
|
|
|
2016-02-28 08:25:54 +08:00
|
|
|
namespace elf {
|
2015-09-05 06:28:10 +08:00
|
|
|
|
|
|
|
using llvm::object::Archive;
|
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
class Symbol;
|
2015-07-25 05:03:07 +08:00
|
|
|
|
2021-10-26 03:52:06 +08:00
|
|
|
// If --reproduce is specified, all input files are written to this tar archive.
|
2018-12-19 07:50:37 +08:00
|
|
|
extern std::unique_ptr<llvm::TarWriter> tar;
|
2017-01-09 09:42:02 +08:00
|
|
|
|
|
|
|
// Opens a given file.
|
|
|
|
llvm::Optional<MemoryBufferRef> readFile(StringRef path);
|
|
|
|
|
2019-05-14 20:03:13 +08:00
|
|
|
// Add symbols in File to the symbol table.
|
2019-05-16 11:45:13 +08:00
|
|
|
void parseFile(InputFile *file);
|
2019-05-14 20:03:13 +08:00
|
|
|
|
2015-07-25 05:03:07 +08:00
|
|
|
// The root class of input files.
|
|
|
|
class InputFile {
|
2021-12-15 12:55:32 +08:00
|
|
|
private:
|
|
|
|
// Cache for getNameForScript().
|
|
|
|
mutable SmallString<0> nameForScriptCache;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
SmallVector<InputSectionBase *, 0> sections;
|
|
|
|
|
2015-07-25 05:03:07 +08:00
|
|
|
public:
|
2021-12-15 12:55:32 +08:00
|
|
|
enum Kind : uint8_t {
|
2017-08-19 08:13:54 +08:00
|
|
|
ObjKind,
|
2016-04-08 03:24:51 +08:00
|
|
|
SharedKind,
|
2017-08-19 08:13:54 +08:00
|
|
|
LazyObjKind,
|
2016-04-08 03:24:51 +08:00
|
|
|
ArchiveKind,
|
|
|
|
BitcodeKind,
|
2016-09-10 06:08:04 +08:00
|
|
|
BinaryKind,
|
2016-04-08 03:24:51 +08:00
|
|
|
};
|
|
|
|
|
2015-07-25 05:03:07 +08:00
|
|
|
Kind kind() const { return fileKind; }
|
|
|
|
|
2017-12-23 08:04:34 +08:00
|
|
|
bool isElf() const {
|
|
|
|
Kind k = kind();
|
|
|
|
return k == ObjKind || k == SharedKind;
|
|
|
|
}
|
|
|
|
|
2015-08-05 20:03:34 +08:00
|
|
|
StringRef getName() const { return mb.getBufferIdentifier(); }
|
2016-02-13 04:54:57 +08:00
|
|
|
MemoryBufferRef mb;
|
2015-08-05 20:03:34 +08:00
|
|
|
|
2017-03-22 01:22:13 +08:00
|
|
|
// Returns sections. It is a runtime error to call this function
|
|
|
|
// on files that don't have the notion of sections.
|
2017-03-21 16:19:34 +08:00
|
|
|
ArrayRef<InputSectionBase *> getSections() const {
|
2017-08-19 08:13:54 +08:00
|
|
|
assert(fileKind == ObjKind || fileKind == BinaryKind);
|
2017-03-21 16:19:34 +08:00
|
|
|
return sections;
|
|
|
|
}
|
|
|
|
|
2017-08-04 19:07:42 +08:00
|
|
|
// Returns object file symbols. It is a runtime error to call this
|
|
|
|
// function on files of other types.
|
Change how we handle -wrap.
We have an issue with -wrap that the option doesn't work well when
renamed symbols get PLT entries. I'll explain what is the issue and
how this patch solves it.
For one -wrap option, we have three symbols: foo, wrap_foo and real_foo.
Currently, we use memcpy to overwrite wrapped symbols so that they get
the same contents. This works in most cases but doesn't when the relocation
processor sets some flags in the symbol. memcpy'ed symbols are just
aliases, so they always have to have the same contents, but the
relocation processor breaks that assumption.
r336609 is an attempt to fix the issue by memcpy'ing again after
processing relocations, so that symbols that are out of sync get the
same contents again. That works in most cases as well, but it breaks
ASan build in a mysterious way.
We could probably fix the issue by choosing symbol attributes that need
to be copied after they are updated. But it feels too complicated to me.
So, in this patch, I fixed it once and for all. With this patch, we no
longer memcpy symbols. All references to renamed symbols point to new
symbols after wrapSymbols() is done.
Differential Revision: https://reviews.llvm.org/D50569
llvm-svn: 340387
2018-08-22 15:02:26 +08:00
|
|
|
ArrayRef<Symbol *> getSymbols() { return getMutableSymbols(); }
|
|
|
|
|
2019-05-24 22:14:25 +08:00
|
|
|
MutableArrayRef<Symbol *> getMutableSymbols() {
|
2018-02-05 17:47:24 +08:00
|
|
|
assert(fileKind == BinaryKind || fileKind == ObjKind ||
|
2018-02-17 04:23:54 +08:00
|
|
|
fileKind == BitcodeKind);
|
2017-08-04 19:07:42 +08:00
|
|
|
return symbols;
|
|
|
|
}
|
|
|
|
|
2020-09-09 17:48:21 +08:00
|
|
|
// Get filename to use for linker script processing.
|
|
|
|
StringRef getNameForScript() const;
|
|
|
|
|
2020-12-02 08:00:48 +08:00
|
|
|
// If not empty, this stores the name of the archive containing this file.
|
|
|
|
// We use this string for creating error messages.
|
2021-12-15 12:55:32 +08:00
|
|
|
SmallString<0> archiveName;
|
|
|
|
|
|
|
|
// Cache for toString(). Only toString() should use this member.
|
|
|
|
mutable SmallString<0> toStringCache;
|
|
|
|
|
|
|
|
SmallVector<Symbol *, 0> symbols;
|
|
|
|
|
|
|
|
// Index of MIPS GOT built for this file.
|
|
|
|
llvm::Optional<uint32_t> mipsGotIndex;
|
|
|
|
|
|
|
|
// outSecOff of .got2 in the current file. This is used by PPC32 -fPIC/-fPIE
|
|
|
|
// to compute offsets in PLT call stubs.
|
|
|
|
uint32_t ppc32Got2OutSecOff = 0;
|
|
|
|
|
|
|
|
// groupId is used for --warn-backrefs which is an optional error
|
|
|
|
// checking feature. All files within the same --{start,end}-group or
|
|
|
|
// --{start,end}-lib get the same group ID. Otherwise, each file gets a new
|
|
|
|
// group ID. For more info, see checkDependency() in SymbolTable.cpp.
|
|
|
|
uint32_t groupId;
|
|
|
|
static bool isInGroup;
|
|
|
|
static uint32_t nextGroupId;
|
2016-02-02 16:22:41 +08:00
|
|
|
|
2016-06-29 09:30:50 +08:00
|
|
|
// If this is an architecture-specific file, the following members
|
|
|
|
// have ELF type (i.e. ELF{32,64}{LE,BE}) and target machine type.
|
|
|
|
uint16_t emachine = llvm::ELF::EM_NONE;
|
2021-12-15 12:55:32 +08:00
|
|
|
const Kind fileKind;
|
|
|
|
ELFKind ekind = ELFNoneKind;
|
2016-10-27 22:00:51 +08:00
|
|
|
uint8_t osabi = 0;
|
2019-02-15 07:59:44 +08:00
|
|
|
uint8_t abiVersion = 0;
|
2018-03-30 09:15:36 +08:00
|
|
|
// True if this is an argument for --just-symbols. Usually false.
|
|
|
|
bool justSymbols = false;
|
|
|
|
|
2021-12-15 12:55:32 +08:00
|
|
|
std::string getSrcMsg(const Symbol &sym, InputSectionBase &sec,
|
|
|
|
uint64_t offset);
|
[PPC32] Improve the 32-bit PowerPC port
Many -static/-no-pie/-shared/-pie applications linked against glibc or musl
should work with this patch. This also helps FreeBSD PowerPC64 to migrate
their lib32 (PR40888).
* Fix default image base and max page size.
* Support new-style Secure PLT (see below). Old-style BSS PLT is not
implemented, so it is not suitable for FreeBSD rtld now because it doesn't
support Secure PLT yet.
* Support more initial relocation types:
R_PPC_ADDR32, R_PPC_REL16*, R_PPC_LOCAL24PC, R_PPC_PLTREL24, and R_PPC_GOT16.
The addend of R_PPC_PLTREL24 is special: it decides the call stub PLT type
but it should be ignored for the computation of target symbol VA.
* Support GNU ifunc
* Support .glink used for lazy PLT resolution in glibc
* Add a new thunk type: PPC32PltCallStub that is similar to PPC64PltCallStub.
It is used by R_PPC_REL24 and R_PPC_PLTREL24.
A PLT stub used in -fPIE/-fPIC usually loads an address relative to
.got2+0x8000 (-fpie/-fpic code uses _GLOBAL_OFFSET_TABLE_ relative
addresses).
Two .got2 sections in two object files have different addresses, thus a PLT stub
can't be shared by two object files. To handle this incompatibility,
change the parameters of Thunk::isCompatibleWith to
`const InputSection &, const Relocation &`.
PowerPC psABI specified an old-style .plt (BSS PLT) that is both
writable and executable. Linkers don't make separate RW- and RWE segments,
which causes all initially writable memory (think .data) executable.
This is a big security concern so a new PLT scheme (secure PLT) was developed to
address the security issue.
TLS will be implemented in D62940.
glibc older than ~2012 requires .rela.dyn to include .rela.plt, it can
not handle the DT_RELA+DT_RELASZ == DT_JMPREL case correctly. A hack
(not included in this patch) in LinkerScript.cpp addOrphanSections() to
work around the issue:
if (Config->EMachine == EM_PPC) {
// Older glibc assumes .rela.dyn includes .rela.plt
Add(In.RelaDyn);
if (In.RelaPlt->isLive() && !In.RelaPlt->Parent)
In.RelaDyn->getParent()->addSection(In.RelaPlt);
}
Reviewed By: ruiu
Differential Revision: https://reviews.llvm.org/D62464
llvm-svn: 362721
2019-06-07 01:03:00 +08:00
|
|
|
|
2019-01-25 02:17:40 +08:00
|
|
|
// On PPC64 we need to keep track of which files contain small code model
|
2019-02-12 23:35:49 +08:00
|
|
|
// relocations that access the .toc section. To minimize the chance of a
|
|
|
|
// relocation overflow, files that do contain said relocations should have
|
|
|
|
// their .toc sections sorted closer to the .got section than files that do
|
|
|
|
// not contain any small code model relocations. Thats because the toc-pointer
|
|
|
|
// is defined to point at .got + 0x8000 and the instructions used with small
|
|
|
|
// code model relocations support immediates in the range [-0x8000, 0x7FFC],
|
|
|
|
// making the addressable range relative to the toc pointer
|
|
|
|
// [.got, .got + 0xFFFC].
|
|
|
|
bool ppc64SmallCodeModelTocRelocs = false;
|
2019-01-25 02:17:40 +08:00
|
|
|
|
[ELF][PPC64] Detect missing R_PPC64_TLSGD/R_PPC64_TLSLD and disable TLS relaxation
Alternative to D91611.
The TLS General Dynamic/Local Dynamic code sequences need to mark
`__tls_get_addr` with R_PPC64_TLSGD or R_PPC64_TLSLD, e.g.
```
addis r3, r2, x@got@tlsgd@ha # R_PPC64_GOT_TLSGD16_HA
addi r3, r3, x@got@tlsgd@l # R_PPC64_GOT_TLSGD16_LO
bl __tls_get_addr(x@tlsgd) # R_PPC64_TLSGD followed by R_PPC64_REL24
nop
```
However, there are two deviations form the above:
1. direct call to `__tls_get_addr`. This is essential to implement ld.so in glibc/musl/FreeBSD.
```
bl __tls_get_addr
nop
```
This is only used in a -shared link, and thus not subject to the GD/LD to IE/LE
relaxation issue below.
2. Missing R_PPC64_TLSGD/R_PPC64_TLSGD for compiler generated TLS references
According to Stefan Pintille, "In the early days of the transition from the
ELFv1 ABI that is used for big endian PowerPC Linux distributions to the ELFv2
ABI that is used for little endian PowerPC Linux distributions, there was some
ambiguity in the specification of the relocations for TLS. The GNU linker has
implemented support for correct handling of calls to __tls_get_addr with a
missing relocation. Unfortunately, we didn't notice that the IBM XL compiler
did not handle TLS according to the updated ABI until we tried linking XL
compiled libraries with LLD."
In short, LLD needs to work around the old IBM XL compiler issue.
Otherwise, if the object file is linked in -no-pie or -pie mode,
the result will be incorrect because the 4 instructions are partially
rewritten (the latter 2 are not changed).
Work around the compiler bug by disable General Dynamic/Local Dynamic to
Initial Exec/Local Exec relaxation. Note, we also disable Initial Exec
to Local Exec relaxation for implementation simplicity, though technically it can be kept.
ppc64-tls-missing-gdld.s demonstrates the updated behavior.
Reviewed By: #powerpc, stefanp, grimar
Differential Revision: https://reviews.llvm.org/D92959
2020-12-22 00:45:41 +08:00
|
|
|
// True if the file has TLSGD/TLSLD GOT relocations without R_PPC64_TLSGD or
|
|
|
|
// R_PPC64_TLSLD. Disable TLS relaxation to avoid bad code generation.
|
|
|
|
bool ppc64DisableTLSRelax = false;
|
|
|
|
|
2015-07-25 05:03:07 +08:00
|
|
|
protected:
|
2017-03-31 05:13:00 +08:00
|
|
|
InputFile(Kind k, MemoryBufferRef m);
|
2015-07-25 05:03:07 +08:00
|
|
|
};
|
|
|
|
|
2019-04-06 04:16:26 +08:00
|
|
|
class ELFFileBase : public InputFile {
|
2015-09-04 04:03:54 +08:00
|
|
|
public:
|
2015-10-13 09:17:02 +08:00
|
|
|
ELFFileBase(Kind k, MemoryBufferRef m);
|
2017-12-23 08:04:34 +08:00
|
|
|
static bool classof(const InputFile *f) { return f->isElf(); }
|
2015-09-04 04:03:54 +08:00
|
|
|
|
2019-04-06 04:16:26 +08:00
|
|
|
template <typename ELFT> llvm::object::ELFFile<ELFT> getObj() const {
|
2017-10-11 06:18:16 +08:00
|
|
|
return check(llvm::object::ELFFile<ELFT>::create(mb.getBuffer()));
|
2016-11-04 04:44:50 +08:00
|
|
|
}
|
2015-10-12 09:55:32 +08:00
|
|
|
|
|
|
|
StringRef getStringTable() const { return stringTable; }
|
2015-09-23 00:53:55 +08:00
|
|
|
|
2021-11-30 16:50:19 +08:00
|
|
|
ArrayRef<Symbol *> getLocalSymbols() {
|
|
|
|
if (symbols.empty())
|
|
|
|
return {};
|
|
|
|
return llvm::makeArrayRef(symbols).slice(1, firstGlobal - 1);
|
|
|
|
}
|
|
|
|
ArrayRef<Symbol *> getGlobalSymbols() {
|
|
|
|
return llvm::makeArrayRef(symbols).slice(firstGlobal);
|
|
|
|
}
|
|
|
|
|
2019-04-06 04:16:26 +08:00
|
|
|
template <typename ELFT> typename ELFT::SymRange getELFSyms() const {
|
|
|
|
return typename ELFT::SymRange(
|
|
|
|
reinterpret_cast<const typename ELFT::Sym *>(elfSyms), numELFSyms);
|
|
|
|
}
|
|
|
|
template <typename ELFT> typename ELFT::SymRange getGlobalELFSyms() const {
|
|
|
|
return getELFSyms<ELFT>().slice(firstGlobal);
|
|
|
|
}
|
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
|
|
|
|
2015-09-04 04:03:54 +08:00
|
|
|
protected:
|
2019-05-28 13:17:21 +08:00
|
|
|
// Initializes this class's member variables.
|
|
|
|
template <typename ELFT> void init();
|
|
|
|
|
2019-04-06 04:16:26 +08:00
|
|
|
const void *elfSyms = nullptr;
|
2021-12-15 12:55:32 +08:00
|
|
|
uint32_t numELFSyms = 0;
|
2018-03-29 06:55:40 +08:00
|
|
|
uint32_t firstGlobal = 0;
|
2015-10-12 23:15:45 +08:00
|
|
|
StringRef stringTable;
|
2015-10-12 20:14:30 +08:00
|
|
|
};
|
|
|
|
|
2015-10-12 10:22:58 +08:00
|
|
|
// .o file.
|
2019-04-06 04:16:26 +08:00
|
|
|
template <class ELFT> class ObjFile : public ELFFileBase {
|
2020-12-28 18:20:00 +08:00
|
|
|
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
|
2015-07-25 05:03:07 +08:00
|
|
|
|
|
|
|
public:
|
2019-04-06 04:16:26 +08:00
|
|
|
static bool classof(const InputFile *f) { return f->kind() == ObjKind; }
|
|
|
|
|
|
|
|
llvm::object::ELFFile<ELFT> getObj() const {
|
|
|
|
return this->ELFFileBase::getObj<ELFT>();
|
|
|
|
}
|
2015-08-05 20:03:34 +08:00
|
|
|
|
2019-05-28 13:17:21 +08:00
|
|
|
ObjFile(MemoryBufferRef m, StringRef archiveName) : ELFFileBase(ObjKind, m) {
|
2021-12-15 12:55:32 +08:00
|
|
|
this->archiveName = archiveName;
|
2019-05-28 13:17:21 +08:00
|
|
|
}
|
|
|
|
|
2019-06-06 01:39:37 +08:00
|
|
|
void parse(bool ignoreComdats = false);
|
2019-05-22 17:06:42 +08:00
|
|
|
|
|
|
|
StringRef getShtGroupSignature(ArrayRef<Elf_Shdr> sections,
|
|
|
|
const Elf_Shdr &sec);
|
2015-07-25 05:03:07 +08:00
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
Symbol &getSymbol(uint32_t symbolIndex) const {
|
2017-08-04 19:07:42 +08:00
|
|
|
if (symbolIndex >= this->symbols.size())
|
2016-11-24 02:07:33 +08:00
|
|
|
fatal(toString(this) + ": invalid symbol index");
|
2017-08-04 19:07:42 +08:00
|
|
|
return *this->symbols[symbolIndex];
|
2015-08-28 07:15:56 +08:00
|
|
|
}
|
|
|
|
|
2019-04-04 11:13:51 +08:00
|
|
|
uint32_t getSectionIndex(const Elf_Sym &sym) const;
|
|
|
|
|
2017-11-04 05:21:47 +08:00
|
|
|
template <typename RelT> Symbol &getRelocTargetSym(const RelT &rel) const {
|
2017-03-18 07:29:01 +08:00
|
|
|
uint32_t symIndex = rel.getSymbol(config->isMips64EL);
|
2017-11-04 05:21:47 +08:00
|
|
|
return getSymbol(symIndex);
|
2016-04-27 07:52:44 +08:00
|
|
|
}
|
|
|
|
|
2017-03-31 03:13:47 +08:00
|
|
|
llvm::Optional<llvm::DILineInfo> getDILineInfo(InputSectionBase *, uint64_t);
|
2017-11-01 15:42:38 +08:00
|
|
|
llvm::Optional<std::pair<std::string, unsigned>> getVariableLoc(StringRef name);
|
2016-10-26 19:07:09 +08:00
|
|
|
|
2021-12-15 12:55:32 +08:00
|
|
|
// Name of source file obtained from STT_FILE symbol value,
|
|
|
|
// or empty string if there is no such symbol in object file
|
|
|
|
// symbol table.
|
|
|
|
StringRef sourceFile;
|
|
|
|
|
|
|
|
// Pointer to this input file's .llvm_addrsig section, if it has one.
|
|
|
|
const Elf_Shdr *addrsigSec = nullptr;
|
|
|
|
|
|
|
|
// SHT_LLVM_CALL_GRAPH_PROFILE section index.
|
|
|
|
uint32_t cgProfileSectionIndex = 0;
|
|
|
|
|
2016-11-10 05:36:56 +08:00
|
|
|
// MIPS GP0 value defined by this file. This value represents the gp value
|
2015-12-25 21:02:13 +08:00
|
|
|
// used to create the relocatable object and required to support
|
|
|
|
// R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.
|
2016-11-10 05:36:56 +08:00
|
|
|
uint32_t mipsGp0 = 0;
|
2015-12-25 21:02:13 +08:00
|
|
|
|
2019-06-05 11:04:46 +08:00
|
|
|
uint32_t andFeatures = 0;
|
|
|
|
|
2018-07-18 07:16:02 +08:00
|
|
|
// True if the file defines functions compiled with
|
|
|
|
// -fsplit-stack. Usually false.
|
|
|
|
bool splitStack = false;
|
|
|
|
|
|
|
|
// True if the file defines functions compiled with -fsplit-stack,
|
|
|
|
// but had one or more functions with the no_split_stack attribute.
|
|
|
|
bool someNoSplitStack = false;
|
|
|
|
|
2020-02-28 01:38:42 +08:00
|
|
|
// Get cached DWARF information.
|
|
|
|
DWARFCache *getDwarf();
|
|
|
|
|
2015-07-25 05:03:07 +08:00
|
|
|
private:
|
2019-06-06 01:39:37 +08:00
|
|
|
void initializeSections(bool ignoreComdats);
|
2016-11-08 23:51:00 +08:00
|
|
|
void initializeSymbols();
|
2018-03-30 09:15:36 +08:00
|
|
|
void initializeJustSymbols();
|
2020-02-28 01:38:42 +08:00
|
|
|
|
2021-11-10 01:54:12 +08:00
|
|
|
InputSectionBase *getRelocTarget(uint32_t idx, StringRef name,
|
|
|
|
const Elf_Shdr &sec);
|
2021-10-28 00:51:06 +08:00
|
|
|
InputSectionBase *createInputSection(uint32_t idx, const Elf_Shdr &sec,
|
|
|
|
StringRef shstrtab);
|
2015-07-25 05:03:07 +08:00
|
|
|
|
2019-10-10 16:32:12 +08:00
|
|
|
bool shouldMerge(const Elf_Shdr &sec, StringRef name);
|
2015-07-25 05:03:07 +08:00
|
|
|
|
2019-04-10 14:32:05 +08:00
|
|
|
// Each ELF symbol contains a section index which the symbol belongs to.
|
|
|
|
// However, because the number of bits dedicated for that is limited, a
|
|
|
|
// symbol can directly point to a section only when the section index is
|
|
|
|
// equal to or smaller than 65280.
|
|
|
|
//
|
|
|
|
// If an object file contains more than 65280 sections, the file must
|
2019-04-12 10:20:52 +08:00
|
|
|
// contain .symtab_shndx section. The section contains an array of
|
2019-04-10 14:32:05 +08:00
|
|
|
// 32-bit integers whose size is the same as the number of symbols.
|
2019-04-12 10:20:52 +08:00
|
|
|
// Nth symbol's section index is in the Nth entry of .symtab_shndx.
|
2019-04-10 14:32:05 +08:00
|
|
|
//
|
2019-04-12 10:20:52 +08:00
|
|
|
// The following variable contains the contents of .symtab_shndx.
|
2019-04-10 14:32:05 +08:00
|
|
|
// If the section does not exist (which is common), the array is empty.
|
|
|
|
ArrayRef<Elf_Word> shndxTable;
|
2019-04-04 11:13:51 +08:00
|
|
|
|
2016-11-03 02:42:13 +08:00
|
|
|
// Debugging information to retrieve source file and line for error
|
|
|
|
// reporting. Linker may find reasonable number of errors in a
|
|
|
|
// single object file, so we cache debugging information in order to
|
|
|
|
// parse it only once for each object file we link.
|
2020-02-28 01:38:42 +08:00
|
|
|
std::unique_ptr<DWARFCache> dwarf;
|
|
|
|
llvm::once_flag initDwarf;
|
2015-07-25 05:03:07 +08:00
|
|
|
};
|
|
|
|
|
2017-07-27 06:13:32 +08:00
|
|
|
// LazyObjFile is analogous to ArchiveFile in the sense that
|
2016-04-08 03:24:51 +08:00
|
|
|
// the file contains lazy symbols. The difference is that
|
2017-07-27 06:13:32 +08:00
|
|
|
// LazyObjFile wraps a single file instead of multiple files.
|
2016-04-08 03:24:51 +08:00
|
|
|
//
|
|
|
|
// This class is used for --start-lib and --end-lib options which
|
|
|
|
// instruct the linker to link object files between them with the
|
|
|
|
// archive file semantics.
|
2017-07-27 06:13:32 +08:00
|
|
|
class LazyObjFile : public InputFile {
|
2016-04-08 03:24:51 +08:00
|
|
|
public:
|
2017-07-27 06:13:32 +08:00
|
|
|
LazyObjFile(MemoryBufferRef m, StringRef archiveName,
|
|
|
|
uint64_t offsetInArchive)
|
2017-08-19 08:13:54 +08:00
|
|
|
: InputFile(LazyObjKind, m), offsetInArchive(offsetInArchive) {
|
2021-12-15 12:55:32 +08:00
|
|
|
this->archiveName = archiveName;
|
2017-05-05 21:55:51 +08:00
|
|
|
}
|
2016-04-08 03:24:51 +08:00
|
|
|
|
2017-08-19 08:13:54 +08:00
|
|
|
static bool classof(const InputFile *f) { return f->kind() == LazyObjKind; }
|
2016-04-08 03:24:51 +08:00
|
|
|
|
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
|
|
|
template <class ELFT> void parse();
|
2021-11-27 02:58:50 +08:00
|
|
|
void extract();
|
2016-04-08 03:24:51 +08:00
|
|
|
|
2021-11-27 02:58:50 +08:00
|
|
|
// Check if a non-common symbol should be extracted to override a common
|
2020-12-07 22:28:17 +08:00
|
|
|
// definition.
|
2021-11-27 02:58:50 +08:00
|
|
|
bool shouldExtractForCommon(const StringRef &name);
|
2020-12-07 22:28:17 +08:00
|
|
|
|
2021-11-27 02:58:50 +08:00
|
|
|
bool extracted = false;
|
2020-06-10 02:25:55 +08:00
|
|
|
|
2016-04-08 03:24:51 +08:00
|
|
|
private:
|
2017-05-05 23:17:07 +08:00
|
|
|
uint64_t offsetInArchive;
|
2016-04-08 03:24:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
// An ArchiveFile object represents a .a file.
|
2015-09-05 06:28:10 +08:00
|
|
|
class ArchiveFile : public InputFile {
|
|
|
|
public:
|
2017-05-04 05:03:08 +08:00
|
|
|
explicit ArchiveFile(std::unique_ptr<Archive> &&file);
|
2015-09-05 06:28:10 +08:00
|
|
|
static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; }
|
2019-05-16 11:45:13 +08:00
|
|
|
void parse();
|
2015-09-05 06:28:10 +08:00
|
|
|
|
2018-04-03 10:06:57 +08:00
|
|
|
// Pulls out an object file that contains a definition for Sym and
|
|
|
|
// returns it. If the same file was instantiated before, this
|
2019-05-23 18:15:12 +08:00
|
|
|
// function does nothing (so we don't instantiate the same file
|
2018-04-03 10:06:57 +08:00
|
|
|
// more than once.)
|
2021-11-27 02:58:50 +08:00
|
|
|
void extract(const Archive::Symbol &sym);
|
2015-09-05 06:28:10 +08:00
|
|
|
|
2021-11-27 02:58:50 +08:00
|
|
|
// Check if a non-common symbol should be extracted to override a common
|
2020-12-07 22:28:17 +08:00
|
|
|
// definition.
|
2021-11-27 02:58:50 +08:00
|
|
|
bool shouldExtractForCommon(const Archive::Symbol &sym);
|
2020-12-07 22:28:17 +08:00
|
|
|
|
2020-04-28 10:30:09 +08:00
|
|
|
size_t getMemberCount() const;
|
2021-11-27 02:58:50 +08:00
|
|
|
size_t getExtractedMemberCount() const { return seen.size(); }
|
2020-04-28 10:30:09 +08:00
|
|
|
|
2020-06-10 02:25:55 +08:00
|
|
|
bool parsed = false;
|
|
|
|
|
2015-09-05 06:28:10 +08:00
|
|
|
private:
|
|
|
|
std::unique_ptr<Archive> file;
|
|
|
|
llvm::DenseSet<uint64_t> seen;
|
|
|
|
};
|
|
|
|
|
2016-02-13 04:54:57 +08:00
|
|
|
class BitcodeFile : public InputFile {
|
|
|
|
public:
|
2017-04-14 10:55:06 +08:00
|
|
|
BitcodeFile(MemoryBufferRef m, StringRef archiveName,
|
|
|
|
uint64_t offsetInArchive);
|
ELF: New symbol table design.
This patch implements a new design for the symbol table that stores
SymbolBodies within a memory region of the Symbol object. Symbols are mutated
by constructing SymbolBodies in place over existing SymbolBodies, rather
than by mutating pointers. As mentioned in the initial proposal [1], this
memory layout helps reduce the cache miss rate by improving memory locality.
Performance numbers:
old(s) new(s)
Without debug info:
chrome 7.178 6.432 (-11.5%)
LLVMgold.so 0.505 0.502 (-0.5%)
clang 0.954 0.827 (-15.4%)
llvm-as 0.052 0.045 (-15.5%)
With debug info:
scylla 5.695 5.613 (-1.5%)
clang 14.396 14.143 (-1.8%)
Performance counter results show that the fewer required indirections is
indeed the cause of the improved performance. For example, when linking
chrome, stalled cycles decreases from 14,556,444,002 to 12,959,238,310, and
instructions per cycle increases from 0.78 to 0.83. We are also executing
many fewer instructions (15,516,401,933 down to 15,002,434,310), probably
because we spend less time allocating SymbolBodies.
The new mechanism by which symbols are added to the symbol table is by calling
add* functions on the SymbolTable.
In this patch, I handle local symbols by storing them inside "unparented"
SymbolBodies. This is suboptimal, but if we do want to try to avoid allocating
these SymbolBodies, we can probably do that separately.
I also removed a few members from the SymbolBody class that were only being
used to pass information from the input file to the symbol table.
This patch implements the new design for the ELF linker only. I intend to
prepare a similar patch for the COFF linker.
[1] http://lists.llvm.org/pipermail/llvm-dev/2016-April/098832.html
Differential Revision: http://reviews.llvm.org/D19752
llvm-svn: 268178
2016-05-01 12:55:03 +08:00
|
|
|
static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }
|
2019-06-06 01:39:37 +08:00
|
|
|
template <class ELFT> void parse();
|
2016-09-29 08:40:08 +08:00
|
|
|
std::unique_ptr<llvm::lto::InputFile> obj;
|
2016-02-13 04:54:57 +08:00
|
|
|
};
|
|
|
|
|
2015-09-04 04:03:54 +08:00
|
|
|
// .so file.
|
2019-04-09 01:35:55 +08:00
|
|
|
class SharedFile : public ELFFileBase {
|
2015-09-04 04:03:54 +08:00
|
|
|
public:
|
2019-05-28 13:17:21 +08:00
|
|
|
SharedFile(MemoryBufferRef m, StringRef defaultSoName)
|
2021-10-26 06:54:04 +08:00
|
|
|
: ELFFileBase(SharedKind, m), soName(defaultSoName),
|
2019-05-28 13:17:21 +08:00
|
|
|
isNeeded(!config->asNeeded) {}
|
|
|
|
|
2019-04-09 01:35:55 +08:00
|
|
|
// This is actually a vector of Elf_Verdef pointers.
|
2021-12-15 13:11:45 +08:00
|
|
|
SmallVector<const void *, 0> verdefs;
|
2019-04-09 01:48:05 +08:00
|
|
|
|
|
|
|
// If the output file needs Elf_Verneed data structures for this file, this is
|
|
|
|
// a vector of Elf_Vernaux version identifiers that map onto the entries in
|
|
|
|
// Verdefs, otherwise it is empty.
|
2021-12-15 13:11:45 +08:00
|
|
|
SmallVector<uint32_t, 0> vernauxs;
|
2019-04-09 01:48:05 +08:00
|
|
|
|
|
|
|
static unsigned vernauxNum;
|
|
|
|
|
2021-12-15 13:11:45 +08:00
|
|
|
SmallVector<StringRef, 0> dtNeeded;
|
2021-10-26 06:54:04 +08:00
|
|
|
StringRef soName;
|
2017-04-25 05:44:20 +08:00
|
|
|
|
2019-04-06 04:16:26 +08:00
|
|
|
static bool classof(const InputFile *f) { return f->kind() == SharedKind; }
|
2015-09-04 04:03:54 +08:00
|
|
|
|
2019-04-09 01:35:55 +08:00
|
|
|
template <typename ELFT> void parse();
|
2016-04-28 04:22:31 +08:00
|
|
|
|
2015-10-12 10:22:58 +08:00
|
|
|
// Used for --as-needed
|
2017-11-23 01:50:42 +08:00
|
|
|
bool isNeeded;
|
2020-05-16 11:36:41 +08:00
|
|
|
|
2021-05-06 21:45:29 +08:00
|
|
|
// Non-weak undefined symbols which are not yet resolved when the SO is
|
|
|
|
// parsed. Only filled for `--no-allow-shlib-undefined`.
|
2021-12-15 13:11:45 +08:00
|
|
|
SmallVector<Symbol *, 0> requiredSymbols;
|
2021-05-06 21:45:29 +08:00
|
|
|
|
2020-05-16 11:36:41 +08:00
|
|
|
private:
|
|
|
|
template <typename ELFT>
|
|
|
|
std::vector<uint32_t> parseVerneed(const llvm::object::ELFFile<ELFT> &obj,
|
|
|
|
const typename ELFT::Shdr *sec);
|
2015-09-04 04:03:54 +08:00
|
|
|
};
|
|
|
|
|
2016-09-10 06:08:04 +08:00
|
|
|
class BinaryFile : public InputFile {
|
|
|
|
public:
|
|
|
|
explicit BinaryFile(MemoryBufferRef m) : InputFile(BinaryKind, m) {}
|
|
|
|
static bool classof(const InputFile *f) { return f->kind() == BinaryKind; }
|
2017-12-24 01:21:39 +08:00
|
|
|
void parse();
|
2016-09-10 06:08:04 +08:00
|
|
|
};
|
|
|
|
|
2016-10-29 04:57:25 +08:00
|
|
|
InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = "",
|
2016-10-13 03:35:54 +08:00
|
|
|
uint64_t offsetInArchive = 0);
|
2015-09-05 06:28:10 +08:00
|
|
|
|
2018-05-03 05:40:07 +08:00
|
|
|
inline bool isBitcode(MemoryBufferRef mb) {
|
|
|
|
return identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode;
|
|
|
|
}
|
|
|
|
|
2018-05-18 02:27:12 +08:00
|
|
|
std::string replaceThinLTOSuffix(StringRef path);
|
2018-05-17 05:04:08 +08:00
|
|
|
|
2020-04-28 10:30:09 +08:00
|
|
|
extern std::vector<ArchiveFile *> archiveFiles;
|
2017-09-19 17:20:54 +08:00
|
|
|
extern std::vector<BinaryFile *> binaryFiles;
|
|
|
|
extern std::vector<BitcodeFile *> bitcodeFiles;
|
2018-05-03 05:40:07 +08:00
|
|
|
extern std::vector<LazyObjFile *> lazyObjFiles;
|
2017-09-19 17:20:54 +08:00
|
|
|
extern std::vector<InputFile *> objectFiles;
|
2019-04-09 01:35:55 +08:00
|
|
|
extern std::vector<SharedFile *> sharedFiles;
|
2017-09-19 17:20:54 +08:00
|
|
|
|
2016-02-28 08:25:54 +08:00
|
|
|
} // namespace elf
|
2015-07-25 05:03:07 +08:00
|
|
|
} // namespace lld
|
|
|
|
|
|
|
|
#endif
|