[lld] r249998 - ELF2: Implement --as-needed.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 11 13:59:13 PDT 2015


Author: ruiu
Date: Sun Oct 11 15:59:12 2015
New Revision: 249998

URL: http://llvm.org/viewvc/llvm-project?rev=249998&view=rev
Log:
ELF2: Implement --as-needed.

This patch adds AsNeeded and IsUsed bool fields to SharedFile. AsNeeded bit
is set if the DSO is enclosed with --as-needed and --no-as-needed. IsUsed
bit is off by default. When we adds a symbol to the symbol table for dynamic
linking, we set its SharedFile's IsUsed bit.

If AsNeeded is set but IsUsed is not set, we don't want to write that
file's SO name to DT_NEEDED field.

http://reviews.llvm.org/D13579

Added:
    lld/trunk/test/elf2/Inputs/shared2.s
    lld/trunk/test/elf2/Inputs/shared3.s
    lld/trunk/test/elf2/as-needed.s
Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/InputFiles.cpp
    lld/trunk/ELF/InputFiles.h
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/Options.td
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/Symbols.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=249998&r1=249997&r2=249998&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Sun Oct 11 15:59:12 2015
@@ -43,6 +43,7 @@ struct Configuration {
   std::string RPath;
   std::vector<llvm::StringRef> SearchPaths;
   bool AllowMultipleDefinition;
+  bool AsNeeded = false;
   bool DiscardAll;
   bool DiscardLocals;
   bool DiscardNone;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=249998&r1=249997&r2=249998&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Sun Oct 11 15:59:12 2015
@@ -100,9 +100,12 @@ void LinkerDriver::addFile(StringRef Pat
     }
     Files.push_back(make_unique<ArchiveFile>(MBRef));
     return;
-  case file_magic::elf_shared_object:
-    Files.push_back(createELFFile<SharedFile>(MBRef));
+  case file_magic::elf_shared_object: {
+    std::unique_ptr<ELFFileBase> File = createELFFile<SharedFile>(MBRef);
+    cast<SharedFileBase>(File.get())->AsNeeded = Config->AsNeeded;
+    Files.push_back(std::move(File));
     return;
+  }
   default:
     Files.push_back(createELFFile<ObjectFile>(MBRef));
   }
@@ -187,6 +190,12 @@ void LinkerDriver::createFiles(opt::Inpu
     case OPT_script:
       addFile(Arg->getValue());
       break;
+    case OPT_as_needed:
+      Config->AsNeeded = true;
+      break;
+    case OPT_no_as_needed:
+      Config->AsNeeded = false;
+      break;
     case OPT_Bstatic:
       Config->Static = true;
       break;

Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=249998&r1=249997&r2=249998&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Sun Oct 11 15:59:12 2015
@@ -329,7 +329,7 @@ template <class ELFT> void SharedFile<EL
     error(NameOrErr.getError());
     StringRef Name = *NameOrErr;
 
-    SymbolBodies.emplace_back(Name, Sym);
+    SymbolBodies.emplace_back(this, Name, Sym);
   }
 }
 

Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=249998&r1=249997&r2=249998&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Sun Oct 11 15:59:12 2015
@@ -146,7 +146,7 @@ public:
     uint32_t FirstNonLocal = this->Symtab->sh_info;
     if (SymbolIndex < FirstNonLocal)
       return nullptr;
-    return SymbolBodies[SymbolIndex - FirstNonLocal]->repl();
+    return SymbolBodies[SymbolIndex - FirstNonLocal];
   }
 
   Elf_Sym_Range getLocalSymbols();
@@ -198,6 +198,11 @@ public:
   StringRef getSoName() const { return SoName; }
   virtual void parseSoName() = 0;
   virtual void parse() = 0;
