[lld] r249295 - [ELF2] Add --undefined option

Denis Protivensky via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 5 02:43:58 PDT 2015


Author: denis-protivensky
Date: Mon Oct  5 04:43:57 2015
New Revision: 249295

URL: http://llvm.org/viewvc/llvm-project?rev=249295&view=rev
Log:
[ELF2] Add --undefined option

Add symbol specified with -u as undefined which may cause additional
object files from archives to be linked into the resulting binary.

Differential Revision: http://reviews.llvm.org/D13345

Added:
    lld/trunk/test/elf2/undefined-opt.s
Modified:
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/Options.td
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/SymbolTable.h
    lld/trunk/ELF/Symbols.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=249295&r1=249294&r2=249295&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Mon Oct  5 04:43:57 2015
@@ -157,6 +157,9 @@ void LinkerDriver::link(ArrayRef<const c
   if (Symtab.getObjectFiles().empty())
     error("no input files.");
 
+  for (auto *Arg : Args.filtered(OPT_undefined))
+    Symtab.addUndefinedSym(Arg->getValue());
+
   // Write the result.
   const ELFFileBase *FirstObj = Symtab.getFirstELF();
   switch (FirstObj->getELFKind()) {

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=249295&r1=249294&r2=249295&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Mon Oct  5 04:43:57 2015
@@ -61,6 +61,9 @@ def soname : Joined<["-"], "soname=">,
 def sysroot : Joined<["--"], "sysroot=">,
   HelpText<"Set the system root">;
 
+def undefined : Joined<["--"], "undefined=">,
+  HelpText<"Force undefined symbol during linking">;
+
 def whole_archive : Flag<["--"], "whole-archive">,
   HelpText<"Force load of all members in a static library">;
 
@@ -78,6 +81,7 @@ def alias_l__library : Joined<["--"], "l
 def alias_rpath_rpath : Joined<["-"], "rpath=">, Alias<rpath>;
 def alias_soname_h : Separate<["-"], "h">, Alias<soname>;
 def alias_soname_soname : Separate<["-"], "soname">, Alias<soname>;
+def alias_undefined_u : Separate<["-"], "u">, Alias<undefined>;
 
 // Options listed below are silently ignored now.
 def O3 : Flag<["-"], "O3">;

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=249295&r1=249294&r2=249295&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Mon Oct  5 04:43:57 2015
@@ -70,6 +70,29 @@ static TargetInfo *createTarget(uint16_t
   error("Unknown target machine");
 }
 
+void SymbolTable::addUndefinedSym(StringRef Name) {
+  switch (getFirstELF()->getELFKind()) {
+  case ELF32LEKind:
+    addUndefinedSym<ELF32LE>(Name);
+    break;
+  case ELF32BEKind:
+    addUndefinedSym<ELF32BE>(Name);
+    break;
+  case ELF64LEKind:
+    addUndefinedSym<ELF64LE>(Name);
+    break;
+  case ELF64BEKind:
+    addUndefinedSym<ELF64BE>(Name);
+    break;
+  }
+}
+
+template <class ELFT> void SymbolTable::addUndefinedSym(StringRef Name) {
+  Undefined<ELFT>::SyntheticOptional.setVisibility(STV_HIDDEN);
+  resolve<ELFT>(new (Alloc)
+                    Undefined<ELFT>(Name, Undefined<ELFT>::SyntheticOptional));
+}
+
 template <class ELFT>
 void SymbolTable::addSyntheticSym(StringRef Name, OutputSection<ELFT> &Section,
                                   typename ELFFile<ELFT>::uintX_t Value) {
@@ -94,7 +117,7 @@ template <class ELFT> void SymbolTable::
     return;
   EntrySym = new (Alloc) Undefined<ELFT>(
       Config->Entry.empty() ? Target->getDefaultEntry() : Config->Entry,
-      Undefined<ELFT>::Synthetic);
+      Undefined<ELFT>::SyntheticRequired);
   resolve<ELFT>(EntrySym);
 
   // In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol is magical

Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=249295&r1=249294&r2=249295&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Mon Oct  5 04:43:57 2015
@@ -61,6 +61,8 @@ public:
     return EntrySym->getReplacement();
   }
 
+  void addUndefinedSym(StringRef Name);
+
   template <class ELFT>
   void addSyntheticSym(StringRef Name, OutputSection<ELFT> &Section,
                        typename llvm::object::ELFFile<ELFT>::uintX_t Value);
@@ -73,6 +75,7 @@ private:
   void addELFFile(ELFFileBase *File);
   void addLazy(Lazy *New);
   void addMemberFile(Lazy *Body);
+  template <class ELFT> void addUndefinedSym(StringRef Name);
 
   template <class ELFT> void init(uint16_t EMachine);
   template <class ELFT> void resolve(SymbolBody *Body);

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=249295&r1=249294&r2=249295&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Mon Oct  5 04:43:57 2015
@@ -53,7 +53,6 @@ public:
   bool isWeak() const { return IsWeak; }
   bool isUndefined() const { return SymbolKind == UndefinedKind; }
   bool isDefined() const { return SymbolKind <= DefinedLast; }
-  bool isStrongUndefined() const { return !IsWeak && isUndefined(); }
   bool isCommon() const { return SymbolKind == DefinedCommonKind; }
   bool isLazy() const { return SymbolKind == LazyKind; }
   bool isShared() const { return SymbolKind == SharedKind; }
@@ -235,7 +234,8 @@ template <class ELFT> class Undefined :
   typedef typename Base::Elf_Sym Elf_Sym;
 
 public:
-  static Elf_Sym Synthetic;
+  static Elf_Sym SyntheticRequired;
+  static Elf_Sym SyntheticOptional;
 
   Undefined(StringRef N, const Elf_Sym &Sym)
       : ELFSymbolBody<ELFT>(Base::UndefinedKind, N, Sym) {}
@@ -243,10 +243,14 @@ public:
   static bool classof(const SymbolBody *S) {
     return S->kind() == Base::UndefinedKind;
   }
+
+  bool canKeepUndefined() const { return &this->Sym == &SyntheticOptional; }
 };
 
 template <class ELFT>
