Index: ELF/InputSection.cpp
===================================================================
--- ELF/InputSection.cpp
+++ ELF/InputSection.cpp
@@ -173,9 +173,9 @@
       if (!Body)
         SymVA = getLocalRelTarget(*File, RI, 0);
       else if (Target->needsGot(Type, *Body))
-        SymVA = Out<ELFT>::Got->getEntryAddr(*Body);
+        SymVA = Body->getGotVA<ELFT>();
       else
-        SymVA = getSymVA<ELFT>(*Body);
+        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.
@@ -213,9 +213,9 @@
       continue;
     }
 
-    uintX_t SymVA = getSymVA<ELFT>(*Body);
+    uintX_t SymVA = Body->getVA<ELFT>();
     if (Target->needsPlt(Type, *Body)) {
-      SymVA = Out<ELFT>::Plt->getEntryAddr(*Body);
+      SymVA = Body->getPltVA<ELFT>();
     } else if (Target->needsGot(Type, *Body)) {
       if (Config->EMachine == EM_MIPS && needsMipsLocalGot(Type, Body))
         // Under some conditions relocations against non-local symbols require
@@ -223,7 +223,7 @@
         // initialized by full address of the symbol.
         SymVA = Out<ELFT>::Got->getMipsLocalFullAddr(*Body);
       else
-        SymVA = Out<ELFT>::Got->getEntryAddr(*Body);
+        SymVA = Body->getGotVA<ELFT>();
       if (Body->isTls())
         Type = Target->getTlsGotRel(Type);
     } else if (!Target->needsCopyRel(Type, *Body) &&
Index: ELF/OutputSections.h
===================================================================
--- ELF/OutputSections.h
+++ ELF/OutputSections.h
@@ -47,9 +47,6 @@
   return Rel.r_addend;
 }
 
-template <class ELFT>
-typename llvm::object::ELFFile<ELFT>::uintX_t getSymVA(const SymbolBody &S);
-
 template <class ELFT, bool IsRela>
 typename llvm::object::ELFFile<ELFT>::uintX_t
 getLocalRelTarget(const ObjectFile<ELFT> &File,
@@ -118,7 +115,6 @@
   bool addDynTlsEntry(SymbolBody *Sym);
   bool addCurrentModuleTlsIndex();
   bool empty() const { return MipsLocalEntries == 0 && Entries.empty(); }
-  uintX_t getEntryAddr(const SymbolBody &B) const;
   uintX_t getMipsLocalFullAddr(const SymbolBody &B);
   uintX_t getMipsLocalPageAddr(uintX_t Addr);
   uintX_t getGlobalDynAddr(const SymbolBody &B) const;
@@ -155,7 +151,6 @@
   void writeTo(uint8_t *Buf) override;
   void addEntry(SymbolBody *Sym);
   bool empty() const;
-  uintX_t getEntryAddr(const SymbolBody &B) const;
 
 private:
   std::vector<const SymbolBody *> Entries;
@@ -171,7 +166,6 @@
   void writeTo(uint8_t *Buf) override;
   void addEntry(SymbolBody *Sym);
   bool empty() const { return Entries.empty(); }
-  uintX_t getEntryAddr(const SymbolBody &B) const;
 
 private:
   std::vector<std::pair<const SymbolBody *, unsigned>> Entries;
Index: ELF/OutputSections.cpp
===================================================================
--- ELF/OutputSections.cpp
+++ ELF/OutputSections.cpp
@@ -47,12 +47,6 @@
   return Entries.empty();
 }
 
-template <class ELFT>
-typename GotPltSection<ELFT>::uintX_t
-GotPltSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
-  return this->getVA() + B.GotPltIndex * sizeof(uintX_t);
-}
-
 template <class ELFT> void GotPltSection<ELFT>::finalize() {
   this->Header.sh_size =
       (Target->GotPltHeaderEntriesNum + Entries.size()) * sizeof(uintX_t);
@@ -62,7 +56,7 @@
   Target->writeGotPltHeader(Buf);
   Buf += Target->GotPltHeaderEntriesNum * sizeof(uintX_t);
   for (const SymbolBody *B : Entries) {
-    Target->writeGotPlt(Buf, Out<ELFT>::Plt->getEntryAddr(*B));
+    Target->writeGotPlt(Buf, B->getPltVA<ELFT>());
     Buf += sizeof(uintX_t);
   }
 }
@@ -105,16 +99,8 @@
 
 template <class ELFT>
 typename GotSection<ELFT>::uintX_t
-GotSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
-  return this->getVA() +
-         (Target->GotHeaderEntriesNum + MipsLocalEntries + B.GotIndex) *
-             sizeof(uintX_t);
-}
-
-template <class ELFT>
-typename GotSection<ELFT>::uintX_t
 GotSection<ELFT>::getMipsLocalFullAddr(const SymbolBody &B) {
-  return getMipsLocalEntryAddr(getSymVA<ELFT>(B));
+  return getMipsLocalEntryAddr(B.getVA<ELFT>());
 }
 
 template <class ELFT>
@@ -176,7 +162,7 @@
     // As the first approach, we can just store addresses for all symbols.
     if (Config->EMachine != EM_MIPS && canBePreempted(B, false))
       continue; // The dynamic linker will take care of it.
-    uintX_t VA = getSymVA<ELFT>(*B);
+    uintX_t VA = B->getVA<ELFT>();
     write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, VA);
   }
 }
@@ -197,8 +183,8 @@
   for (auto &I : Entries) {
     const SymbolBody *B = I.first;
     unsigned RelOff = I.second;
-    uint64_t Got = Target->UseLazyBinding ? Out<ELFT>::GotPlt->getEntryAddr(*B)
-                                          : Out<ELFT>::Got->getEntryAddr(*B);
+    uint64_t Got =
+        Target->UseLazyBinding ? B->getGotPltVA<ELFT>() : B->getGotVA<ELFT>();
     uint64_t Plt = this->getVA() + Off;
     Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff);
     Off += Target->PltEntrySize;
@@ -213,13 +199,6 @@
   Entries.push_back(std::make_pair(Sym, RelOff));
 }
 
-template <class ELFT>
-typename PltSection<ELFT>::uintX_t
-PltSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
-  return this->getVA() + Target->PltZeroSize +
-         B.PltIndex * Target->PltEntrySize;
-}
-
 template <class ELFT> void PltSection<ELFT>::finalize() {
   this->Header.sh_size =
       Target->PltZeroSize + Entries.size() * Target->PltEntrySize;
@@ -251,7 +230,7 @@
   if (Target->canRelaxTls(Type, Body)) {
     P->setSymbolAndType(Body->DynsymIndex, Target->getTlsGotRel(),
                         Config->Mips64EL);
-    P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
+    P->r_offset = Body->getGotVA<ELFT>();
     return true;
   }
 
@@ -312,9 +291,9 @@
     if (!CBP && Body && isGnuIFunc<ELFT>(*Body)) {
       P->setSymbolAndType(0, Target->IRelativeRel, Config->Mips64EL);
       if (Out<ELFT>::GotPlt)
-        P->r_offset = Out<ELFT>::GotPlt->getEntryAddr(*Body);
+        P->r_offset = Body->getGotPltVA<ELFT>();
       else
-        P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
+        P->r_offset = Body->getGotVA<ELFT>();
       continue;
     }
 
@@ -333,9 +312,9 @@
     P->setSymbolAndType(CBP ? Body->DynsymIndex : 0, Reloc, Config->Mips64EL);
 
     if (LazyReloc)
-      P->r_offset = Out<ELFT>::GotPlt->getEntryAddr(*Body);
+      P->r_offset = Body->getGotPltVA<ELFT>();
     else if (NeedsGot)
-      P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
+      P->r_offset = Body->getGotVA<ELFT>();
     else
       P->r_offset = C.getOffset(RI.r_offset) + C.OutSec->getVA();
 
@@ -348,7 +327,7 @@
     if (CBP)
       S->r_addend = A;
     else if (Body)
-      S->r_addend = getSymVA<ELFT>(*Body) + A;
+      S->r_addend = Body->getVA<ELFT>() + A;
     else
       S->r_addend = getLocalRelTarget(File, R, A);
   }
@@ -715,7 +694,7 @@
       P->d_un.d_ptr = E.OutSec->getVA();
       break;
     case Entry::SymAddr:
-      P->d_un.d_ptr = getSymVA<ELFT>(*E.Sym);
+      P->d_un.d_ptr = E.Sym->template getVA<ELFT>();
       break;
     case Entry::PlainInt:
       P->d_un.d_val = E.Val;
@@ -836,48 +815,8 @@
   this->Header.sh_size = Off;
 }
 
