[PATCH] D13615: [lld][elf2] Local Dynamic TLS

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 12 15:41:19 PDT 2015


ruiu added inline comments.

================
Comment at: ELF/OutputSections.cpp:58
@@ -55,1 +57,3 @@
+    if (!B)
+      continue;
     if (canBePreempted(B))
----------------
  continue;  // skip TLS empty second slot

================
Comment at: ELF/OutputSections.cpp:128
@@ -123,3 +127,3 @@
 
-    bool CanBePreempted = canBePreempted(Body);
+    bool CanBePreempted = canBePreempted(Body) || Type == R_X86_64_TLSLD;
     uintX_t Addend = 0;
----------------
I don't understand this. Is R_x86_64_TLSLD interpositioned? This function is really complicated and needs cleanup.

================
Comment at: ELF/OutputSections.h:111
@@ -110,3 +110,3 @@
   void writeTo(uint8_t *Buf) override;
-  void addEntry(SymbolBody *Sym);
+  void addEntry(SymbolBody *Sym, int Size = 1);
   bool empty() const { return Entries.empty(); }
----------------
It seems that we don't really have to pass the number to this function because the symbol should know that. If it's STT_TLS, we need two slots. Otherwise one. Can you remove the second parameter?

================
Comment at: ELF/Writer.cpp:143
@@ -141,2 +142,3 @@
   Out<ELFT>::Dynamic = &Dynamic;
+  Out<ELFT>::ThreadDataStart = 0;
 
----------------
Global uninitialized values should be initialized with zero, so no need to assign the same value again.

================
Comment at: ELF/Writer.cpp:220
@@ -217,3 +219,3 @@
     }
-    if (canBePreempted(Body)) {
+    if (canBePreempted(Body) || Type == R_X86_64_TLSLD) {
       Body->setUsedInDynamicReloc();
----------------
This is another use of canBePreempted(Body) || Type == R_X86_64_TLSLD

================
Comment at: ELF/Writer.cpp:292-327
@@ -289,11 +291,38 @@
 
-  uintX_t AFlags = A->getFlags();
-  uintX_t BFlags = B->getFlags();
-
-  // Allocatable sections go first to reduce the total PT_LOAD size and
-  // so debug info doesn't change addresses in actual code.
-  bool AIsAlloc = AFlags & SHF_ALLOC;
-  bool BIsAlloc = BFlags & SHF_ALLOC;
-  if (AIsAlloc != BIsAlloc)
-    return AIsAlloc;
+  auto CalcRank = [](OutputSectionBase<ELFT::Is64Bits> *Sec) {
+    uintX_t Flags = Sec->getFlags();
+    // The TLS initialization block goes at the start of the read/write PT_LOAD
+    // as it needs to first be loaded into memory so relocations can be applied.
+    // The rest of the flags are ignored as there can only be one TLS
+    // initialization block per binary.
+    if ((Flags & (SHF_ALLOC | SHF_TLS)) == (SHF_ALLOC | SHF_TLS))
+      return 2;
+
+    switch (Flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR)) {
+    case SHF_ALLOC:
+      // We want the read only sections first so that they go in the PT_LOAD
+      // covering the program headers at the start of the file.
+      return 0;
+
+    // The relative order of the following 3 cases is arbitrary.
+
+    case SHF_ALLOC | SHF_EXECINSTR:
+      return 1;
+    case SHF_ALLOC | SHF_WRITE:
+      return 3;
+    case SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR:
+      return 4;
+
+    case 0:
+    case SHF_WRITE | SHF_EXECINSTR:
+    case SHF_WRITE:
+    case SHF_EXECINSTR:
+      // Non allocatable sections go last to reduce the total PT_LOAD size and
+      // so debug info doesn't change addresses in actual code. There are also
+      // no special requirements for the relative order of non allocatable
+      // sections.
+      return 5;
+    }
+    llvm_unreachable("Covered switch.");
+  };
 
----------------
Can you move this function to top level? This doesn't have to be a lambda.

================
Comment at: ELF/Writer.cpp:298
@@ +297,3 @@
+    // initialization block per binary.
+    if ((Flags & (SHF_ALLOC | SHF_TLS)) == (SHF_ALLOC | SHF_TLS))
+      return 2;
----------------
  (Flags & SHF_ALLOC) && (Flags | SHF_TLS)

================
Comment at: ELF/Writer.cpp:563
@@ -542,1 +562,3 @@
       FileOff += Size;
+    if ((Sec->getFlags() & (SHF_ALLOC | SHF_TLS)) == (SHF_ALLOC | SHF_TLS)) {
+      if (Sec->getType() != SHT_NOBITS)
----------------
  (Sec->getFlags() & SHF_ALLOC) && (Sec->getFalgs() & SHF_TLS)

================
Comment at: ELF/Writer.cpp:563-586
@@ -542,2 +562,26 @@
       FileOff += Size;
+    if ((Sec->getFlags() & (SHF_ALLOC | SHF_TLS)) == (SHF_ALLOC | SHF_TLS)) {
+      if (Sec->getType() != SHT_NOBITS)
+        VA = RoundUpToAlignment(VA, Align);
+      uintX_t TVA = RoundUpToAlignment(VA + ThreadBSSOffset, Align);
+      Sec->setVA(TVA);
+      ThreadBSSOffset = TVA - VA;
+      if (Sec->getType() == SHT_NOBITS)
+        ThreadBSSOffset += Size;
+      else
+        VA += Size;
+      if (TlsPHDR.Header.p_offset == 0) {
+        TlsPHDR.Header.p_offset = Sec->getFileOff();
+        TlsPHDR.Header.p_vaddr = Sec->getVA();
+        TlsPHDR.Header.p_paddr = TlsPHDR.Header.p_vaddr;
+        Out<ELFT>::ThreadDataStart = TlsPHDR.Header.p_vaddr;
+      }
+      TlsPHDR.Header.p_filesz += Sec->getType() == SHT_NOBITS ? 0 : Size;
+      TlsPHDR.Header.p_memsz += Size;
+      TlsPHDR.Header.p_align = std::max<uintX_t>(TlsPHDR.Header.p_align, Align);
+    } else if (Sec->getFlags() & SHF_ALLOC) {
+      VA = RoundUpToAlignment(VA, Align);
+      Sec->setVA(VA);
+      VA += Size;
+    }
   }
----------------
ruiu wrote:
>   (Sec->getFlags() & SHF_ALLOC) && (Sec->getFalgs() & SHF_TLS)
Please try to reduce the amount of code to add this code, or completely split this function. This function is already too long.


http://reviews.llvm.org/D13615





More information about the llvm-commits mailing list