[lld] r251872 - [elf2] Generate PT_TLS.

Michael J. Spencer via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 2 16:34:39 PST 2015


Author: mspencer
Date: Mon Nov  2 18:34:39 2015
New Revision: 251872

URL: http://llvm.org/viewvc/llvm-project?rev=251872&view=rev
Log:
[elf2] Generate PT_TLS.

Differential Revision: http://reviews.llvm.org/D14167

Modified:
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/elf2/tls.s

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=251872&r1=251871&r2=251872&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon Nov  2 18:34:39 2015
@@ -644,15 +644,6 @@ static uint32_t toPhdrFlags(uint64_t Fla
   return Ret;
 }
 
-template <class ELFT>
-static bool consumesVirtualAddressSpace(OutputSectionBase<ELFT> *Sec) {
-  return (Sec->getFlags() & SHF_ALLOC) &&
-         // Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is
-         // responsible for allocating space for them, not the PT_LOAD that
-         // contains the TLS initialization image.
-         !((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS);
-}
-
 // Visits all sections to create PHDRs and to assign incremental,
 // non-overlapping addresses to output sections.
 template <class ELFT> void Writer<ELFT>::assignAddresses() {
@@ -679,6 +670,9 @@ template <class ELFT> void Writer<ELFT>:
   setPhdr(&Phdrs[++PhdrIdx], PT_LOAD, PF_R, 0, getVAStart(), FileOff,
           Target->getPageSize());
 
+  Elf_Phdr TlsPhdr;
+  std::memset(&TlsPhdr, 0, sizeof(Elf_Phdr));
+  uintX_t ThreadBSSOffset = 0;
   // Create phdrs as we assign VAs and file offsets to all output sections.
   SmallPtrSet<Elf_Phdr *, 8> Closed;
   for (OutputSectionBase<ELFT> *Sec : OutputSections) {
@@ -701,17 +695,38 @@ template <class ELFT> void Writer<ELFT>:
       }
     }
 
-    if (consumesVirtualAddressSpace<ELFT>(Sec)) {
+    if (Sec->getSize() && (Sec->getFlags() & SHF_ALLOC) &&
+        (Sec->getFlags() & SHF_TLS)) {
+      if (!TlsPhdr.p_vaddr) {
+        setPhdr(&TlsPhdr, PT_TLS, PF_R, FileOff, VA, 0, Sec->getAlign());
+      }
+      if (Sec->getType() != SHT_NOBITS)
+        VA = RoundUpToAlignment(VA, Sec->getAlign());
+      uintX_t TVA = RoundUpToAlignment(VA + ThreadBSSOffset, Sec->getAlign());
+      Sec->setVA(TVA);
+      TlsPhdr.p_memsz += Sec->getSize();
+      if (Sec->getType() == SHT_NOBITS)
+        ThreadBSSOffset = TVA - VA + Sec->getSize();
+      else {
+        TlsPhdr.p_filesz += Sec->getSize();
+        VA += Sec->getSize();
+      }
+      TlsPhdr.p_align = std::max<uintX_t>(TlsPhdr.p_align, Sec->getAlign());
+    } else if (Sec->getFlags() & SHF_ALLOC) {
       VA = RoundUpToAlignment(VA, Sec->getAlign());
       Sec->setVA(VA);
       VA += Sec->getSize();
     }
+
     FileOff = RoundUpToAlignment(FileOff, Sec->getAlign());
     Sec->setFileOffset(FileOff);
     if (Sec->getType() != SHT_NOBITS)
       FileOff += Sec->getSize();
   }
 
+  if (TlsPhdr.p_vaddr)
+    Phdrs[++PhdrIdx] = TlsPhdr;
+
   // Add an entry for .dynamic.
   if (isOutputDynamic()) {
     Elf_Phdr *PH = &Phdrs[++PhdrIdx];
@@ -732,6 +747,7 @@ template <class ELFT> void Writer<ELFT>:
 
 // Returns the number of PHDR entries.
 template <class ELFT> int Writer<ELFT>::getPhdrsNum() const {
+  bool Tls = false;
   int I = 2; // 2 for PT_PHDR and the first PT_LOAD
   if (needsInterpSection())
     ++I;
@@ -741,12 +757,16 @@ template <class ELFT> int Writer<ELFT>::
   for (OutputSectionBase<ELFT> *Sec : OutputSections) {
     if (!Sec->getSize() || !needsPhdr<ELFT>(Sec))
       continue;
+    if (Sec->getFlags() & SHF_TLS)
+      Tls = true;
     uintX_t Flags = toPhdrFlags(Sec->getFlags());
     if (Last != Flags) {
       Last = Flags;
       ++I;
     }
   }
+  if (Tls)
+    ++I;
   return I;
 }
 

Modified: lld/trunk/test/elf2/tls.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/tls.s?rev=251872&r1=251871&r2=251872&view=diff
==============================================================================
--- lld/trunk/test/elf2/tls.s (original)
+++ lld/trunk/test/elf2/tls.s Mon Nov  2 18:34:39 2015
@@ -25,7 +25,7 @@ _start:
 // CHECK-NEXT:       SHF_TLS
 // CHECK-NEXT:       SHF_WRITE
 // CHECK-NEXT:     ]
-// CHECK-NEXT:     Address:
+// CHECK-NEXT:     Address: [[TDATA_ADDR:0x.*]]
 // CHECK-NEXT:     Offset:
 // CHECK-NEXT:     Size: 4
 // CHECK-NEXT:     Link:
@@ -59,7 +59,7 @@ _start:
 // CHECK-NEXT:       SHF_TLS
 // CHECK-NEXT:       SHF_WRITE
 // CHECK-NEXT:     ]
-// CHECK-NEXT:     Address:
+// CHECK-NEXT:     Address: [[TBSS_ADDR:0x.*]]
 // CHECK-NEXT:     Offset:
 // CHECK-NEXT:     Size: 4
 // CHECK-NEXT:     Link:
@@ -76,9 +76,26 @@ _start:
 // CHECK-NEXT:       SHF_TLS
 // CHECK-NEXT:       SHF_WRITE
 // CHECK-NEXT:     ]
-// CHECK-NEXT:     Address:
+
+// 0x1100C = TBSS_ADDR + 4
+
+// CHECK-NEXT:     Address: 0x1100C
 // CHECK-NEXT:     Offset:
 // CHECK-NEXT:     Size: 4
+// CHECK-NEXT:     Link:
+// CHECK-NEXT:     Info:
+// CHECK-NEXT:     AddressAlignment:
+// CHECK-NEXT:     EntrySize:
+// CHECK-NEXT:   }
+// CHECK-NEXT:   Section {
+// CHECK-NEXT:     Index:
+// CHECK-NEXT:     Name:
+// CHECK-NEXT:     Type:
+// CHECK-NEXT:     Flags [
+// CHECK-NEXT:       SHF_ALLOC
+// CHECK-NEXT:       SHF_WRITE
+// CHECK-NEXT:     ]
+// CHECK-NEXT:     Address: [[TBSS_ADDR]]
 
 // Check that the TLS NOBITS sections weren't added to the R/W PT_LOAD's size.
 
@@ -91,3 +108,14 @@ _start:
 // CHECK-NEXT:       PF_R
 // CHECK-NEXT:       PF_W
 // CHECK-NEXT:     ]
+// CHECK:          Type: PT_TLS
+// CHECK-NEXT:     Offset:
+// CHECK-NEXT:     VirtualAddress: [[TDATA_ADDR]]
+// CHECK-NEXT:     PhysicalAddress: [[TDATA_ADDR]]
+// CHECK-NEXT:     FileSize: 8
+// CHECK-NEXT:     MemSize: 16
+// CHECK-NEXT:     Flags [
+// CHECK-NEXT:       PF_R
+// CHECK-NEXT:     ]
+// CHECK-NEXT:     Alignment:
+// CHECK-NEXT:   }




More information about the llvm-commits mailing list