[lld] r241341 - [ELF] Define __start_XXX/__stop_XXX symbols where XXX is a section name

Simon Atanasyan simon at atanasyan.com
Fri Jul 3 04:25:37 PDT 2015


Author: atanasyan
Date: Fri Jul  3 06:25:37 2015
New Revision: 241341

URL: http://llvm.org/viewvc/llvm-project?rev=241341&view=rev
Log:
[ELF] Define __start_XXX/__stop_XXX symbols where XXX is a section name

This is GNU ELF linker extension used particularly by LibC code.
If input object files contain section named XXX, and the XXX is a valid C
identifier, and there are undefined or weak symbols __start_XXX/__stop_XXX,
linker should define __start_XXX/__stop_XXX symbols point to the begin/end
of the XXX section correspondingly.

For example, without support of this extension statically linked executables
for X86_64 and Mips (maybe other) targets do not flush IO buffers at the end
of executing.

Added:
    lld/trunk/test/elf/start-stop-sym.test
Modified:
    lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h
    lld/trunk/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h
    lld/trunk/lib/ReaderWriter/ELF/ELFFile.cpp
    lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
    lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.cpp
    lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h

Modified: lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h?rev=241341&r1=241340&r2=241341&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/ELFLinkingContext.h Fri Jul  3 06:25:37 2015
@@ -346,6 +346,13 @@ public:
   script::Sema &linkerScriptSema() { return _linkerScriptSema; }
   const script::Sema &linkerScriptSema() const { return _linkerScriptSema; }
 
+  /// Notify the ELFLinkingContext when the new ELF section is read.
+  void notifyInputSectionName(StringRef name);
+  /// Encountered C-ident input section names.
+  const llvm::StringSet<> &cidentSectionNames() const {
+    return _cidentSections;
+  }
+
   // Set R_ARM_TARGET1 relocation behaviour
   bool armTarget1Rel() const { return _armTarget1Rel; }
   void setArmTarget1Rel(bool value) { _armTarget1Rel = value; }
@@ -401,6 +408,7 @@ protected:
   std::map<std::string, uint64_t> _absoluteSymbols;
   llvm::StringSet<> _dynamicallyExportedSymbols;
   std::unique_ptr<File> _resolver;
+  llvm::StringSet<> _cidentSections;
 
   // The linker script semantic object, which owns all script ASTs, is stored
   // in the current linking context via _linkerScriptSema.

Modified: lld/trunk/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h?rev=241341&r1=241340&r2=241341&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h Fri Jul  3 06:25:37 2015
@@ -50,6 +50,8 @@ void ARMExecutableWriter::createImplicit
 
 void ARMExecutableWriter::processUndefinedSymbol(
     StringRef symName, RuntimeFile<ELF32LE> &file) const {
+  ARMELFWriter<ExecutableWriter<ELF32LE>>::processUndefinedSymbol(symName,
+                                                                  file);
   if (symName == gotSymbol) {
     file.addAbsoluteAtom(gotSymbol);
   } else if (symName.startswith("__exidx")) {

Modified: lld/trunk/lib/ReaderWriter/ELF/ELFFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFFile.cpp?rev=241341&r1=241340&r2=241341&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFFile.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFFile.cpp Fri Jul  3 06:25:37 2015
@@ -152,6 +152,10 @@ std::error_code ELFFile<ELFT>::createAto
       _relocationReferences[sHdr] = make_range(ri, re);
       totalRelocs += std::distance(ri, re);
     } else {
+      auto sectionName = _objFile->getSectionName(&section);
+      if (std::error_code ec = sectionName.getError())
+        return ec;
+      _ctx.notifyInputSectionName(*sectionName);
       _sectionSymbols[&section];
     }
   }

Modified: lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp?rev=241341&r1=241340&r2=241341&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/ELFLinkingContext.cpp Fri Jul  3 06:25:37 2015
@@ -247,4 +247,13 @@ void ELFLinkingContext::setUndefinesReso
   _resolver = std::move(resolver);
 }
 
+void ELFLinkingContext::notifyInputSectionName(StringRef name) {
+  // Save sections names which can be represented as a C identifier.
+  if (name.find_first_not_of("0123456789"
+                             "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                             "abcdefghijklmnopqrstuvwxyz"
+                             "_") == StringRef::npos)
+    _cidentSections.insert(name);
+}
+
 } // end namespace lld

Modified: lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.cpp?rev=241341&r1=241340&r2=241341&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.cpp (original)
+++ lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.cpp Fri Jul  3 06:25:37 2015
@@ -246,6 +246,14 @@ template <class ELFT> void OutputELFWrit
     assert(a);
     a->_virtualAddr = res;
   }
+  // If there is a section named XXX, and XXX is a valid C identifier,
+  // and there are undefined or weak __start_XXX/__stop_XXX symbols,
+  // set the symbols values to the begin/end of the XXX section
+  // correspondingly.
+  for (const auto &name : _ctx.cidentSectionNames())
+    updateScopeAtomValues((Twine("__start_") + name.getKey()).str(),
+                          (Twine("__stop_") + name.getKey()).str(),
+                          name.getKey());
 }
 
 template <class ELFT> void OutputELFWriter<ELFT>::createDefaultSections() {
@@ -455,23 +463,35 @@ std::error_code OutputELFWriter<ELFT>::w
 }
 
 template <class ELFT>
