[lld] r287913 - [ELF] - Add support for access to most of synthetic sections from linkerscript.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 25 00:05:41 PST 2016


Author: grimar
Date: Fri Nov 25 02:05:41 2016
New Revision: 287913

URL: http://llvm.org/viewvc/llvm-project?rev=287913&view=rev
Log:
[ELF] - Add support for access to most of synthetic sections from linkerscript.

This is important for cases like:

  .sdata        : {
    *(.got.plt .got)
...
  }

That was not supported before as there was no way to get access to 
synthetic sections from script.

More details on review page.

Differential revision: https://reviews.llvm.org/D27040

Added:
    lld/trunk/test/ELF/synthetic-got.s
Modified:
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/SyntheticSections.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/ELF/eh-align-cie.s
    lld/trunk/test/ELF/eh-frame-hdr-augmentation.s
    lld/trunk/test/ELF/eh-frame-marker.s
    lld/trunk/test/ELF/eh-frame-merge.s
    lld/trunk/test/ELF/linkerscript/phdrs.s

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=287913&r1=287912&r2=287913&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Fri Nov 25 02:05:41 2016
@@ -426,6 +426,12 @@ template <class ELFT> void GotSection<EL
   Size = Entries.size() * sizeof(uintX_t);
 }
 
+template <class ELFT> bool GotSection<ELFT>::empty() const {
+  // If we have a relocation that is relative to GOT (such as GOTOFFREL),
+  // we need to emit a GOT even if it's empty.
+  return Entries.empty() && !HasGotOffRel;
+}
+
 template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
   for (const SymbolBody *B : Entries) {
     uint8_t *Entry = Buf;
@@ -614,6 +620,12 @@ template <class ELFT> void MipsGotSectio
   Size = EntriesNum * sizeof(uintX_t);
 }
 
+template <class ELFT> bool MipsGotSection<ELFT>::empty() const {
+  // We add the .got section to the result for dynamic MIPS target because
+  // its address and properties are mentioned in the .dynamic section.
+  return Config->Relocatable;
+}
+
 template <class ELFT> unsigned MipsGotSection<ELFT>::getGp() const {
   return ElfSym<ELFT>::MipsGp->template getVA<ELFT>(0);
 }
@@ -691,10 +703,6 @@ template <class ELFT> void GotPltSection
   Entries.push_back(&Sym);
 }
 
