This revision was automatically updated to reflect the committed changes.
Closed by commit rLLD360984: [ELF] Implement Dependent Libraries Feature 
(authored by bd1976llvm, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D60274?vs=195495&id=199972#toc

Repository:
  rLLD LLVM Linker

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D60274/new/

https://reviews.llvm.org/D60274

Files:
  ELF/Config.h
  ELF/Driver.cpp
  ELF/Driver.h
  ELF/DriverUtils.cpp
  ELF/InputFiles.cpp
  ELF/Options.td
  test/ELF/Inputs/deplibs-lib_bar.s
  test/ELF/Inputs/deplibs-lib_foo.s
  test/ELF/deplibs-colon-prefix.s
  test/ELF/deplibs-corrupt.s
  test/ELF/deplibs.s
  test/ELF/lto/deplibs.s

Index: ELF/Config.h
===================================================================
--- ELF/Config.h
+++ ELF/Config.h
@@ -137,6 +137,7 @@
   bool Cref;
   bool DefineCommon;
   bool Demangle = true;
+  bool DependentLibraries;
   bool DisableVerify;
   bool EhFrameHdr;
   bool EmitLLVM;
Index: ELF/Driver.cpp
===================================================================
--- ELF/Driver.cpp
+++ ELF/Driver.cpp
@@ -790,6 +790,7 @@
   Config->DefineCommon = Args.hasFlag(OPT_define_common, OPT_no_define_common,
                                       !Args.hasArg(OPT_relocatable));
   Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true);
+  Config->DependentLibraries = Args.hasFlag(OPT_dependent_libraries, OPT_no_dependent_libraries, true);
   Config->DisableVerify = Args.hasArg(OPT_disable_verify);
   Config->Discard = getDiscard(Args);
   Config->DwoDir = Args.getLastArgValue(OPT_plugin_opt_dwo_dir_eq);
@@ -1548,9 +1549,11 @@
     Symtab->trace(Arg->getValue());
 
   // Add all files to the symbol table. This will add almost all
-  // symbols that we need to the symbol table.
-  for (InputFile *F : Files)
-    parseFile(F);
+  // symbols that we need to the symbol table. This process might
+  // add files to the link, via autolinking, these files are always
+  // appended to the Files vector.
+  for (size_t I = 0; I < Files.size(); ++I)
+    parseFile(Files[I]);
 
   // Now that we have every file, we can decide if we will need a
   // dynamic symbol table.
Index: ELF/InputFiles.cpp
===================================================================
--- ELF/InputFiles.cpp
+++ ELF/InputFiles.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "InputFiles.h"
+#include "Driver.h"
 #include "InputSection.h"
 #include "LinkerScript.h"
 #include "SymbolTable.h"
@@ -499,6 +500,27 @@
   }
 }
 
+// An ELF object file may contain a `.deplibs` section. If it exists, the
+// section contains a list of library specifiers such as `m` for libm. This
+// function resolves a given name by finding the first matching library checking
+// the various ways that a library can be specified to LLD. This ELF extension
+// is a form of autolinking and is called `dependent libraries`. It is currently
+// unique to LLVM and lld.
+static void addDependentLibrary(StringRef Specifier, const InputFile *F) {
+  if (!Config->DependentLibraries)
+    return;
+  if (fs::exists(Specifier))
+    Driver->addFile(Specifier, /*WithLOption=*/false);
+  else if (Optional<std::string> S = findFromSearchPaths(Specifier))
+    Driver->addFile(*S, /*WithLOption=*/true);
+  else if (Optional<std::string> S = searchLibraryBaseName(Specifier))
+    Driver->addFile(*S, /*WithLOption=*/true);
+  else
+    error(toString(F) +
+          ": unable to find library from dependent library specifier: " +
+          Specifier);
+}
+
 template <class ELFT>
 void ObjFile<ELFT>::initializeSections(
     DenseSet<CachedHashStringRef> &ComdatGroups) {
@@ -740,6 +762,24 @@
     }
     return &InputSection::Discarded;
   }
