Don't store an Elf_Sym for most symbols.

Our symbol representation was redundant, and some times would get out of
sync. It had an Elf_Sym, but some fields were copied to SymbolBody.

Different parts of the code were checking the bits in SymbolBody and
others were checking Elf_Sym.

There are two general approaches to fix this:
* Copy the required information and don't store and Elf_Sym.
* Don't copy the information and always use the Elf_Smy.

The second way sounds tempting, but has a big problem: we would have to
template SymbolBody. I started doing it, but it requires templeting
*everything* and creates a bit chicken and egg problem at the driver
where we have to find ELFT before we can create an ArchiveFile for
example.

As much as possible I compared the test differences with what gold and
bfd produce to make sure they are still valid. In most cases we are just
adding hidden visibility to a local symbol, which is harmless.

In most tests this is a small speedup. The only slowdown was scylla
(1.006X). The largest speedup was clang with no --build-id, -O3 or
--gc-sections (i.e.: focus on the relocations): 1.019X.

llvm-svn: 265293
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 47e7a1b..1d8fdcf 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -287,7 +287,7 @@
     return 1;
   }
 
-  if (!Body.IsTls)
+  if (!Body.isTls())
     return 0;
 
   if (Target->isTlsGlobalDynamicRel(Type)) {
@@ -403,7 +403,7 @@
       Out<ELFT>::Plt->addEntry(Body);
 
       uint32_t Rel;
-      if (Body.IsGnuIFunc)
+      if (Body.isGnuIFunc())
         Rel = Preemptible ? Target->PltRel : Target->IRelativeRel;
       else
         Rel = Target->UseLazyBinding ? Target->PltRel : Target->GotRel;
@@ -440,7 +440,7 @@
                     !Target->isSizeRel(Type);
       if (Preemptible || Dynrel) {
         uint32_t DynType;
-        if (Body.IsTls)
+        if (Body.isTls())
           DynType = Target->TlsGotRel;
         else if (Preemptible)
           DynType = Target->GotRel;
@@ -525,23 +525,17 @@
 }
 
 template <class ELFT>
-static bool shouldKeepInSymtab(const elf::ObjectFile<ELFT> &File,
-                               StringRef SymName,
-                               const typename ELFT::Sym &Sym) {
-  if (Sym.getType() == STT_FILE)
+static bool shouldKeepInSymtab(InputSectionBase<ELFT> *Sec, StringRef SymName,
+                               const SymbolBody &B) {
+  if (B.isFile())
     return false;
 
   // We keep sections in symtab for relocatable output.
-  if (Sym.getType() == STT_SECTION)
+  if (B.isSection())
     return Config->Relocatable;
 
-  // No reason to keep local undefined symbol in symtab.
-  if (Sym.st_shndx == SHN_UNDEF)
-    return false;
-
-  InputSectionBase<ELFT> *Sec = File.getSection(Sym);
   // If sym references a section in a discarded group, don't keep it.
-  if (Sec == InputSection<ELFT>::Discarded)
+  if (Sec == &InputSection<ELFT>::Discarded)
     return false;
 
   if (Config->DiscardNone)
@@ -568,18 +562,23 @@
     return;
   for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
        Symtab.getObjectFiles()) {
+    const char *StrTab = F->getStringTable().data();
     for (SymbolBody *B : F->getLocalSymbols()) {
-      const Elf_Sym &Sym = cast<DefinedRegular<ELFT>>(B)->Sym;
-      StringRef SymName = check(Sym.getName(F->getStringTable()));
-      if (!shouldKeepInSymtab<ELFT>(*F, SymName, Sym))
+      auto *DR = dyn_cast<DefinedRegular<ELFT>>(B);
+      // No reason to keep local undefined symbol in symtab.
+      if (!DR)
         continue;
-      if (Sym.st_shndx != SHN_ABS && !F->getSection(Sym)->Live)
+      StringRef SymName(StrTab + B->getNameOffset());
+      InputSectionBase<ELFT> *Sec = DR->Section;
+      if (!shouldKeepInSymtab<ELFT>(Sec, SymName, *B))
+        continue;
+      if (Sec && !Sec->Live)
         continue;
       ++Out<ELFT>::SymTab->NumLocals;
       if (Config->Relocatable)
         B->DynsymIndex = Out<ELFT>::SymTab->NumLocals;
-      F->KeptLocalSyms.push_back(std::make_pair(
-          &Sym, Out<ELFT>::SymTab->StrTabSec.addString(SymName)));
+      F->KeptLocalSyms.push_back(
+          std::make_pair(DR, Out<ELFT>::SymTab->StrTabSec.addString(SymName)));
     }
   }
 }
@@ -754,7 +753,7 @@
     uintX_t Align = getAlignment(SS);
     Off = alignTo(Off, Align);
     SS->OffsetInBss = Off;
-    Off += SS->Sym.st_size;
+    Off += SS->template getSize<ELFT>();
     MaxAlign = std::max(MaxAlign, Align);
   }
   Out<ELFT>::Bss->setSize(Off);