-template <class ELFT> bool GotPltSection<ELFT>::empty() const {
-  return Entries.empty();
-}
-
 template <class ELFT> size_t GotPltSection<ELFT>::getSize() const {
   return (Target->GotPltHeaderEntriesNum + Entries.size()) *
          Target->GotPltEntrySize;
@@ -808,7 +816,7 @@ template <class ELFT> void DynamicSectio
 
   this->Link = In<ELFT>::DynStrTab->OutSec->SectionIndex;
 
-  if (In<ELFT>::RelaDyn->hasRelocs()) {
+  if (!In<ELFT>::RelaDyn->empty()) {
     bool IsRela = Config->Rela;
     add({IsRela ? DT_RELA : DT_REL, In<ELFT>::RelaDyn});
     add({IsRela ? DT_RELASZ : DT_RELSZ, In<ELFT>::RelaDyn->getSize()});
@@ -824,7 +832,7 @@ template <class ELFT> void DynamicSectio
         add({IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels});
     }
   }
-  if (In<ELFT>::RelaPlt->hasRelocs()) {
+  if (!In<ELFT>::RelaPlt->empty()) {
     add({DT_JMPREL, In<ELFT>::RelaPlt});
     add({DT_PLTRELSZ, In<ELFT>::RelaPlt->getSize()});
     add({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT,
@@ -1490,6 +1498,10 @@ void EhFrameHeader<ELFT>::addFde(uint32_
   Fdes.push_back({Pc, FdeVA});
 }
 
+template <class ELFT> bool EhFrameHeader<ELFT>::empty() const {
+  return Out<ELFT>::EhFrame->empty();
+}
+
 template <class ELFT>
 VersionDefinitionSection<ELFT>::VersionDefinitionSection()
     : SyntheticSection<ELFT>(SHF_ALLOC, SHT_GNU_verdef, sizeof(uint32_t),
@@ -1573,6 +1585,10 @@ template <class ELFT> void VersionTableS
   }
 }
 
+template <class ELFT> bool VersionTableSection<ELFT>::empty() const {
+  return !In<ELFT>::VerDef && In<ELFT>::VerNeed->empty();
+}
+
 template <class ELFT>
 VersionNeedSection<ELFT>::VersionNeedSection()
     : SyntheticSection<ELFT>(SHF_ALLOC, SHT_GNU_verneed, sizeof(uint32_t),
@@ -1654,6 +1670,10 @@ template <class ELFT> size_t VersionNeed
   return Size;
 }
 
+template <class ELFT> bool VersionNeedSection<ELFT>::empty() const {
+  return getNeedNum() == 0;
+}
+
 template <class ELFT>
 MipsRldMapSection<ELFT>::MipsRldMapSection()
     : SyntheticSection<ELFT>(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=287913&r1=287912&r2=287913&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Fri Nov 25 02:05:41 2016
@@ -32,6 +32,7 @@ public:
   virtual void writeTo(uint8_t *Buf) = 0;
   virtual size_t getSize() const = 0;
   virtual void finalize() {}
+  virtual bool empty() const { return false; }
 
   uintX_t getVA() const {
     return this->OutSec ? this->OutSec->Addr + this->OutSecOff : 0;
@@ -50,10 +51,11 @@ public:
   void writeTo(uint8_t *Buf) override;
   size_t getSize() const override { return Size; }
   void finalize() override;
+  bool empty() const override;
+
   void addEntry(SymbolBody &Sym);
   bool addDynTlsEntry(SymbolBody &Sym);
   bool addTlsIndex();
-  bool empty() const { return Entries.empty(); }
   uintX_t getGlobalDynAddr(const SymbolBody &B) const;
   uintX_t getGlobalDynOffset(const SymbolBody &B) const;
 
@@ -98,6 +100,7 @@ public:
   void writeTo(uint8_t *Buf) override;
   size_t getSize() const override { return Size; }
   void finalize() override;
+  bool empty() const override;
   void addEntry(SymbolBody &Sym, uintX_t Addend, RelExpr Expr);
   bool addDynTlsEntry(SymbolBody &Sym);
   bool addTlsIndex();
@@ -194,9 +197,9 @@ class GotPltSection final : public Synth
 public:
   GotPltSection();
   void addEntry(SymbolBody &Sym);
-  bool empty() const;
   size_t getSize() const override;
   void writeTo(uint8_t *Buf) override;
+  bool empty() const override { return Entries.empty(); }
 
 private:
   std::vector<const SymbolBody *> Entries;
@@ -315,8 +318,8 @@ public:
   unsigned getRelocOffset();
   void finalize() override;
   void writeTo(uint8_t *Buf) override;
+  bool empty() const override { return Relocs.empty(); }
   size_t getSize() const override { return Relocs.size() * this->Entsize; }
-  bool hasRelocs() const { return !Relocs.empty(); }
   size_t getRelativeRelocCount() const { return NumRelativeRelocs; }
 
 private:
@@ -421,7 +424,7 @@ public:
   void writeTo(uint8_t *Buf) override;
   size_t getSize() const override;
   void addEntry(SymbolBody &Sym);
-  bool empty() const { return Entries.empty(); }
+  bool empty() const override { return Entries.empty(); }
 
 private:
   std::vector<std::pair<const SymbolBody *, unsigned>> Entries;
@@ -471,6 +474,7 @@ public:
   void writeTo(uint8_t *Buf) override;
   size_t getSize() const override;
   void addFde(uint32_t Pc, uint32_t FdeVA);
+  bool empty() const override;
 
 private:
   struct FdeData {
@@ -521,6 +525,7 @@ public:
   void finalize() override;
   size_t getSize() const override;
   void writeTo(uint8_t *Buf) override;
+  bool empty() const override;
 };
 
 // The .gnu.version_r section defines the version identifiers used by
@@ -547,6 +552,7 @@ public:
   void writeTo(uint8_t *Buf) override;
   size_t getSize() const override;
   size_t getNeedNum() const { return Needed.size(); }
+  bool empty() const override;
 };
 
 // .MIPS.abiflags section.

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=287913&r1=287912&r2=287913&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Fri Nov 25 02:05:41 2016
@@ -58,7 +58,6 @@ private:
   void sortSections();
   void finalizeSections();
   void addPredefinedSections();
-  bool needsGot();
 
   std::vector<Phdr> createPhdrs();
   void assignAddresses();
@@ -242,8 +241,6 @@ template <class ELFT> void Writer<ELFT>:
   In<ELFT>::RelaDyn = make<RelocationSection<ELFT>>(
       Config->Rela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc);
   In<ELFT>::ShStrTab = make<StringTableSection<ELFT>>(".shstrtab", false);
-  In<ELFT>::VerSym = make<VersionTableSection<ELFT>>();
-  In<ELFT>::VerNeed = make<VersionNeedSection<ELFT>>();
 
   Out<ELFT>::ElfHeader = make<OutputSectionBase>("", 0, SHF_ALLOC);
   Out<ELFT>::ElfHeader->Size = sizeof(Elf_Ehdr);
@@ -257,17 +254,9 @@ template <class ELFT> void Writer<ELFT>:
     In<ELFT>::Interp = nullptr;
   }
 
-  if (!Symtab<ELFT>::X->getSharedFiles().empty() || Config->Pic) {
-    In<ELFT>::DynSymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::DynStrTab);
-  }
-
   if (Config->EhFrameHdr)
     In<ELFT>::EhFrameHdr = make<EhFrameHeader<ELFT>>();
 
-  if (Config->GnuHash)
-    In<ELFT>::GnuHashTab = make<GnuHashTableSection<ELFT>>();
-  if (Config->SysvHash)
-    In<ELFT>::HashTab = make<HashTableSection<ELFT>>();
   if (Config->GdbIndex)
     In<ELFT>::GdbIndex = make<GdbIndexSection<ELFT>>();
 
@@ -278,9 +267,6 @@ template <class ELFT> void Writer<ELFT>:
     In<ELFT>::SymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::StrTab);
   }
 
-  if (!Config->VersionDefinitions.empty())
-    In<ELFT>::VerDef = make<VersionDefinitionSection<ELFT>>();
-
   // Initialize linker generated sections
   if (!Config->Relocatable)
     Symtab<ELFT>::X->Sections.push_back(createCommentSection<ELFT>());
@@ -297,8 +283,9 @@ template <class ELFT> void Writer<ELFT>:
   }
 
   // Add MIPS-specific sections.
