Vendor import of lld release_50 branch r309439:

https://llvm.org/svn/llvm-project/lld/branches/release_50@309439
This commit is contained in:
Dimitry Andric 2017-07-29 21:30:27 +00:00
parent da06c7cfa0
commit 9e3ca9b3ba
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/lld/dist/; revision=321698
svn path=/vendor/lld/lld-release_50-r310316/; revision=322266; tag=vendor/lld/lld-release_50-r310316
12 changed files with 246 additions and 61 deletions

View File

@ -130,7 +130,7 @@ struct Configuration {
std::map<StringRef, uint32_t> Section;
// Options for manifest files.
ManifestKind Manifest = SideBySide;
ManifestKind Manifest = No;
int ManifestID = 1;
StringRef ManifestDependency;
bool ManifestUAC = true;

View File

@ -899,18 +899,25 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
for (auto *Arg : Args.filtered(OPT_section))
parseSection(Arg->getValue());
// Handle /manifest
if (auto *Arg = Args.getLastArg(OPT_manifest_colon))
parseManifest(Arg->getValue());
// Handle /manifestdependency. This enables /manifest unless /manifest:no is
// also passed.
if (auto *Arg = Args.getLastArg(OPT_manifestdependency)) {
Config->ManifestDependency = Arg->getValue();
Config->Manifest = Configuration::SideBySide;
}
// Handle /manifest and /manifest:
if (auto *Arg = Args.getLastArg(OPT_manifest, OPT_manifest_colon)) {
if (Arg->getOption().getID() == OPT_manifest)
Config->Manifest = Configuration::SideBySide;
else
parseManifest(Arg->getValue());
}
// Handle /manifestuac
if (auto *Arg = Args.getLastArg(OPT_manifestuac))
parseManifestUAC(Arg->getValue());
// Handle /manifestdependency
if (auto *Arg = Args.getLastArg(OPT_manifestdependency))
Config->ManifestDependency = Arg->getValue();
// Handle /manifestfile
if (auto *Arg = Args.getLastArg(OPT_manifestfile))
Config->ManifestFile = Arg->getValue();
@ -919,6 +926,11 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
for (auto *Arg : Args.filtered(OPT_manifestinput))
Config->ManifestInput.push_back(Arg->getValue());
if (!Config->ManifestInput.empty() &&
Config->Manifest != Configuration::Embed) {
fatal("/MANIFESTINPUT: requires /MANIFEST:EMBED");
}
// Handle miscellaneous boolean flags.
if (Args.hasArg(OPT_allowisolation_no))
Config->AllowIsolation = false;

View File

@ -91,8 +91,7 @@ template <class ELFT> void elf::ObjectFile<ELFT>::initializeDwarfLine() {
template <class ELFT>
Optional<DILineInfo> elf::ObjectFile<ELFT>::getDILineInfo(InputSectionBase *S,
uint64_t Offset) {
if (!DwarfLine)
initializeDwarfLine();
llvm::call_once(InitDwarfLine, [this]() { initializeDwarfLine(); });
// The offset to CU is 0.
const DWARFDebugLine::LineTable *Tbl = DwarfLine->getLineTable(0);

View File

@ -24,6 +24,7 @@
#include "llvm/Object/Archive.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/IRObjectFile.h"
#include "llvm/Support/Threading.h"
#include <map>
@ -211,6 +212,7 @@ template <class ELFT> class ObjectFile : public ELFFileBase<ELFT> {
// single object file, so we cache debugging information in order to
// parse it only once for each object file we link.
std::unique_ptr<llvm::DWARFDebugLine> DwarfLine;
llvm::once_flag InitDwarfLine;
};
// LazyObjectFile is analogous to ArchiveFile in the sense that

View File

@ -211,6 +211,12 @@ static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
// Find an existing symbol or create and insert a new one.
template <class ELFT>
std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) {
// <name>@@<version> means the symbol is the default version. In that
// case <name>@@<version> will be used to resolve references to <name>.
size_t Pos = Name.find("@@");
if (Pos != StringRef::npos)
Name = Name.take_front(Pos);
auto P = Symtab.insert(
{CachedHashStringRef(Name), SymIndex((int)SymVector.size(), false)});
SymIndex &V = P.first->second;
@ -312,15 +318,36 @@ Symbol *SymbolTable<ELFT>::addUndefined(StringRef Name, bool IsLocal,
return S;
}
// Using .symver foo,foo@@VER unfortunately creates two symbols: foo and
// foo@@VER. We want to effectively ignore foo, so give precedence to
// foo@@VER.
// FIXME: If users can transition to using
// .symver foo,foo@@@VER
// we can delete this hack.
static int compareVersion(Symbol *S, StringRef Name) {
if (Name.find("@@") != StringRef::npos &&
S->body()->getName().find("@@") == StringRef::npos)
return 1;
if (Name.find("@@") == StringRef::npos &&
S->body()->getName().find("@@") != StringRef::npos)
return -1;
return 0;
}
// We have a new defined symbol with the specified binding. Return 1 if the new
// symbol should win, -1 if the new symbol should lose, or 0 if both symbols are
// strong defined symbols.
static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) {
static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding,
StringRef Name) {
if (WasInserted)
return 1;
SymbolBody *Body = S->body();
if (!Body->isInCurrentDSO())
return 1;
if (int R = compareVersion(S, Name))
return R;
if (Binding == STB_WEAK)
return -1;
if (S->isWeak())
@ -333,8 +360,9 @@ static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) {
// is a conflict. If the new symbol wins, also update the binding.
template <typename ELFT>
static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding,
bool IsAbsolute, typename ELFT::uint Value) {
if (int Cmp = compareDefined(S, WasInserted, Binding)) {
bool IsAbsolute, typename ELFT::uint Value,
StringRef Name) {
if (int Cmp = compareDefined(S, WasInserted, Binding, Name)) {
if (Cmp > 0)
S->Binding = Binding;
return Cmp;
@ -362,7 +390,7 @@ Symbol *SymbolTable<ELFT>::addCommon(StringRef N, uint64_t Size,
bool WasInserted;
std::tie(S, WasInserted) = insert(N, Type, getVisibility(StOther),
/*CanOmitFromDynSym*/ false, File);
int Cmp = compareDefined(S, WasInserted, Binding);
int Cmp = compareDefined(S, WasInserted, Binding, N);
if (Cmp > 0) {
S->Binding = Binding;
replaceBody<DefinedCommon>(S, N, Size, Alignment, StOther, Type, File);
@ -439,7 +467,7 @@ Symbol *SymbolTable<ELFT>::addRegular(StringRef Name, uint8_t StOther,
std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther),
/*CanOmitFromDynSym*/ false, File);
int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, Binding,
Section == nullptr, Value);
Section == nullptr, Value, Name);
if (Cmp > 0)
replaceBody<DefinedRegular>(S, Name, /*IsLocal=*/false, StOther, Type,
Value, Size, Section, File);
@ -485,7 +513,7 @@ Symbol *SymbolTable<ELFT>::addBitcode(StringRef Name, uint8_t Binding,
std::tie(S, WasInserted) =
insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, F);
int Cmp = compareDefinedNonCommon<ELFT>(S, WasInserted, Binding,
/*IsAbs*/ false, /*Value*/ 0);
/*IsAbs*/ false, /*Value*/ 0, Name);
if (Cmp > 0)
replaceBody<DefinedRegular>(S, Name, /*IsLocal=*/false, StOther, Type, 0, 0,
nullptr, F);
@ -717,32 +745,9 @@ void SymbolTable<ELFT>::assignWildcardVersion(SymbolVersion Ver,
B->symbol()->VersionId = VersionId;
}
static bool isDefaultVersion(SymbolBody *B) {
return B->isInCurrentDSO() && B->getName().find("@@") != StringRef::npos;
}
// This function processes version scripts by updating VersionId
// member of symbols.
template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() {
// Symbol themselves might know their versions because symbols
// can contain versions in the form of <name>@<version>.
// Let them parse and update their names to exclude version suffix.
for (Symbol *Sym : SymVector) {
SymbolBody *Body = Sym->body();
bool IsDefault = isDefaultVersion(Body);
Body->parseSymbolVersion();
if (!IsDefault)
continue;
// <name>@@<version> means the symbol is the default version. If that's the
// case, the symbol is not used only to resolve <name> of version <version>
// but also undefined unversioned symbols with name <name>.
SymbolBody *S = find(Body->getName());
if (S && S->isUndefined())
S->copy(Body);
}
// Handle edge cases first.
handleAnonymousVersion();

View File

@ -1,5 +1,5 @@
=======================
LLD 5.0.0 Release Notes
lld 5.0.0 Release Notes
=======================
.. contents::
@ -13,10 +13,16 @@ LLD 5.0.0 Release Notes
Introduction
============
This document contains the release notes for the LLD linker, release 5.0.0.
Here we describe the status of LLD, including major improvements
from the previous release. All LLD releases may be downloaded
from the `LLVM releases web site <http://llvm.org/releases/>`_.
lld is a linker from the LLVM project. It supports ELF (Unix), COFF (Windows)
and Mach-O (macOS), and it is generally faster than the GNU bfd or gold linkers
or the MSVC linker.
lld is designed to be a drop-in replacement for the system linkers, so that
users don't need to change their build systems other than swapping the linker
command.
All lld releases may be downloaded from the `LLVM releases web site
<http://llvm.org/releases/>`_.
Non-comprehensive list of changes in this release
=================================================
@ -24,14 +30,153 @@ Non-comprehensive list of changes in this release
ELF Improvements
----------------
* Item 1.
* First and foremost, a lot of compatibility issues and bugs have been fixed.
Linker script support has significantly improved. As a result, we believe you
are very likely to be able to link your programs with lld without experiencing
any problem now.
* Error message format has changed in order to improve readability.
Traditionally, linker's error messages are concise and arguably too terse.
This is an example of lld 4.0's error message (they are actually in one line)::
/ssd/clang/bin/ld.lld: error: /ssd/llvm-project/lld/ELF/Writer.cpp:207:
undefined symbol 'lld::elf::EhFrameSection::addSection()'
It is not easy to read because too much information is packed into a single line
and the embedded text, particularly a symbol name, is sometimes too long.
In lld 5.0, we use more vertical space to print out error messages in a more
structured manner like this::
bin/ld.lld: error: undefined symbol: lld::elf::EhFrameSection::addSection()
>>> Referenced by Writer.cpp:207 (/ssd/llvm-project/lld/ELF/Writer.cpp:207)
>>> Writer.cpp.o in archive lib/liblldELF.a
As a bonus, the new error message contains source code location of the error
if it is available from debug info.
* ``./configure`` scripts generated by GNU autoconf determines whether a linker
supports modern GNU-compatible features or not by searching for "GNU" in the
``--help`` message. To be compatible with the scripts, we decided to add a
string "(compatible with GNU linkers)" to our ``--help`` message. This is a
hack, but just like the web browser's User-Agent string (which everyone still
claim they are "Mozilla/5.0"), we had no choice other than doing this to claim
that we accept GNU-compatible options.
* The ``-Map`` option is added. The option is to make the linker to print out how
input files are mapped to the output file. Here is an example::
Address Size Align Out In Symbol
00000000016d84d8 00000000008f8f50 8 .eh_frame
00000000016d84d8 00000000008f8f50 8 <internal>:(.eh_frame)
0000000001fd2000 00000000034b3bd0 16 .text
0000000001fd2000 000000000000002a 1 /usr/lib/x86_64-linux-gnu/crt1.o:(.text)
0000000001fd2000 0000000000000000 0 _start
0000000001fd202a 0000000000000000 1 /usr/lib/x86_64-linux-gnu/crti.o:(.text)
0000000001fd2030 00000000000000bd 16 /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o:(.text)
0000000001fd2030 0000000000000000 0 deregister_tm_clones
0000000001fd2060 0000000000000000 0 register_tm_clones
This format is not the same as GNU linkers as our linker internal data
structure is different from them but contains the same amount of information
and should be more readable than their outputs.
As with other lld features, the ``-Map`` option is designed with speed in mind.
The option would generate a hundred megabyte text file if you link a large
program with it. lld can usually do that in a few seconds, and it is generally
a few times faster than the GNU gold's ``-Map`` option.
* lld's ``--gdb-index`` option used to be slow, but we sped it up so that it is
at least as fast as the GNU gold.
* Some nonstandard relocations, such as R_X86_64_8 or R_X86_64_16, are supported.
They are not used for 32/64-bit applications, but some 16-bit bootloaders need
them.
* Paddings in executable text sections are now filled with trap instructions
(such as INT3) instead of being left as null bytes. This change improves
disassembler outputs because it now prints out trap instructions instead of
trying to decode 0x00 as an instruction. It also makes debugging of some type
of program easier because when the control reaches a padding, the program
immediately raises an error.
* The following options are added: ``-M``, ``-Map``,
``-compress-debug-sections``, ``-emit-relocs``,
``-error-unresolved-symbols``, ``-exclude-libs``, ``-filter``,
``-no-dynamic-linker``, ``-no-export-dynamic``, ``-no-fatal-warnings``,
``-print-map``, ``-warn-unresolved-symbols``, ``-z nocopyreloc``,
``-z notext``, ``-z rodynamic``
COFF Improvements
-----------------
* Item 1.
MachO Improvements
------------------
Contributors to lld 5.0
=======================
* Item 1.
We had 63 individuals contribute to lld 5.0. Thank you so much!
- Adrian McCarthy
- Alberto Magni
- Alexander Richardson
- Andre Vieira
- Andrew Ng
- Anton Korobeynikov
- Bob Haarman
- David Blaikie
- Davide Italiano
- David L. Jones
- Dmitry Mikulin
- Ed Maste
- Ed Schouten
- Eric Beckmann
- Eric Fiselier
- Eugene Leviant
- Evgeniy Stepanov
- Galina Kistanova
- George Rimar
- Hans Wennborg
- Igor Kudrin
- Ismail Donmez
- Jake Ehrlich
- James Henderson
- Joel Jones
- Jon Chesterfield
- Kamil Rytarowski
- Kevin Enderby
- Konstantin Zhuravlyov
- Kyungwoo Lee
- Leslie Zhai
- Mark Kettenis
- Martell Malone
- Martin Storsjo
- Meador Inge
- Mehdi Amini
- Michal Gorny
- NAKAMURA Takumi
- Paul Robinson
- Pavel Labath
- Petar Jovanovic
- Peter Collingbourne
- Peter Smith
- Petr Hosek
- Rafael Espindola
- Reid Kleckner
- Richard Smith
- Robert Clarke
- Rui Ueyama
- Saleem Abdulrasool
- Sam Clegg
- Sean Eveson
- Sean Silva
- Shankar Easwaran
- Shoaib Meenai
- Simon Atanasyan
- Simon Dardis
- Simon Tatham
- Sylvestre Ledru
- Tom Stellard
- Vitaly Buka
- Yuka Takahashi
- Zachary Turner

View File

@ -11,6 +11,7 @@
#include "ArchHandler.h"
#include "File.h"
#include "MachONormalizedFileBinaryUtils.h"
#include "MachOPasses.h"
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/File.h"
@ -29,7 +30,7 @@ namespace mach_o {
///
class ObjCImageInfoAtom : public SimpleDefinedAtom {
public:
ObjCImageInfoAtom(const File &file,
ObjCImageInfoAtom(const File &file, bool isBig,
MachOLinkingContext::ObjCConstraint objCConstraint,
uint32_t swiftVersion)
: SimpleDefinedAtom(file) {
@ -54,6 +55,8 @@ class ObjCImageInfoAtom : public SimpleDefinedAtom {
}
Data.info.flags |= (swiftVersion << 8);
normalized::write32(Data.bytes + 4, Data.info.flags, isBig);
}
~ObjCImageInfoAtom() override = default;
@ -109,7 +112,8 @@ class ObjCPass : public Pass {
private:
const DefinedAtom* getImageInfo() {
return new (_file.allocator()) ObjCImageInfoAtom(_file,
bool IsBig = MachOLinkingContext::isBigEndian(_ctx.arch());
return new (_file.allocator()) ObjCImageInfoAtom(_file, IsBig,
_ctx.objcConstraint(),
_ctx.swiftVersion());
}

View File

@ -1,6 +1,10 @@
# RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj
# RUN: rm -f %t.exe.manifest
# RUN: lld-link /out:%t.exe /entry:main %t.obj
# RUN: test ! -e %t.exe.manifest
# RUN: lld-link /manifest /out:%t.exe /entry:main %t.obj
# RUN: FileCheck -check-prefix=MANIFEST %s < %t.exe.manifest
MANIFEST: <?xml version="1.0" standalone="yes"?>
@ -15,7 +19,7 @@ MANIFEST: </security>
MANIFEST: </trustInfo>
MANIFEST: </assembly>
# RUN: lld-link /out:%t.exe /entry:main \
# RUN: lld-link /out:%t.exe /entry:main /manifest \
# RUN: /manifestuac:"level='requireAdministrator' uiAccess='true'" %t.obj
# RUN: FileCheck -check-prefix=UAC %s < %t.exe.manifest
@ -31,6 +35,7 @@ UAC: </security>
UAC: </trustInfo>
UAC: </assembly>
# /manifestdependency implies /manifest. (/manifestuac doesn't.)
# RUN: lld-link /out:%t.exe /entry:main \
# RUN: /manifestdependency:"foo='bar'" %t.obj
# RUN: FileCheck -check-prefix=DEPENDENCY %s < %t.exe.manifest
@ -52,7 +57,7 @@ DEPENDENCY: </dependentAssembly>
DEPENDENCY: </dependency>
DEPENDENCY: </assembly>
# RUN: lld-link /out:%t.exe /entry:main /manifestuac:no %t.obj
# RUN: lld-link /manifest /out:%t.exe /entry:main /manifestuac:no %t.obj
# RUN: FileCheck -check-prefix=NOUAC %s < %t.exe.manifest
NOUAC: <?xml version="1.0" standalone="yes"?>

View File

@ -1,14 +1,5 @@
# REQUIRES: win_mt
# RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj
# RUN: lld-link /out:%t.exe /entry:main \
# RUN: /manifestuac:"level='requireAdministrator'" \
# RUN: /manifestinput:%p/Inputs/manifestinput.test %t.obj
# RUN: FileCheck %s < %t.exe.manifest
CHECK: <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
CHECK: <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity></dependentAssembly></dependency><trustInfo><security><requestedPrivileges><requestedExecutionLevel level="requireAdministrator" uiAccess="false"></requestedExecutionLevel></requestedPrivileges></security></trustInfo></assembly>
# RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj
# RUN: lld-link /out:%t.exe /entry:main \
# RUN: /manifest:embed \

View File

@ -0,0 +1,6 @@
.text
.globl x
.type x, @function
x:
.symver x, xx@@VER

View File

@ -0,0 +1 @@
call xx@PLT

15
test/ELF/symver-archive.s Normal file
View File

@ -0,0 +1,15 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1
# RUN: rm -f %t.a
# RUN: llvm-ar rcs %t.a %t1
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/symver-archive1.s -o %t2.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/symver-archive2.s -o %t3.o
# RUN: ld.lld -o %t.out %t2.o %t3.o %t.a
.text
.globl x
.type x, @function
x:
.globl xx
xx = x