@@ -787,7 +786,7 @@
 
 template <class ELFT>
 bool Writer<ELFT>::isDiscarded(InputSectionBase<ELFT> *S) const {
-  return !S || S == InputSection<ELFT>::Discarded || !S->Live ||
+  return !S || S == &InputSection<ELFT>::Discarded || !S->Live ||
          Script->isDiscarded(S);
 }
 
@@ -802,12 +801,10 @@
   if (isOutputDynamic() || !Out<ELFT>::RelaPlt)
     return;
   StringRef S = Config->Rela ? "__rela_iplt_start" : "__rel_iplt_start";
-  if (Symtab.find(S))
-    Symtab.addAbsolute(S, ElfSym<ELFT>::RelaIpltStart);
+  ElfSym<ELFT>::RelaIpltStart = Symtab.addIgnored(S);
 
   S = Config->Rela ? "__rela_iplt_end" : "__rel_iplt_end";
-  if (Symtab.find(S))
-    Symtab.addAbsolute(S, ElfSym<ELFT>::RelaIpltEnd);
+  ElfSym<ELFT>::RelaIpltEnd = Symtab.addIgnored(S);
 }
 
 template <class ELFT> static bool includeInSymtab(const SymbolBody &B) {
@@ -815,9 +812,6 @@
     return false;
 
   if (auto *D = dyn_cast<DefinedRegular<ELFT>>(&B)) {
-    // Don't include synthetic symbols like __init_array_start in every output.
-    if (&D->Sym == &ElfSym<ELFT>::Ignored)
-      return false;
     // Exclude symbols pointing to garbage-collected sections.
     if (D->Section && !D->Section->Live)
       return false;
@@ -922,6 +916,32 @@
 // The linker is expected to define some symbols depending on
 // the linking result. This function defines such symbols.
 template <class ELFT> void Writer<ELFT>::addReservedSymbols() {
+  if (Config->EMachine == EM_MIPS) {
+    // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
+    // start of function and 'gp' pointer into GOT.
+    Config->MipsGpDisp = Symtab.addIgnored("_gp_disp");
+    // The __gnu_local_gp is a magic symbol equal to the current value of 'gp'
+    // pointer. This symbol is used in the code generated by .cpload pseudo-op
+    // in case of using -mno-shared option.
+    // https://sourceware.org/ml/binutils/2004-12/msg00094.html
+    Config->MipsLocalGp = Symtab.addIgnored("__gnu_local_gp");
+  }
+
+  // In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol
+  // is magical and is used to produce a R_386_GOTPC relocation.
+  // The R_386_GOTPC relocation value doesn't actually depend on the
+  // symbol value, so it could use an index of STN_UNDEF which, according
+  // to the spec, means the symbol value is 0.
+  // Unfortunately both gas and MC keep the _GLOBAL_OFFSET_TABLE_ symbol in
+  // the object file.
+  // The situation is even stranger on x86_64 where the assembly doesn't
+  // need the magical symbol, but gas still puts _GLOBAL_OFFSET_TABLE_ as
+  // an undefined symbol in the .o files.
+  // Given that the symbol is effectively unused, we just create a dummy
+  // hidden one to avoid the undefined symbol error.
+  if (!Config->Relocatable)
+    Symtab.addIgnored("_GLOBAL_OFFSET_TABLE_");
+
   // __tls_get_addr is defined by the dynamic linker for dynamic ELFs. For
   // static linking the linker is required to optimize away any references to
   // __tls_get_addr, so it's not defined anywhere. Create a hidden definition
@@ -929,9 +949,9 @@
   if (!isOutputDynamic())
     Symtab.addIgnored("__tls_get_addr");
 
-  auto Define = [this](StringRef S, Elf_Sym &Sym) {
-    if (Symtab.find(S))
-      Symtab.addAbsolute(S, Sym);
+  auto Define = [this](StringRef S, DefinedRegular<ELFT> *&Sym,
+                       DefinedRegular<ELFT> *&Sym2) {
+    Sym = Symtab.addIgnored(S, STV_DEFAULT);
 
     // The name without the underscore is not a reserved name,
     // so it is defined only when there is a reference against it.
@@ -939,12 +959,12 @@
     S = S.substr(1);
     if (SymbolBody *B = Symtab.find(S))
       if (B->isUndefined())
-        Symtab.addAbsolute(S, Sym);
+        Sym2 = Symtab.addAbsolute(S, STV_DEFAULT);
   };
 
-  Define("_end", ElfSym<ELFT>::End);
-  Define("_etext", ElfSym<ELFT>::Etext);
-  Define("_edata", ElfSym<ELFT>::Edata);
+  Define("_end", ElfSym<ELFT>::End, ElfSym<ELFT>::End2);
+  Define("_etext", ElfSym<ELFT>::Etext, ElfSym<ELFT>::Etext2);
+  Define("_edata", ElfSym<ELFT>::Edata, ElfSym<ELFT>::Edata2);
 }
 
 // Sort input sections by section name suffixes for
@@ -1467,13 +1487,15 @@
   // to beginning or ending of .rela.plt section, respectively.
   if (Out<ELFT>::RelaPlt) {
     uintX_t Start = Out<ELFT>::RelaPlt->getVA();
-    ElfSym<ELFT>::RelaIpltStart.st_value = Start;
-    ElfSym<ELFT>::RelaIpltEnd.st_value = Start + Out<ELFT>::RelaPlt->getSize();
+    if (ElfSym<ELFT>::RelaIpltStart)
+      ElfSym<ELFT>::RelaIpltStart->Value = Start;
+    if (ElfSym<ELFT>::RelaIpltEnd)
+      ElfSym<ELFT>::RelaIpltEnd->Value = Start + Out<ELFT>::RelaPlt->getSize();
   }
 
   // Update MIPS _gp absolute symbol so that it points to the static data.
   if (Config->EMachine == EM_MIPS)
-    ElfSym<ELFT>::MipsGp.st_value = getMipsGpAddr<ELFT>();
+    ElfSym<ELFT>::MipsGp->Value = getMipsGpAddr<ELFT>();
 
   // _etext is the first location after the last read-only loadable segment.
   // _edata is the first location after the last read-write loadable segment.
@@ -1482,12 +1504,24 @@
     Elf_Phdr &H = P.H;
     if (H.p_type != PT_LOAD)
       continue;
-    ElfSym<ELFT>::End.st_value = H.p_vaddr + H.p_memsz;
-    uintX_t Val = H.p_vaddr + H.p_filesz;
-    if (H.p_flags & PF_W)
-      ElfSym<ELFT>::Edata.st_value = Val;
-    else
-      ElfSym<ELFT>::Etext.st_value = Val;
+    uintX_t Val = H.p_vaddr + H.p_memsz;
+    if (ElfSym<ELFT>::End)
+      ElfSym<ELFT>::End->Value = Val;
+    if (ElfSym<ELFT>::End2)
+      ElfSym<ELFT>::End2->Value = Val;
+
+    Val = H.p_vaddr + H.p_filesz;
+    if (H.p_flags & PF_W) {
+      if (ElfSym<ELFT>::Edata)
+        ElfSym<ELFT>::Edata->Value = Val;
+      if (ElfSym<ELFT>::Edata2)
+        ElfSym<ELFT>::Edata2->Value = Val;
+    } else {
+      if (ElfSym<ELFT>::Etext)
+        ElfSym<ELFT>::Etext->Value = Val;
+      if (ElfSym<ELFT>::Etext2)
+        ElfSym<ELFT>::Etext2->Value = Val;
+    }
   }
 }