[lld] r280205 - Allow adding start/end symbols to any section

Eugene Leviant via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 31 01:13:33 PDT 2016


Author: evgeny777
Date: Wed Aug 31 03:13:33 2016
New Revision: 280205

URL: http://llvm.org/viewvc/llvm-project?rev=280205&view=rev
Log:
Allow adding start/end symbols to any section

Allows adding start and/or end symbols to special output sections,
like .eh_frame_hdr, which aren't lists of regular input sections. 

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

Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/test/ELF/linkerscript/linkerscript-symbols-synthetic.s

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=280205&r1=280204&r2=280205&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Wed Aug 31 03:13:33 2016
@@ -310,10 +310,43 @@ void LinkerScript<ELFT>::createSections(
   }
 }
 
-template <class ELFT> void assignOffsets(OutputSectionBase<ELFT> *Sec) {
+// Linker script may define start and end symbols for special section types,
+// like .got, .eh_frame_hdr, .eh_frame and others. Those sections are not a list
+// of regular input input sections, therefore our way of defining symbols for
+// regular sections will not work. The approach we use for special section types
+// is not perfect - it handles only start and end symbols.
+template <class ELFT>
+void addStartEndSymbols(OutputSectionCommand *Cmd,
+                        OutputSectionBase<ELFT> *Sec) {
+  bool Start = true;
+  BaseCommand *PrevCmd = nullptr;
+
+  for (std::unique_ptr<BaseCommand> &Base : Cmd->Commands) {
+    if (auto *AssignCmd = dyn_cast<SymbolAssignment>(Base.get())) {
+      if (auto *Sym = cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) {
+        Sym->Section = Sec;
+        Sym->Value =
+            AssignCmd->Expression(Sec->getVA() + (Start ? 0 : Sec->getSize())) -
+            Sec->getVA();
+      }
+    } else {
+      if (!Start && isa<SymbolAssignment>(PrevCmd))
+        error("section '" + Sec->getName() +
+              "' supports only start and end symbols");
+      Start = false;
+    }
+    PrevCmd = Base.get();
+  }
+}
+
+template <class ELFT>
+void assignOffsets(OutputSectionCommand *Cmd, OutputSectionBase<ELFT> *Sec) {
   auto *OutSec = dyn_cast<OutputSection<ELFT>>(Sec);
   if (!OutSec) {
     Sec->assignOffsets();
+    // This section is not regular output section. However linker script may
+    // have defined start/end symbols for it. This case is handled below.
+    addStartEndSymbols(Cmd, Sec);
     return;
   }
 
@@ -404,19 +437,19 @@ template <class ELFT> void LinkerScript<
       uintX_t TVA = Dot + ThreadBssOffset;
       TVA = alignTo(TVA, Sec->getAlignment());
       Sec->setVA(TVA);
-      assignOffsets(Sec);
+      assignOffsets(Cmd, Sec);
       ThreadBssOffset = TVA - Dot + Sec->getSize();
       continue;
     }
 
     if (!(Sec->getFlags() & SHF_ALLOC)) {
-      Sec->assignOffsets();
+      assignOffsets(Cmd, Sec);
       continue;
     }
 
     Dot = alignTo(Dot, Sec->getAlignment());
     Sec->setVA(Dot);
-    assignOffsets(Sec);
+    assignOffsets(Cmd, Sec);
     MinVA = std::min(MinVA, Dot);
     Dot += Sec->getSize();
   }

Modified: lld/trunk/test/ELF/linkerscript/linkerscript-symbols-synthetic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/linkerscript-symbols-synthetic.s?rev=280205&r1=280204&r2=280205&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/linkerscript-symbols-synthetic.s (original)
+++ lld/trunk/test/ELF/linkerscript/linkerscript-symbols-synthetic.s Wed Aug 31 03:13:33 2016
@@ -1,36 +1,69 @@
 # REQUIRES: x86
 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
-
 # Simple symbol assignment within input section list. The '.' symbol
 # is not location counter but offset from the beginning of output
 # section .foo
 # RUN: echo "SECTIONS { \
 # RUN:          .foo : { \
 # RUN:              begin_foo = .; \
-# RUN:              PROVIDE(_begin_foo = .); \
+# RUN:              PROVIDE(_begin_sec = .); \
 # RUN:              *(.foo) \
 # RUN:              end_foo = .; \
-# RUN:              PROVIDE_HIDDEN(_end_foo = .); \
+# RUN:              PROVIDE_HIDDEN(_end_sec = .); \
 # RUN:              size_foo_1 = SIZEOF(.foo); \
 # RUN:              . = ALIGN(0x1000); \
 # RUN:              begin_bar = .; \
 # RUN:              *(.bar) \
 # RUN:              end_bar = .; \