-template <class ELFT>
-typename ELFFile<ELFT>::uintX_t elf2::getSymVA(const SymbolBody &S) {
-  switch (S.kind()) {
-  case SymbolBody::DefinedSyntheticKind: {
-    auto &D = cast<DefinedSynthetic<ELFT>>(S);
-    return D.Section.getVA() + D.Value;
-  }
-  case SymbolBody::DefinedRegularKind: {
-    const auto &DR = cast<DefinedRegular<ELFT>>(S);
-    InputSectionBase<ELFT> *SC = DR.Section;
-    if (!SC)
-      return DR.Sym.st_value;
-
-    // Symbol offsets for AMDGPU need to be the offset in bytes of the symbol
-    // from the beginning of the section.
-    if (Config->EMachine == EM_AMDGPU)
-      return SC->getOffset(DR.Sym);
-    if (DR.Sym.getType() == STT_TLS)
-      return SC->OutSec->getVA() + SC->getOffset(DR.Sym) -
-             Out<ELFT>::TlsPhdr->p_vaddr;
-    return SC->OutSec->getVA() + SC->getOffset(DR.Sym);
-  }
-  case SymbolBody::DefinedCommonKind:
-    return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(S).OffsetInBss;
-  case SymbolBody::SharedKind: {
-    auto &SS = cast<SharedSymbol<ELFT>>(S);
-    if (SS.NeedsCopy)
-      return Out<ELFT>::Bss->getVA() + SS.OffsetInBss;
-    return 0;
-  }
-  case SymbolBody::UndefinedElfKind:
-  case SymbolBody::UndefinedKind:
-    return 0;
-  case SymbolBody::LazyKind:
-    assert(S.isUsedInRegularObj() && "Lazy symbol reached writer");
-    return 0;
-  }
-  llvm_unreachable("Invalid symbol kind");
-}
-
 // Returns a VA which a relocatin RI refers to. Used only for local symbols.
-// For non-local symbols, use getSymVA instead.
+// For non-local symbols, use SymbolBody::getVA instead.
 template <class ELFT, bool IsRela>
 typename ELFFile<ELFT>::uintX_t
 elf2::getLocalRelTarget(const ObjectFile<ELFT> &File,
@@ -1526,7 +1465,7 @@
     ESym->setBindingAndType(getSymbolBinding(Body), Type);
     ESym->st_size = Size;
     ESym->setVisibility(Body->getVisibility());
-    ESym->st_value = getSymVA<ELFT>(*Body);
+    ESym->st_value = Body->getVA<ELFT>();
 
     if (OutSec)
       ESym->st_shndx = OutSec->SectionIndex;
@@ -1653,11 +1592,6 @@
 template class SymbolTableSection<ELF64LE>;
 template class SymbolTableSection<ELF64BE>;
 
-template ELFFile<ELF32LE>::uintX_t getSymVA<ELF32LE>(const SymbolBody &);
-template ELFFile<ELF32BE>::uintX_t getSymVA<ELF32BE>(const SymbolBody &);
-template ELFFile<ELF64LE>::uintX_t getSymVA<ELF64LE>(const SymbolBody &);
-template ELFFile<ELF64BE>::uintX_t getSymVA<ELF64BE>(const SymbolBody &);
-
 template uint32_t getLocalRelTarget(const ObjectFile<ELF32LE> &,
                                     const ELFFile<ELF32LE>::Elf_Rel &,
                                     uint32_t);
Index: ELF/Symbols.h
===================================================================
--- ELF/Symbols.h
+++ ELF/Symbols.h
@@ -101,6 +101,15 @@
   bool isInGot() const { return GotIndex != -1U; }
   bool isInPlt() const { return PltIndex != -1U; }
 
+  template <class ELFT>
+  typename llvm::object::ELFFile<ELFT>::uintX_t getVA() const;
+  template <class ELFT>
+  typename llvm::object::ELFFile<ELFT>::uintX_t getGotVA() const;
+  template <class ELFT>
+  typename llvm::object::ELFFile<ELFT>::uintX_t getGotPltVA() const;
+  template <class ELFT>
+  typename llvm::object::ELFFile<ELFT>::uintX_t getPltVA() const;
+
   // A SymbolBody has a backreference to a Symbol. Originally they are
   // doubly-linked. A backreference will never change. But the pointer
   // in the Symbol may be mutated by the resolver. If you have a
Index: ELF/Symbols.cpp
===================================================================
--- ELF/Symbols.cpp
+++ ELF/Symbols.cpp
@@ -8,9 +8,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "Symbols.h"
-#include "InputSection.h"
 #include "Error.h"
 #include "InputFiles.h"
+#include "InputSection.h"
+#include "OutputSections.h"
+#include "Target.h"
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Config/config.h"
@@ -26,6 +28,67 @@
 using namespace lld;
 using namespace lld::elf2;
 
+template <class ELFT>
+typename ELFFile<ELFT>::uintX_t SymbolBody::getVA() const {
+  switch (kind()) {
+  case DefinedSyntheticKind: {
+    auto *D = cast<DefinedSynthetic<ELFT>>(this);
+    return D->Section.getVA() + D->Value;
+  }
+  case DefinedRegularKind: {
+    auto *D = cast<DefinedRegular<ELFT>>(this);
+    InputSectionBase<ELFT> *SC = D->Section;
+
+    // This is an absolute symbol.
+    if (!SC)
+      return D->Sym.st_value;
+
+    // Symbol offsets for AMDGPU need to be the offset in bytes of the symbol
+    // from the beginning of the section.
+    if (Config->EMachine == EM_AMDGPU)
+      return SC->getOffset(D->Sym);
+    if (D->Sym.getType() == STT_TLS)
+      return SC->OutSec->getVA() + SC->getOffset(D->Sym) -
+             Out<ELFT>::TlsPhdr->p_vaddr;
+    return SC->OutSec->getVA() + SC->getOffset(D->Sym);
+  }
+  case DefinedCommonKind:
+    return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(this)->OffsetInBss;
+  case SharedKind: {
+    auto *SS = cast<SharedSymbol<ELFT>>(this);
+    if (SS->NeedsCopy)
+      return Out<ELFT>::Bss->getVA() + SS->OffsetInBss;
+    return 0;
+  }
+  case UndefinedElfKind:
+  case UndefinedKind:
+    return 0;
+  case LazyKind:
+    assert(isUsedInRegularObj() && "Lazy symbol reached writer");
+    return 0;
+  }
+  llvm_unreachable("Invalid symbol kind");
+}
+
+template <class ELFT>
+typename ELFFile<ELFT>::uintX_t SymbolBody::getGotVA() const {
+  return Out<ELFT>::Got->getVA() +
+         (Out<ELFT>::Got->getMipsLocalEntriesNum() + GotIndex) *
+             sizeof(typename ELFFile<ELFT>::uintX_t);
+}
+
+template <class ELFT>
+typename ELFFile<ELFT>::uintX_t SymbolBody::getGotPltVA() const {
+  return Out<ELFT>::GotPlt->getVA() +
+         GotPltIndex * sizeof(typename ELFFile<ELFT>::uintX_t);
+}
+
+template <class ELFT>
+typename ELFFile<ELFT>::uintX_t SymbolBody::getPltVA() const {
+  return Out<ELFT>::Plt->getVA() + Target->PltZeroSize +
+         PltIndex * Target->PltEntrySize;
+}
+
 static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
   if (VA == STV_DEFAULT)
     return VB;
@@ -166,6 +229,26 @@
 #endif
 }
 