+void OutputELFWriter<ELFT>::processUndefinedSymbol(
+    StringRef symName, RuntimeFile<ELFT> &file) const {
+  if (symName.startswith("__start_")) {
+    if (_ctx.cidentSectionNames().count(symName.drop_front(8)))
+      file.addAbsoluteAtom(symName);
+  } else if (symName.startswith("__stop_")) {
+    if (_ctx.cidentSectionNames().count(symName.drop_front(7)))
+      file.addAbsoluteAtom(symName);
+  }
+}
+
+template <class ELFT>
 void OutputELFWriter<ELFT>::updateScopeAtomValues(StringRef sym,
                                                   StringRef sec) {
-  std::string start = ("__" + sym + "_start").str();
-  std::string end = ("__" + sym + "_end").str();
+  updateScopeAtomValues(("__" + sym + "_start").str().c_str(),
+                        ("__" + sym + "_end").str().c_str(), sec);
+}
+
+template <class ELFT>
+void OutputELFWriter<ELFT>::updateScopeAtomValues(StringRef start,
+                                                  StringRef end,
+                                                  StringRef sec) {
   AtomLayout *s = _layout.findAbsoluteAtom(start);
   AtomLayout *e = _layout.findAbsoluteAtom(end);
-  OutputSection<ELFT> *section = _layout.findOutputSection(sec);
-  if (!s || !e)
-    return;
-
-  if (section) {
-    s->_virtualAddr = section->virtualAddr();
-    e->_virtualAddr = section->virtualAddr() + section->memSize();
-  } else {
-    s->_virtualAddr = 0;
-    e->_virtualAddr = 0;
-  }
+  const OutputSection<ELFT> *section = _layout.findOutputSection(sec);
+  if (s)
+    s->_virtualAddr = section ? section->virtualAddr() : 0;
+  if (e)
+    e->_virtualAddr = section ? section->virtualAddr() + section->memSize() : 0;
 }
 
 template class OutputELFWriter<ELF32LE>;

Modified: lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h?rev=241341&r1=241340&r2=241341&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/OutputELFWriter.h Fri Jul  3 06:25:37 2015
@@ -113,7 +113,7 @@ protected:
 
   /// \brief Process undefined symbols that left after resolution step.
   virtual void processUndefinedSymbol(StringRef symName,
-                                      RuntimeFile<ELFT> &file) const {}
+                                      RuntimeFile<ELFT> &file) const;
 
   /// \brief Assign addresses to atoms marking section's start and end.
   void updateScopeAtomValues(StringRef sym, StringRef sec);
@@ -144,6 +144,7 @@ protected:
 
 private:
   static StringRef maybeGetSOName(Node *node);
+  void updateScopeAtomValues(StringRef start, StringRef end, StringRef sec);
 };
 
 } // namespace elf

Added: lld/trunk/test/elf/start-stop-sym.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/start-stop-sym.test?rev=241341&view=auto
==============================================================================
--- lld/trunk/test/elf/start-stop-sym.test (added)
+++ lld/trunk/test/elf/start-stop-sym.test Fri Jul  3 06:25:37 2015
@@ -0,0 +1,108 @@
+# Check __start_XXX and __stop_XXX symbols handling where XXX
+# is a section name which can be represented as a C identifier.
+
+# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o
+# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o
+# RUN: lld -flavor gnu -target mipsel -static -e T0 -o %t.exe %t1.o %t2.o
+# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
+
+# CHECK:      Contents of section .text:
+# CHECK-NEXT:  400080 a0004000 b4004000 00000000 00000000
+#                     ^ start of _csec section
+#                              ^ end of _csec section
+# CHECK-NEXT:  400090 a0004000 b4004000
+# CHECK-NEXT: Contents of section _csec:
+# CHECK-NEXT:  4000a0 00000000 00000000 00000000 00000000
+# CHECK-NEXT:  4000b0 00000000
+
+# CHECK: 004000a0  g  *ABS*  00000000 __start__csec
+# CHECK: 004000b4  g  *ABS*  00000000 __stop__csec
+
+---
+FileHeader:
+  Class:    ELFCLASS32
+  Data:     ELFDATA2LSB
+  Type:     ET_REL
+  Machine:  EM_MIPS
+  Flags:    [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  16
+    Size:          8
+
+  - Name:          .rel.text
+    Type:          SHT_REL
+    Link:          .symtab
+    AddressAlign:  4
+    Info:          .text
+    Relocations:
+      - Offset:  0
+        Symbol:  __start__csec
+        Type:    R_MIPS_32
+      - Offset:  4
+        Symbol:  __stop__csec
+        Type:    R_MIPS_32
+
+  - Name:          _csec
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC ]
+    AddressAlign:  16
+    Size:          4
+
+Symbols:
+  Weak:
+    - Name:     __start__csec
+    - Name:     __stop__csec
+  Global:
+    - Name:     T0
+      Type:     STT_FUNC
+      Section:  .text
+      Size:     8
+
+---
+FileHeader:
+  Class:    ELFCLASS32
+  Data:     ELFDATA2LSB
+  Type:     ET_REL
+  Machine:  EM_MIPS
+  Flags:    [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32]
+
+Sections:
+  - Name:          .text
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC, SHF_EXECINSTR ]
+    AddressAlign:  16
+    Size:          8
+
+  - Name:          .rel.text
+    Type:          SHT_REL
+    Link:          .symtab
+    AddressAlign:  4
+    Info:          .text
+    Relocations:
+      - Offset:  0
+        Symbol:  __start__csec
+        Type:    R_MIPS_32
+      - Offset:  4
+        Symbol:  __stop__csec
+        Type:    R_MIPS_32
+
+  - Name:          _csec
+    Type:          SHT_PROGBITS
+    Flags:         [ SHF_ALLOC ]
+    AddressAlign:  16
+    Size:          4
+
+Symbols:
+  Weak:
+    - Name:     __start__csec
+    - Name:     __stop__csec
+  Global:
+    - Name:     T1
+      Type:     STT_FUNC
+      Section:  .text
+      Size:     8
+...





More information about the llvm-commits mailing list