[lld] r253637 - [ELF] Define symbols "_end" and "end" if referenced.

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 19 18:32:36 PST 2015


Author: ikudrin
Date: Thu Nov 19 20:32:35 2015
New Revision: 253637

URL: http://llvm.org/viewvc/llvm-project?rev=253637&view=rev
Log:
[ELF] Define symbols "_end" and "end" if referenced.

These symbols are expected to point to the end of the data segment.

Implements http://llvm.org/pr25528.

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

Added:
    lld/trunk/test/ELF/end-preserve.s
    lld/trunk/test/ELF/end-update.s
    lld/trunk/test/ELF/end.s
Modified:
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/Symbols.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/ELF/entry.s

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=253637&r1=253636&r2=253637&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Thu Nov 19 20:32:35 2015
@@ -85,6 +85,7 @@ std::unique_ptr<InputFile> Lazy::getMemb
 }
 
 template <class ELFT> static void doInitSymbols() {
+  DefinedAbsolute<ELFT>::End.setBinding(STB_GLOBAL);
   DefinedAbsolute<ELFT>::IgnoreUndef.setBinding(STB_WEAK);
   DefinedAbsolute<ELFT>::IgnoreUndef.setVisibility(STV_HIDDEN);
   Undefined<ELFT>::Optional.setVisibility(STV_HIDDEN);

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=253637&r1=253636&r2=253637&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Thu Nov 19 20:32:35 2015
@@ -177,9 +177,14 @@ template <class ELFT> class DefinedAbsol
 public:
   static Elf_Sym IgnoreUndef;
 
+  // The following symbols must be added early to reserve their places
+  // in symbol tables. The value of the symbols are set when all sections
+  // are finalized and their addresses are determined.
+
+  // The content for _end and end symbols.
+  static Elf_Sym End;
+
   // The content for _gp symbol for MIPS target.
-  // The symbol has to be added early to reserve a place in symbol tables.
-  // The value of the symbol is computed later by Writer.
   static Elf_Sym MipsGp;
 
   DefinedAbsolute(StringRef N, const Elf_Sym &Sym)
@@ -194,6 +199,9 @@ template <class ELFT>
 typename DefinedAbsolute<ELFT>::Elf_Sym DefinedAbsolute<ELFT>::IgnoreUndef;
 
 template <class ELFT>
+typename DefinedAbsolute<ELFT>::Elf_Sym DefinedAbsolute<ELFT>::End;
+
+template <class ELFT>
 typename DefinedAbsolute<ELFT>::Elf_Sym DefinedAbsolute<ELFT>::MipsGp;
 
 template <class ELFT> class DefinedCommon : public Defined<ELFT> {

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=253637&r1=253636&r2=253637&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Nov 19 20:32:35 2015
@@ -623,6 +623,23 @@ template <class ELFT> void Writer<ELFT>:
   if (!isOutputDynamic())
     Symtab.addIgnoredSym("__tls_get_addr");
 
+  // If the "_end" symbol is referenced, it is expected to point to the address
+  // right after the data segment. Usually, this symbol points to the end
+  // of .bss section or to the end of .data section if .bss section is absent.
+  // The order of the sections can be affected by linker script,
+  // so it is hard to predict which section will be the last one.
+  // So, if this symbol is referenced, we just add the placeholder here
+  // and update its value later.
+  if (Symtab.find("_end"))
+    Symtab.addAbsoluteSym("_end", DefinedAbsolute<ELFT>::End);
+
+  // If there is an undefined symbol "end", we should initialize it
+  // with the same value as "_end". In any other case it should stay intact,
+  // because it is an allowable name for a user symbol.
+  if (SymbolBody *B = Symtab.find("end"))
+    if (B->isUndefined())
+      Symtab.addAbsoluteSym("end", DefinedAbsolute<ELFT>::End);
+
   // Scan relocations. This must be done after every symbol is declared so that
   // we can correctly decide if a dynamic relocation is needed.
   for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
@@ -879,6 +896,10 @@ template <class ELFT> void Writer<ELFT>:
   SectionHeaderOff = RoundUpToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4);
   FileSize = SectionHeaderOff + getNumSections() * sizeof(Elf_Shdr);
 
+  // Update "_end" and "end" symbols so that they
+  // point to the end of the data segment.
+  DefinedAbsolute<ELFT>::End.st_value = VA;
+
   // Update MIPS _gp absolute symbol so that it points to the static data.
   if (Config->EMachine == EM_MIPS)
     DefinedAbsolute<ELFT>::MipsGp.st_value = getMipsGpAddr<ELFT>();

Added: lld/trunk/test/ELF/end-preserve.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/end-preserve.s?rev=253637&view=auto
==============================================================================
--- lld/trunk/test/ELF/end-preserve.s (added)
+++ lld/trunk/test/ELF/end-preserve.s Thu Nov 19 20:32:35 2015
@@ -0,0 +1,16 @@
+// Should preserve the value of the "end" symbol if it is defined.
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t
+// RUN: llvm-nm %t | FileCheck %s
+
+// CHECK: 0000000000000005 A end
+
+.global _start,end
+end = 5
+.text
+_start:
+    nop
+.bss
+    .space 6

Added: lld/trunk/test/ELF/end-update.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/end-update.s?rev=253637&view=auto
==============================================================================
--- lld/trunk/test/ELF/end-update.s (added)
+++ lld/trunk/test/ELF/end-update.s Thu Nov 19 20:32:35 2015
@@ -0,0 +1,29 @@
+// Should set the value of the "end" symbol if it is undefined.
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t
+// RUN: llvm-readobj -sections -symbols %t | FileCheck %s
+
+// CHECK: Sections [
+// CHECK:     Name: .bss
+// CHECK-NEXT:     Type:
+// CHECK-NEXT:     Flags [
+// CHECK-NEXT:       SHF_ALLOC
+// CHECK-NEXT:       SHF_WRITE
+// CHECK-NEXT:     ]
+// CHECK-NEXT:     Address: 0x12000
+// CHECK-NEXT:     Offset:
+// CHECK-NEXT:     Size: 6
+// CHECK: ]
+// CHECK: Symbols [
+// CHECK:     Name: end
+// CHECK-NEXT:     Value: 0x12006
+// CHECK: ]
+
+.global _start,end
+.text
+_start:
+    nop
+.bss
+    .space 6

Added: lld/trunk/test/ELF/end.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/end.s?rev=253637&view=auto
==============================================================================
--- lld/trunk/test/ELF/end.s (added)
+++ lld/trunk/test/ELF/end.s Thu Nov 19 20:32:35 2015
@@ -0,0 +1,79 @@
+// Should set the value of the "_end" symbol to the end of the data segment.
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+
+// By default, the .bss section is the latest section of the data segment.
+// RUN: ld.lld %t.o -o %t
+// RUN: llvm-readobj -sections -symbols %t | FileCheck %s --check-prefix=DEFAULT
+
+// DEFAULT: Sections [
+// DEFAULT:     Name: .bss
+// DEFAULT-NEXT:     Type:
+// DEFAULT-NEXT:     Flags [
+// DEFAULT-NEXT:       SHF_ALLOC
+// DEFAULT-NEXT:       SHF_WRITE
+// DEFAULT-NEXT:     ]
+// DEFAULT-NEXT:     Address: 0x12002
+// DEFAULT-NEXT:     Offset:
+// DEFAULT-NEXT:     Size: 6
+// DEFAULT: ]
+// DEFAULT: Symbols [
+// DEFAULT:     Name: _end
+// DEFAULT-NEXT:     Value: 0x12008
+// DEFAULT: ]
+
+// If there is no .bss section, "_end" should point to the end of the .data section.
+// RUN: echo "SECTIONS { \
+// RUN:          /DISCARD/ : { *(.bss) } }" > %t.script
+// RUN: ld.lld %t.o --script %t.script -o %t
+// RUN: llvm-readobj -sections -symbols %t | FileCheck %s --check-prefix=NOBSS
+
+// NOBSS: Sections [
+// NOBSS:     Name: .data
+// NOBSS-NEXT:     Type:
+// NOBSS-NEXT:     Flags [
+// NOBSS-NEXT:       SHF_ALLOC
+// NOBSS-NEXT:       SHF_WRITE
+// NOBSS-NEXT:     ]
+// NOBSS-NEXT:     Address: 0x12000
+// NOBSS-NEXT:     Offset:
+// NOBSS-NEXT:     Size: 2
+// NOBSS: ]
+// NOBSS: Symbols [
+// NOBSS:     Name: _end
+// NOBSS-NEXT:     Value: 0x12002
+// NOBSS: ]
+
+// If the layout of the sections is changed, "_end" should point to the end of allocated address space.
+// RUN: echo "SECTIONS { \
+// RUN:          .bss : { *(.bss) } \
+// RUN:          .data : { *(.data) } \
+// RUN:          .text : { *(.text) } }" > %t.script
+// RUN: ld.lld %t.o --script %t.script -o %t
+// RUN: llvm-readobj -sections -symbols %t | FileCheck %s --check-prefix=TEXTATEND
+
+// TEXTATEND: Sections [
+// TEXTATEND:     Name: .text
+// TEXTATEND-NEXT:     Type:
+// TEXTATEND-NEXT:     Flags [
+// TEXTATEND-NEXT:       SHF_ALLOC
+// TEXTATEND-NEXT:       SHF_EXECINSTR
+// TEXTATEND-NEXT:     ]
+// TEXTATEND-NEXT:     Address: 0x12000
+// TEXTATEND-NEXT:     Offset:
+// TEXTATEND-NEXT:     Size: 1
+// TEXTATEND: ]
+// TEXTATEND: Symbols [
+// TEXTATEND:     Name: _end
+// TEXTATEND-NEXT:     Value: 0x12001
+// TEXTATEND: ]
+
+.global _start,_end
+.text
+_start:
+    nop
+.data
+    .word 1
+.bss
+    .space 6

Modified: lld/trunk/test/ELF/entry.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/entry.s?rev=253637&r1=253636&r2=253637&view=diff
==============================================================================
--- lld/trunk/test/ELF/entry.s (original)
+++ lld/trunk/test/ELF/entry.s Thu Nov 19 20:32:35 2015
@@ -1,6 +1,6 @@
 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1
 # RUN: not ld.lld %t1 -o %t2
-# RUN: ld.lld %t1 -o %t2 -e _end
+# RUN: ld.lld %t1 -o %t2 -e entry
 
 # RUN: ld.lld %t1 -o %t2 -e 4096
 # RUN: llvm-readobj -file-headers %t2 | FileCheck -check-prefix=DEC %s
@@ -13,5 +13,5 @@
 # HEX: Entry: 0xCAFE
 # OCT: Entry: 0x1FF
 
-.globl _end
-_end:
+.globl entry
+entry:




More information about the llvm-commits mailing list