+  bool HasDynSymTab = !Symtab<ELFT>::X->getSharedFiles().empty() || Config->Pic;
   if (Config->EMachine == EM_MIPS) {
-    if (!Config->Shared && In<ELFT>::DynSymTab) {
+    if (!Config->Shared && HasDynSymTab) {
       In<ELFT>::MipsRldMap = make<MipsRldMapSection<ELFT>>();
       Symtab<ELFT>::X->Sections.push_back(In<ELFT>::MipsRldMap);
     }
@@ -310,14 +297,48 @@ template <class ELFT> void Writer<ELFT>:
       Symtab<ELFT>::X->Sections.push_back(Sec);
   }
 
+  if (HasDynSymTab) {
+    In<ELFT>::DynSymTab = make<SymbolTableSection<ELFT>>(*In<ELFT>::DynStrTab);
+    Symtab<ELFT>::X->Sections.push_back(In<ELFT>::DynSymTab);
+
+    In<ELFT>::VerSym = make<VersionTableSection<ELFT>>();
+    Symtab<ELFT>::X->Sections.push_back(In<ELFT>::VerSym);
+
+    if (!Config->VersionDefinitions.empty()) {
+      In<ELFT>::VerDef = make<VersionDefinitionSection<ELFT>>();
+      Symtab<ELFT>::X->Sections.push_back(In<ELFT>::VerDef);
+    }
+
+    In<ELFT>::VerNeed = make<VersionNeedSection<ELFT>>();
+    Symtab<ELFT>::X->Sections.push_back(In<ELFT>::VerNeed);
+
+    if (Config->GnuHash) {
+      In<ELFT>::GnuHashTab = make<GnuHashTableSection<ELFT>>();
+      Symtab<ELFT>::X->Sections.push_back(In<ELFT>::GnuHashTab);
+    }
+
+    if (Config->SysvHash) {
+      In<ELFT>::HashTab = make<HashTableSection<ELFT>>();
+      Symtab<ELFT>::X->Sections.push_back(In<ELFT>::HashTab);
+    }
+
+    Symtab<ELFT>::X->Sections.push_back(In<ELFT>::Dynamic);
+    Symtab<ELFT>::X->Sections.push_back(In<ELFT>::DynStrTab);
+    Symtab<ELFT>::X->Sections.push_back(In<ELFT>::RelaDyn);
+  }
+
   // Add .got. MIPS' .got is so different from the other archs,
   // it has its own class.
-  if (Config->EMachine == EM_MIPS)
+  if (Config->EMachine == EM_MIPS) {
     In<ELFT>::MipsGot = make<MipsGotSection<ELFT>>();
-  else
+    Symtab<ELFT>::X->Sections.push_back(In<ELFT>::MipsGot);
+  } else {
     In<ELFT>::Got = make<GotSection<ELFT>>();
+    Symtab<ELFT>::X->Sections.push_back(In<ELFT>::Got);
+  }
 
   In<ELFT>::GotPlt = make<GotPltSection<ELFT>>();
+  Symtab<ELFT>::X->Sections.push_back(In<ELFT>::GotPlt);
 }
 
 template <class ELFT>
