summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/include/lld/ReaderWriter/LinkerScript.h10
-rw-r--r--lld/lib/Driver/GnuLdInputGraph.cpp1
-rw-r--r--lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp9
-rw-r--r--lld/lib/ReaderWriter/LinkerScript.cpp42
-rw-r--r--lld/test/LinkerScript/libname-err-1.test11
-rw-r--r--lld/test/LinkerScript/libname-err-2.test11
-rw-r--r--lld/test/LinkerScript/linker-script.test6
-rw-r--r--lld/test/elf/Inputs/group-cmd-search-3.ls1
-rw-r--r--lld/test/elf/group-cmd-search.test13
9 files changed, 93 insertions, 11 deletions
diff --git a/lld/include/lld/ReaderWriter/LinkerScript.h b/lld/include/lld/ReaderWriter/LinkerScript.h
index 7d52f596fd5..ede0e350b92 100644
--- a/lld/include/lld/ReaderWriter/LinkerScript.h
+++ b/lld/include/lld/ReaderWriter/LinkerScript.h
@@ -34,6 +34,7 @@ public:
unknown,
eof,
identifier,
+ libname,
comma,
l_paren,
r_paren,
@@ -145,10 +146,11 @@ private:
struct Path {
StringRef _path;
bool _asNeeded;
+ bool _isDashlPrefix;
- Path() : _asNeeded(false) {}
- explicit Path(StringRef path, bool asNeeded = false)
- : _path(path), _asNeeded(asNeeded) {}
+ Path() : _asNeeded(false), _isDashlPrefix(false) {}
+ explicit Path(StringRef path, bool asNeeded = false, bool isLib = false)
+ : _path(path), _asNeeded(asNeeded), _isDashlPrefix(isLib) {}
};
class Group : public Command {
@@ -169,6 +171,8 @@ public:
first = false;
if (path._asNeeded)
os << "AS_NEEDED(";
+ if (path._isDashlPrefix)
+ os << "-l";
os << path._path;
if (path._asNeeded)
os << ")";
diff --git a/lld/lib/Driver/GnuLdInputGraph.cpp b/lld/lib/Driver/GnuLdInputGraph.cpp
index f634c2eba58..ac85565d100 100644
--- a/lld/lib/Driver/GnuLdInputGraph.cpp
+++ b/lld/lib/Driver/GnuLdInputGraph.cpp
@@ -96,6 +96,7 @@ std::error_code ELFGNULdScript::parse(const LinkingContext &ctx,
for (const script::Path &path : group->getPaths()) {
// TODO : Propagate Set WholeArchive/dashlPrefix
attributes.setAsNeeded(path._asNeeded);
+ attributes.setDashlPrefix(path._isDashlPrefix);
auto inputNode = new ELFFileNode(
_elfLinkingContext, _elfLinkingContext.allocateString(path._path),
attributes);
diff --git a/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
index 23036bca9f9..fe33d403d10 100644
--- a/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
+++ b/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
@@ -163,18 +163,23 @@ static void buildSearchPath(SmallString<128> &path, StringRef dir,
}
ErrorOr<StringRef> ELFLinkingContext::searchLibrary(StringRef libName) const {
+ bool hasColonPrefix = libName[0] == ':';
+ Twine soName =
+ hasColonPrefix ? libName.drop_front() : Twine("lib", libName) + ".so";
+ Twine archiveName =
+ hasColonPrefix ? libName.drop_front() : Twine("lib", libName) + ".a";
SmallString<128> path;
for (StringRef dir : _inputSearchPaths) {
// Search for dynamic library
if (!_isStaticExecutable) {
buildSearchPath(path, dir, _sysrootPath);
- llvm::sys::path::append(path, Twine("lib") + libName + ".so");
+ llvm::sys::path::append(path, soName);
if (llvm::sys::fs::exists(path.str()))
return StringRef(*new (_allocator) std::string(path.str()));
}
// Search for static libraries too
buildSearchPath(path, dir, _sysrootPath);
- llvm::sys::path::append(path, Twine("lib") + libName + ".a");
+ llvm::sys::path::append(path, archiveName);
if (llvm::sys::fs::exists(path.str()))
return StringRef(*new (_allocator) std::string(path.str()));
}
diff --git a/lld/lib/ReaderWriter/LinkerScript.cpp b/lld/lib/ReaderWriter/LinkerScript.cpp
index 796fa24a566..8ba5f47e5c4 100644
--- a/lld/lib/ReaderWriter/LinkerScript.cpp
+++ b/lld/lib/ReaderWriter/LinkerScript.cpp
@@ -24,6 +24,7 @@ void Token::dump(raw_ostream &os) const {
break;
CASE(eof)
CASE(identifier)
+ CASE(libname)
CASE(kw_as_needed)
CASE(kw_entry)
CASE(kw_group)
@@ -118,6 +119,24 @@ void Lexer::lex(Token &tok) {
_buffer = _buffer.drop_front(quotedStringEnd + 1);
return;
}
+ // -l<lib name>
+ if (_buffer.startswith("-l")) {
+ _buffer = _buffer.drop_front(2);
+ StringRef::size_type start = 0;
+ if (_buffer[start] == ':')
+ ++start;
+ if (!canStartName(_buffer[start]))
+ // Create 'unknown' token.
+ break;
+ auto libNameEnd =
+ std::find_if(_buffer.begin() + start + 1, _buffer.end(),
+ [=](char c) { return !canContinueName(c); });
+ StringRef::size_type libNameLen =
+ std::distance(_buffer.begin(), libNameEnd);
+ tok = Token(_buffer.substr(0, libNameLen), Token::libname);
+ _buffer = _buffer.drop_front(libNameLen);
+ return;
+ }
/// keyword or identifer.
if (!canStartName(_buffer[0]))
break;
@@ -295,12 +314,17 @@ Group *Parser::parseGroup() {
std::vector<Path> paths;
- while (_tok._kind == Token::identifier || _tok._kind == Token::kw_as_needed) {
+ while (_tok._kind == Token::identifier || _tok._kind == Token::libname ||
+ _tok._kind == Token::kw_as_needed) {
switch (_tok._kind) {
case Token::identifier:
paths.push_back(Path(_tok._range));
consumeToken();
break;
+ case Token::libname:
+ paths.push_back(Path(_tok._range, false, true));
+ consumeToken();
+ break;
case Token::kw_as_needed:
if (!parseAsNeeded(paths))
return nullptr;
@@ -325,9 +349,19 @@ bool Parser::parseAsNeeded(std::vector<Path> &paths) {
if (!expectAndConsume(Token::l_paren, "expected ("))
return false;
- while (_tok._kind == Token::identifier) {
- paths.push_back(Path(_tok._range, true));
- consumeToken();
+ while (_tok._kind == Token::identifier || _tok._kind == Token::libname) {
+ switch (_tok._kind) {
+ case Token::identifier:
+ paths.push_back(Path(_tok._range, true, false));
+ consumeToken();
+ break;
+ case Token::libname:
+ paths.push_back(Path(_tok._range, true, true));
+ consumeToken();
+ break;
+ default:
+ llvm_unreachable("Invalid token.");
+ }
}
if (!expectAndConsume(Token::r_paren, "expected )"))
diff --git a/lld/test/LinkerScript/libname-err-1.test b/lld/test/LinkerScript/libname-err-1.test
new file mode 100644
index 00000000000..a31b35e93e3
--- /dev/null
+++ b/lld/test/LinkerScript/libname-err-1.test
@@ -0,0 +1,11 @@
+/* RUN: linker-script-test %s 2>&1 | FileCheck %s
+*/
+
+OUTPUT_ARCH(i386:x86_64)
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+GROUP( -l### )
+ENTRY(init)
+
+/*
+CHECK: test/LinkerScript/libname-err-1.test:6:10: error: expected )
+*/
diff --git a/lld/test/LinkerScript/libname-err-2.test b/lld/test/LinkerScript/libname-err-2.test
new file mode 100644
index 00000000000..1e300947a96
--- /dev/null
+++ b/lld/test/LinkerScript/libname-err-2.test
@@ -0,0 +1,11 @@
+/* RUN: linker-script-test %s 2>&1 | FileCheck %s
+*/
+
+OUTPUT_ARCH(i386:x86_64)
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+GROUP( -l )
+ENTRY(init)
+
+/*
+CHECK: test/LinkerScript/libname-err-2.test:6:10: error: expected )
+*/
diff --git a/lld/test/LinkerScript/linker-script.test b/lld/test/LinkerScript/linker-script.test
index a050c5637a5..4c6643566c7 100644
--- a/lld/test/LinkerScript/linker-script.test
+++ b/lld/test/LinkerScript/linker-script.test
@@ -3,7 +3,7 @@
OUTPUT_ARCH(i386:x86_64)
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
-GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED ( /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ) )
+GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED ( /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ) -lm -l:libgcc.a )
ENTRY(init)
/*
@@ -27,6 +27,8 @@ CHECK: kw_as_needed: AS_NEEDED
CHECK: l_paren: (
CHECK: identifier: /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
CHECK: r_paren: )
+CHECK: libname: m
+CHECK: libname: :libgcc.a
CHECK: r_paren: )
CHECK: kw_entry: ENTRY
CHECK: l_paren: (
@@ -34,6 +36,6 @@ CHECK: identifier: init
CHECK: r_paren: )
CHECK: eof:
CHECK: OUTPUT_FORMAT(elf64-x86-64,elf64-x86-64,elf64-x86-64)
-CHECK: GROUP(/lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED(/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2))
+CHECK: GROUP(/lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED(/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2) -lm -l:libgcc.a)
CHECK: ENTRY(init)
*/
diff --git a/lld/test/elf/Inputs/group-cmd-search-3.ls b/lld/test/elf/Inputs/group-cmd-search-3.ls
new file mode 100644
index 00000000000..83ce0ca62fb
--- /dev/null
+++ b/lld/test/elf/Inputs/group-cmd-search-3.ls
@@ -0,0 +1 @@
+GROUP ( -l:shared.so-x86-64 -lfnarchive )
diff --git a/lld/test/elf/group-cmd-search.test b/lld/test/elf/group-cmd-search.test
index 01af279b683..2f5c0f48501 100644
--- a/lld/test/elf/group-cmd-search.test
+++ b/lld/test/elf/group-cmd-search.test
@@ -101,6 +101,19 @@ RUN: %p/Inputs/group-cmd-search-2.ls -o %t6
*/
/*
+ This link should finish successfully. The group-cmd-search-3.ls
+ script contains GROUP command with two elements. The first one
+ has a -l:<path> form and should be found by iterating through
+ lib dirs and searching the 'path' name exactly. The second element
+ has a -l<lib name> form and should be found by constructing a full
+ library name lib<lib name>.a and iterating through lib dirs.
+
+RUN: lld -flavor gnu -target x86_64 -shared \
+RUN: -L%p/Inputs %p/Inputs/use-shared.x86-64 \
+RUN: %p/Inputs/group-cmd-search-3.ls -o %t8
+*/
+
+/*
This link should fail with unknown input file format error.
The linker script from this file contains GROUP with an absolute
path which can be found under provided sysroot directory.
OpenPOWER on IntegriCloud