[lld] r213077 - [ELF] Implement parsing `-l` prefixed items in the `GROUP` linker script command.

Simon Atanasyan simon at atanasyan.com
Tue Jul 15 10:17:33 PDT 2014


Author: atanasyan
Date: Tue Jul 15 12:17:30 2014
New Revision: 213077

URL: http://llvm.org/viewvc/llvm-project?rev=213077&view=rev
Log:
[ELF] Implement parsing `-l` prefixed items in the `GROUP` linker script command.
There are two forms of `-l` prefixed expression:

* -l<libname>
* -l:<filename>

In the first case a linker should construct a full library name
`lib + libname + .[so|a]` and search this library as usual. In the second case
a linker should use the `<filename>` as is and search this file through library
search directories.

The patch reviewed by Shankar Easwaran.

Added:
    lld/trunk/test/LinkerScript/libname-err-1.test
    lld/trunk/test/LinkerScript/libname-err-2.test
    lld/trunk/test/elf/Inputs/group-cmd-search-3.ls
Modified:
    lld/trunk/include/lld/ReaderWriter/LinkerScript.h
    lld/trunk/lib/Driver/GnuLdInputGraph.cpp
    lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
    lld/trunk/lib/ReaderWriter/LinkerScript.cpp
    lld/trunk/test/LinkerScript/linker-script.test
    lld/trunk/test/elf/group-cmd-search.test

Modified: lld/trunk/include/lld/ReaderWriter/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/LinkerScript.h?rev=213077&r1=213076&r2=213077&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/LinkerScript.h (original)
+++ lld/trunk/include/lld/ReaderWriter/LinkerScript.h Tue Jul 15 12:17:30 2014
@@ -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 << ")";

Modified: lld/trunk/lib/Driver/GnuLdInputGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdInputGraph.cpp?rev=213077&r1=213076&r2=213077&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdInputGraph.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdInputGraph.cpp Tue Jul 15 12:17:30 2014
@@ -96,6 +96,7 @@ std::error_code ELFGNULdScript::parse(co
     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);

Modified: lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp?rev=213077&r1=213076&r2=213077&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp Tue Jul 15 12:17:30 2014
@@ -163,18 +163,23 @@ static void buildSearchPath(SmallString<
 }
 
 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()));
   }

Modified: lld/trunk/lib/ReaderWriter/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/LinkerScript.cpp?rev=213077&r1=213076&r2=213077&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/LinkerScript.cpp (original)
+++ lld/trunk/lib/ReaderWriter/LinkerScript.cpp Tue Jul 15 12:17:30 2014
@@ -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<P
   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 )"))

Added: lld/trunk/test/LinkerScript/libname-err-1.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/LinkerScript/libname-err-1.test?rev=213077&view=auto
==============================================================================
--- lld/trunk/test/LinkerScript/libname-err-1.test (added)
+++ lld/trunk/test/LinkerScript/libname-err-1.test Tue Jul 15 12:17:30 2014
@@ -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 )
+*/

Added: lld/trunk/test/LinkerScript/libname-err-2.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/LinkerScript/libname-err-2.test?rev=213077&view=auto
==============================================================================
--- lld/trunk/test/LinkerScript/libname-err-2.test (added)
+++ lld/trunk/test/LinkerScript/libname-err-2.test Tue Jul 15 12:17:30 2014
@@ -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 )
+*/

Modified: lld/trunk/test/LinkerScript/linker-script.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/LinkerScript/linker-script.test?rev=213077&r1=213076&r2=213077&view=diff
==============================================================================
--- lld/trunk/test/LinkerScript/linker-script.test (original)
+++ lld/trunk/test/LinkerScript/linker-script.test Tue Jul 15 12:17:30 2014
@@ -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)
 */

Added: lld/trunk/test/elf/Inputs/group-cmd-search-3.ls
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/Inputs/group-cmd-search-3.ls?rev=213077&view=auto
==============================================================================
--- lld/trunk/test/elf/Inputs/group-cmd-search-3.ls (added)
+++ lld/trunk/test/elf/Inputs/group-cmd-search-3.ls Tue Jul 15 12:17:30 2014
@@ -0,0 +1 @@
+GROUP ( -l:shared.so-x86-64 -lfnarchive )

Modified: lld/trunk/test/elf/group-cmd-search.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/group-cmd-search.test?rev=213077&r1=213076&r2=213077&view=diff
==============================================================================
--- lld/trunk/test/elf/group-cmd-search.test (original)
+++ lld/trunk/test/elf/group-cmd-search.test Tue Jul 15 12:17:30 2014
@@ -101,6 +101,19 @@ RUN:     %p/Inputs/group-cmd-search-2.ls
 */
 
 /*
+  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.





More information about the llvm-commits mailing list