[PATCH] D81052: [ELF] Handle -u before input files

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 2 21:21:08 PDT 2020


MaskRay created this revision.
MaskRay added reviewers: grimar, jyknight, psmith, ruiu.
Herald added subscribers: llvm-commits, arichardson, emaste.
Herald added a reviewer: espindola.
Herald added a project: LLVM.
MaskRay edited the summary of this revision.

If both a.a and b.so define foo

  ld.bfd -u foo a.a b.so  # foo is defined
  ld.bfd a.a b.so -u foo  # foo is defined
  ld.bfd -u foo b.so a.a  # foo is undefined (provided at runtime by b.so)
  ld.bfd b.so a.a -u foo  # foo is undefined (provided at runtime by b.so)

In all cases we make foo undefined in the output.  I tend to think the
GNU ld behavior makes more sense.

- In their model, they have to treat -u as a fake object file with an undefined symbol before all input files, otherwise the first archive would not be fetched.
- Following their behavior allows us to drop a --warn-backrefs special case.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D81052

Files:
  lld/ELF/Driver.cpp
  lld/test/ELF/undefined-opt.s


Index: lld/test/ELF/undefined-opt.s
===================================================================
--- lld/test/ELF/undefined-opt.s
+++ lld/test/ELF/undefined-opt.s
@@ -54,13 +54,18 @@
 # UNK-UNDEFINED-SO: ]
 
 # Added undefined symbols should appear in the dynamic table if necessary.
-# RUN: ld.lld -shared -o %t5 %t.o -u export
-# RUN: llvm-readobj --dyn-symbols %t5 | \
+# RUN: ld.lld -shared -soname=t -o %t.so %t.o -u export
+# RUN: llvm-readobj --dyn-symbols %t.so | \
 # RUN:     FileCheck --check-prefix=EXPORT-SO %s
 # EXPORT-SO: DynamicSymbols [
 # EXPORT-SO:   Name: export
 # EXPORT-SO: ]
 
+## Test that We handle -u before input files: -u can fetch an archive.
+# RUN: rm -f %t.a && llvm-ar rc %t.a %t.o
+# RUN: ld.lld -u export %t.a %t.so -o %t5
+# RUN: llvm-readobj --dyn-symbols %t5 | FileCheck --check-prefix=EXPORT-SO %s
+
 .globl _start
 _start:
 
Index: lld/ELF/Driver.cpp
===================================================================
--- lld/ELF/Driver.cpp
+++ lld/ELF/Driver.cpp
@@ -1476,10 +1476,6 @@
   // eliminate it. Mark the symbol as "used" to prevent it.
   sym->isUsedInRegularObj = true;
 
-  // GNU linkers allow -u foo -ldef -lref. We should not treat it as a backward
-  // reference.
-  backwardReferences.erase(sym);
-
   if (sym->isLazy())
     sym->fetch();
 }
@@ -1675,6 +1671,12 @@
       Undefined{nullptr, name, STB_GLOBAL, STV_DEFAULT, 0});
 }
 
+static Symbol *addUnusedUndefined(StringRef name) {
+  Undefined sym{nullptr, name, STB_GLOBAL, STV_DEFAULT, 0};
+  sym.isUsedInRegularObj = false;
+  return symtab->addSymbol(sym);
+}
+
 // This function is where all the optimizations of link-time
 // optimization takes place. When LTO is in use, some input files are
 // not in native object file format but in the LLVM bitcode format.
@@ -1851,6 +1853,11 @@
   for (auto *arg : args.filtered(OPT_trace_symbol))
     symtab->insert(arg->getValue())->traced = true;
 
+  // Handle -u/--undefined before input files. If both a.a and b.so define foo,
+  // -u foo a.a b.so will fetch a.a.
+  for (StringRef name : config->undefined)
+    addUnusedUndefined(name);
+
   // Add all files to the symbol table. This will add almost all
   // symbols that we need to the symbol table. This process might
   // add files to the link, via autolinking, these files are always
@@ -1870,16 +1877,16 @@
   config->hasDynSymTab =
       !sharedFiles.empty() || config->isPic || config->exportDynamic;
 
+  // Keep bitcode definitions in the symbol table.
+  for (StringRef name : config->undefined)
+    if (Defined *sym = dyn_cast_or_null<Defined>(symtab->find(name)))
+      sym->isUsedInRegularObj = true;
+
   // Some symbols (such as __ehdr_start) are defined lazily only when there
   // are undefined symbols for them, so we add these to trigger that logic.
   for (StringRef name : script->referencedSymbols)
     addUndefined(name);
 
-  // Handle the `--undefined <sym>` options.
-  for (StringRef arg : config->undefined)
-    if (Symbol *sym = symtab->find(arg))
-      handleUndefined(sym);
-
   // If an entry symbol is in a static archive, pull out that file now.
   if (Symbol *sym = symtab->find(config->entry))
     handleUndefined(sym);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D81052.268048.patch
Type: text/x-patch
Size: 3198 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200603/a23160c3/attachment.bin>


More information about the llvm-commits mailing list