<div dir="ltr">Good point. I only tested it on x86. x64 is the next step.</div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Sep 17, 2014 at 7:23 PM, David Majnemer <span dir="ltr"><<a href="mailto:david.majnemer@gmail.com" target="_blank">david.majnemer@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">I thought the symbol name varies depending on the platform, x86 is __tls_used and all other platforms have _tls_used.</div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Sep 17, 2014 at 10:02 PM, Rui Ueyama <span dir="ltr"><<a href="mailto:ruiu@google.com" target="_blank">ruiu@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: ruiu<br>
Date: Wed Sep 17 21:02:52 2014<br>
New Revision: 218007<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=218007&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=218007&view=rev</a><br>
Log:<br>
[PECOFF] Support TLS callbacks.<br>
<br>
The contents from section .CRT$XLA to .CRT$XLZ is an array of function<br>
pointers. They are called by the runtime when a new thread is created<br>
or (gracefully) terminated.<br>
<br>
You can make your own initialization function to be called by that<br>
mechanism. All you have to do is:<br>
<br>
- Define a pointer to a function in a .CRT$XL* section using pragma<br>
- Make an external reference to "__tls_used" symbol<br>
<br>
That technique is used in many projects. This patch is to support that.<br>
<br>
What this patch does is to set the relative virtual address of<br>
"__tls_used" to the PECOFF directory table. __tls_used is actually a<br>
struct containing pointers to a symbol in .CRT$XLA and another symbol<br>
in .CRT$XLZ. The runtime looks at the directory table, gets the address<br>
of the struct, and call the function pointers between XLA and XLZ.<br>
<br>
Added:<br>
    lld/trunk/test/pecoff/Inputs/tlsused.obj.yaml<br>
    lld/trunk/test/pecoff/tls.test<br>
Modified:<br>
    lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp?rev=218007&r1=218006&r2=218007&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp?rev=218007&r1=218006&r2=218007&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp (original)<br>
+++ lld/trunk/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp Wed Sep 17 21:02:52 2014<br>
@@ -885,6 +885,9 @@ private:<br>
   // The size of the image on disk. This is basically the sum of all chunks in<br>
   // the output file with paddings between them.<br>
   uint32_t _imageSizeOnDisk;<br>
+<br>
+  // The map from atom to its relative virtual address.<br>
+  std::map<const Atom *, uint64_t> _atomRva;<br>
 };<br>
<br>
 StringRef customSectionName(const DefinedAtom *atom) {<br>
@@ -933,6 +936,13 @@ void groupAtoms(const PECOFFLinkingConte<br>
   }<br>
 }<br>
<br>
+static const DefinedAtom *findTLSUsedSymbol(const File &file) {<br>
+  for (const DefinedAtom *atom : file.defined())<br>
+    if (atom->name() == "__tls_used")<br>
+      return atom;<br>
+  return nullptr;<br>
+}<br>
+<br>
 // Create all chunks that consist of the output file.<br>
 template <class PEHeader><br>
 void PECOFFWriter::build(const File &linkedFile) {<br>
@@ -949,6 +959,7 @@ void PECOFFWriter::build(const File &lin<br>
   addChunk(dataDirectory);<br>
   addChunk(sectionTable);<br>
<br>
+  // Create sections and add the atoms to them.<br>
   for (auto i : atoms) {<br>
     StringRef sectionName = i.first;<br>
     std::vector<const DefinedAtom *> &contents = i.second;<br>
@@ -957,9 +968,14 @@ void PECOFFWriter::build(const File &lin<br>
       addSectionChunk(section, sectionTable);<br>
   }<br>
<br>
-  // Now that we know the addresses of all defined atoms that needs to be<br>
-  // relocated. So we can create the ".reloc" section which contains all the<br>
-  // relocation sites.<br>
+  // Build atom to its RVA map.<br>
+  for (std::unique_ptr<Chunk> &cp : _chunks)<br>
+    if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp))<br>
+      chunk->buildAtomRvaMap(_atomRva);<br>
+<br>
+  // We know the addresses of all defined atoms that needs to be<br>
+  // relocated. So we can create the ".reloc" section which contains<br>
+  // all the relocation sites.<br>
   if (_ctx.getBaseRelocationEnabled()) {<br>
     BaseRelocChunk *baseReloc = new BaseRelocChunk(_chunks, _ctx);<br>
     if (baseReloc->size()) {<br>
@@ -1014,6 +1030,11 @@ void PECOFFWriter::build(const File &lin<br>
                               section->getVirtualAddress(), section->size());<br>
   }<br>
<br>
+  if (const DefinedAtom *atom = findTLSUsedSymbol(linkedFile)) {<br>
+    dataDirectory->setField(DataDirectoryIndex::TLS_TABLE,<br>
+                            _atomRva[atom], 0x18);<br>
+  }<br>
+<br>
   // Now that we know the size and file offset of sections. Set the file<br>
   // header accordingly.<br>
   peHeader->setSizeOfCode(calcSizeOfCode());<br>
@@ -1057,27 +1078,20 @@ std::error_code PECOFFWriter::writeFile(<br>
 /// address. In the second pass, we visit all relocation references to fix<br>
 /// up addresses in the buffer.<br>
 void PECOFFWriter::applyAllRelocations(uint8_t *bufferStart) {<br>
-  std::map<const Atom *, uint64_t> atomRva;<br>
+  // Create the list of section start addresses. It's needed for<br>
+  // relocations of SECREL type.<br>
   std::vector<uint64_t> sectionRva;<br>
-<br>
-  // Create the list of section start addresses.<br>
   for (auto &cp : _chunks)<br>
     if (SectionChunk *section = dyn_cast<SectionChunk>(&*cp))<br>
       sectionRva.push_back(section->getVirtualAddress());<br>
<br>
-  // Pass 1<br>
-  for (auto &cp : _chunks)<br>
-    if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp))<br>
-      chunk->buildAtomRvaMap(atomRva);<br>
-<br>
-  // Pass 2<br>
   uint64_t base = _ctx.getBaseAddress();<br>
   for (auto &cp : _chunks) {<br>
     if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp)) {<br>
       if (_ctx.is64Bit()) {<br>
-        chunk->applyRelocations64(bufferStart, atomRva, sectionRva, base);<br>
+        chunk->applyRelocations64(bufferStart, _atomRva, sectionRva, base);<br>
       } else {<br>
-        chunk->applyRelocations32(bufferStart, atomRva, sectionRva, base);<br>
+        chunk->applyRelocations32(bufferStart, _atomRva, sectionRva, base);<br>
       }<br>
     }<br>
   }<br>
