[PATCH] D26238: [LLD][ARM] Correct ARM TLS GOT entries without dynamic relocations.

Rafael EspĂ­ndola via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 18 14:12:34 PST 2016


> The difficulty with this approach at the time was how to avoid writing the relocation into the file as well as statically resolving it. I thought that this would probably be messier than localising it here. With the new refactoring this might be easier so it will be worth taking another look.

I gave it a quick try to handle the x86_64 case. The patch is
attached. It is still pretty incomplete, but I think it is promising
in making it explicit that sometimes the dynamic linker computes a
value, sometimes lld computes the value.

Cheers,
Rafael
-------------- next part --------------
diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp
index 8bcf4d2..ba9fc5f 100644
--- a/ELF/Relocations.cpp
+++ b/ELF/Relocations.cpp
@@ -188,10 +188,13 @@ static unsigned handleTlsRelocation(uint32_t Type, SymbolBody &Body,
 
         // If the symbol is preemptible we need the dynamic linker to write
         // the offset too.
+        uintX_t OffsetOff = Off + (uintX_t)sizeof(uintX_t);
         if (isPreemptible(Body, Type))
           In<ELFT>::RelaDyn->addReloc({Target->TlsOffsetRel, In<ELFT>::Got,
-                                       Off + (uintX_t)sizeof(uintX_t), false,
-                                       &Body, 0});
+                                       OffsetOff, false, &Body, 0});
+        else
+          In<ELFT>::Got->Relocations.push_back(
+              {R_ABS, Target->TlsOffsetRel, OffsetOff, 0, &Body});
       }
       C.Relocations.push_back({Expr, Type, Offset, Addend, &Body});
       return 1;
@@ -778,16 +781,19 @@ static void scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
         continue;
 
       In<ELFT>::Got->addEntry(Body);
+      uintX_t Off = Body.getGotOffset<ELFT>();
+      uint32_t DynType;
+      if (Body.isTls())
+        DynType = Target->TlsGotRel;
+      else if (!Preemptible && Config->Pic && !isAbsolute<ELFT>(Body))
+        DynType = Target->RelativeRel;
+      else
+        DynType = Target->GotRel;
+
       if (Preemptible || (Config->Pic && !isAbsolute<ELFT>(Body))) {
-        uint32_t DynType;
-        if (Body.isTls())
-          DynType = Target->TlsGotRel;
-        else if (Preemptible)
-          DynType = Target->GotRel;
-        else
-          DynType = Target->RelativeRel;
-        AddDyn({DynType, In<ELFT>::Got, Body.getGotOffset<ELFT>(), !Preemptible,
-                &Body, 0});
+        AddDyn({DynType, In<ELFT>::Got, Off, !Preemptible, &Body, 0});
+      } else {
+        In<ELFT>::Got->Relocations.push_back({R_ABS, DynType, Off, 0, &Body});
       }
       continue;
     }
diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp
index 8f66ade..cc57690 100644
--- a/ELF/SyntheticSections.cpp
+++ b/ELF/SyntheticSections.cpp
@@ -350,17 +350,16 @@ GotSection<ELFT>::GotSection()
                              Target->GotEntrySize, ".got") {}
 
 template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody &Sym) {
-  Sym.GotIndex = Entries.size();
-  Entries.push_back(&Sym);
+  Sym.GotIndex = NumEntries;
+  ++NumEntries;
 }
 
 template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) {
   if (Sym.GlobalDynIndex != -1U)
     return false;
-  Sym.GlobalDynIndex = Entries.size();
+  Sym.GlobalDynIndex = NumEntries;
   // Global Dynamic TLS entries take two GOT slots.
-  Entries.push_back(nullptr);
-  Entries.push_back(&Sym);
+  NumEntries += 2;
   return true;
 }
 
@@ -369,9 +368,8 @@ template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) {
 template <class ELFT> bool GotSection<ELFT>::addTlsIndex() {
   if (TlsIndexOff != uint32_t(-1))
     return false;
-  TlsIndexOff = Entries.size() * sizeof(uintX_t);
-  Entries.push_back(nullptr);
-  Entries.push_back(nullptr);
+  TlsIndexOff = NumEntries * sizeof(uintX_t);
+  NumEntries += 2;
   return true;
 }
 
@@ -388,20 +386,13 @@ GotSection<ELFT>::getGlobalDynOffset(const SymbolBody &B) const {
 }
 
 template <class ELFT> void GotSection<ELFT>::finalize() {
-  Size = Entries.size() * sizeof(uintX_t);
+  Size = NumEntries * sizeof(uintX_t);
 }
 
 template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
-  for (const SymbolBody *B : Entries) {
-    uint8_t *Entry = Buf;
-    Buf += sizeof(uintX_t);
-    if (!B)
-      continue;
-    if (B->isPreemptible())
-      continue; // The dynamic linker will take care of it.
-    uintX_t VA = B->getVA<ELFT>();
-    write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, VA);
-  }
+  // dup?
+  uint8_t *BufEnd = Buf + Size;
+  this->relocate(Buf, BufEnd);
 }
 
 template <class ELFT>
diff --git a/ELF/SyntheticSections.h b/ELF/SyntheticSections.h
index e441f99..085a872 100644
--- a/ELF/SyntheticSections.h
+++ b/ELF/SyntheticSections.h
@@ -149,7 +149,7 @@ public:
   void addEntry(SymbolBody &Sym);
   bool addDynTlsEntry(SymbolBody &Sym);
   bool addTlsIndex();
-  bool empty() const { return Entries.empty(); }
+  bool empty() const { return NumEntries == 0; }
   uintX_t getGlobalDynAddr(const SymbolBody &B) const;
   uintX_t getGlobalDynOffset(const SymbolBody &B) const;
 
@@ -161,7 +161,7 @@ public:
   bool HasGotOffRel = false;
 
 private:
-  std::vector<const SymbolBody *> Entries;
+  size_t NumEntries = 0;
   uint32_t TlsIndexOff = -1;
   uintX_t Size = 0;
 };
diff --git a/ELF/Target.cpp b/ELF/Target.cpp
index bcada08..ed50e6f 100644
--- a/ELF/Target.cpp
+++ b/ELF/Target.cpp
@@ -804,6 +804,7 @@ void X86_64TargetInfo<ELFT>::relocateOne(uint8_t *Loc, uint32_t Type,
   case R_X86_64_DTPOFF64:
   case R_X86_64_SIZE64:
   case R_X86_64_PC64:
+  case R_X86_64_GLOB_DAT:
     write64le(Loc, Val);
     break;
   default:


More information about the llvm-commits mailing list