-typename Undefined<ELFT>::Elf_Sym Undefined<ELFT>::Synthetic;
+typename Undefined<ELFT>::Elf_Sym Undefined<ELFT>::SyntheticRequired;
+template <class ELFT>
+typename Undefined<ELFT>::Elf_Sym Undefined<ELFT>::SyntheticOptional;
 
 template <class ELFT> class SharedSymbol : public Defined<ELFT> {
   typedef Defined<ELFT> Base;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=249295&r1=249294&r2=249295&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon Oct  5 04:43:57 2015
@@ -334,8 +334,10 @@ template <class ELFT> void Writer<ELFT>:
   for (auto &P : Symtab.getSymbols()) {
     StringRef Name = P.first;
     SymbolBody *Body = P.second->Body;
-    if (Body->isStrongUndefined())
-      reportUndefined<ELFT>(Symtab, *Body);
+    if (auto *U = dyn_cast<Undefined<ELFT>>(Body)) {
+      if (!U->isWeak() && !U->canKeepUndefined())
+        reportUndefined<ELFT>(Symtab, *Body);
+    }
 
     if (auto *C = dyn_cast<DefinedCommon<ELFT>>(Body))
       CommonSymbols.push_back(C);

Added: lld/trunk/test/elf2/undefined-opt.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/undefined-opt.s?rev=249295&view=auto
==============================================================================
--- lld/trunk/test/elf2/undefined-opt.s (added)
+++ lld/trunk/test/elf2/undefined-opt.s Mon Oct  5 04:43:57 2015
@@ -0,0 +1,51 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+# RUN:     %p/Inputs/abs.s -o %tabs.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+# RUN:     %p/Inputs/shared.s -o %tshared.o
+# RUN: rm -f %tar.a
+# RUN: llvm-ar rcs %tar.a %tabs.o %tshared.o
+# REQUIRES: x86
+
+# Symbols from the archive are not in if not needed
+# RUN: lld -flavor gnu2 -o %t1 %t.o %tar.a
+# RUN: llvm-readobj --symbols %t1 | FileCheck --check-prefix=NO-UNDEFINED %s
+# NO-UNDEFINED: Symbols [
+# NO-UNDEFINED-NOT: Name: abs
+# NO-UNDEFINED-NOT: Name: big
+# NO-UNDEFINED-NOT: Name: bar
+# NO-UNDEFINED-NOT: Name: zed
+# NO-UNDEFINED: ]
+
+# Symbols from the archive are in if needed, but only from the
+# containing object file
+# RUN: lld -flavor gnu2 -o %t2 %t.o %tar.a -u bar
+# RUN: llvm-readobj --symbols %t2 | FileCheck --check-prefix=ONE-UNDEFINED %s
+# ONE-UNDEFINED: Symbols [
+# ONE-UNDEFINED-NOT: Name: abs
+# ONE-UNDEFINED-NOT: Name: big
+# ONE-UNDEFINED: Name: bar
+# ONE-UNDEFINED: Name: zed
+# ONE-UNDEFINED: ]
+
+# Use the option couple of times, both short and long forms
+# RUN: lld -flavor gnu2 -o %t3 %t.o %tar.a -u bar --undefined=abs
+# RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=TWO-UNDEFINED %s
+# TWO-UNDEFINED: Symbols [
+# TWO-UNDEFINED: Name: abs
+# TWO-UNDEFINED: Name: big
+# TWO-UNDEFINED: Name: bar
+# TWO-UNDEFINED: Name: zed
+# TWO-UNDEFINED: ]
+
+# Added undefined symbol may be left undefined without error, but
+# shouldn't show up in the dynamic table.
+# RUN: lld -flavor gnu2 -shared -o %t4 %t.o %tar.a -u unknown
+# RUN: llvm-readobj --dyn-symbols %t4 | \
+# RUN:     FileCheck --check-prefix=UNK-UNDEFINED-SO %s
+# UNK-UNDEFINED-SO: DynamicSymbols [
+# UNK-UNDEFINED-SO-NOT:     Name: unknown
+# UNK-UNDEFINED-SO: ]
+
+.globl _start;
+_start:




More information about the llvm-commits mailing list