[PATCH] D30193: [ELF] - Scan lazy linkerscipt symbols early.

George Rimar via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 21 04:29:38 PST 2017


grimar created this revision.

This is PR32026, we have next issue currently:

If script has a symbol assignment, for example PROVIDE(foo = 5)
and that foo is a lazy symbol. Then code that invokes processCommands()...addSymbol(Cmd);
will fetch that archive much later than we expect to see new sections to appear.

We have next code and comment:

  void LinkerDriver::link(opt::InputArgList &Args) {
  ..
    // Now that we have a complete list of input files.
    // Beyond this point, no new files are added.

But that comment becomes not true in that case. We are adding new sections
from that archive for processing foo much later. Also if object where foo lives contains
mergeable section, then code that do splitIntoPieces() is completely skipped,
also this section is not merged into synthetic output section, because we doo that early.

To avoid that, patch implement early scan of assignments.
One of problems is that it does not support symbols definitions inside sections declarations,
like: ".foo : { ...; bar = .; }". It is complicated to implement those because we still need to filter
out sections not matching the constraints, so cant just add such symbols early like I did in this patch for
symbols outside. (Though I am not sure such symbols are really used in real livfe)

I think best way to implement it (if we want) is the next: 
As an alternative solution probably we can reimplement handling of mergeable sections
and do not merge them into synthetics early, just like https://reviews.llvm.org/D29223 did. 
I think that way later addition of sections and files will not be a problem, we should be 
able to invoke merging and splitIntoPieces() from script side when we need it.
That way support of symbols like bar from above should be easy, though that complicates
the implementation of other parts, not sure if we want it now.


https://reviews.llvm.org/D30193

Files:
  ELF/Driver.cpp
  ELF/LinkerScript.cpp
  ELF/LinkerScript.h
  ELF/Writer.cpp
  test/ELF/linkerscript/Inputs/lazy-symbols.s
  test/ELF/linkerscript/lazy-symbols.s


Index: test/ELF/linkerscript/lazy-symbols.s
===================================================================
--- test/ELF/linkerscript/lazy-symbols.s
+++ test/ELF/linkerscript/lazy-symbols.s
@@ -0,0 +1,10 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/lazy-symbols.s -o %t1
+# RUN: llvm-ar rcs %tar %t1
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2
+# RUN: echo "PROVIDE(foo = 1);" > %t.script
+# RUN: ld.lld %t2 %tar --script %t.script -o %tout
+# RUN: llvm-readobj -symbols %tout | FileCheck %s
+
+# CHECK: Name: foo
+# CHECK-NEXT: Value: 0x1
Index: test/ELF/linkerscript/Inputs/lazy-symbols.s
===================================================================
--- test/ELF/linkerscript/Inputs/lazy-symbols.s
+++ test/ELF/linkerscript/Inputs/lazy-symbols.s
@@ -0,0 +1,7 @@
+.globl foo
+foo:
+ .long .Linfo_string
+ 
+.section .debug_str,"MS", at progbits,1
+.Linfo_string:
+  .asciz "foo\0bar\0baz"
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -18,6 +18,7 @@
 #include "SymbolTable.h"
 #include "SyntheticSections.h"
 #include "Target.h"
+#include "Threads.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/FileOutputBuffer.h"
Index: ELF/LinkerScript.h
===================================================================
--- ELF/LinkerScript.h
+++ ELF/LinkerScript.h
@@ -244,6 +244,7 @@
   LinkerScript();
   ~LinkerScript();
 
+  void fetchLazySymbols();
   void processCommands(OutputSectionFactory<ELFT> &Factory);
   void addOrphanSections(OutputSectionFactory<ELFT> &Factory);
   void removeEmptyCommands();
Index: ELF/LinkerScript.cpp
===================================================================
--- ELF/LinkerScript.cpp
+++ ELF/LinkerScript.cpp
@@ -319,6 +319,17 @@
   return Ret;
 }
 
+// Script can contain assignments to lazy symbols. In that case
+// we should scan such symbols early to fetch objects from archives
+// and create input sections.
+template <class ELFT> void LinkerScript<ELFT>::fetchLazySymbols() {
+  for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands)
+    if (auto *Cmd = dyn_cast<SymbolAssignment>(Base.get()))
+      if (SymbolBody *Sym = Symtab<ELFT>::X->find(Cmd->Name))
+        if (Sym->isLazy())
+          addSymbol(Cmd);
+}
+
 template <class ELFT>
 void LinkerScript<ELFT>::processCommands(OutputSectionFactory<ELFT> &Factory) {
   for (unsigned I = 0; I < Opt.Commands.size(); ++I) {
Index: ELF/Driver.cpp
===================================================================
--- ELF/Driver.cpp
+++ ELF/Driver.cpp
@@ -839,6 +839,8 @@
   for (auto *Arg : Args.filtered(OPT_wrap))
     Symtab.wrap(Arg->getValue());
 
+  Script<ELFT>::X->fetchLazySymbols();
+
   // Now that we have a complete list of input files.
   // Beyond this point, no new files are added.
   // Aggregate all input sections into one place.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D30193.89188.patch
Type: text/x-patch
Size: 2970 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170221/61003d3c/attachment.bin>


More information about the llvm-commits mailing list