From d2f3d7bad26ac75b6729d27bf04d497621e84ed4 Mon Sep 17 00:00:00 2001 From: Daniel Bertalan Date: Sat, 24 Sep 2022 21:10:31 +0200 Subject: [PATCH] [lld-macho] Force higher alignment for __thread_vars `__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 | 6 ++++++ lld/test/MachO/tlv-dylib.s | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp index d0207bbf500e..014e543e69c2 100644 --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -960,6 +960,12 @@ template 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(osec->align, target->wordSize); + getOrCreateOutputSegment(segname)->addOutputSection(osec); } } diff --git a/lld/test/MachO/tlv-dylib.s b/lld/test/MachO/tlv-dylib.s index 8a179ffc3490..0aff5f5040a2 100644 --- a/lld/test/MachO/tlv-dylib.s +++ b/lld/test/MachO/tlv-dylib.s @@ -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