<br>
Added: lld/trunk/test/pecoff/Inputs/tlsused.obj.yaml<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/Inputs/tlsused.obj.yaml?rev=218007&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/Inputs/tlsused.obj.yaml?rev=218007&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/pecoff/Inputs/tlsused.obj.yaml (added)<br>
+++ lld/trunk/test/pecoff/Inputs/tlsused.obj.yaml Wed Sep 17 21:02:52 2014<br>
@@ -0,0 +1,29 @@<br>
+---<br>
+header:<br>
+  Machine:         IMAGE_FILE_MACHINE_I386<br>
+  Characteristics: []<br>
+sections:<br>
+  - Name:            .data<br>
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]<br>
+    Alignment:       4<br>
+    SectionData:     "0000000000000000"<br>
+symbols:<br>
+  - Name:            .data<br>
+    Value:           0<br>
+    SectionNumber:   1<br>
+    SimpleType:      IMAGE_SYM_TYPE_NULL<br>
+    ComplexType:     IMAGE_SYM_DTYPE_NULL<br>
+    StorageClass:    IMAGE_SYM_CLASS_STATIC<br>
+    SectionDefinition:<br>
+      Length:          8<br>
+      NumberOfRelocations: 0<br>
+      NumberOfLinenumbers: 0<br>
+      CheckSum:        0<br>
+      Number:          0<br>
+  - Name:            __tls_used<br>
+    Value:           0<br>
+    SectionNumber:   1<br>
+    SimpleType:      IMAGE_SYM_TYPE_NULL<br>
+    ComplexType:     IMAGE_SYM_DTYPE_NULL<br>
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL<br>
+...<br>
<br>
Added: lld/trunk/test/pecoff/tls.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/tls.test?rev=218007&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/tls.test?rev=218007&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/pecoff/tls.test (added)<br>
+++ lld/trunk/test/pecoff/tls.test Wed Sep 17 21:02:52 2014<br>
@@ -0,0 +1,14 @@<br>
+# RUN: yaml2obj %p/Inputs/hello.obj.yaml > %t1.obj<br>
+# RUN: yaml2obj %p/Inputs/tlsused.obj.yaml > %t2.obj<br>
+<br>
+# RUN: lld -flavor link /out:%t1.exe /subsystem:console /force -- %t1.obj<br>
+# RUN: llvm-readobj -file-headers %t1.exe | FileCheck -check-prefix=NOTLS %s<br>
+<br>
+# RUN: lld -flavor link /out:%t2.exe /subsystem:console /force -- %t1.obj %t2.obj<br>
+# RUN: llvm-readobj -file-headers %t2.exe | FileCheck -check-prefix=TLS %s<br>
+<br>
+NOTLS: TLSTableRVA: 0x0<br>
+NOTLS: TLSTableSize: 0x0<br>
+<br>
+TLS: TLSTableRVA: 0x1014<br>
+TLS: TLSTableSize: 0x18<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>