@@ -870,6 +891,30 @@ finalizeSynthetic(const std::vector<Synt
     }
 }
 
+// We need to add input synthetic sections early in createSyntheticSections()
+// to make them visible from linkescript side. But not all sections are always
+// required to be in output. For example we don't need dynamic section content
+// sometimes. This function filters out such unused sections from output.
+template <class ELFT>
+static void removeUnusedSyntheticSections(std::vector<OutputSectionBase *> &V) {
+  // Input synthetic sections are placed after all regular ones. We iterate over
+  // them all and exit at first non-synthetic.
+  for (InputSectionBase<ELFT> *S : llvm::reverse(Symtab<ELFT>::X->Sections)) {
+    SyntheticSection<ELFT> *SS = dyn_cast<SyntheticSection<ELFT>>(S);
+    if (!SS)
+      return;
+    if (!SS->empty() || !SS->OutSec)
+      continue;
+
+    OutputSection<ELFT> *OutSec = cast<OutputSection<ELFT>>(SS->OutSec);
+    OutSec->Sections.erase(
+        std::find(OutSec->Sections.begin(), OutSec->Sections.end(), SS));
+    // If there is no other sections in output section, remove it from output.
+    if (OutSec->Sections.empty())
+      V.erase(std::find(V.begin(), V.end(), OutSec));
+  }
+}
+
 // Create output section objects and add them to OutputSections.
 template <class ELFT> void Writer<ELFT>::finalizeSections() {
   Out<ELFT>::DebugInfo = findSection(".debug_info");
@@ -930,6 +975,7 @@ template <class ELFT> void Writer<ELFT>:
   // So far we have added sections from input object files.
   // This function adds linker-created Out<ELFT>::* sections.
   addPredefinedSections();
+  removeUnusedSyntheticSections<ELFT>(OutputSections);
 
   sortSections();
 
@@ -956,20 +1002,6 @@ template <class ELFT> void Writer<ELFT>:
        In<ELFT>::VerNeed, In<ELFT>::Dynamic});
 }
 
