Compute section names only once.
authorRafael Espindola <rafael.espindola@gmail.com>
Thu, 8 Sep 2016 14:06:08 +0000 (14:06 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Thu, 8 Sep 2016 14:06:08 +0000 (14:06 +0000)
This simplifies error handling as there is now only one place in the
code that needs to consider the possibility that the name is
corrupted. Before we would do it in every access.

llvm-svn: 280937

lld/ELF/ICF.cpp
lld/ELF/InputFiles.cpp
lld/ELF/InputSection.cpp
lld/ELF/InputSection.h
lld/ELF/LinkerScript.cpp
lld/ELF/MarkLive.cpp
lld/ELF/OutputSections.cpp
lld/ELF/Writer.cpp

index 209cf20439caf3788977640e59031f852c03c303..5fa7aa04f484cf9ef46a2875b18f45a8a2f3e7d1 100644 (file)
@@ -137,7 +137,7 @@ template <class ELFT> bool ICF<ELFT>::isEligible(InputSectionBase<ELFT> *Sec) {
   // .init and .fini contains instructions that must be executed to
   // initialize and finalize the process. They cannot and should not
   // be merged.
-  StringRef Name = S->getSectionName();
+  StringRef Name = S->Name;
   if (Name == ".init" || Name == ".fini")
     return false;
 
@@ -331,10 +331,10 @@ template <class ELFT> void ICF<ELFT>::run() {
     });
     if (I == Bound)
       continue;
-    log("selected " + Head->getSectionName());
+    log("selected " + Head->Name);
     while (I != Bound) {
       InputSection<ELFT> *S = *I++;
-      log("  removed " + S->getSectionName());
+      log("  removed " + S->Name);
       Head->replace(S);
     }
   }
index 4db990774e5b0f28f75cc906d66769f82878ff14..9589a50f7a5fa96fb7e8a0d91b6685ab17b9b539 100644 (file)
@@ -233,53 +233,6 @@ void elf::ObjectFile<ELFT>::initializeSections(
     case SHT_STRTAB:
     case SHT_NULL:
       break;
-    case SHT_RELA:
-    case SHT_REL: {
-      // This section contains relocation information.
-      // If -r is given, we do not interpret or apply relocation
-      // but just copy relocation sections to output.
-      if (Config->Relocatable) {
-        Sections[I] = new (IAlloc.Allocate()) InputSection<ELFT>(this, &Sec);
-        break;
-      }
-
-      // Find the relocation target section and associate this
-      // section with it.
-      InputSectionBase<ELFT> *Target = getRelocTarget(Sec);
-      if (!Target)
-        break;
-      if (auto *S = dyn_cast<InputSection<ELFT>>(Target)) {
-        S->RelocSections.push_back(&Sec);
-        break;
-      }
-      if (auto *S = dyn_cast<EhInputSection<ELFT>>(Target)) {
-        if (S->RelocSection)
-          fatal(
-              getFilename(this) +
-              ": multiple relocation sections to .eh_frame are not supported");
-        S->RelocSection = &Sec;
-        break;
-      }
-      fatal(getFilename(this) +
-            ": relocations pointing to SHF_MERGE are not supported");
-    }
-    case SHT_ARM_ATTRIBUTES:
-      // FIXME: ARM meta-data section. At present attributes are ignored,
-      // they can be used to reason about object compatibility.
-      Sections[I] = &InputSection<ELFT>::Discarded;
-      break;
-    case SHT_MIPS_REGINFO:
-      MipsReginfo.reset(new MipsReginfoInputSection<ELFT>(this, &Sec));
-      Sections[I] = MipsReginfo.get();
-      break;
-    case SHT_MIPS_OPTIONS:
-      MipsOptions.reset(new MipsOptionsInputSection<ELFT>(this, &Sec));
-      Sections[I] = MipsOptions.get();
-      break;
-    case SHT_MIPS_ABIFLAGS:
-      MipsAbiFlags.reset(new MipsAbiFlagsInputSection<ELFT>(this, &Sec));
-      Sections[I] = MipsAbiFlags.get();
-      break;
     default:
       Sections[I] = createInputSection(Sec);
     }