+
+  // Used for --as-needed
+  bool AsNeeded = false;
+  bool IsUsed = false;
+  bool isNeeded() const { return !AsNeeded || IsUsed; }
 };
 
 template <class ELFT>

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=249998&r1=249997&r2=249998&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Sun Oct 11 15:59:12 2015
@@ -46,7 +46,7 @@ void InputSection<ELFT>::relocate(
         continue;
       SymVA = getLocalSymVA(Sym, File);
     } else {
-      SymbolBody &Body = *File.getSymbolBody(SymIndex);
+      SymbolBody &Body = *File.getSymbolBody(SymIndex)->repl();
       SymVA = getSymVA<ELFT>(Body);
       if (Target->relocNeedsPlt(Type, Body)) {
         SymVA = Out<ELFT>::Plt->getEntryAddr(Body);

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=249998&r1=249997&r2=249998&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Sun Oct 11 15:59:12 2015
@@ -155,12 +155,15 @@ void LinkerScript::addFile(StringRef S)
 
 void LinkerScript::readAsNeeded() {
   expect("(");
+  bool Orig = Config->AsNeeded;
+  Config->AsNeeded = true;
   for (;;) {
     StringRef Tok = next();
     if (Tok == ")")
-      return;
+      break;
     addFile(Tok);
   }
+  Config->AsNeeded = Orig;
 }
 
 void LinkerScript::readEntry() {

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=249998&r1=249997&r2=249998&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Sun Oct 11 15:59:12 2015
@@ -14,6 +14,8 @@ def allow_multiple_definition: Flag<["--
 
 def allow_shlib_undefined : Flag<["--", "-"], "allow-shlib-undefined">;
 
+def as_needed : Flag<["--"], "as-needed">;
+
 def disable_new_dtags : Flag<["--"], "disable-new-dtags">,
   HelpText<"Disable new dynamic tags">;
 
@@ -52,6 +54,8 @@ def m : Separate<["-"], "m">,
 
 def no_allow_shlib_undefined : Flag<["--"], "no-allow-shlib-undefined">;
 
+def no_as_needed : Flag<["--"], "no-as-needed">;
+
 def no_whole_archive : Flag<["--"], "no-whole-archive">,
   HelpText<"Restores the default behavior of loading archive members">;
 
@@ -111,14 +115,12 @@ def alias_undefined_u : Separate<["-"],
 
 // Options listed below are silently ignored now.
 def O3 : Flag<["-"], "O3">;
-def as_needed : Flag<["--"], "as-needed">;
 def build_id : Flag<["--"], "build-id">;
 def eh_frame_hdr : Flag<["--"], "eh-frame-hdr">;
 def end_group : Flag<["--"], "end-group">;
 def gc_sections : Flag<["--"], "gc-sections">;
 def hash_style : Joined<["--"], "hash-style=">;
 def no_add_needed : Flag<["--"], "no-add-needed">;
-def no_as_needed : Flag<["--"], "no-as-needed">;
 def no_fatal_warnings : Flag<["--"], "no-fatal-warnings">;
 def start_group : Flag<["--"], "start-group">;
 def strip_all : Flag<["--"], "strip-all">;

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=249998&r1=249997&r2=249998&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Sun Oct 11 15:59:12 2015
@@ -116,8 +116,10 @@ template <class ELFT> void RelocationSec
     OutputSection<ELFT> *OutSec = C.getOutputSection();
     uint32_t SymIndex = RI.getSymbol(IsMips64EL);
     const ObjectFile<ELFT> &File = *C.getFile();
-    const SymbolBody *Body = File.getSymbolBody(SymIndex);
+    SymbolBody *Body = File.getSymbolBody(SymIndex);
     const ELFFile<ELFT> &Obj = File.getObj();
+    if (Body)
+      Body = Body->repl();
 
     uint32_t Type = RI.getType(IsMips64EL);
 
@@ -279,6 +281,8 @@ template <class ELFT> void DynamicSectio
     NumEntries += 2;
 
   for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles()) {
+    if (!F->isNeeded())
+      continue;
     Out<ELFT>::DynStrTab->add(F->getSoName());
     ++NumEntries;
   }
@@ -356,7 +360,8 @@ template <class ELFT> void DynamicSectio
   WriteArray(DT_FINI_ARRAY, DT_FINI_ARRAYSZ, FiniArraySec);
 
   for (const std::unique_ptr<SharedFile<ELFT>> &F : SymTab.getSharedFiles())
-    WriteVal(DT_NEEDED, Out<ELFT>::DynStrTab->getFileOff(F->getSoName()));
+    if (F->isNeeded())
+      WriteVal(DT_NEEDED, Out<ELFT>::DynStrTab->getFileOff(F->getSoName()));
 
   if (InitSym)
     WritePtr(DT_INIT, getSymVA<ELFT>(*InitSym));

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=249998&r1=249997&r2=249998&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Sun Oct 11 15:59:12 2015
@@ -24,6 +24,7 @@ class InputFile;
 class SymbolBody;
 template <class ELFT> class ObjectFile;
 template <class ELFT> class OutputSection;
+template <class ELFT> class SharedFile;
 
 // Initializes global objects defined in this file.
 // Called at the beginning of main().
@@ -263,8 +264,10 @@ public:
     return S->kind() == Base::SharedKind;
   }
 
-  SharedSymbol(StringRef Name, const Elf_Sym &Sym)
-      : Defined<ELFT>(Base::SharedKind, Name, Sym) {}
+  SharedSymbol(SharedFile<ELFT> *F, StringRef Name, const Elf_Sym &Sym)
+      : Defined<ELFT>(Base::SharedKind, Name, Sym), File(F) {}
+
+  SharedFile<ELFT> *File;
 };
 
 // This class represents a symbol defined in an archive file. It is

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=249998&r1=249997&r2=249998&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Sun Oct 11 15:59:12 2015
@@ -174,6 +174,14 @@ void Writer<ELFT>::scanRelocs(
     uint32_t SymIndex = RI.getSymbol(IsMips64EL);
     SymbolBody *Body = File.getSymbolBody(SymIndex);
     uint32_t Type = RI.getType(IsMips64EL);
+
+    // Set "used" bit for --as-needed.
+    if (Body && Body->isUndefined() && !Body->isWeak())
+      if (auto *S = dyn_cast<SharedSymbol<ELFT>>(Body->repl()))
+        S->File->IsUsed = true;
+
+    if (Body)
+      Body = Body->repl();
     if (Body) {
       if (Target->relocNeedsPlt(Type, *Body)) {
         if (Body->isInPlt())
@@ -186,12 +194,13 @@ void Writer<ELFT>::scanRelocs(
         Out<ELFT>::Got->addEntry(Body);
       }
     }
-    if (canBePreempted(Body)) {
+
+    bool CBP = canBePreempted(Body);
+    if (!CBP && (!Config->Shared || Target->isRelRelative(Type)))
+      continue;
+    if (CBP)
       Body->setUsedInDynamicReloc();
-      Out<ELFT>::RelaDyn->addReloc({C, RI});
-    } else if (Config->Shared && !Target->isRelRelative(Type)) {
-      Out<ELFT>::RelaDyn->addReloc({C, RI});
-    }
+    Out<ELFT>::RelaDyn->addReloc({C, RI});
   }
 }
 

Added: lld/trunk/test/elf2/Inputs/shared2.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/shared2.s?rev=249998&view=auto
==============================================================================
--- lld/trunk/test/elf2/Inputs/shared2.s (added)
+++ lld/trunk/test/elf2/Inputs/shared2.s Sun Oct 11 15:59:12 2015
@@ -0,0 +1,6 @@
+.global bar2
+.type bar2, @function
+bar2:
+
+.global zed2
+zed2:

Added: lld/trunk/test/elf2/Inputs/shared3.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/shared3.s?rev=249998&view=auto
==============================================================================
--- lld/trunk/test/elf2/Inputs/shared3.s (added)
+++ lld/trunk/test/elf2/Inputs/shared3.s Sun Oct 11 15:59:12 2015
@@ -0,0 +1,3 @@
+.global baz
+.type barz, @function
+baz:

Added: lld/trunk/test/elf2/as-needed.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/as-needed.s?rev=249998&view=auto
==============================================================================
--- lld/trunk/test/elf2/as-needed.s (added)
+++ lld/trunk/test/elf2/as-needed.s Sun Oct 11 15:59:12 2015
@@ -0,0 +1,43 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared2.s -o %t3.o
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared3.s -o %t4.o
+// RUN: ld.lld2 -shared %t2.o -soname shared1 -o %t2.so
+// RUN: ld.lld2 -shared %t3.o -soname shared2 -o %t3.so
+// RUN: ld.lld2 -shared %t4.o -soname shared3 -o %t4.so
+
+/// Check if --as-needed actually works.
+
+// RUN: ld.lld2 %t.o %t2.so %t3.so %t4.so -o %t2
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s
+
+// RUN: ld.lld2 --as-needed %t.o %t2.so %t3.so %t4.so -o %t2
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck -check-prefix=CHECK2 %s
+
+// RUN: ld.lld2 --as-needed %t.o %t2.so --no-as-needed %t3.so %t4.so -o %t2
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s
+
+/// GROUP directive is the same as --as-needed.
+
+// RUN: echo "GROUP(" %t2.so %t3.so %t4.so ")" > %t.script
+// RUN: ld.lld2 %t.o %t.script -o %t2
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s
+
+// RUN: echo "GROUP(AS_NEEDED(" %t2.so %t3.so %t4.so "))" > %t.script
+// RUN: ld.lld2 %t.o %t.script -o %t2
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck -check-prefix=CHECK2 %s
+
+// CHECK: NEEDED SharedLibrary (shared1)
+// CHECK: NEEDED SharedLibrary (shared2)
+// CHECK: NEEDED SharedLibrary (shared3)
+
+// CHECK2:     NEEDED SharedLibrary (shared1)
+// CHECK2-NOT: NEEDED SharedLibrary (shared2)
+// CHECK2-NOT: NEEDED SharedLibrary (shared3)
+
+.global _start
+_start:
+.long bar
+.long zed
+.weak baz




More information about the llvm-commits mailing list