-template <class ELFT> bool Writer<ELFT>::needsGot() {
-  // We add the .got section to the result for dynamic MIPS target because
-  // its address and properties are mentioned in the .dynamic section.
-  if (Config->EMachine == EM_MIPS)
-    return !Config->Relocatable;
-
-  if (!In<ELFT>::Got->empty())
-    return true;
-
-  // If we have a relocation that is relative to GOT (such as GOTOFFREL),
-  // we need to emit a GOT even if it's empty.
-  return In<ELFT>::Got->HasGotOffRel;
-}
-
 // This function add Out<ELFT>::* sections to OutputSections.
 template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
   auto Add = [&](OutputSectionBase *OS) {
@@ -984,41 +1016,12 @@ template <class ELFT> void Writer<ELFT>:
   addInputSec(In<ELFT>::SymTab);
   addInputSec(In<ELFT>::ShStrTab);
   addInputSec(In<ELFT>::StrTab);
-  if (In<ELFT>::DynSymTab) {
-    addInputSec(In<ELFT>::DynSymTab);
-
-    bool HasVerNeed = In<ELFT>::VerNeed->getNeedNum() != 0;
-    if (In<ELFT>::VerDef || HasVerNeed)
-      addInputSec(In<ELFT>::VerSym);
-    addInputSec(In<ELFT>::VerDef);
-    if (HasVerNeed)
-      addInputSec(In<ELFT>::VerNeed);
-
-    addInputSec(In<ELFT>::GnuHashTab);
-    addInputSec(In<ELFT>::HashTab);
-    addInputSec(In<ELFT>::Dynamic);
-    addInputSec(In<ELFT>::DynStrTab);
-    if (In<ELFT>::RelaDyn->hasRelocs())
-      addInputSec(In<ELFT>::RelaDyn);
-  }
 
   // We always need to add rel[a].plt to output if it has entries.
   // Even during static linking it can contain R_[*]_IRELATIVE relocations.
-  if (In<ELFT>::RelaPlt->hasRelocs())
+  if (!In<ELFT>::RelaPlt->empty())
     addInputSec(In<ELFT>::RelaPlt);
 
-  // We fill .got and .got.plt sections in scanRelocs(). This is the
-  // reason we don't add it earlier in createSections().
-  if (needsGot()) {
-    if (Config->EMachine == EM_MIPS)
-      addInputSec(In<ELFT>::MipsGot);
-    else
-      addInputSec(In<ELFT>::Got);
-  }
-
-  if (!In<ELFT>::GotPlt->empty())
-    addInputSec(In<ELFT>::GotPlt);
-
   if (!In<ELFT>::Plt->empty())
     addInputSec(In<ELFT>::Plt);
   if (!Out<ELFT>::EhFrame->empty())

Modified: lld/trunk/test/ELF/eh-align-cie.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/eh-align-cie.s?rev=287913&r1=287912&r2=287913&view=diff
==============================================================================
--- lld/trunk/test/ELF/eh-align-cie.s (original)
+++ lld/trunk/test/ELF/eh-align-cie.s Fri Nov 25 02:05:41 2016
@@ -51,7 +51,7 @@ bar:
 // CHECK-NEXT: EntrySize:
 // CHECK-NEXT: SectionData (
 // CHECK-NEXT:   0000: 1C000000 00000000 017A5052 00017810
-// CHECK-NEXT:   0010: 061B260E 00001B0C 07089001 00000000
-// CHECK-NEXT:   0020: 14000000 24000000 100E0000 00000000
+// CHECK-NEXT:   0010: 061BF60D 00001B0C 07089001 00000000
+// CHECK-NEXT:   0020: 14000000 24000000 E00D0000 00000000
 // CHECK-NEXT:   0030: 00000000 00000000
 // CHECK-NEXT: )

Modified: lld/trunk/test/ELF/eh-frame-hdr-augmentation.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/eh-frame-hdr-augmentation.s?rev=287913&r1=287912&r2=287913&view=diff
==============================================================================
--- lld/trunk/test/ELF/eh-frame-hdr-augmentation.s (original)
+++ lld/trunk/test/ELF/eh-frame-hdr-augmentation.s Fri Nov 25 02:05:41 2016
@@ -18,7 +18,7 @@
 // CHECK-NEXT: DW_CFA_nop:
 // CHECK-NEXT: DW_CFA_nop:
 
-// CHECK:      00000020 00000014 00000024 FDE cie=00000024 pc=00000dd8...00000dd8
+// CHECK:      00000020 00000014 00000024 FDE cie=00000024 pc=00000da8...00000da8
 // CHECK-NEXT:   DW_CFA_nop:
 // CHECK-NEXT:   DW_CFA_nop:
 // CHECK-NEXT:   DW_CFA_nop:

Modified: lld/trunk/test/ELF/eh-frame-marker.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/eh-frame-marker.s?rev=287913&r1=287912&r2=287913&view=diff
==============================================================================
--- lld/trunk/test/ELF/eh-frame-marker.s (original)
+++ lld/trunk/test/ELF/eh-frame-marker.s Fri Nov 25 02:05:41 2016
@@ -8,10 +8,10 @@
 // CHECK-NEXT: Flags [
 // CHECK-NEXT:   SHF_ALLOC
 // CHECK-NEXT: ]
-// CHECK-NEXT: Address: 0x200
+// CHECK-NEXT: Address: 0x229
 
 // CHECK:      Name: foo
-// CHECK-NEXT: Value: 0x200
+// CHECK-NEXT: Value: 0x229
 
         .section .eh_frame
 foo:

Modified: lld/trunk/test/ELF/eh-frame-merge.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/eh-frame-merge.s?rev=287913&r1=287912&r2=287913&view=diff
==============================================================================
--- lld/trunk/test/ELF/eh-frame-merge.s (original)
+++ lld/trunk/test/ELF/eh-frame-merge.s Fri Nov 25 02:05:41 2016
@@ -35,10 +35,10 @@
 // CHECK-NEXT: SectionData (
 // CHECK-NEXT: 0000: 14000000 00000000 017A5200 01781001  |
 // CHECK-NEXT: 0010: 1B0C0708 90010000 14000000 1C000000  |
-// CHECK-NEXT: 0020: 180E0000 01000000 00000000 00000000  |
-// CHECK-NEXT: 0030: 14000000 34000000 020E0000 02000000  |
+// CHECK-NEXT: 0020: E80D0000 01000000 00000000 00000000  |
+// CHECK-NEXT: 0030: 14000000 34000000 D20D0000 02000000  |
 // CHECK-NEXT: 0040: 00000000 00000000 14000000 4C000000  |
-// CHECK-NEXT: 0050: E90D0000 01000000 00000000 00000000  |
+// CHECK-NEXT: 0050: B90D0000 01000000 00000000 00000000  |
 // CHECK-NEXT: )
 
 // CHECK:      Name: foo

Modified: lld/trunk/test/ELF/linkerscript/phdrs.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/phdrs.s?rev=287913&r1=287912&r2=287913&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/phdrs.s (original)
+++ lld/trunk/test/ELF/linkerscript/phdrs.s Fri Nov 25 02:05:41 2016
@@ -102,7 +102,7 @@
 # INT-PHDRS-NEXT:        PF_W
 # INT-PHDRS-NEXT:        PF_X
 # INT-PHDRS-NEXT:      ]
-# INT-PHDRS-NEXT:      Alignment: 4
+# INT-PHDRS-NEXT:      Alignment:
 # INT-PHDRS-NEXT:    }
 # INT-PHDRS-NEXT:  ]
 

Added: lld/trunk/test/ELF/synthetic-got.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/synthetic-got.s?rev=287913&view=auto
==============================================================================
--- lld/trunk/test/ELF/synthetic-got.s (added)
+++ lld/trunk/test/ELF/synthetic-got.s Fri Nov 25 02:05:41 2016
@@ -0,0 +1,32 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: echo "SECTIONS { }" > %t0.script
+# RUN: ld.lld -shared %t.o -o %t0.out --script %t0.script
+# RUN: llvm-objdump -section-headers %t0.out | FileCheck %s --check-prefix=GOT
+# RUN: llvm-objdump -s -section=.got -section=.got.plt %t0.out \
+# RUN:   | FileCheck %s --check-prefix=GOTDATA
+
+# GOT:     Sections:
+# GOT:      9  .got         00000008 00000000000001b0 DATA
+# GOT-NEXT: 10 .got.plt     00000020 00000000000001b8 DATA
+# GOTDATA:     Contents of section .got:
+# GOTDATA-NEXT:  01b0 00000000 00000000
+# GOTDATA-NEXT: Contents of section .got.plt:
+# GOTDATA-NEXT:  01b8 e0000000 00000000 00000000 00000000
+# GOTDATA-NEXT:  01c8 00000000 00000000 d6000000 00000000
+
+# RUN: echo "SECTIONS { .mygot : { *(.got) *(.got.plt) } }" > %t1.script
+# RUN: ld.lld -shared %t.o -o %t1.out --script %t1.script
+# RUN: llvm-objdump -section-headers %t1.out | FileCheck %s --check-prefix=MYGOT
+# RUN: llvm-objdump -s -section=.mygot %t1.out | FileCheck %s --check-prefix=MYGOTDATA
+
+# MYGOT:     Sections:
+# MYGOT:      9  .mygot     00000028 00000000000001b0 DATA
+# MYGOT-NOT:  .got
+# MYGOT-NOT:  .got.plt
+# MYGOTDATA:      01b0 00000000 00000000 e0000000 00000000
+# MYGOTDATA-NEXT: 01c0 00000000 00000000 00000000 00000000
+# MYGOTDATA-NEXT: 01d0 d6000000 00000000
+
+mov bar at gotpcrel(%rip), %rax
+call foo at plt




More information about the llvm-commits mailing list