[lld] 319181f - [lld-macho] Fix alignment of TLV data sections

Jez Ng via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 28 16:27:07 PST 2021


Author: Mike Hommey
Date: 2021-12-28T19:03:13-05:00
New Revision: 319181f7671868be6cd4865e9bcc63f6ba2ddb06

URL: https://github.com/llvm/llvm-project/commit/319181f7671868be6cd4865e9bcc63f6ba2ddb06
DIFF: https://github.com/llvm/llvm-project/commit/319181f7671868be6cd4865e9bcc63f6ba2ddb06.diff

LOG: [lld-macho] Fix alignment of TLV data sections

References from thread-local variable sections are treated as offsets
relative to the start of the thread-local data memory area, which is
initialized via copying all the TLV data sections (which are all
contiguous). If later data sections require a greater alignment than
earlier ones, the offsets of data within those sections won't be
guaranteed to aligned unless we normalize alignments. We therefore use
the largest alignment for all TLV data sections.

Reviewed By: #lld-macho, int3

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

Added: 
    

Modified: 
    lld/MachO/Writer.cpp
    lld/test/MachO/tlv.s

Removed: 
    


################################################################################
diff  --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index 8903f0189ef91..3c7bea335c669 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -908,13 +908,28 @@ static void sortSegmentsAndSections() {
   uint32_t sectionIndex = 0;
   for (OutputSegment *seg : outputSegments) {
     seg->sortOutputSections();
+    // References from thread-local variable sections are treated as offsets
+    // relative to the start of the thread-local data memory area, which
+    // is initialized via copying all the TLV data sections (which are all
+    // contiguous). If later data sections require a greater alignment than
+    // earlier ones, the offsets of data within those sections won't be
+    // guaranteed to aligned unless we normalize alignments. We therefore use
+    // the largest alignment for all TLV data sections.
+    uint32_t tlvAlign = 0;
+    for (const OutputSection *osec : seg->getSections())
+      if (isThreadLocalData(osec->flags) && osec->align > tlvAlign)
+        tlvAlign = osec->align;
+
     for (OutputSection *osec : seg->getSections()) {
       // Now that the output sections are sorted, assign the final
       // output section indices.
       if (!osec->isHidden())
         osec->index = ++sectionIndex;
-      if (!firstTLVDataSection && isThreadLocalData(osec->flags))
-        firstTLVDataSection = osec;
+      if (isThreadLocalData(osec->flags)) {
+        if (!firstTLVDataSection)
+          firstTLVDataSection = osec;
+        osec->align = tlvAlign;
+      }
 
       if (!isecPriorities.empty()) {
         if (auto *merged = dyn_cast<ConcatOutputSection>(osec)) {

diff  --git a/lld/test/MachO/tlv.s b/lld/test/MachO/tlv.s
index f188bf7279a89..e71fe76980e24 100644
--- a/lld/test/MachO/tlv.s
+++ b/lld/test/MachO/tlv.s
@@ -24,12 +24,12 @@
 # RUN: llvm-objdump -d --bind --rebase %t/regular-and-tbss | FileCheck %s --check-prefixes=REG,TBSS,LINKEDIT
 # RUN: llvm-objdump --macho --section=__DATA,__thread_vars %t/regular-and-tbss | \
 # RUN:   FileCheck %s --check-prefix=REG-TBSS-TLVP
-# RUN: llvm-objdump --section-headers %t/regular-and-tbss | FileCheck %s --check-prefix=SECTION-ORDER
+# RUN: llvm-objdump --section-headers %t/regular-and-tbss | FileCheck %s --check-prefix=SECTIONS
 
 ## Check that we always put __thread_bss immediately after __thread_data,
 ## regardless of the order of the input files.
 # RUN: %lld -lSystem %t/tbss.o %t/regular.o -o %t/regular-and-tbss
-# RUN: llvm-objdump --section-headers %t/regular-and-tbss | FileCheck %s --check-prefix=SECTION-ORDER
+# RUN: llvm-objdump --section-headers %t/regular-and-tbss | FileCheck %s --check-prefix=SECTIONS
 
 # HEADER: MH_HAS_TLV_DESCRIPTORS
 
@@ -41,6 +41,7 @@
 # TBSS:       <_f>:
 # TBSS-NEXT:  leaq    {{.*}}(%rip), %rax  ## {{.*}} <_baz>
 # TBSS-NEXT:  leaq    {{.*}}(%rip), %rax  ## {{.*}} <_qux>
+# TBSS-NEXT:  leaq    {{.*}}(%rip), %rax  ## {{.*}} <_hoge>
 # TBSS-NEXT:  retq
 
 # REG-TLVP:      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
@@ -53,10 +54,12 @@
 
 # REG-TBSS-TLVP:      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 # REG-TBSS-TLVP-NEXT: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-# REG-TBSS-TLVP-NEXT: 00 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00
+# REG-TBSS-TLVP-NEXT: 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00
 # REG-TBSS-TLVP-NEXT: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-# REG-TBSS-TLVP-NEXT: 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-# REG-TBSS-TLVP-NEXT: 00 00 00 00 00 00 00 00 18 00 00 00 00 00 00 00
+# REG-TBSS-TLVP-NEXT: 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# REG-TBSS-TLVP-NEXT: 00 00 00 00 00 00 00 00 28 00 00 00 00 00 00 00
+# REG-TBSS-TLVP-NEXT: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# REG-TBSS-TLVP-NEXT: 30 00 00 00 00 00 00 00
 
 ## Make sure we don't emit rebase opcodes for relocations in __thread_vars.
 # LINKEDIT:       Rebase table:
@@ -66,9 +69,14 @@
 # LINKEDIT:       __DATA  __thread_vars   0x{{[0-9a-f]*}}  pointer 0 libSystem __tlv_bootstrap
 # LINKEDIT:       __DATA  __thread_vars   0x{{[0-9a-f]*}}  pointer 0 libSystem __tlv_bootstrap
 
-# SECTION-ORDER:      __thread_data
-# SECTION-ORDER:      more_thread_data
-# SECTION-ORDER-NEXT: __thread_bss
+## Make sure we have an odd number of tlv vars, and that the __thread_vars
+## section starts 16-bytes aligned. This is the setup required for __thread_data
+## not to be automatically 16-bytes aligned, ensuring the linker does its
+## expected job of aligning _hoge$tlv$init.
+# SECTIONS:      __thread_vars {{[0-9]+}}8 {{[0-9]+}}0
+# SECTIONS:      __thread_data
+# SECTIONS:      more_thread_data
+# SECTIONS-NEXT: __thread_bss
 
 #--- regular.s
 .globl _main
@@ -102,10 +110,12 @@ _bar:
 _f:
   mov _baz at TLVP(%rip), %rax
   mov _qux at TLVP(%rip), %rax
+  mov _hoge at TLVP(%rip), %rax
   ret
 
 .tbss _baz$tlv$init, 8, 3
 .tbss _qux$tlv$init, 8, 3
+.tbss _hoge$tlv$init, 16, 4
 
 .section __DATA,__thread_vars,thread_local_variables
 _baz:
@@ -116,3 +126,7 @@ _qux:
   .quad  __tlv_bootstrap
   .quad  0
   .quad  _qux$tlv$init
+_hoge:
+  .quad  __tlv_bootstrap
+  .quad  0
+  .quad  _hoge$tlv$init


        


More information about the llvm-commits mailing list