@@ -311,6 +264,49 @@ InputSectionBase<ELFT> *
 elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
   StringRef Name = check(this->ELFObj.getSectionName(&Sec));
 
+  switch (Sec.sh_type) {
+  case SHT_ARM_ATTRIBUTES:
+    // FIXME: ARM meta-data section. At present attributes are ignored,
+    // they can be used to reason about object compatibility.
+    return &InputSection<ELFT>::Discarded;
+  case SHT_MIPS_REGINFO:
+    MipsReginfo.reset(new MipsReginfoInputSection<ELFT>(this, &Sec, Name));
+    return MipsReginfo.get();
+  case SHT_MIPS_OPTIONS:
+    MipsOptions.reset(new MipsOptionsInputSection<ELFT>(this, &Sec, Name));
+    return MipsOptions.get();
+  case SHT_MIPS_ABIFLAGS:
+    MipsAbiFlags.reset(new MipsAbiFlagsInputSection<ELFT>(this, &Sec, Name));
+    return MipsAbiFlags.get();
+  case SHT_RELA:
+  case SHT_REL: {
+    // This section contains relocation information.
+    // If -r is given, we do not interpret or apply relocation
+    // but just copy relocation sections to output.
+    if (Config->Relocatable)
+      return new (IAlloc.Allocate()) InputSection<ELFT>(this, &Sec, Name);
+
+    // Find the relocation target section and associate this
+    // section with it.
+    InputSectionBase<ELFT> *Target = getRelocTarget(Sec);
+    if (!Target)
+      return nullptr;
+    if (auto *S = dyn_cast<InputSection<ELFT>>(Target)) {
+      S->RelocSections.push_back(&Sec);
+      return nullptr;
+    }
+    if (auto *S = dyn_cast<EhInputSection<ELFT>>(Target)) {
+      if (S->RelocSection)
+        fatal(getFilename(this) +
+              ": multiple relocation sections to .eh_frame are not supported");
+      S->RelocSection = &Sec;
+      return nullptr;
+    }
+    fatal(getFilename(this) +
+          ": relocations pointing to SHF_MERGE are not supported");
+  }
+  }
+
   // .note.GNU-stack is a marker section to control the presence of
   // PT_GNU_STACK segment in outputs. Since the presence of the segment
   // is controlled only by the command line option (-z execstack) in LLD,
@@ -330,11 +326,11 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
   // .eh_frame_hdr section for runtime. So we handle them with a special
   // class. For relocatable outputs, they are just passed through.
   if (Name == ".eh_frame" && !Config->Relocatable)
-    return new (EHAlloc.Allocate()) EhInputSection<ELFT>(this, &Sec);
+    return new (EHAlloc.Allocate()) EhInputSection<ELFT>(this, &Sec, Name);
 
   if (shouldMerge(Sec))