+template uint32_t SymbolBody::template getVA<ELF32LE>() const;
+template uint32_t SymbolBody::template getVA<ELF32BE>() const;
+template uint64_t SymbolBody::template getVA<ELF64LE>() const;
+template uint64_t SymbolBody::template getVA<ELF64BE>() const;
+
+template uint32_t SymbolBody::template getGotVA<ELF32LE>() const;
+template uint32_t SymbolBody::template getGotVA<ELF32BE>() const;
+template uint64_t SymbolBody::template getGotVA<ELF64LE>() const;
+template uint64_t SymbolBody::template getGotVA<ELF64BE>() const;
+
+template uint32_t SymbolBody::template getGotPltVA<ELF32LE>() const;
+template uint32_t SymbolBody::template getGotPltVA<ELF32BE>() const;
+template uint64_t SymbolBody::template getGotPltVA<ELF64LE>() const;
+template uint64_t SymbolBody::template getGotPltVA<ELF64BE>() const;
+
+template uint32_t SymbolBody::template getPltVA<ELF32LE>() const;
+template uint32_t SymbolBody::template getPltVA<ELF32BE>() const;
+template uint64_t SymbolBody::template getPltVA<ELF64LE>() const;
+template uint64_t SymbolBody::template getPltVA<ELF64BE>() const;
+
 template int SymbolBody::compare<ELF32LE>(SymbolBody *Other);
 template int SymbolBody::compare<ELF32BE>(SymbolBody *Other);
 template int SymbolBody::compare<ELF64LE>(SymbolBody *Other);
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -1257,8 +1257,8 @@
 template <class ELFT>
 static typename ELFFile<ELFT>::uintX_t getEntryAddr() {
   if (Config->EntrySym) {
-    if (SymbolBody *E = Config->EntrySym->repl())
-      return getSymVA<ELFT>(*E);
+    if (SymbolBody *B = Config->EntrySym->repl())
+      return B->getVA<ELFT>();
     return 0;
   }
   if (Config->EntryAddr != uint64_t(-1))