[lld] r323729 - [ELF] - Define linkerscript symbols early.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 30 01:04:27 PST 2018


Author: grimar
Date: Tue Jan 30 01:04:27 2018
New Revision: 323729

URL: http://llvm.org/viewvc/llvm-project?rev=323729&view=rev
Log:
[ELF] - Define linkerscript symbols early.

Currently symbols assigned or created by linkerscript are not processed early
enough. As a result it is not possible to version them or assign any other flags/properties.

Patch creates Defined symbols for -defsym and linkerscript symbols early,
so that issue from above can be addressed.

It is based on Rafael Espindola's version of D38239 patch.

Fixes PR34121.

Differential revision: https://reviews.llvm.org/D41987

Added:
    lld/trunk/test/ELF/linkerscript/version-script.s
Modified:
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/LTO.cpp
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h
    lld/trunk/test/ELF/linkerscript/symbols-synthetic.s
    lld/trunk/test/ELF/lto/defsym.ll
    lld/trunk/test/ELF/lto/linker-script-symbols-assign.ll
    lld/trunk/test/ELF/lto/linker-script-symbols-ipo.ll

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=323729&r1=323728&r2=323729&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Tue Jan 30 01:04:27 2018
@@ -1063,6 +1063,10 @@ template <class ELFT> void LinkerDriver:
   if (!Config->Relocatable)
     addReservedSymbols();
 
+  // We want to declare linker script's symbols early,
+  // so that we can version them.
+  Script->declareSymbols();
+
   // Apply version scripts.
   Symtab->scanVersionScript();
 

Modified: lld/trunk/ELF/LTO.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LTO.cpp?rev=323729&r1=323728&r2=323729&view=diff
==============================================================================
--- lld/trunk/ELF/LTO.cpp (original)
+++ lld/trunk/ELF/LTO.cpp Tue Jan 30 01:04:27 2018
@@ -129,11 +129,6 @@ void BitcodeCompiler::add(BitcodeFile &F
   std::vector<Symbol *> Syms = F.getSymbols();
   std::vector<lto::SymbolResolution> Resols(Syms.size());
 
-  DenseSet<StringRef> ScriptSymbols;
-  for (BaseCommand *Base : Script->SectionCommands)
-    if (auto *Cmd = dyn_cast<SymbolAssignment>(Base))
-      ScriptSymbols.insert(Cmd->Name);
-
   bool IsExecutable = !Config->Shared && !Config->Relocatable;
 
   // Provide a resolution to the LTO API for each symbol.
@@ -164,12 +159,10 @@ void BitcodeCompiler::add(BitcodeFile &F
     if (R.Prevailing)
       undefine(Sym);
 
-    // We tell LTO to not apply interprocedural optimization for following
-    // symbols because otherwise LTO would inline them while their values are
-    // still not final:
-    // 1) Aliased (with --defsym) or wrapped (with --wrap) symbols.
-    // 2) Symbols redefined in linker script.
-    R.LinkerRedefined = !Sym->CanInline || ScriptSymbols.count(Sym->getName());
+    // We tell LTO to not apply interprocedural optimization for wrapped
+    // (with --wrap) symbols because otherwise LTO would inline them while
+    // their values are still not final.
+    R.LinkerRedefined = !Sym->CanInline;
   }
   checkError(LTOObj->add(std::move(F.Obj), Resols));
 }

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=323729&r1=323728&r2=323729&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Tue Jan 30 01:04:27 2018
@@ -114,16 +114,28 @@ void LinkerScript::setDot(Expr E, const
     Ctx->OutSec->Size = Dot - Ctx->OutSec->Addr;
 }
 
