aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-07-29 21:30:27 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-07-29 21:30:27 +0000
commit9e3ca9b3ba1e0fdf794978cb8c8ae386aad936ad (patch)
tree520d351b4ea72ceaff73c29410c126db55bdabef
parentda06c7cfa0388de29a4024d8d386e48f2fb13ed6 (diff)
downloadsrc-9e3ca9b3ba1e0fdf794978cb8c8ae386aad936ad.tar.gz
src-9e3ca9b3ba1e0fdf794978cb8c8ae386aad936ad.zip
Vendor import of lld release_50 branch r309439:vendor/lld/lld-release_50-r310316vendor/lld/lld-release_50-r309439
Notes
Notes: svn path=/vendor/lld/dist/; revision=321698 svn path=/vendor/lld/lld-release_50-r310316/; revision=322266; tag=vendor/lld/lld-release_50-r310316
-rw-r--r--COFF/Config.h2
-rw-r--r--COFF/Driver.cpp26
-rw-r--r--ELF/InputFiles.cpp3
-rw-r--r--ELF/InputFiles.h2
-rw-r--r--ELF/SymbolTable.cpp63
-rw-r--r--docs/ReleaseNotes.rst163
-rw-r--r--lib/ReaderWriter/MachO/ObjCPass.cpp8
-rw-r--r--test/COFF/manifest.test9
-rw-r--r--test/COFF/manifestinput.test9
-rw-r--r--test/ELF/Inputs/symver-archive1.s6
-rw-r--r--test/ELF/Inputs/symver-archive2.s1
-rw-r--r--test/ELF/symver-archive.s15
12 files changed, 246 insertions, 61 deletions
diff --git a/COFF/Config.h b/COFF/Config.h
index a58e7d5585f2..7f8259d016e1 100644
--- a/COFF/Config.h
+++ b/COFF/Config.h
@@ -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;
diff --git a/COFF/Driver.cpp b/COFF/Driver.cpp
index 35f4a04866c5..6df59e4b08df 100644
--- a/COFF/Driver.cpp
+++ b/COFF/Driver.cpp
@@ -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;
diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp
index d3c307d5cb6b..c609615fcc2e 100644
--- a/ELF/InputFiles.cpp
+++ b/ELF/InputFiles.cpp
@@ -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);
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
index f6d3f907850c..006218b45d9e 100644
--- a/ELF/InputFiles.h
+++ b/ELF/InputFiles.h
@@ -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 @@ private:
// 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
diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp
index 83091057ebed..0c932400f0ad 100644
--- a/ELF/SymbolTable.cpp
+++ b/ELF/SymbolTable.cpp
@@ -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();
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index 0d75311e4bce..fa6536ff46a8 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -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
diff --git a/lib/ReaderWriter/MachO/ObjCPass.cpp b/lib/ReaderWriter/MachO/ObjCPass.cpp
index 4712d8ca969c..ccea081f053d 100644
--- a/lib/ReaderWriter/MachO/ObjCPass.cpp
+++ b/lib/ReaderWriter/MachO/ObjCPass.cpp
@@ -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 @@ public:
}
Data.info.flags |= (swiftVersion << 8);
+
+ normalized::write32(Data.bytes + 4, Data.info.flags, isBig);
}
~ObjCImageInfoAtom() override = default;
@@ -109,7 +112,8 @@ public:
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());
}
diff --git a/test/COFF/manifest.test b/test/COFF/manifest.test
index 33e80e75a4d5..accec48d6866 100644
--- a/test/COFF/manifest.test
+++ b/test/COFF/manifest.test
@@ -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"?>
diff --git a/test/COFF/manifestinput.test b/test/COFF/manifestinput.test
index 4eb1730bb0e4..95ebc22f7410 100644
--- a/test/COFF/manifestinput.test
+++ b/test/COFF/manifestinput.test
@@ -2,15 +2,6 @@
# 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 \
# RUN: /manifestuac:"level='requireAdministrator'" \
# RUN: /manifestinput:%p/Inputs/manifestinput.test %t.obj
diff --git a/test/ELF/Inputs/symver-archive1.s b/test/ELF/Inputs/symver-archive1.s
new file mode 100644
index 000000000000..be7c64494215
--- /dev/null
+++ b/test/ELF/Inputs/symver-archive1.s
@@ -0,0 +1,6 @@
+.text
+.globl x
+.type x, @function
+x:
+
+.symver x, xx@@VER
diff --git a/test/ELF/Inputs/symver-archive2.s b/test/ELF/Inputs/symver-archive2.s
new file mode 100644
index 000000000000..a9b9d0b0a35b
--- /dev/null
+++ b/test/ELF/Inputs/symver-archive2.s
@@ -0,0 +1 @@
+call xx@PLT
diff --git a/test/ELF/symver-archive.s b/test/ELF/symver-archive.s
new file mode 100644
index 000000000000..be50503a3f5d
--- /dev/null
+++ b/test/ELF/symver-archive.s
@@ -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