wip patch: Create SymbolBody for all symbols

Rafael EspĂ­ndola via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 9 15:21:12 PST 2016


llvm.org/pr26878 has a case where we need to put a local symbol in the
got. Given that we have to allocate something to remember the got
index.

One way to do it is to create SymbolBodies. The attached patch does it
an has the potential of further simplifications.

Unfortunately with it I am seeing a 1.09X slowdown when linking clang.
The link line has --export-dynamic -O3 --gc-sections.

Cheers,
Rafael
-------------- next part --------------
diff --git a/ELF/ICF.cpp b/ELF/ICF.cpp
index bef5277..7fad3df 100644
--- a/ELF/ICF.cpp
+++ b/ELF/ICF.cpp
@@ -93,7 +93,7 @@ private:
   static uint64_t getHash(InputSection<ELFT> *S);
   static bool isEligible(InputSectionBase<ELFT> *Sec);
   static std::vector<InputSection<ELFT> *> getSections(SymbolTable<ELFT> *S);
-  static SymbolBody *getSymbol(const InputSection<ELFT> *Sec,
+  static SymbolBody &getSymbol(const InputSection<ELFT> *Sec,
                                const Elf_Rel *Rel);
 
   void segregate(InputSection<ELFT> **Begin, InputSection<ELFT> **End,
@@ -161,10 +161,10 @@ ICF<ELFT>::getSections(SymbolTable<ELFT> *Symtab) {
 }
 
 template <class ELFT>
-SymbolBody *ICF<ELFT>::getSymbol(const InputSection<ELFT> *Sec,
+SymbolBody &ICF<ELFT>::getSymbol(const InputSection<ELFT> *Sec,
                                  const Elf_Rel *Rel) {
   uint32_t SymIdx = Rel->getSymbol(Config->Mips64EL);
-  return Sec->File->getSymbolBody(SymIdx);
+  return Sec->File->getSymbolBody(SymIdx).repl();
 }
 
 // All sections between Begin and End must have the same group ID before
@@ -259,26 +259,15 @@ bool ICF<ELFT>::variableEq(const InputSection<ELFT> *A,
   const RelTy *EA = RelsA.end();
   const RelTy *IB = RelsB.begin();
   for (; IA != EA; ++IA, ++IB) {
-    // If both IA and IB are pointing to the same local symbol,
-    // this "if" condition must be true.
-    if (A->File == B->File &&
-        IA->getSymbol(Config->Mips64EL) == IB->getSymbol(Config->Mips64EL))
-      continue;
-
-    // Otherwise, IA and IB must be pointing to the global symbols.
-    SymbolBody *SA = getSymbol(A, (const Elf_Rel *)IA);
-    SymbolBody *SB = getSymbol(B, (const Elf_Rel *)IB);
-    if (!SA || !SB)
-      return false;
-
-    // The global symbols should be simply the same.
-    if (SA->repl() == SB->repl())
+    SymbolBody &SA = getSymbol(A, (const Elf_Rel *)IA);
+    SymbolBody &SB = getSymbol(B, (const Elf_Rel *)IB);
+    if (&SA == &SB)
       continue;
 
     // Or, the symbols should be pointing to the same section
     // in terms of the group ID.
-    auto *DA = dyn_cast<DefinedRegular<ELFT>>(SA->repl());
-    auto *DB = dyn_cast<DefinedRegular<ELFT>>(SB->repl());
+    auto *DA = dyn_cast<DefinedRegular<ELFT>>(&SA);
+    auto *DB = dyn_cast<DefinedRegular<ELFT>>(&SB);
     if (!DA || !DB)
       return false;
     if (DA->Sym.st_value != DB->Sym.st_value)
diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp
index ee5c691..b6ebb80 100644
--- a/ELF/InputFiles.cpp
+++ b/ELF/InputFiles.cpp
@@ -46,7 +46,7 @@ ELFKind ELFFileBase<ELFT>::getELFKind() {
 
 template <class ELFT>
 typename ELFFileBase<ELFT>::Elf_Sym_Range
-ELFFileBase<ELFT>::getSymbolsHelper(bool Local) {
+ELFFileBase<ELFT>::getElfSymbols(bool OnlyGlobals) {
   if (!Symtab)
     return Elf_Sym_Range(nullptr, nullptr);
   Elf_Sym_Range Syms = ELFObj.symbols(Symtab);
@@ -54,10 +54,10 @@ ELFFileBase<ELFT>::getSymbolsHelper(bool Local) {
   uint32_t FirstNonLocal = Symtab->sh_info;
   if (FirstNonLocal > NumSymbols)
     fatal("Invalid sh_info in symbol table");
-  if (!Local)
+
+  if (OnlyGlobals)
     return make_range(Syms.begin() + FirstNonLocal, Syms.end());
-  // +1 to skip over dummy symbol.
-  return make_range(Syms.begin() + 1, Syms.begin() + FirstNonLocal);
+  return make_range(Syms.begin(), Syms.end());
 }
 
 template <class ELFT>
@@ -77,19 +77,30 @@ template <class ELFT> void ELFFileBase<ELFT>::initStringTable() {
 }
 
 template <class ELFT>
-typename ELFFileBase<ELFT>::Elf_Sym_Range
-ELFFileBase<ELFT>::getNonLocalSymbols() {
-  return getSymbolsHelper(false);
+elf::ObjectFile<ELFT>::ObjectFile(MemoryBufferRef M)
+    : ELFFileBase<ELFT>(Base::ObjectKind, M) {}
+
+template <class ELFT>
+ArrayRef<SymbolBody *> elf::ObjectFile<ELFT>::getNonLocalSymbolBodies() {
+  if (!this->Symtab)
+    return this->SymbolBodies;
+  uint32_t FirstNonLocal = this->Symtab->sh_info;
+  return makeArrayRef(this->SymbolBodies).slice(FirstNonLocal);
 }
 
 template <class ELFT>
-elf::ObjectFile<ELFT>::ObjectFile(MemoryBufferRef M)
-    : ELFFileBase<ELFT>(Base::ObjectKind, M) {}
+ArrayRef<SymbolBody *> elf::ObjectFile<ELFT>::getLocalSymbolBodies() {
+  if (!this->Symtab)
+    return this->SymbolBodies;
+  uint32_t FirstNonLocal = this->Symtab->sh_info;
+  return makeArrayRef(this->SymbolBodies).slice(1, FirstNonLocal - 1);
+}
 
 template <class ELFT>
-typename elf::ObjectFile<ELFT>::Elf_Sym_Range
-elf::ObjectFile<ELFT>::getLocalSymbols() {
-  return this->getSymbolsHelper(true);
+ArrayRef<SymbolBody *> elf::ObjectFile<ELFT>::getSymbols() {
+  if (!this->Symtab)
+    return this->SymbolBodies;
+  return makeArrayRef(this->SymbolBodies).slice(1);
 }
 
 template <class ELFT> uint32_t elf::ObjectFile<ELFT>::getMipsGp0() const {
@@ -99,16 +110,6 @@ template <class ELFT> uint32_t elf::ObjectFile<ELFT>::getMipsGp0() const {
 }
 
 template <class ELFT>
-const typename elf::ObjectFile<ELFT>::Elf_Sym *
-elf::ObjectFile<ELFT>::getLocalSymbol(uintX_t SymIndex) {
-  uint32_t FirstNonLocal = this->Symtab->sh_info;
-  if (SymIndex >= FirstNonLocal)
-    return nullptr;
-  Elf_Sym_Range Syms = this->ELFObj.symbols(this->Symtab);
-  return Syms.begin() + SymIndex;
-}
-
-template <class ELFT>
 void elf::ObjectFile<ELFT>::parse(DenseSet<StringRef> &ComdatGroups) {
   // Read section and symbol tables.
   initializeSections(ComdatGroups);
@@ -266,7 +267,7 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
 
 template <class ELFT> void elf::ObjectFile<ELFT>::initializeSymbols() {
   this->initStringTable();
-  Elf_Sym_Range Syms = this->getNonLocalSymbols();
+  Elf_Sym_Range Syms = this->getElfSymbols(false);
   uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
   SymbolBodies.reserve(NumSymbols);
   for (const Elf_Sym &Sym : Syms)
@@ -289,6 +290,10 @@ elf::ObjectFile<ELFT>::getSection(const Elf_Sym &Sym) const {
 
 template <class ELFT>
 SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
+  unsigned char Binding = Sym->getBinding();
+  if (Binding == STB_LOCAL)
+    return new (Alloc) LocalSymbol<ELFT>(*Sym);
+
   StringRef Name = check(Sym->getName(this->StringTable));
 
   switch (Sym->st_shndx) {
@@ -300,7 +305,7 @@ SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
                                      Sym->getVisibility());
   }
 
-  switch (Sym->getBinding()) {
+  switch (Binding) {
   default:
     fatal("unexpected binding");
   case STB_GLOBAL:
@@ -399,7 +404,7 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() {
 
 // Fully parse the shared object file. This must be called after parseSoName().
 template <class ELFT> void SharedFile<ELFT>::parseRest() {
-  Elf_Sym_Range Syms = this->getNonLocalSymbols();
+  Elf_Sym_Range Syms = this->getElfSymbols(true);
   uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
   SymbolBodies.reserve(NumSymbols);
   for (const Elf_Sym &Sym : Syms) {
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
index 48fe27d..4b3aa88 100644
--- a/ELF/InputFiles.h
+++ b/ELF/InputFiles.h
@@ -84,8 +84,7 @@ protected:
   ArrayRef<Elf_Word> SymtabSHNDX;
   StringRef StringTable;
   void initStringTable();
-  Elf_Sym_Range getNonLocalSymbols();
-  Elf_Sym_Range getSymbolsHelper(bool);
+  Elf_Sym_Range getElfSymbols(bool OnlyGlobals);
 };
 
 // .o file.
@@ -110,7 +109,9 @@ public:
     return F->kind() == Base::ObjectKind;
   }
 
-  ArrayRef<SymbolBody *> getSymbols() { return SymbolBodies; }
+  ArrayRef<SymbolBody *> getSymbols();
+  ArrayRef<SymbolBody *> getLocalSymbolBodies();
+  ArrayRef<SymbolBody *> getNonLocalSymbolBodies();
 
   explicit ObjectFile(MemoryBufferRef M);
   void parse(llvm::DenseSet<StringRef> &ComdatGroups);
@@ -118,16 +119,10 @@ public:
   ArrayRef<InputSectionBase<ELFT> *> getSections() const { return Sections; }
   InputSectionBase<ELFT> *getSection(const Elf_Sym &Sym) const;
 
-  SymbolBody *getSymbolBody(uint32_t SymbolIndex) const {
-    uint32_t FirstNonLocal = this->Symtab->sh_info;
-    if (SymbolIndex < FirstNonLocal)
-      return nullptr;
-    return SymbolBodies[SymbolIndex - FirstNonLocal];
+  SymbolBody &getSymbolBody(uint32_t SymbolIndex) const {
+    return *SymbolBodies[SymbolIndex];
   }
 
-  Elf_Sym_Range getLocalSymbols();
-  const Elf_Sym *getLocalSymbol(uintX_t SymIndex);
-
   const Elf_Shdr *getSymbolTable() const { return this->Symtab; };
 
   // Get MIPS GP0 value defined by this file. This value represents the gp value
diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp
index 08424b2..726914d 100644
--- a/ELF/InputSection.cpp
+++ b/ELF/InputSection.cpp
@@ -77,12 +77,11 @@ InputSectionBase<ELFT> *
 InputSectionBase<ELFT>::getRelocTarget(const Elf_Rel &Rel) const {
   // Global symbol
   uint32_t SymIndex = Rel.getSymbol(Config->Mips64EL);
-  if (SymbolBody *B = File->getSymbolBody(SymIndex))
-    if (auto *D = dyn_cast<DefinedRegular<ELFT>>(B->repl()))
-      return D->Section->Repl;
-  // Local symbol
-  if (const Elf_Sym *Sym = File->getLocalSymbol(SymIndex))
-    if (InputSectionBase<ELFT> *Sec = File->getSection(*Sym))
+  SymbolBody &B = File->getSymbolBody(SymIndex).repl();
+  if (auto *D = dyn_cast<DefinedRegular<ELFT>>(&B))
+    return D->Section->Repl;
+  if (auto *L = dyn_cast<LocalSymbol<ELFT>>(&B))
+    if (InputSectionBase<ELFT> *Sec = File->getSection(L->Sym))
       return Sec;
   return nullptr;
 }
@@ -122,24 +121,13 @@ void InputSection<ELFT>::copyRelocations(uint8_t *Buf,
   for (const RelType &Rel : Rels) {
     uint32_t SymIndex = Rel.getSymbol(Config->Mips64EL);
     uint32_t Type = Rel.getType(Config->Mips64EL);
-    const Elf_Shdr *SymTab = this->File->getSymbolTable();
+    SymbolBody &Body = this->File->getSymbolBody(SymIndex).repl();
 
     RelType *P = reinterpret_cast<RelType *>(Buf);
     Buf += sizeof(RelType);
 
-    // Relocation against local symbol here means that it is probably
-    // rel[a].eh_frame section which has references to sections in r_info field.
-    if (SymIndex < SymTab->sh_info) {
-      const Elf_Sym *Sym = this->File->getLocalSymbol(SymIndex);
-      uint32_t Idx = Out<ELFT>::SymTab->Locals[Sym];
-      P->r_offset = RelocatedSection->getOffset(Rel.r_offset);
-      P->setSymbolAndType(Idx, Type, Config->Mips64EL);
-      continue;
-    }
-
-    SymbolBody *Body = this->File->getSymbolBody(SymIndex)->repl();
     P->r_offset = RelocatedSection->getOffset(Rel.r_offset);
-    P->setSymbolAndType(Body->DynsymIndex, Type, Config->Mips64EL);
+    P->setSymbolAndType(Body.DynsymIndex, Type, Config->Mips64EL);
   }
 }
 
@@ -209,19 +197,16 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
       continue;
     }
 
-    const Elf_Shdr *SymTab = File->getSymbolTable();
-    SymbolBody *Body = nullptr;
-    if (SymIndex >= SymTab->sh_info)
-      Body = File->getSymbolBody(SymIndex)->repl();
+    SymbolBody &Body = File->getSymbolBody(SymIndex).repl();
 
-    if (Target->canRelaxTls(Type, Body)) {
+    if (Target->canRelaxTls(Type, &Body)) {
       uintX_t SymVA;
-      if (!Body)
+      if (Body.isLocal())
         SymVA = getLocalRelTarget(*File, RI, 0);
-      else if (Target->needsGot(Type, *Body))
-        SymVA = Body->getGotVA<ELFT>();
+      else if (Target->needsGot(Type, Body))
+        SymVA = Body.getGotVA<ELFT>();
       else
-        SymVA = Body->getVA<ELFT>();
+        SymVA = Body.getVA<ELFT>();
       // By optimizing TLS relocations, it is sometimes needed to skip
       // relocations that immediately follow TLS relocations. This function
       // knows how many slots we need to skip.
@@ -232,7 +217,7 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
     // Handle relocations for local symbols -- they never get
     // resolved so we don't allocate a SymbolBody.
     uintX_t A = getAddend<ELFT>(RI);
-    if (!Body) {
+    if (Body.isLocal()) {
       uintX_t SymVA = getLocalRelTarget(*File, RI, A);
       uint8_t *PairedLoc = nullptr;
       if (Config->EMachine == EM_MIPS) {
@@ -263,26 +248,26 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
     }
 
     if (Target->isTlsGlobalDynamicRel(Type) &&
-        !Target->canRelaxTls(Type, Body)) {
+        !Target->canRelaxTls(Type, &Body)) {
       Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc,
-                          Out<ELFT>::Got->getGlobalDynAddr(*Body) +
+                          Out<ELFT>::Got->getGlobalDynAddr(Body) +
                               getAddend<ELFT>(RI));
       continue;
     }
 
-    uintX_t SymVA = Body->getVA<ELFT>();
+    uintX_t SymVA = Body.getVA<ELFT>();
     bool CBP = canBePreempted(Body);
-    if (Target->needsPlt<ELFT>(Type, *Body)) {
-      SymVA = Body->getPltVA<ELFT>();
-    } else if (Target->needsGot(Type, *Body)) {
+    if (Target->needsPlt<ELFT>(Type, Body)) {
+      SymVA = Body.getPltVA<ELFT>();
+    } else if (Target->needsGot(Type, Body)) {
       if (Config->EMachine == EM_MIPS && !CBP)
         // Under some conditions relocations against non-local symbols require
         // entries in the local part of MIPS GOT. In that case we need an entry
         // initialized by full address of the symbol.
-        SymVA = Out<ELFT>::Got->getMipsLocalFullAddr(*Body);
+        SymVA = Out<ELFT>::Got->getMipsLocalFullAddr(Body);
       else
-        SymVA = Body->getGotVA<ELFT>();
-      if (Body->IsTls)
+        SymVA = Body.getGotVA<ELFT>();
+      if (Body.IsTls)
         Type = Target->getTlsGotRel(Type);
     } else if (Target->isSizeRel(Type) && CBP) {
       // A SIZE relocation is supposed to set a symbol size, but if a symbol
@@ -291,16 +276,16 @@ void InputSectionBase<ELFT>::relocate(uint8_t *Buf, uint8_t *BufEnd,
       // with a possibly incorrect value.
       continue;
     } else if (Config->EMachine == EM_MIPS) {
-      if (Type == R_MIPS_HI16 && Body == Config->MipsGpDisp)
+      if (Type == R_MIPS_HI16 && &Body == Config->MipsGpDisp)
         SymVA = getMipsGpAddr<ELFT>() - AddrLoc;
-      else if (Type == R_MIPS_LO16 && Body == Config->MipsGpDisp)
+      else if (Type == R_MIPS_LO16 && &Body == Config->MipsGpDisp)
         SymVA = getMipsGpAddr<ELFT>() - AddrLoc + 4;
-      else if (Body == Config->MipsLocalGp)
+      else if (&Body == Config->MipsLocalGp)
         SymVA = getMipsGpAddr<ELFT>();
-    } else if (!Target->needsCopyRel<ELFT>(Type, *Body) && CBP) {
+    } else if (!Target->needsCopyRel<ELFT>(Type, Body) && CBP) {
       continue;
     }
-    uintX_t Size = Body->getSize<ELFT>();
+    uintX_t Size = Body.getSize<ELFT>();
     Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc, SymVA + A, Size + A,
                         findMipsPairedReloc(Buf, SymIndex,
                                             getMipsPairedRelocType(Type),
diff --git a/ELF/MarkLive.cpp b/ELF/MarkLive.cpp
index 40bcee5..0afb707 100644
--- a/ELF/MarkLive.cpp
+++ b/ELF/MarkLive.cpp
@@ -99,7 +99,7 @@ template <class ELFT> void elf::markLive(SymbolTable<ELFT> *Symtab) {
 
   auto MarkSymbol = [&](SymbolBody *Sym) {
     if (Sym)
-      if (auto *D = dyn_cast<DefinedRegular<ELFT>>(Sym->repl()))
+      if (auto *D = dyn_cast<DefinedRegular<ELFT>>(&Sym->repl()))
         Enqueue(D->Section);
   };
 
diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp
index 1e83fc6..46e7e25 100644
--- a/ELF/OutputSections.cpp
+++ b/ELF/OutputSections.cpp
@@ -52,9 +52,9 @@ GotPltSection<ELFT>::GotPltSection()
   this->Header.sh_addralign = sizeof(uintX_t);
 }
 
-template <class ELFT> void GotPltSection<ELFT>::addEntry(SymbolBody *Sym) {
-  Sym->GotPltIndex = Target->GotPltHeaderEntriesNum + Entries.size();
-  Entries.push_back(Sym);
+template <class ELFT> void GotPltSection<ELFT>::addEntry(SymbolBody &Sym) {
+  Sym.GotPltIndex = Target->GotPltHeaderEntriesNum + Entries.size();
+  Entries.push_back(&Sym);
 }
 
 template <class ELFT> bool GotPltSection<ELFT>::empty() const {
@@ -83,21 +83,21 @@ GotSection<ELFT>::GotSection()
   this->Header.sh_addralign = sizeof(uintX_t);
 }
 
-template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody *Sym) {
-  Sym->GotIndex = Entries.size();
-  Entries.push_back(Sym);
+template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody &Sym) {
+  Sym.GotIndex = Entries.size();
+  Entries.push_back(&Sym);
 }
 
 template <class ELFT> void GotSection<ELFT>::addMipsLocalEntry() {
   ++MipsLocalEntries;
 }
 
-template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody *Sym) {
-  if (Sym->hasGlobalDynIndex())
+template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) {
+  if (Sym.hasGlobalDynIndex())
     return false;
-  Sym->GlobalDynIndex = Target->GotHeaderEntriesNum + Entries.size();
+  Sym.GlobalDynIndex = Target->GotHeaderEntriesNum + Entries.size();
   // Global Dynamic TLS entries take two GOT slots.
-  Entries.push_back(Sym);
+  Entries.push_back(&Sym);
   Entries.push_back(nullptr);
   return true;
 }
@@ -176,7 +176,7 @@ template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
     // for detailed description:
     // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
     // As the first approach, we can just store addresses for all symbols.
-    if (Config->EMachine != EM_MIPS && canBePreempted(B))
+    if (Config->EMachine != EM_MIPS && canBePreempted(*B))
       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);
@@ -208,12 +208,12 @@ template <class ELFT> void PltSection<ELFT>::writeTo(uint8_t *Buf) {
   }
 }
 
-template <class ELFT> void PltSection<ELFT>::addEntry(SymbolBody *Sym) {
-  Sym->PltIndex = Entries.size();
+template <class ELFT> void PltSection<ELFT>::addEntry(SymbolBody &Sym) {
+  Sym.PltIndex = Entries.size();
   unsigned RelOff = Target->UseLazyBinding
                         ? Out<ELFT>::RelaPlt->getRelocOffset()
                         : Out<ELFT>::RelaDyn->getRelocOffset();
-  Entries.push_back(std::make_pair(Sym, RelOff));
+  Entries.push_back(std::make_pair(&Sym, RelOff));
 }
 
 template <class ELFT> void PltSection<ELFT>::finalize() {
@@ -932,14 +932,15 @@ elf::getLocalRelTarget(const ObjectFile<ELFT> &File,
 
 // Returns true if a symbol can be replaced at load-time by a symbol
 // with the same name defined in other ELF executable or DSO.
-bool elf::canBePreempted(const SymbolBody *Body) {
-  if (!Body)
-    return false;  // Body is a local symbol.
-  if (Body->isShared())
+bool elf::canBePreempted(const SymbolBody &Body) {
+  if (Body.isLocal())
+    return false;
+
+  if (Body.isShared())
     return true;
 
-  if (Body->isUndefined()) {
-    if (!Body->isWeak())
+  if (Body.isUndefined()) {
+    if (!Body.isWeak())
       return true;
 
     // Ideally the static linker should see a definition for every symbol, but
@@ -953,9 +954,9 @@ bool elf::canBePreempted(const SymbolBody *Body) {
   }
   if (!Config->Shared)
     return false;
-  if (Body->getVisibility() != STV_DEFAULT)
+  if (Body.getVisibility() != STV_DEFAULT)
     return false;
-  if (Config->Bsymbolic || (Config->BsymbolicFunctions && Body->IsFunc))
+  if (Config->Bsymbolic || (Config->BsymbolicFunctions && Body.IsFunc))
     return false;
   return true;
 }
@@ -1168,7 +1169,7 @@ void EHOutputSection<ELFT>::addSectionAux(
       SymbolBody *Personality = nullptr;
       if (HasReloc) {
         uint32_t SymIndex = RelI->getSymbol(Config->Mips64EL);
-        Personality = S->getFile()->getSymbolBody(SymIndex)->repl();
+        Personality = &S->getFile()->getSymbolBody(SymIndex).repl();
       }
 
       std::pair<StringRef, SymbolBody *> CieInfo(Entry, Personality);
@@ -1532,9 +1533,9 @@ SymbolTableSection<ELFT>::getOutputSection(SymbolBody *Sym) {
   case SymbolBody::DefinedSyntheticKind:
     return &cast<DefinedSynthetic<ELFT>>(Sym)->Section;
   case SymbolBody::DefinedRegularKind: {
-    auto *D = cast<DefinedRegular<ELFT>>(Sym->repl());
-    if (D->Section)
-      return D->Section->OutSec;
+    auto &D = cast<DefinedRegular<ELFT>>(Sym->repl());
+    if (D.Section)
+      return D.Section->OutSec;
     break;
   }
   case SymbolBody::DefinedCommonKind:
@@ -1549,6 +1550,8 @@ SymbolTableSection<ELFT>::getOutputSection(SymbolBody *Sym) {
     break;
   case SymbolBody::DefinedBitcodeKind:
     llvm_unreachable("Should have been replaced");
+  case SymbolBody::DefinedLocalKind:
+    llvm_unreachable("Should not be used");
   }
   return nullptr;
 }
diff --git a/ELF/OutputSections.h b/ELF/OutputSections.h
index 6810352..1e840d1 100644
--- a/ELF/OutputSections.h
+++ b/ELF/OutputSections.h
@@ -53,7 +53,7 @@ getLocalRelTarget(const ObjectFile<ELFT> &File,
                   const llvm::object::Elf_Rel_Impl<ELFT, IsRela> &Rel,
                   typename llvm::object::ELFFile<ELFT>::uintX_t Addend);
 
-bool canBePreempted(const SymbolBody *Body);
+bool canBePreempted(const SymbolBody &Body);
 
 bool isValidCIdentifier(StringRef S);
 
@@ -112,9 +112,9 @@ public:
   GotSection();
   void finalize() override;
   void writeTo(uint8_t *Buf) override;
-  void addEntry(SymbolBody *Sym);
+  void addEntry(SymbolBody &Sym);
   void addMipsLocalEntry();
-  bool addDynTlsEntry(SymbolBody *Sym);
+  bool addDynTlsEntry(SymbolBody &Sym);
   bool addTlsIndex();
   bool empty() const { return MipsLocalEntries == 0 && Entries.empty(); }
   uintX_t getMipsLocalFullAddr(const SymbolBody &B);
@@ -151,7 +151,7 @@ public:
   GotPltSection();
   void finalize() override;
   void writeTo(uint8_t *Buf) override;
-  void addEntry(SymbolBody *Sym);
+  void addEntry(SymbolBody &Sym);
   bool empty() const;
 
 private:
@@ -166,7 +166,7 @@ public:
   PltSection();
   void finalize() override;
   void writeTo(uint8_t *Buf) override;
-  void addEntry(SymbolBody *Sym);
+  void addEntry(SymbolBody &Sym);
   bool empty() const { return Entries.empty(); }
 
 private:
@@ -241,9 +241,6 @@ public:
   unsigned NumLocals = 0;
   StringTableSection<ELFT> &StrTabSec;
 
-  // Local symbol -> ID, filled only when producing relocatable output.
-  llvm::DenseMap<const Elf_Sym *, uint32_t> Locals;
-
 private:
   void writeLocalSymbols(uint8_t *&Buf);
   void writeGlobalSymbols(uint8_t *Buf);
diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp
index 9334f21..8951fa7 100644
--- a/ELF/SymbolTable.cpp
+++ b/ELF/SymbolTable.cpp
@@ -92,7 +92,7 @@ void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
   auto *F = cast<ObjectFile<ELFT>>(FileP);
   ObjectFiles.emplace_back(cast<ObjectFile<ELFT>>(File.release()));
   F->parse(ComdatGroups);
-  for (SymbolBody *B : F->getSymbols())
+  for (SymbolBody *B : F->getNonLocalSymbolBodies())
     resolve(B);
 }
 
@@ -135,7 +135,7 @@ static void addBitcodeFile(IRMover &Mover, BitcodeFile &F,
                                  /*ShouldLazyLoadMetadata*/ false));
   std::vector<GlobalValue *> Keep;
   for (SymbolBody *B : F.getSymbols()) {
-    if (B->repl() != B)
+    if (&B->repl() != B)
       continue;
     auto *DB = dyn_cast<DefinedBitcode>(B);
     if (!DB)
@@ -178,7 +178,7 @@ template <class ELFT> void SymbolTable<ELFT>::addCombinedLtoObject() {
   ObjectFile<ELFT> *Obj = createCombinedLtoObject();
   llvm::DenseSet<StringRef> DummyGroups;
   Obj->parse(DummyGroups);
-  for (SymbolBody *Body : Obj->getSymbols()) {
+  for (SymbolBody *Body : Obj->getNonLocalSymbolBodies()) {
     Symbol *Sym = insert(Body);
     if (!Sym->Body->isUndefined() && Body->isUndefined())
       continue;
diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp
index 51ab667..6f85e33 100644
--- a/ELF/Symbols.cpp
+++ b/ELF/Symbols.cpp
@@ -68,6 +68,8 @@ typename ELFFile<ELFT>::uintX_t SymbolBody::getVA() const {
     return 0;
   case DefinedBitcodeKind:
     llvm_unreachable("Should have been replaced");
+  case DefinedLocalKind:
+    llvm_unreachable("Should not be used");
   }
   llvm_unreachable("Invalid symbol kind");
 }
diff --git a/ELF/Symbols.h b/ELF/Symbols.h
index b0b0faa..d4569eb 100644
--- a/ELF/Symbols.h
+++ b/ELF/Symbols.h
@@ -63,7 +63,8 @@ public:
     DefinedFirst,
     DefinedRegularKind = DefinedFirst,
     SharedKind,
-    DefinedElfLast = SharedKind,
+    DefinedLocalKind,
+    DefinedElfLast = DefinedLocalKind,
     DefinedCommonKind,
     DefinedBitcodeKind,
     DefinedSyntheticKind,
@@ -83,6 +84,7 @@ public:
   bool isCommon() const { return SymbolKind == DefinedCommonKind; }
   bool isLazy() const { return SymbolKind == LazyKind; }
   bool isShared() const { return SymbolKind == SharedKind; }
+  bool isLocal() const { return SymbolKind == DefinedLocalKind; }
   bool isUsedInRegularObj() const { return IsUsedInRegularObj; }
 
   // Returns the symbol name.
@@ -117,7 +119,7 @@ public:
   // has chosen the object among other objects having the same name,
   // you can access P->Backref->Body to get the resolver's result.
   void setBackref(Symbol *P) { Backref = P; }
-  SymbolBody *repl() { return Backref ? Backref->Body : this; }
+  SymbolBody &repl() { return Backref ? *Backref->Body : *this; }
   Symbol *getSymbol() { return Backref; }
 
   // Decides which symbol should "win" in the symbol table, this or
@@ -308,6 +310,18 @@ public:
   bool needsCopy() const { return this->NeedsCopyOrPltAddr && !this->IsFunc; }
 };
 
+template <class ELFT> class LocalSymbol : public DefinedElf<ELFT> {
+  typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+
+public:
+  LocalSymbol(const Elf_Sym &Sym)
+      : DefinedElf<ELFT>(SymbolBody::DefinedLocalKind, "", Sym) {}
+
+  static bool classof(const SymbolBody *S) {
+    return S->kind() == SymbolBody::DefinedLocalKind;
+  }
+};
+
 // This class represents a symbol defined in an archive file. It is
 // created from an archive file header, and it knows how to load an
 // object file from an archive to replace itself with a defined
diff --git a/ELF/Target.cpp b/ELF/Target.cpp
index 1e2d620..1415df6 100644
--- a/ELF/Target.cpp
+++ b/ELF/Target.cpp
@@ -99,7 +99,7 @@ public:
                    uint64_t SA, uint64_t ZA = 0,
                    uint8_t *PairedLoc = nullptr) const override;
   size_t relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
-                  uint64_t SA, const SymbolBody *S) const override;
+                  uint64_t SA, const SymbolBody &S) const override;
   bool isGotRelative(uint32_t Type) const override;
   bool refersToGotEntry(uint32_t Type) const override;
 
@@ -137,7 +137,7 @@ public:
   bool isRelRelative(uint32_t Type) const override;
   bool isSizeRel(uint32_t Type) const override;
   size_t relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
-                  uint64_t SA, const SymbolBody *S) const override;
+                  uint64_t SA, const SymbolBody &S) const override;
 
 private:
   void relocateTlsLdToLe(uint8_t *Loc, uint8_t *BufEnd, uint64_t P,
@@ -191,7 +191,7 @@ public:
                    uint64_t SA, uint64_t ZA = 0,
                    uint8_t *PairedLoc = nullptr) const override;
   size_t relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
-                  uint64_t SA, const SymbolBody *S) const override;
+                  uint64_t SA, const SymbolBody &S) const override;
 
 private:
   void relocateTlsGdToLe(uint32_t Type, uint8_t *Loc, uint8_t *BufEnd,
@@ -278,7 +278,7 @@ bool TargetInfo::canRelaxTls(uint32_t Type, const SymbolBody *S) const {
   // Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally
   // defined.
   if (isTlsInitialExecRel(Type))
-    return !canBePreempted(S);
+    return !canBePreempted(*S);
 
   return false;
 }
@@ -317,7 +317,7 @@ TargetInfo::PltNeed TargetInfo::needsPlt(uint32_t Type,
                                          const SymbolBody &S) const {
   if (isGnuIFunc<ELFT>(S))
     return Plt_Explicit;
-  if (canBePreempted(&S) && needsPltImpl(Type))
+  if (canBePreempted(S) && needsPltImpl(Type))
     return Plt_Explicit;
 
   // This handles a non PIC program call to function in a shared library.
@@ -363,7 +363,7 @@ bool TargetInfo::isTlsGlobalDynamicRel(uint32_t Type) const {
 
 size_t TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
                             uint64_t P, uint64_t SA,
-                            const SymbolBody *S) const {
+                            const SymbolBody &S) const {
   return 0;
 }
 
@@ -470,7 +470,7 @@ bool X86TargetInfo::needsCopyRelImpl(uint32_t Type) const {
 
 bool X86TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
   if (S.IsTls && Type == R_386_TLS_GD)
-    return Target->canRelaxTls(Type, &S) && canBePreempted(&S);
+    return Target->canRelaxTls(Type, &S) && canBePreempted(S);
   if (Type == R_386_TLS_GOTIE || Type == R_386_TLS_IE)
     return !canRelaxTls(Type, &S);
   return Type == R_386_GOT32 || needsPlt<ELF32LE>(Type, S);
@@ -545,7 +545,7 @@ bool X86TargetInfo::needsDynRelative(uint32_t Type) const {
 
 size_t X86TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
                                uint64_t P, uint64_t SA,
-                               const SymbolBody *S) const {
+                               const SymbolBody &S) const {
   switch (Type) {
   case R_386_TLS_GD:
     if (canBePreempted(S))
@@ -732,7 +732,7 @@ bool X86_64TargetInfo::refersToGotEntry(uint32_t Type) const {
 
 bool X86_64TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const {
   if (Type == R_X86_64_TLSGD)
-    return Target->canRelaxTls(Type, &S) && canBePreempted(&S);
+    return Target->canRelaxTls(Type, &S) && canBePreempted(S);
   if (Type == R_X86_64_GOTTPOFF)
     return !canRelaxTls(Type, &S);
   return refersToGotEntry(Type) || needsPlt<ELF64LE>(Type, S);
@@ -890,7 +890,7 @@ void X86_64TargetInfo::relocateTlsIeToLe(uint8_t *Loc, uint8_t *BufEnd,
 // This function returns a number of relocations that need to be skipped.
 size_t X86_64TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
                                   uint64_t P, uint64_t SA,
-                                  const SymbolBody *S) const {
+                                  const SymbolBody &S) const {
   switch (Type) {
   case R_X86_64_DTPOFF32:
     relocateOne(Loc, BufEnd, R_X86_64_TPOFF32, P, SA);
@@ -1460,7 +1460,7 @@ void AArch64TargetInfo::relocateOne(uint8_t *Loc, uint8_t *BufEnd,
 
 size_t AArch64TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
                                    uint64_t P, uint64_t SA,
-                                   const SymbolBody *S) const {
+                                   const SymbolBody &S) const {
   switch (Type) {
   case R_AARCH64_TLSDESC_ADR_PAGE21:
   case R_AARCH64_TLSDESC_LD64_LO12_NC:
@@ -1468,13 +1468,13 @@ size_t AArch64TargetInfo::relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
   case R_AARCH64_TLSDESC_CALL: {
     if (canBePreempted(S))
       fatal("Unsupported TLS optimization");
-    uint64_t X = S ? S->getVA<ELF64LE>() : SA;
+    uint64_t X = S.getVA<ELF64LE>();
     relocateTlsGdToLe(Type, Loc, BufEnd, P, X);
     return 0;
   }
   case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
   case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
-    relocateTlsIeToLe(Type, Loc, BufEnd, P, S->getVA<ELF64LE>());
+    relocateTlsIeToLe(Type, Loc, BufEnd, P, S.getVA<ELF64LE>());
     return 0;
   }
   llvm_unreachable("Unknown TLS optimization");
diff --git a/ELF/Target.h b/ELF/Target.h
index ab4defa..2668908 100644
--- a/ELF/Target.h
+++ b/ELF/Target.h
@@ -70,7 +70,7 @@ public:
   template <class ELFT>
   bool needsCopyRel(uint32_t Type, const SymbolBody &S) const;
   virtual size_t relaxTls(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type,
-                          uint64_t P, uint64_t SA, const SymbolBody *S) const;
+                          uint64_t P, uint64_t SA, const SymbolBody &S) const;
   virtual ~TargetInfo();
 
   unsigned PageSize = 4096;
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index ad6e966..87ff1ef 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -256,7 +256,7 @@ template <bool Is64Bits> struct DenseMapInfo<SectionKey<Is64Bits>> {
 }
 
 template <class ELFT, class RelT>
-static bool handleTlsRelocation(uint32_t Type, SymbolBody *Body,
+static bool handleTlsRelocation(uint32_t Type, SymbolBody &Body,
                                 InputSectionBase<ELFT> &C, RelT &RI) {
   if (Target->pointsToLocalDynamicGotEntry(Type)) {
     if (Target->canRelaxTls(Type, nullptr))
@@ -268,16 +268,17 @@ static bool handleTlsRelocation(uint32_t Type, SymbolBody *Body,
     return true;
   }
 
-  if (!Body || !Body->IsTls)
+  if (!Body.IsTls)
     return false;
 
   if (Target->isTlsGlobalDynamicRel(Type)) {
-    if (!Target->canRelaxTls(Type, Body)) {
+    if (!Target->canRelaxTls(Type, &Body)) {
       if (Out<ELFT>::Got->addDynTlsEntry(Body)) {
         Out<ELFT>::RelaDyn->addReloc({Target->TlsModuleIndexRel,
-                                      DynamicReloc<ELFT>::Off_GTlsIndex, Body});
+                                      DynamicReloc<ELFT>::Off_GTlsIndex,
+                                      &Body});
         Out<ELFT>::RelaDyn->addReloc(
-            {Target->TlsOffsetRel, DynamicReloc<ELFT>::Off_GTlsOffset, Body});
+            {Target->TlsOffsetRel, DynamicReloc<ELFT>::Off_GTlsOffset, &Body});
       }
       return true;
     }
@@ -309,7 +310,8 @@ void Writer<ELFT>::scanRelocs(
   const ObjectFile<ELFT> &File = *C.getFile();
   for (const RelType &RI : Rels) {
     uint32_t SymIndex = RI.getSymbol(Config->Mips64EL);
-    SymbolBody *Body = File.getSymbolBody(SymIndex);
+    SymbolBody &OrigBody = File.getSymbolBody(SymIndex);
+    SymbolBody &Body = OrigBody.repl();
     uint32_t Type = RI.getType(Config->Mips64EL);
 
     // Ignore "hint" relocation because it is for optional code optimization.
@@ -320,20 +322,17 @@ void Writer<ELFT>::scanRelocs(
       HasGotOffRel = true;
 
     // Set "used" bit for --as-needed.
-    if (Body && Body->isUndefined() && !Body->isWeak())
-      if (auto *S = dyn_cast<SharedSymbol<ELFT>>(Body->repl()))
+    if (OrigBody.isUndefined() && !OrigBody.isWeak())
+      if (auto *S = dyn_cast<SharedSymbol<ELFT>>(&Body))
         S->File->IsUsed = true;
 
-    if (Body)
-      Body = Body->repl();
-
     bool CBP = canBePreempted(Body);
     if (handleTlsRelocation<ELFT>(Type, Body, C, RI))
       continue;
 
     if (Target->needsDynRelative(Type))
       Out<ELFT>::RelaDyn->addReloc({Target->RelativeRel, &C, RI.r_offset, true,
-                                    Body, getAddend<ELFT>(RI)});
+                                    &Body, getAddend<ELFT>(RI)});
 
     // MIPS has a special rule to create GOTs for local symbols.
     if (Config->EMachine == EM_MIPS && !CBP &&
@@ -345,7 +344,7 @@ void Writer<ELFT>::scanRelocs(
 
     // If a symbol in a DSO is referenced directly instead of through GOT,
     // we need to create a copy relocation for the symbol.
-    if (auto *B = dyn_cast_or_null<SharedSymbol<ELFT>>(Body)) {
+    if (auto *B = dyn_cast_or_null<SharedSymbol<ELFT>>(&Body)) {
       if (B->needsCopy())
         continue;
       if (Target->needsCopyRel<ELFT>(Type, *B)) {
@@ -359,53 +358,51 @@ void Writer<ELFT>::scanRelocs(
     // An STT_GNU_IFUNC symbol always uses a PLT entry, and all references
     // to the symbol go through the PLT. This is true even for a local
     // symbol, although local symbols normally do not require PLT entries.
-    if (Body && isGnuIFunc<ELFT>(*Body)) {
-      if (Body->isInPlt())
+    if (isGnuIFunc<ELFT>(Body)) {
+      if (Body.isInPlt())
         continue;
       Out<ELFT>::Plt->addEntry(Body);
       if (Target->UseLazyBinding) {
         Out<ELFT>::GotPlt->addEntry(Body);
         Out<ELFT>::RelaPlt->addReloc(
             {CBP ? Target->PltRel : Target->IRelativeRel,
-             DynamicReloc<ELFT>::Off_GotPlt, !CBP, Body});
+             DynamicReloc<ELFT>::Off_GotPlt, !CBP, &Body});
       } else {
         Out<ELFT>::Got->addEntry(Body);
         Out<ELFT>::RelaDyn->addReloc(
             {CBP ? Target->PltRel : Target->IRelativeRel,
-             DynamicReloc<ELFT>::Off_Got, !CBP, Body});
+             DynamicReloc<ELFT>::Off_Got, !CBP, &Body});
       }
       continue;
     }
 
     // If a relocation needs PLT, we create a PLT and a GOT slot
     // for the symbol.
-    TargetInfo::PltNeed NeedPlt = TargetInfo::Plt_No;
-    if (Body)
-      NeedPlt = Target->needsPlt<ELFT>(Type, *Body);
+    TargetInfo::PltNeed NeedPlt = Target->needsPlt<ELFT>(Type, Body);
     if (NeedPlt) {
       if (NeedPlt == TargetInfo::Plt_Implicit)
-        Body->NeedsCopyOrPltAddr = true;
-      if (Body->isInPlt())
+        Body.NeedsCopyOrPltAddr = true;
+      if (Body.isInPlt())
         continue;
       Out<ELFT>::Plt->addEntry(Body);
 
       if (Target->UseLazyBinding) {
         Out<ELFT>::GotPlt->addEntry(Body);
         Out<ELFT>::RelaPlt->addReloc(
-            {Target->PltRel, DynamicReloc<ELFT>::Off_GotPlt, Body});
+            {Target->PltRel, DynamicReloc<ELFT>::Off_GotPlt, &Body});
       } else {
-        if (Body->isInGot())
+        if (Body.isInGot())
           continue;
         Out<ELFT>::Got->addEntry(Body);
         Out<ELFT>::RelaDyn->addReloc(
-            {Target->GotRel, DynamicReloc<ELFT>::Off_Got, Body});
+            {Target->GotRel, DynamicReloc<ELFT>::Off_Got, &Body});
       }
       continue;
     }
 
     // If a relocation needs GOT, we create a GOT slot for the symbol.
-    if (Body && Target->needsGot(Type, *Body)) {
-      if (Body->isInGot())
+    if (Target->needsGot(Type, Body)) {
+      if (Body.isInGot())
         continue;
       Out<ELFT>::Got->addEntry(Body);
 
@@ -415,7 +412,7 @@ void Writer<ELFT>::scanRelocs(
         // See "Global Offset Table" in Chapter 5 in the following document
         // for detailed description:
         // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
-        Body->MustBeInDynSym = true;
+        Body.MustBeInDynSym = true;
         continue;
       }
 
@@ -424,11 +421,11 @@ void Writer<ELFT>::scanRelocs(
       if (CBP || Dynrel) {
         uint32_t DynType;
         if (CBP)
-          DynType = Body->IsTls ? Target->TlsGotRel : Target->GotRel;
+          DynType = Body.IsTls ? Target->TlsGotRel : Target->GotRel;
         else
           DynType = Target->RelativeRel;
         Out<ELFT>::RelaDyn->addReloc(
-            {DynType, DynamicReloc<ELFT>::Off_Got, !CBP, Body});
+            {DynType, DynamicReloc<ELFT>::Off_Got, !CBP, &Body});
       }
       continue;
     }
@@ -443,7 +440,7 @@ void Writer<ELFT>::scanRelocs(
         // relocation too because that case is possible for executable file
         // linking only.
         continue;
-      if (Body == Config->MipsGpDisp || Body == Config->MipsLocalGp)
+      if (&Body == Config->MipsGpDisp || &Body == Config->MipsLocalGp)
         // MIPS _gp_disp designates offset between start of function and 'gp'
         // pointer into GOT. __gnu_local_gp is equal to the current value of
         // the 'gp'. Therefore any relocations against them do not require
@@ -455,7 +452,7 @@ void Writer<ELFT>::scanRelocs(
       // We don't know anything about the finaly symbol. Just ask the dynamic
       // linker to handle the relocation for us.
       Out<ELFT>::RelaDyn->addReloc({Target->getDynRel(Type), &C, RI.r_offset,
-                                    false, Body, getAddend<ELFT>(RI)});
+                                    false, &Body, getAddend<ELFT>(RI)});
       continue;
     }
 
@@ -477,16 +474,15 @@ void Writer<ELFT>::scanRelocs(
                                     (uintX_t)getPPC64TocBase() + Addend});
       continue;
     }
-    if (Body) {
+    if (!Body.isLocal()) {
       Out<ELFT>::RelaDyn->addReloc(
-          {Target->RelativeRel, &C, RI.r_offset, true, Body, Addend});
+          {Target->RelativeRel, &C, RI.r_offset, true, &Body, Addend});
       continue;
     }
-    const Elf_Sym *Sym =
-        File.getObj().getRelocationSymbol(&RI, File.getSymbolTable());
-    InputSectionBase<ELFT> *Section = File.getSection(*Sym);
-    uintX_t Offset = Sym->st_value;
-    if (Sym->getType() == STT_SECTION) {
+    const Elf_Sym &Sym = cast<LocalSymbol<ELFT>>(Body).Sym;
+    InputSectionBase<ELFT> *Section = File.getSection(Sym);
+    uintX_t Offset = Sym.st_value;
+    if (Sym.getType() == STT_SECTION) {
       Offset += Addend;
       Addend = 0;
     }
@@ -563,7 +559,9 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
   if (!Out<ELFT>::SymTab)
     return;
   for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
-    for (const Elf_Sym &Sym : F->getLocalSymbols()) {
+    for (SymbolBody *B : F->getLocalSymbolBodies()) {
+      auto *L = dyn_cast<LocalSymbol<ELFT>>(B);
+      const Elf_Sym &Sym = cast<LocalSymbol<ELFT>>(B)->Sym;
       StringRef SymName = check(Sym.getName(F->getStringTable()));
       if (!shouldKeepInSymtab<ELFT>(*F, SymName, Sym))
         continue;
@@ -577,7 +575,7 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
       }
       ++Out<ELFT>::SymTab->NumLocals;
       if (Config->Relocatable)
-        Out<ELFT>::SymTab->Locals[&Sym] = Out<ELFT>::SymTab->NumLocals;
+        L->DynsymIndex = Out<ELFT>::SymTab->NumLocals;
       F->KeptLocalSyms.push_back(std::make_pair(
           &Sym, Out<ELFT>::SymTab->StrTabSec.addString(SymName)));
     }
@@ -1428,11 +1426,8 @@ static uint32_t getELFFlags() {
 
 template <class ELFT>
 static typename ELFFile<ELFT>::uintX_t getEntryAddr() {
-  if (Config->EntrySym) {
-    if (SymbolBody *B = Config->EntrySym->repl())
-      return B->getVA<ELFT>();
-    return 0;
-  }
+  if (SymbolBody *B = Config->EntrySym)
+    return B->repl().getVA<ELFT>();
   if (Config->EntryAddr != uint64_t(-1))
     return Config->EntryAddr;
   return 0;


More information about the llvm-commits mailing list