[lld-macho] Force higher alignment for __thread_vars
authorDaniel Bertalan <dani@danielbertalan.dev>
Sat, 24 Sep 2022 19:10:31 +0000 (21:10 +0200)
committerDaniel Bertalan <dani@danielbertalan.dev>
Sun, 25 Sep 2022 06:02:07 +0000 (08:02 +0200)
`__thread_vars` contains pointers to `__tlv_bootstrap`, which are fixed
up by dyld; however the section's alignment is not specified. This means
that the relocations might end up on odd addresses, which is not
representable by the soon to be added chained fixups.

This is arguably a bug in MC, but this behavior has been there since TLV
support was originally added.

This patch forces the `__thread_vars` sections to be aligned to the
target's pointer size. This is done by ld64 as well.

Differential Revision: https://reviews.llvm.org/D134594

lld/MachO/Writer.cpp
lld/test/MachO/tlv-dylib.s

index d0207bb..014e543 100644 (file)
@@ -960,6 +960,12 @@ template <class LP> void Writer::createOutputSections() {
           segname == segment_names::text)
         osec->align = target->wordSize;
 
+      // MC keeps the default 1-byte alignment for __thread_vars, even though it
+      // contains pointers that are fixed up by dyld, which requires proper
+      // alignment.
+      if (isThreadLocalVariables(osec->flags))
+        osec->align = std::max<uint32_t>(osec->align, target->wordSize);
+
       getOrCreateOutputSegment(segname)->addOutputSection(osec);
     }
   }
index 8a179ff..0aff5f5 100644 (file)
@@ -43,7 +43,7 @@
 # FLAGS-NEXT:      addr
 # FLAGS-NEXT:      size 0x0000000000000030
 # FLAGS-NEXT:    offset
-# FLAGS-NEXT:     align
+# FLAGS-NEXT:     align 2^3 (8)
 # FLAGS-NEXT:    reloff 0
 # FLAGS-NEXT:    nreloc 0
 # FLAGS-NEXT:      type S_THREAD_LOCAL_VARIABLES