-    return new (MAlloc.Allocate()) MergeInputSection<ELFT>(this, &Sec);
-  return new (IAlloc.Allocate()) InputSection<ELFT>(this, &Sec);
+    return new (MAlloc.Allocate()) MergeInputSection<ELFT>(this, &Sec, Name);
+  return new (IAlloc.Allocate()) InputSection<ELFT>(this, &Sec, Name);
 }
 
 template <class ELFT> void elf::ObjectFile<ELFT>::initializeSymbols() {
index d4f7acb2c1dc78eb74c3135d5e9fb26fd61fbe16..01d97eda908840b189d8553210dd7fa663d43083 100644 (file)
@@ -30,8 +30,9 @@ using namespace lld::elf;
 
 template <class ELFT>
 InputSectionBase<ELFT>::InputSectionBase(elf::ObjectFile<ELFT> *File,
-                                         const Elf_Shdr *Hdr, Kind SectionKind)
-    : InputSectionData(SectionKind, Hdr->sh_flags & SHF_COMPRESSED,
+                                         const Elf_Shdr *Hdr, StringRef Name,
+                                         Kind SectionKind)
+    : InputSectionData(SectionKind, Name, Hdr->sh_flags & SHF_COMPRESSED,
                        !Config->GcSections),
       Header(Hdr), File(File), Repl(this) {
   // The ELF spec states that a value of 0 means the section has
@@ -46,10 +47,6 @@ template <class ELFT> size_t InputSectionBase<ELFT>::getSize() const {
   return Header->sh_size;
 }
 
-template <class ELFT> StringRef InputSectionBase<ELFT>::getSectionName() const {
-  return check(File->getObj().getSectionName(this->Header));
-}
-
 template <class ELFT>
 ArrayRef<uint8_t> InputSectionBase<ELFT>::getSectionData() const {
   if (Compressed)
@@ -60,7 +57,7 @@ ArrayRef<uint8_t> InputSectionBase<ELFT>::getSectionData() const {
 
 // Returns a string for an error message.
 template <class SectionT> static std::string getName(SectionT *Sec) {
-  return (Sec->getFile()->getName() + "(" + Sec->getSectionName() + ")").str();
+  return (Sec->getFile()->getName() + "(" + Sec->Name + ")").str();
 }
 
 template <class ELFT>
@@ -84,7 +81,7 @@ typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) const {
     // corresponding input section. Redirect it to the produced output section.
     if (Offset != 0)
       fatal(getName(this) + ": unsupported reference to the middle of '" +
-            getSectionName() + "' section");
+            Name + "' section");
     return this->OutSec->getVA();
   }
   llvm_unreachable("invalid section kind");
@@ -121,8 +118,8 @@ InputSectionBase<ELFT>::getOffset(const DefinedRegular<ELFT> &Sym) const {
 
 template <class ELFT>
 InputSection<ELFT>::InputSection(elf::ObjectFile<ELFT> *F,
-                                 const Elf_Shdr *Header)
-    : InputSectionBase<ELFT>(F, Header, Base::Regular) {}
+                                 const Elf_Shdr *Header, StringRef Name)
+    : InputSectionBase<ELFT>(F, Header, Name, Base::Regular) {}
 
 template <class ELFT>
 bool InputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
@@ -436,8 +433,8 @@ void InputSection<ELFT>::replace(InputSection<ELFT> *Other) {
 
 template <class ELFT>
 EhInputSection<ELFT>::EhInputSection(elf::ObjectFile<ELFT> *F,
-                                     const Elf_Shdr *Header)
-    : InputSectionBase<ELFT>(F, Header, InputSectionBase<ELFT>::EHFrame) {
+                                     const Elf_Shdr *Header, StringRef Name)
+    : InputSectionBase<ELFT>(F, Header, Name, InputSectionBase<ELFT>::EHFrame) {
   // Mark .eh_frame sections as live by default because there are
   // usually no relocations that point to .eh_frames. Otherwise,
   // the garbage collector would drop all .eh_frame sections.
@@ -552,8 +549,9 @@ MergeInputSection<ELFT>::splitNonStrings(ArrayRef<uint8_t> Data,
 
 template <class ELFT>
 MergeInputSection<ELFT>::MergeInputSection(elf::ObjectFile<ELFT> *F,
-                                           const Elf_Shdr *Header)
-    : InputSectionBase<ELFT>(F, Header, InputSectionBase<ELFT>::Merge) {}
+                                           const Elf_Shdr *Header,
+                                           StringRef Name)
+    : InputSectionBase<ELFT>(F, Header, Name, InputSectionBase<ELFT>::Merge) {}
 
 template <class ELFT> void MergeInputSection<ELFT>::splitIntoPieces() {
   ArrayRef<uint8_t> Data = this->getSectionData();
@@ -634,8 +632,10 @@ template <class ELFT> void  MergeInputSection<ELFT>::finalizePieces() {
 
 template <class ELFT>
 MipsReginfoInputSection<ELFT>::MipsReginfoInputSection(elf::ObjectFile<ELFT> *F,
-                                                       const Elf_Shdr *Hdr)
-    : InputSectionBase<ELFT>(F, Hdr, InputSectionBase<ELFT>::MipsReginfo) {
+                                                       const Elf_Shdr *Hdr,
+                                                       StringRef Name)
+    : InputSectionBase<ELFT>(F, Hdr, Name,
+                             InputSectionBase<ELFT>::MipsReginfo) {
   // Initialize this->Reginfo.
   ArrayRef<uint8_t> D = this->getSectionData();
   if (D.size() != sizeof(Elf_Mips_RegInfo<ELFT>)) {
@@ -652,8 +652,10 @@ bool MipsReginfoInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
 
 template <class ELFT>
 MipsOptionsInputSection<ELFT>::MipsOptionsInputSection(elf::ObjectFile<ELFT> *F,
-                                                       const Elf_Shdr *Hdr)
-    : InputSectionBase<ELFT>(F, Hdr, InputSectionBase<ELFT>::MipsOptions) {
+                                                       const Elf_Shdr *Hdr,
+                                                       StringRef Name)
+    : InputSectionBase<ELFT>(F, Hdr, Name,
+                             InputSectionBase<ELFT>::MipsOptions) {
   // Find ODK_REGINFO option in the section's content.
   ArrayRef<uint8_t> D = this->getSectionData();
   while (!D.empty()) {
@@ -677,8 +679,9 @@ bool MipsOptionsInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
 
 template <class ELFT>
 MipsAbiFlagsInputSection<ELFT>::MipsAbiFlagsInputSection(
-    elf::ObjectFile<ELFT> *F, const Elf_Shdr *Hdr)
-    : InputSectionBase<ELFT>(F, Hdr, InputSectionBase<ELFT>::MipsAbiFlags) {
+    elf::ObjectFile<ELFT> *F, const Elf_Shdr *Hdr, StringRef Name)
+    : InputSectionBase<ELFT>(F, Hdr, Name,
+                             InputSectionBase<ELFT>::MipsAbiFlags) {
   // Initialize this->Flags.
   ArrayRef<uint8_t> D = this->getSectionData();
   if (D.size() != sizeof(Elf_Mips_ABIFlags<ELFT>)) {
@@ -695,7 +698,7 @@ bool MipsAbiFlagsInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
 
 template <class ELFT>
 CommonInputSection<ELFT>::CommonInputSection(std::vector<DefinedCommon *> Syms)
-    : InputSection<ELFT>(nullptr, &Hdr) {
+    : InputSection<ELFT>(nullptr, &Hdr, "") {
   Hdr.sh_size = 0;
   Hdr.sh_type = SHT_NOBITS;
   Hdr.sh_flags = SHF_ALLOC | SHF_WRITE;
index 9e66c6c096b2dbadf9ff833c61b977bae7bbbaf9..f11dc67afcb9777492e2b860fa4408729dede64b 100644 (file)
@@ -42,8 +42,9 @@ public:
 
   // The garbage collector sets sections' Live bits.
   // If GC is disabled, all sections are considered live by default.
-  InputSectionData(Kind SectionKind, bool Compressed, bool Live)
-      : SectionKind(SectionKind), Live(Live), Compressed(Compressed) {}
+  InputSectionData(Kind SectionKind, StringRef Name, bool Compressed, bool Live)
+      : SectionKind(SectionKind), Live(Live), Compressed(Compressed),
+        Name(Name) {}
 
 private:
   unsigned SectionKind : 3;
@@ -58,6 +59,8 @@ public:
 
   uint32_t Alignment;
 
+  StringRef Name;
+
   // If a section is compressed, this vector has uncompressed section data.
   SmallVector<char, 0> Uncompressed;
 
@@ -79,10 +82,11 @@ protected:
   ObjectFile<ELFT> *File;
 
 public:
-  InputSectionBase() : InputSectionData(Regular, false, false), Repl(this) {}
+  InputSectionBase()
+      : InputSectionData(Regular, "", false, false), Repl(this) {}
 
   InputSectionBase(ObjectFile<ELFT> *File, const Elf_Shdr *Header,
-                   Kind SectionKind);
+                   StringRef Name, Kind SectionKind);
   OutputSectionBase<ELFT> *OutSec = nullptr;
 
   // This pointer points to the "real" instance of this instance.
@@ -97,7 +101,6 @@ public:
 
   static InputSectionBase<ELFT> Discarded;
 
-  StringRef getSectionName() const;
   const Elf_Shdr *getSectionHdr() const { return Header; }
   ObjectFile<ELFT> *getFile() const { return File; }
   uintX_t getOffset(const DefinedRegular<ELFT> &Sym) const;
@@ -145,7 +148,8 @@ template <class ELFT> class MergeInputSection : public InputSectionBase<ELFT> {
   typedef typename ELFT::Shdr Elf_Shdr;
 
 public:
-  MergeInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header);
+  MergeInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header,
+                    StringRef Name);
   static bool classof(const InputSectionBase<ELFT> *S);
   void splitIntoPieces();
 
@@ -185,7 +189,7 @@ template <class ELFT> class EhInputSection : public InputSectionBase<ELFT> {
 public:
   typedef typename ELFT::Shdr Elf_Shdr;
   typedef typename ELFT::uint uintX_t;
-  EhInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header);
+  EhInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header, StringRef Name);
   static bool classof(const InputSectionBase<ELFT> *S);
   void split();
   template <class RelTy> void split(ArrayRef<RelTy> Rels);
@@ -209,7 +213,7 @@ template <class ELFT> class InputSection : public InputSectionBase<ELFT> {
   typedef typename ELFT::uint uintX_t;
 
 public:
-  InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header);
+  InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header, StringRef Name);
 
   // Write this section to a mmap'ed file, assuming Buf is pointing to
   // beginning of the output section.
@@ -264,7 +268,8 @@ class MipsReginfoInputSection : public InputSectionBase<ELFT> {
   typedef typename ELFT::Shdr Elf_Shdr;
 
 public:
-  MipsReginfoInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Hdr);
+  MipsReginfoInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Hdr,
+                          StringRef Name);
   static bool classof(const InputSectionBase<ELFT> *S);
 
   const llvm::object::Elf_Mips_RegInfo<ELFT> *Reginfo = nullptr;
@@ -275,7 +280,8 @@ class MipsOptionsInputSection : public InputSectionBase<ELFT> {
   typedef typename ELFT::Shdr Elf_Shdr;
 
 public:
-  MipsOptionsInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Hdr);
+  MipsOptionsInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Hdr,
+                          StringRef Name);
   static bool classof(const InputSectionBase<ELFT> *S);
 
   const llvm::object::Elf_Mips_RegInfo<ELFT> *Reginfo = nullptr;
@@ -286,7 +292,8 @@ class MipsAbiFlagsInputSection : public InputSectionBase<ELFT> {
   typedef typename ELFT::Shdr Elf_Shdr;
 
 public:
-  MipsAbiFlagsInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Hdr);
+  MipsAbiFlagsInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Hdr,
+                           StringRef Name);
   static bool classof(const InputSectionBase<ELFT> *S);
 
   const llvm::object::Elf_Mips_ABIFlags<ELFT> *Flags = nullptr;
index 943a4abaff044eecf0cdb4937c9a951301d93e46..7af2a1ad7dee1253133461516ca1ad7db5c2ccd9 100644 (file)
@@ -99,7 +99,7 @@ template <class ELFT> LinkerScript<ELFT>::~LinkerScript() {}
 template <class ELFT>
 bool LinkerScript<ELFT>::shouldKeep(InputSectionBase<ELFT> *S) {
   for (Regex *Re : Opt.KeptSections)
-    if (Re->match(S->getSectionName()))
+    if (Re->match(S->Name))
       return true;
   return false;
 }
@@ -121,7 +121,7 @@ LinkerScript<ELFT>::getInputSections(const InputSectionDescription *I) {
     if (fileMatches(I, sys::path::filename(F->getName())))
       for (InputSectionBase<ELFT> *S : F->getSections())
         if (!isDiscarded(S) && !S->OutSec &&
-            const_cast<Regex &>(Re).match(S->getSectionName()))
+            const_cast<Regex &>(Re).match(S->Name))
           Ret.push_back(S);
   }
 
@@ -132,7 +132,7 @@ LinkerScript<ELFT>::getInputSections(const InputSectionDescription *I) {
 
 template <class ELFT>
 static bool compareName(InputSectionBase<ELFT> *A, InputSectionBase<ELFT> *B) {
-  return A->getSectionName() < B->getSectionName();
+  return A->Name < B->Name;
 }
 
 template <class ELFT>
index 4277b792256e8afa5659fe3303490c3143406c4f..c2316084a7343748d9f0a7a1b2c278a4a71c899b 100644 (file)
@@ -174,7 +174,7 @@ template <class ELFT> static bool isReserved(InputSectionBase<ELFT> *Sec) {
   case SHT_PREINIT_ARRAY:
     return true;
   default:
-    StringRef S = Sec->getSectionName();
+    StringRef S = Sec->Name;
 
     // We do not want to reclaim sections if they can be referred
     // by __start_* and __stop_* symbols.
index 4eda44549d9f16209fb5c52d5fff0569ed33eaa5..97ccb959bf67e4f9c0e0ad93466e6ff73cf81556 100644 (file)
@@ -931,7 +931,7 @@ template <class ELFT> void OutputSection<ELFT>::sortInitFini() {
 
   std::vector<Pair> V;
   for (InputSection<ELFT> *S : Sections)
-    V.push_back({getPriority(S->getSectionName()), S});
+    V.push_back({getPriority(S->Name), S});
   std::stable_sort(V.begin(), V.end(), Comp);
   Sections.clear();
   for (Pair &P : V)
@@ -980,8 +980,8 @@ static bool compCtors(const InputSection<ELFT> *A,
   bool EndB = isCrtend(B->getFile()->getName());
   if (EndA != EndB)
     return EndB;
-  StringRef X = A->getSectionName();
-  StringRef Y = B->getSectionName();
+  StringRef X = A->Name;
+  StringRef Y = B->Name;
   assert(X.startswith(".ctors") || X.startswith(".dtors"));
   assert(Y.startswith(".ctors") || Y.startswith(".dtors"));
   X = X.substr(6);
@@ -1032,7 +1032,7 @@ CieRecord *EhOutputSection<ELFT>::addCie(EhSectionPiece &Piece,
                                          ArrayRef<RelTy> Rels) {
   const endianness E = ELFT::TargetEndianness;
   if (read32<E>(Piece.data().data() + 4) != 0)
-    fatal("CIE expected at beginning of .eh_frame: " + Sec->getSectionName());
+    fatal("CIE expected at beginning of .eh_frame: " + Sec->Name);
 
   SymbolBody *Personality = nullptr;
   unsigned FirstRelI = Piece.FirstRelocation;
index ba583302b25de129bb8b290aafa24f7de2631702..17d3d850f04ac2108f4e906889a7d3b42fbb4432 100644 (file)
@@ -89,7 +89,7 @@ private:
 
 template <class ELFT>
 StringRef elf::getOutputSectionName(InputSectionBase<ELFT> *S) {
-  StringRef Name = S->getSectionName();
+  StringRef Name = S->Name;
   for (StringRef V : {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.",
                       ".init_array.", ".fini_array.", ".ctors.", ".dtors.",
                       ".tbss.", ".gcc_except_table.", ".tdata.", ".ARM.exidx."})
@@ -101,8 +101,8 @@ StringRef elf::getOutputSectionName(InputSectionBase<ELFT> *S) {
 template <class ELFT> void elf::reportDiscarded(InputSectionBase<ELFT> *IS) {
   if (!Config->PrintGcSections || !IS || IS->Live)
     return;
-  errs() << "removing unused section from '" << IS->getSectionName()
-         << "' in file '" << IS->getFile()->getName() << "'\n";
+  errs() << "removing unused section from '" << IS->Name << "' in file '"
+         << IS->getFile()->getName() << "'\n";
 }
 
 template <class ELFT> static bool needsInterpSection() {