+  case SHT_LLVM_DEPENDENT_LIBRARIES: {
+    if (Config->Relocatable)
+      break;
+    ArrayRef<char> Data =
+        CHECK(this->getObj().template getSectionContentsAsArray<char>(&Sec), this);
+    if (!Data.empty() && Data.back() != '\0') {
+      error(toString(this) +
+            ": corrupted dependent libraries section (unterminated string): " +
+            Name);
+      return &InputSection::Discarded;
+    }
+    for (const char *D = Data.begin(), *E = Data.end(); D < E;) {
+      StringRef S(D);
+      addDependentLibrary(S, this);
+      D += S.size() + 1;
+    }
+    return &InputSection::Discarded;
+  }
   case SHT_RELA:
   case SHT_REL: {
     // Find a relocation target section and associate this section with that.
@@ -1302,6 +1342,9 @@
 
   for (const lto::InputFile::Symbol &ObjSym : Obj->symbols())
     Symbols.push_back(createBitcodeSymbol<ELFT>(KeptComdats, ObjSym, *this));
+
+  for (auto L : Obj->getDependentLibraries())
+    addDependentLibrary(L, this);
 }
 
 static ELFKind getELFKind(MemoryBufferRef MB, StringRef ArchiveName) {
Index: ELF/Options.td
===================================================================
--- ELF/Options.td
+++ ELF/Options.td
@@ -71,6 +71,10 @@
     "Apply link-time values for dynamic relocations",
     "Do not apply link-time values for dynamic relocations (default)">;
 
+defm dependent_libraries: B<"dependent-libraries",
+    "Process dependent library specifiers from input files (default)",
+    "Ignore dependent library specifiers from input files">;
+
 defm as_needed: B<"as-needed",
     "Only set DT_NEEDED for shared libraries if used",
     "Always set DT_NEEDED for shared libraries (default)">;
Index: ELF/DriverUtils.cpp
===================================================================
--- ELF/DriverUtils.cpp
+++ ELF/DriverUtils.cpp
@@ -223,12 +223,9 @@
   return None;
 }
 
-// This is for -lfoo. We'll look for libfoo.so or libfoo.a from
+// This is for -l<basename>. We'll look for lib<basename>.so or lib<basename>.a from
 // search paths.
-Optional<std::string> elf::searchLibrary(StringRef Name) {
-  if (Name.startswith(":"))
-    return findFromSearchPaths(Name.substr(1));
-
+Optional<std::string> elf::searchLibraryBaseName(StringRef Name) {
   for (StringRef Dir : Config->SearchPaths) {
     if (!Config->Static)
       if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".so"))
@@ -239,6 +236,13 @@
   return None;
 }
 
+// This is for -l<namespec>.
+Optional<std::string> elf::searchLibrary(StringRef Name) {
+    if (Name.startswith(":"))
+        return findFromSearchPaths(Name.substr(1));
+    return searchLibraryBaseName (Name);
+}
+
 // If a linker/version script doesn't exist in the current directory, we also
 // look for the script in the '-L' search paths. This matches the behaviour of
 // '-T', --version-script=, and linker script INPUT() command in ld.bfd.
Index: ELF/Driver.h
===================================================================
--- ELF/Driver.h
+++ ELF/Driver.h
@@ -63,6 +63,7 @@
 
 llvm::Optional<std::string> findFromSearchPaths(StringRef Path);
 llvm::Optional<std::string> searchScript(StringRef Path);
+llvm::Optional<std::string> searchLibraryBaseName(StringRef Path);
 llvm::Optional<std::string> searchLibrary(StringRef Path);
 
 } // namespace elf
