[lld] r218007 - [PECOFF] Support TLS callbacks.

Rui Ueyama ruiu at google.com
Wed Sep 17 19:02:53 PDT 2014


Author: ruiu
Date: Wed Sep 17 21:02:52 2014
New Revision: 218007

URL: http://llvm.org/viewvc/llvm-project?rev=218007&view=rev
Log:
[PECOFF] Support TLS callbacks.

The contents from section .CRT$XLA to .CRT$XLZ is an array of function
pointers. They are called by the runtime when a new thread is created
or (gracefully) terminated.

You can make your own initialization function to be called by that
mechanism. All you have to do is:

- Define a pointer to a function in a .CRT$XL* section using pragma
- Make an external reference to "__tls_used" symbol

That technique is used in many projects. This patch is to support that.

What this patch does is to set the relative virtual address of
"__tls_used" to the PECOFF directory table. __tls_used is actually a
struct containing pointers to a symbol in .CRT$XLA and another symbol
in .CRT$XLZ. The runtime looks at the directory table, gets the address
of the struct, and call the function pointers between XLA and XLZ.

Added:
    lld/trunk/test/pecoff/Inputs/tlsused.obj.yaml
    lld/trunk/test/pecoff/tls.test
Modified:
    lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp

Modified: lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp?rev=218007&r1=218006&r2=218007&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp Wed Sep 17 21:02:52 2014
@@ -885,6 +885,9 @@ private:
   // The size of the image on disk. This is basically the sum of all chunks in
   // the output file with paddings between them.
   uint32_t _imageSizeOnDisk;
+
+  // The map from atom to its relative virtual address.
+  std::map<const Atom *, uint64_t> _atomRva;
 };
 
 StringRef customSectionName(const DefinedAtom *atom) {
@@ -933,6 +936,13 @@ void groupAtoms(const PECOFFLinkingConte
   }
 }
 
+static const DefinedAtom *findTLSUsedSymbol(const File &file) {
+  for (const DefinedAtom *atom : file.defined())
+    if (atom->name() == "__tls_used")
+      return atom;
+  return nullptr;
+}
+
 // Create all chunks that consist of the output file.
 template <class PEHeader>
 void PECOFFWriter::build(const File &linkedFile) {
@@ -949,6 +959,7 @@ void PECOFFWriter::build(const File &lin
   addChunk(dataDirectory);
   addChunk(sectionTable);
 
+  // Create sections and add the atoms to them.
   for (auto i : atoms) {
     StringRef sectionName = i.first;
     std::vector<const DefinedAtom *> &contents = i.second;
@@ -957,9 +968,14 @@ void PECOFFWriter::build(const File &lin
       addSectionChunk(section, sectionTable);
   }
 
-  // Now that we know the addresses of all defined atoms that needs to be
-  // relocated. So we can create the ".reloc" section which contains all the
-  // relocation sites.
+  // Build atom to its RVA map.
+  for (std::unique_ptr<Chunk> &cp : _chunks)
+    if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp))
+      chunk->buildAtomRvaMap(_atomRva);
+
+  // We know the addresses of all defined atoms that needs to be
+  // relocated. So we can create the ".reloc" section which contains
+  // all the relocation sites.
   if (_ctx.getBaseRelocationEnabled()) {
     BaseRelocChunk *baseReloc = new BaseRelocChunk(_chunks, _ctx);
     if (baseReloc->size()) {
@@ -1014,6 +1030,11 @@ void PECOFFWriter::build(const File &lin
                               section->getVirtualAddress(), section->size());
   }
 
+  if (const DefinedAtom *atom = findTLSUsedSymbol(linkedFile)) {
+    dataDirectory->setField(DataDirectoryIndex::TLS_TABLE,
+                            _atomRva[atom], 0x18);
+  }
+
   // Now that we know the size and file offset of sections. Set the file
   // header accordingly.
   peHeader->setSizeOfCode(calcSizeOfCode());
@@ -1057,27 +1078,20 @@ std::error_code PECOFFWriter::writeFile(
 /// address. In the second pass, we visit all relocation references to fix
 /// up addresses in the buffer.
 void PECOFFWriter::applyAllRelocations(uint8_t *bufferStart) {
-  std::map<const Atom *, uint64_t> atomRva;
+  // Create the list of section start addresses. It's needed for
+  // relocations of SECREL type.
   std::vector<uint64_t> sectionRva;
-
-  // Create the list of section start addresses.
   for (auto &cp : _chunks)
     if (SectionChunk *section = dyn_cast<SectionChunk>(&*cp))
       sectionRva.push_back(section->getVirtualAddress());
 
-  // Pass 1
-  for (auto &cp : _chunks)
-    if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp))
-      chunk->buildAtomRvaMap(atomRva);
-
-  // Pass 2
   uint64_t base = _ctx.getBaseAddress();
   for (auto &cp : _chunks) {
     if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp)) {
       if (_ctx.is64Bit()) {
-        chunk->applyRelocations64(bufferStart, atomRva, sectionRva, base);
+        chunk->applyRelocations64(bufferStart, _atomRva, sectionRva, base);
       } else {
-        chunk->applyRelocations32(bufferStart, atomRva, sectionRva, base);
+        chunk->applyRelocations32(bufferStart, _atomRva, sectionRva, base);
       }
     }
   }

Added: lld/trunk/test/pecoff/Inputs/tlsused.obj.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/Inputs/tlsused.obj.yaml?rev=218007&view=auto
==============================================================================
--- lld/trunk/test/pecoff/Inputs/tlsused.obj.yaml (added)
+++ lld/trunk/test/pecoff/Inputs/tlsused.obj.yaml Wed Sep 17 21:02:52 2014
@@ -0,0 +1,29 @@
+---
+header:
+  Machine:         IMAGE_FILE_MACHINE_I386
+  Characteristics: []
+sections:
+  - Name:            .data
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+    Alignment:       4
+    SectionData:     "0000000000000000"
+symbols:
+  - Name:            .data
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          8
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          0
+  - Name:            __tls_used
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+...

Added: lld/trunk/test/pecoff/tls.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/tls.test?rev=218007&view=auto
==============================================================================
--- lld/trunk/test/pecoff/tls.test (added)
+++ lld/trunk/test/pecoff/tls.test Wed Sep 17 21:02:52 2014
@@ -0,0 +1,14 @@
+# RUN: yaml2obj %p/Inputs/hello.obj.yaml > %t1.obj
+# RUN: yaml2obj %p/Inputs/tlsused.obj.yaml > %t2.obj
+
+# RUN: lld -flavor link /out:%t1.exe /subsystem:console /force -- %t1.obj
+# RUN: llvm-readobj -file-headers %t1.exe | FileCheck -check-prefix=NOTLS %s
+
+# RUN: lld -flavor link /out:%t2.exe /subsystem:console /force -- %t1.obj %t2.obj
+# RUN: llvm-readobj -file-headers %t2.exe | FileCheck -check-prefix=TLS %s
+
+NOTLS: TLSTableRVA: 0x0
+NOTLS: TLSTableSize: 0x0
+
+TLS: TLSTableRVA: 0x1014
+TLS: TLSTableSize: 0x18





More information about the llvm-commits mailing list