-// This function is called from processSectionCommands,
-// while we are fixing the output section layout.
-void LinkerScript::addSymbol(SymbolAssignment *Cmd) {
+// Used for handling linker symbol assignments, for both finalizing
+// their values and doing early declarations. Returns true if symbol
+// should be defined from linker script.
+static bool shouldDefineSym(SymbolAssignment *Cmd) {
   if (Cmd->Name == ".")
-    return;
+    return false;
+
+  if (!Cmd->Provide)
+    return true;
 
-  // If a symbol was in PROVIDE(), we need to define it only when
-  // it is a referenced undefined symbol.
+  // If a symbol was in PROVIDE(), we need to define it only
+  // when it is a referenced undefined symbol.
   Symbol *B = Symtab->find(Cmd->Name);
-  if (Cmd->Provide && (!B || B->isDefined()))
+  if (!B || B->isDefined())
+    return false;
+  return true;
+}
+
+// This function is called from processSectionCommands,
+// while we are fixing the output section layout.
+void LinkerScript::addSymbol(SymbolAssignment *Cmd) {
+  if (!shouldDefineSym(Cmd))
     return;
 
   // Define a symbol.
@@ -153,6 +165,30 @@ void LinkerScript::addSymbol(SymbolAssig
   Cmd->Sym = cast<Defined>(Sym);
 }
 
+// Symbols defined in script should not be inlined by LTO. At the same time
+// we don't know their final values until late stages of link. Here we scan
+// over symbol assignment commands and create placeholder symbols if needed.
+void LinkerScript::declareSymbols() {
+  assert(!Ctx);
+  for (BaseCommand *Base : SectionCommands) {
+    auto *Cmd = dyn_cast<SymbolAssignment>(Base);
+    if (!Cmd || !shouldDefineSym(Cmd))
+      continue;
+
+    // We can't calculate final value right now.
+    Symbol *Sym;
+    uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;
+    std::tie(Sym, std::ignore) =
+        Symtab->insert(Cmd->Name, /*Type*/ 0, Visibility,
+                       /*CanOmitFromDynSym*/ false,
+                       /*File*/ nullptr);
+    replaceSymbol<Defined>(Sym, nullptr, Cmd->Name, STB_GLOBAL, Visibility,
+                           STT_NOTYPE, 0, 0, nullptr);
+    Cmd->Sym = cast<Defined>(Sym);
+    Cmd->Provide = false;
+  }
+}
+
 // This function is called from assignAddresses, while we are
 // fixing the output section addresses. This function is supposed
 // to set the final value for a given symbol assignment.

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=323729&r1=323728&r2=323729&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Tue Jan 30 01:04:27 2018
@@ -265,12 +265,13 @@ public:
   bool needsInterpSection();
 
   bool shouldKeep(InputSectionBase *S);
-  void assignAddresses();
-  void allocateHeaders(std::vector<PhdrEntry *> &Phdrs);
-  void processSectionCommands();
-
-  // SECTIONS command list.
-  std::vector<BaseCommand *> SectionCommands;
+  void assignAddresses();
+  void allocateHeaders(std::vector<PhdrEntry *> &Phdrs);
+  void processSectionCommands();
+  void declareSymbols();
+
+  // SECTIONS command list.
+  std::vector<BaseCommand *> SectionCommands;
 
   // PHDRS command list.
   std::vector<PhdrsCommand> PhdrsCommands;

Modified: lld/trunk/test/ELF/linkerscript/symbols-synthetic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/symbols-synthetic.s?rev=323729&r1=323728&r2=323729&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/symbols-synthetic.s (original)
+++ lld/trunk/test/ELF/linkerscript/symbols-synthetic.s Tue Jan 30 01:04:27 2018
@@ -58,20 +58,20 @@
 # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=IN-SEC %s
 
 # SIMPLE:      0000000000000128         .foo    00000000 .hidden _end_sec
-# SIMPLE-NEXT: 0000000000000120         .foo    00000000 _begin_sec
-# SIMPLE-NEXT: 0000000000000128         *ABS*   00000000 _end_sec_abs
-# SIMPLE-NEXT: 0000000000001048         .text   00000000 _start
-# SIMPLE-NEXT: 0000000000000120         .foo    00000000 begin_foo
-# SIMPLE-NEXT: 0000000000000128         .foo    00000000 end_foo
-# SIMPLE-NEXT: 0000000000000008         *ABS*   00000000 size_foo_1
+# SIMPLE-NEXT: 0000000000000120         .foo    00000000 _begin_sec
+# SIMPLE-NEXT: 0000000000000128         *ABS*   00000000 _end_sec_abs
+# SIMPLE-NEXT: 0000000000001048         .text   00000000 _start
+# SIMPLE-NEXT: 0000000000000ee4         *ABS*   00000000 size_foo_3
+# SIMPLE-NEXT: 0000000000000120         .foo    00000000 begin_foo
+# SIMPLE-NEXT: 0000000000000128         .foo    00000000 end_foo
+# SIMPLE-NEXT: 0000000000000008         *ABS*   00000000 size_foo_1
 # SIMPLE-NEXT: 0000000000000008         *ABS*   00000000 size_foo_1_abs
-# SIMPLE-NEXT: 0000000000001000         .foo    00000000 begin_bar
-# SIMPLE-NEXT: 0000000000001004         .foo    00000000 end_bar
-# SIMPLE-NEXT: 0000000000000ee4         *ABS*   00000000 size_foo_2
-# SIMPLE-NEXT: 0000000000000ee4         *ABS*   00000000 size_foo_3
-# SIMPLE-NEXT: 0000000000001004         .eh_frame_hdr     00000000 __eh_frame_hdr_start
-# SIMPLE-NEXT: 0000000000001010         *ABS*             00000000 __eh_frame_hdr_start2
-# SIMPLE-NEXT: 0000000000001018         .eh_frame_hdr     00000000 __eh_frame_hdr_end
+# SIMPLE-NEXT: 0000000000001000         .foo    00000000 begin_bar
+# SIMPLE-NEXT: 0000000000001004         .foo    00000000 end_bar
+# SIMPLE-NEXT: 0000000000000ee4         *ABS*   00000000 size_foo_2
+# SIMPLE-NEXT: 0000000000001004         .eh_frame_hdr     00000000 __eh_frame_hdr_start
+# SIMPLE-NEXT: 0000000000001010         *ABS*             00000000 __eh_frame_hdr_start2
+# SIMPLE-NEXT: 0000000000001018         .eh_frame_hdr     00000000 __eh_frame_hdr_end
 # SIMPLE-NEXT: 0000000000001020         *ABS*             00000000 __eh_frame_hdr_end2
 
 # NO-SEC:       0000000000201000         .text     00000000 .hidden _begin_sec

Added: lld/trunk/test/ELF/linkerscript/version-script.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/version-script.s?rev=323729&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/version-script.s (added)
+++ lld/trunk/test/ELF/linkerscript/version-script.s Tue Jan 30 01:04:27 2018
@@ -0,0 +1,52 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+
+# RUN: echo "bar = foo; VERSION { V { global: foo; bar; local: *; }; }" > %t.script
+# RUN: ld.lld -T %t.script -shared --no-undefined-version %t.o -o %t.so
+# RUN: llvm-readobj -V %t.so | FileCheck %s
+
+## Check that we are able to version symbols defined in script.
+# CHECK:      Symbols [
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Version: 0
+# CHECK-NEXT:     Name: @
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Version: 0
+# CHECK-NEXT:     Name: und@
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Version: 2
+# CHECK-NEXT:     Name: foo@@V
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Version: 2
+# CHECK-NEXT:     Name: bar@@V
+# CHECK-NEXT:   }
+# CHECK-NEXT: ]
+
+# RUN: echo "bar = und; VERSION { V { global: foo; bar; local: *; }; }" > %t.script
+# RUN: not ld.lld -T %t.script -shared --no-undefined-version %t.o -o %t.so \
+# RUN:   2>&1 | FileCheck --check-prefix=ERR %s
+# ERR: symbol not found: und
+
+# RUN: echo "und = 0x1; VERSION { V { global: und; local: *; }; }" > %t.script
+# RUN: ld.lld -T %t.script -shared --no-undefined-version %t.o -o %t.so
+# RUN: llvm-readobj -V %t.so | FileCheck %s --check-prefix=UNDEF
+# UNDEF:      Symbols [
+# UNDEF-NEXT:   Symbol {
+# UNDEF-NEXT:     Version: 0
+# UNDEF-NEXT:     Name: @
+# UNDEF-NEXT:   }
+# UNDEF-NEXT:   Symbol {
+# UNDEF-NEXT:     Version: 2
+# UNDEF-NEXT:     Name: und@@V
+# UNDEF-NEXT:   }
+# UNDEF-NEXT: ]
+
+.global und
+
+.text
+.globl foo
+.type foo, at function
+foo:

Modified: lld/trunk/test/ELF/lto/defsym.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/lto/defsym.ll?rev=323729&r1=323728&r2=323729&view=diff
==============================================================================
--- lld/trunk/test/ELF/lto/defsym.ll (original)
+++ lld/trunk/test/ELF/lto/defsym.ll Tue Jan 30 01:04:27 2018
@@ -1,18 +1,22 @@
 ; REQUIRES: x86
-; LTO
-; RUN: llvm-as %s -o %t.o
-; RUN: llvm-as %S/Inputs/defsym-bar.ll -o %t1.o
-; RUN: ld.lld %t.o %t1.o -shared -o %t.so -defsym=bar2=bar3
-; RUN: llvm-objdump -d %t.so | FileCheck %s
-
-; ThinLTO
-; RUN: opt -module-summary %s -o %t.o
-; RUN: opt -module-summary %S/Inputs/defsym-bar.ll -o %t1.o
-; RUN: ld.lld %t.o %t1.o -shared -o %t.so -defsym=bar2=bar3
-; RUN: llvm-objdump -d %t.so | FileCheck %s --check-prefix=THIN
-
-; Call to bar2() should not be inlined and should be routed to bar3()
-; Symbol bar3 should not be eliminated
+; LTO
+; RUN: llvm-as %s -o %t.o
+; RUN: llvm-as %S/Inputs/defsym-bar.ll -o %t1.o
+; RUN: ld.lld %t.o %t1.o -shared -o %t.so -defsym=bar2=bar3 -save-temps
+; RUN: llvm-readelf -t %t.so.lto.o | FileCheck --check-prefix=OBJ %s
+; RUN: llvm-objdump -d %t.so | FileCheck %s
+
+; ThinLTO
+; RUN: opt -module-summary %s -o %t.o
+; RUN: opt -module-summary %S/Inputs/defsym-bar.ll -o %t1.o
+; RUN: ld.lld %t.o %t1.o -shared -o %t2.so -defsym=bar2=bar3 -save-temps
+; RUN: llvm-readelf -t %t2.so1.lto.o | FileCheck --check-prefix=OBJ %s
+; RUN: llvm-objdump -d %t2.so | FileCheck %s --check-prefix=THIN
+
+; OBJ:  UND bar2
+
+; Call to bar2() should not be inlined and should be routed to bar3()
+; Symbol bar3 should not be eliminated
 
 ; CHECK:      foo:
 ; CHECK-NEXT: pushq	%rax

Modified: lld/trunk/test/ELF/lto/linker-script-symbols-assign.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/lto/linker-script-symbols-assign.ll?rev=323729&r1=323728&r2=323729&view=diff
==============================================================================
--- lld/trunk/test/ELF/lto/linker-script-symbols-assign.ll (original)
+++ lld/trunk/test/ELF/lto/linker-script-symbols-assign.ll Tue Jan 30 01:04:27 2018
@@ -3,22 +3,13 @@
 
 ; RUN: echo "foo = 1;" > %t.script
 ; RUN: ld.lld -m elf_x86_64 %t.o -o %t2 --script %t.script -save-temps
-; RUN: llvm-readobj -symbols %t2.lto.o | FileCheck %s
-
-; CHECK-NOT: bar
-; CHECK:     Symbol {
-; CHECK:         Name: foo
-; CHECK-NEXT:    Value: 0x0
-; CHECK-NEXT:    Size: 4
-; CHECK-NEXT:    Binding: Weak
-; CHECK-NEXT:    Type: Object
-; CHECK-NEXT:    Other: 0
-; CHECK-NEXT:    Section: .bss.foo
-; CHECK-NEXT:  }
-; CHECK-NEXT:]
-
-; RUN: llvm-readobj -symbols %t2 | FileCheck %s --check-prefix=VAL
-; VAL:       Symbol {
+; RUN: llvm-readobj -symbols %t2.lto.o | FileCheck %s
+
+; CHECK-NOT: bar
+; CHECK-NOT: foo
+
+; RUN: llvm-readobj -symbols %t2 | FileCheck %s --check-prefix=VAL
+; VAL:       Symbol {
 ; VAL:        Name: foo
 ; VAL-NEXT:   Value: 0x1
 ; VAL-NEXT:   Size:

Modified: lld/trunk/test/ELF/lto/linker-script-symbols-ipo.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/lto/linker-script-symbols-ipo.ll?rev=323729&r1=323728&r2=323729&view=diff
==============================================================================
--- lld/trunk/test/ELF/lto/linker-script-symbols-ipo.ll (original)
+++ lld/trunk/test/ELF/lto/linker-script-symbols-ipo.ll Tue Jan 30 01:04:27 2018
@@ -13,15 +13,15 @@
 
 ;; Check that LTO does not do IPO for symbols assigned by script.
 ; RUN: ld.lld  -m elf_x86_64 %t1.o %t2.o -o %t4 --script %t.script -save-temps
-; RUN: llvm-objdump -d %t4 | FileCheck %s --check-prefix=NOIPO
-; NOIPO:      Disassembly of section .text:
-; NOIPO:      foo:
-; NOIPO-NEXT:   201010: {{.*}} movl $2, %eax
-; NOIPO:      _start:
-; NOIPO-NEXT:   201020: {{.*}} jmp -21 <foo>
-
-target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-unknown-linux-gnu"
+; RUN: llvm-objdump -d %t4 | FileCheck %s --check-prefix=NOIPO
+; NOIPO:      Disassembly of section .text:
+; NOIPO:      foo:
+; NOIPO-NEXT:   {{.*}} movl $2, %eax
+; NOIPO:      _start:
+; NOIPO-NEXT:   {{.*}} jmp -21 <foo>
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
 
 define i32 @bar() {
   ret i32 1




More information about the llvm-commits mailing list