Index: test/ELF/lto/deplibs.s
===================================================================
--- test/ELF/lto/deplibs.s
+++ test/ELF/lto/deplibs.s
@@ -0,0 +1,15 @@
+; REQUIRES: x86
+
+; RUN: llvm-as %s -o %t.o
+; RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck %s -DOBJ=%t.o
+
+; CHECK: error: [[OBJ]]: unable to find library from dependent library specifier: foo
+; CHECK: error: [[OBJ]]: unable to find library from dependent library specifier: bar
+
+target triple = "x86_64-unknown-linux-gnu"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+!llvm.dependent-libraries = !{!0, !1}
+
+!0 = !{!"foo"}
+!1 = !{!"bar"}
Index: test/ELF/deplibs-colon-prefix.s
===================================================================
--- test/ELF/deplibs-colon-prefix.s
+++ test/ELF/deplibs-colon-prefix.s
@@ -0,0 +1,15 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/deplibs-lib_foo.s -o %tfoo.o
+# RUN: rm -rf %t.dir
+# RUN: mkdir -p %t.dir
+# RUN: llvm-ar rc %t.dir/foo.a %tfoo.o
+# RUN: not ld.lld %t.o -o /dev/null -L %t.dir 2>&1 | FileCheck %s -DOBJ=%t.o
+# CHECK: error: [[OBJ]]: unable to find library from dependent library specifier: :foo.a
+
+        .global _start
+_start:
+        call foo
+    .section ".deplibs","MS",@llvm_dependent_libraries,1
+        .asciz  ":foo.a"
Index: test/ELF/deplibs.s
===================================================================
--- test/ELF/deplibs.s
+++ test/ELF/deplibs.s
@@ -0,0 +1,56 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/deplibs-lib_foo.s -o %tfoo.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/deplibs-lib_bar.s -o %tbar.o
+# RUN: rm -rf %t.dir %t.cwd
+# RUN: mkdir -p %t.dir
+
+# error if dependent libraries cannot be found
+# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s -DOBJ=%t.o --check-prefix MISSING
+# MISSING: error: [[OBJ]]: unable to find library from dependent library specifier: foo.a
+# MISSING-NEXT: error: [[OBJ]]: unable to find library from dependent library specifier: bar
+
+# can ignore dependent libraries
+# RUN: not ld.lld %t.o -o /dev/null --no-dependent-libraries 2>&1 | FileCheck %s --check-prefix IGNORE
+# IGNORE: error: undefined symbol: foo
+# IGNORE: error: undefined symbol: bar
+
+# -r links preserve dependent libraries
+# RUN: ld.lld %t.o %t.o -r -o %t-r.o
+# RUN: not ld.lld %t-r.o -o /dev/null 2>&1 | sort | FileCheck %s -DOBJ=%t-r.o --check-prefixes MINUSR
+# MINUSR: error: [[OBJ]]: unable to find library from dependent library specifier: bar
+# MINUSR-NEXT: error: [[OBJ]]: unable to find library from dependent library specifier: foo.a
+# MINUSR-NOT: unable to find library from dependent library specifier
+
+# static archives located relative to library search paths
+# RUN: llvm-ar rc %t.dir/foo.a %tfoo.o
+# RUN: llvm-ar rc %t.dir/libbar.a %tbar.o
+# RUN: ld.lld %t.o -o /dev/null -L %t.dir
+
+# shared objects located relative to library search paths
+# RUN: rm %t.dir/libbar.a
+# RUN: ld.lld -shared -o %t.dir/libbar.so %tbar.o
+# RUN: ld.lld -Bdynamic %t.o -o /dev/null -L %t.dir
+
+# dependent libraries searched for symbols after libraries on the command line
+# RUN: mkdir -p %t.cwd
+# RUN: cd %t.cwd
+# RUN: cp %t.dir/foo.a %t.cwd/libcmdline.a
+# RUN: ld.lld %t.o libcmdline.a -o /dev/null -L %t.dir --trace 2>&1 | FileCheck %s -DOBJ=%t.o -DSO=%t.dir --check-prefix CMDLINE --implicit-check-not foo.a
+# CMDLINE: [[OBJ]]
+# CMDLINE-NEXT: {{^libcmdline\.a}}
+# CMDLINE-NEXT: [[SO]]{{[\\/]}}libbar.so
+
+# libraries can be found from specifiers as if the specifiers were listed on on the command-line.
+# RUN: cp %t.dir/foo.a %t.cwd/foo.a
+# RUN: ld.lld %t.o -o /dev/null -L %t.dir --trace 2>&1 | FileCheck %s -DOBJ=%t.o -DSO=%t.dir --check-prefix ASIFCMDLINE --implicit-check-not foo.a
+# ASIFCMDLINE: [[OBJ]]
+# ASIFCMDLINE-NEXT: {{^foo\.a}}
+# ASIFCMDLINE-NEXT: [[SO]]{{[\\/]}}libbar.so
+
+    call foo
+    call bar
+.section ".deplibs","MS",@llvm_dependent_libraries,1
+    .asciz  "foo.a"
+    .asciz  "bar"
Index: test/ELF/deplibs-corrupt.s
===================================================================
--- test/ELF/deplibs-corrupt.s
+++ test/ELF/deplibs-corrupt.s
@@ -0,0 +1,8 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: not ld.lld %t.o -o /dev/null -L %t.dir 2>&1 | FileCheck %s -DOBJ=%t.o
+# CHECK: error: [[OBJ]]: corrupted dependent libraries section (unterminated string): .deplibs
+
+.section ".deplibs","MS",@llvm_dependent_libraries,1
+    .ascii  ":foo.a"
Index: test/ELF/Inputs/deplibs-lib_foo.s
===================================================================
--- test/ELF/Inputs/deplibs-lib_foo.s
+++ test/ELF/Inputs/deplibs-lib_foo.s
@@ -0,0 +1,2 @@
+        .global foo
+foo:
Index: test/ELF/Inputs/deplibs-lib_bar.s
===================================================================
--- test/ELF/Inputs/deplibs-lib_bar.s
+++ test/ELF/Inputs/deplibs-lib_bar.s
@@ -0,0 +1,2 @@
+        .global bar
+bar:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to