-# RUN:              size_foo_2 = SIZEOF(.foo); \ 
-# RUN:            } \
-# RUN:            size_foo_3 = SIZEOF(.foo); }" > %t.script
-# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN:              size_foo_2 = SIZEOF(.foo); } \
+# RUN:          size_foo_3 = SIZEOF(.foo); \
+# RUN:          .eh_frame_hdr : { \
+# RUN:             __eh_frame_hdr_start = .; \
+# RUN:             __eh_frame_hdr_start2 = ALIGN(0x10); \
+# RUN:             *(.eh_frame_hdr) \
+# RUN:             __eh_frame_hdr_end = .; \
+# RUN:             __eh_frame_hdr_end2 = ALIGN(0x10); } \
+# RUN:       }" > %t.script
+# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t
 # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=SIMPLE %s
 
-# SIMPLE:      0000000000000128         .foo    00000000 .hidden _end_foo
-# SIMPLE:      0000000000000120         .foo    00000000 _begin_foo
-# SIMPLE-NEXT: 0000000000000120         .foo    00000000 begin_foo
-# SIMPLE-NEXT: 0000000000000128         .foo    00000000 end_foo
+# The script below contains symbols in the middle of .eh_frame_hdr section.
+# We don't support this.
+# RUN: echo "SECTIONS { \
+# RUN:          .eh_frame_hdr : { \
+# RUN:             PROVIDE_HIDDEN(_begin_sec = .); \
+# RUN:             __eh_frame_hdr_start = .; \
+# RUN:             *(.eh_frame_hdr) \
+# RUN:             __eh_frame_hdr_end = .; \
+# RUN:             *(.eh_frame_hdr) } \
+# RUN:             PROVIDE_HIDDEN(_end_sec = .); \
+# RUN:         }" > %t.script
+# RUN: not ld.lld -o %t1 --eh-frame-hdr --script %t.script %t 2>&1 | FileCheck --check-prefix=ERROR %s
+
+# Check that the following script is processed without errors
+# RUN: echo "SECTIONS { \
+# RUN:          .eh_frame_hdr : { \
+# RUN:             PROVIDE_HIDDEN(_begin_sec = .); \
+# RUN:             *(.eh_frame_hdr) \
+# RUN:             *(.eh_frame_hdr) \
+# RUN:             PROVIDE_HIDDEN(_end_sec = .); } \
+# RUN:         }" > %t.script
+# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t
+
+# SIMPLE:      0000000000000160         .foo    00000000 .hidden _end_sec
+# SIMPLE:      0000000000000158         .foo    00000000 _begin_sec
+# SIMPLE-NEXT: 0000000000000158         .foo    00000000 begin_foo
+# SIMPLE-NEXT: 0000000000000160         .foo    00000000 end_foo
 # SIMPLE-NEXT: 0000000000000008         .foo    00000000 size_foo_1
 # SIMPLE-NEXT: 0000000000001000         .foo    00000000 begin_bar
 # SIMPLE-NEXT: 0000000000001004         .foo    00000000 end_bar
-# SIMPLE-NEXT: 0000000000000ee4         .foo    00000000 size_foo_2
-# SIMPLE-NEXT: 0000000000000ee4         *ABS*   00000000 size_foo_3
+# SIMPLE-NEXT: 0000000000000eac         .foo    00000000 size_foo_2
+# SIMPLE-NEXT: 0000000000000eac         *ABS*   00000000 size_foo_3
+# SIMPLE-NEXT: 0000000000001004         .eh_frame_hdr     00000000 __eh_frame_hdr_start
+# SIMPLE-NEXT: 0000000000001010         .eh_frame_hdr     00000000 __eh_frame_hdr_start2
+# SIMPLE-NEXT: 0000000000001018         .eh_frame_hdr     00000000 __eh_frame_hdr_end
+# SIMPLE-NEXT: 0000000000001020         .eh_frame_hdr     00000000 __eh_frame_hdr_end2
+# ERROR: section '.eh_frame_hdr' supports only start and end symbols
 
 .global _start
 _start:
@@ -42,4 +75,9 @@ _start:
 .section .bar,"a"
  .long 0
 
-.global _begin_foo, _end_foo
+.section .dah,"ax", at progbits
+ .cfi_startproc
+ nop
+ .cfi_endproc
+
+.global _begin_sec, _end_sec




More information about the llvm-commits mailing list