Index: llvm/tools/llvm-readobj/ELFDumper.cpp
===================================================================
--- llvm/tools/llvm-readobj/ELFDumper.cpp
+++ llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -791,13 +791,11 @@
       function_ref<void(const Elf_Shdr &)> OnSectionStart,
       function_ref<void(StringRef, uint64_t)> OnSectionEntry);
 
-  virtual void printRelReloc(const ELFO *Obj, unsigned SecIndex,
-                             const Elf_Shdr *SymTab, const Elf_Rel &R,
-                             unsigned RelIndex) = 0;
-  virtual void printRelaReloc(const ELFO *Obj, unsigned SecIndex,
-                              const Elf_Shdr *SymTab, const Elf_Rela &R,
-                              unsigned RelIndex) = 0;
   virtual void printRelrReloc(const Elf_Relr &R) = 0;
+  virtual void printRelRelaReloc(const ELFO *Obj, unsigned SecIndex,
+                                 const Elf_Shdr *SymTab, const Elf_Rel &R,
+                                 Optional<int64_t> Addend,
+                                 unsigned RelIndex) = 0;
   void printRelocationsHelper(const ELFFile<ELFT> *Obj, const Elf_Shdr &Sec);
 
   void reportUniqueWarning(Error Err) const;
@@ -912,27 +910,21 @@
                          StringRef StrTable, uint32_t Bucket);
   void printRelocHeader(unsigned SType);
 
-  void printRelReloc(const ELFO *Obj, unsigned SecIndex, const Elf_Shdr *SymTab,
-                     const Elf_Rel &R, unsigned RelIndex) override;
-  void printRelaReloc(const ELFO *Obj, unsigned SecIndex,
-                      const Elf_Shdr *SymTab, const Elf_Rela &R,
-                      unsigned RelIndex) override;
   void printRelrReloc(const Elf_Relr &R) override;
-
-  template <class RelTy>
   void printRelRelaReloc(const ELFO *Obj, unsigned SecIndex,
-                         const Elf_Shdr *SymTab, const RelTy &R,
-                         unsigned RelIndex);
-  template <class RelTy>
+                         const Elf_Shdr *SymTab, const Elf_Rel &R,
+                         Optional<int64_t> Addend, unsigned RelIndex) override;
+
   void printRelRelaReloc(const ELFO *Obj, const Elf_Sym *Sym,
-                         StringRef SymbolName, const RelTy &R);
+                         StringRef SymbolName, const Elf_Rel &R,
+                         Optional<int64_t> Addend);
   void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First,
                    Optional<StringRef> StrTable, bool IsDynamic,
                    bool NonVisibilityBitsUsed) override;
   std::string getSymbolSectionNdx(const ELFO *Obj, const Elf_Sym *Symbol,
                                   const Elf_Sym *FirstSym);
-  template <class RelTy>
-  void printDynamicRelocation(const ELFO *Obj, const RelTy &R);
+  void printDynamicRelocation(const ELFO *Obj, const Elf_Rel &R,
+                              Optional<int64_t> Addend);
   void printProgramHeaders(const ELFO *Obj);
   void printSectionMapping(const ELFO *Obj);
   void printGNUVersionSectionProlog(const ELFFile<ELFT> *Obj,
@@ -989,17 +981,12 @@
   void printMipsABIFlags(const ELFObjectFile<ELFT> *Obj) override;
 
 private:
-  void printRelReloc(const ELFO *Obj, unsigned SecIndex, const Elf_Shdr *SymTab,
-                     const Elf_Rel &R, unsigned RelIndex) override;
-  void printRelaReloc(const ELFO *Obj, unsigned SecIndex,
-                      const Elf_Shdr *SymTab, const Elf_Rela &R,
-                      unsigned RelIndex) override;
   void printRelrReloc(const Elf_Relr &R) override;
-  template <class RelTy>
-  void printRelRelaReloc(const ELFO *Obj, unsigned SecIndex, const RelTy &Rel,
-                         unsigned RelIndex, const Elf_Shdr *SymTab);
-  template <class RelTy>
-  void printDynamicRelocation(const ELFO *Obj, const RelTy& Rel);
+  void printRelRelaReloc(const ELFO *Obj, unsigned SecIndex,
+                         const Elf_Shdr *SymTab, const Elf_Rel &R,
+                         Optional<int64_t> Addend, unsigned RelIndex) override;
+  void printDynamicRelocation(const ELFO *Obj, const Elf_Rel &R,
+                              Optional<int64_t> Addend);
 
   void printSymbols(const ELFO *Obj);
   void printDynamicSymbols(const ELFO *Obj);
@@ -3616,28 +3603,14 @@
     OS << "There are no section groups in this file.\n";
 }
 
-template <class ELFT>
-void GNUStyle<ELFT>::printRelReloc(const ELFO *Obj, unsigned SecIndex,
-                                   const Elf_Shdr *SymTab, const Elf_Rel &R,
-                                   unsigned RelIndex) {
-  printRelRelaReloc(Obj, SecIndex, SymTab, R, RelIndex);
-}
-
-template <class ELFT>
-void GNUStyle<ELFT>::printRelaReloc(const ELFO *Obj, unsigned SecIndex,
-                                    const Elf_Shdr *SymTab, const Elf_Rela &R,
-                                    unsigned RelIndex) {
-  printRelRelaReloc(Obj, SecIndex, SymTab, R, RelIndex);
-}
-
 template <class ELFT> void GNUStyle<ELFT>::printRelrReloc(const Elf_Relr &R) {
   OS << to_string(format_hex_no_prefix(R, ELFT::Is64Bits ? 16 : 8)) << "\n";
 }
 
 template <class ELFT>
-template <class RelTy>
 void GNUStyle<ELFT>::printRelRelaReloc(const ELFO *Obj, unsigned SecIndex,
-                                       const Elf_Shdr *SymTab, const RelTy &R,
+                                       const Elf_Shdr *SymTab, const Elf_Rel &R,
+                                       Optional<int64_t> Addend,
                                        unsigned RelIndex) {
   Expected<std::pair<const typename ELFT::Sym *, std::string>> Target =
       this->dumper()->getRelocationTarget(SymTab, R);
@@ -3646,23 +3619,14 @@
         "unable to print relocation " + Twine(RelIndex) + " in section " +
         Twine(SecIndex) + ": " + toString(Target.takeError())));
   else
-    printRelRelaReloc(Obj, /*Sym=*/Target->first, /*Name=*/Target->second, R);
-}
-
-template <class ELFT>
-static Optional<int64_t> getAddend(const typename ELFT::Rela &R) {
-  return (int64_t)R.r_addend;
-}
-
-template <class ELFT>
-static Optional<int64_t> getAddend(const typename ELFT::Rel &) {
-  return None;
+    printRelRelaReloc(Obj, /*Sym=*/Target->first, /*Name=*/Target->second, R,
+                      Addend);
 }
 
 template <class ELFT>
-template <class RelTy>
 void GNUStyle<ELFT>::printRelRelaReloc(const ELFO *Obj, const Elf_Sym *Sym,
-                                       StringRef SymbolName, const RelTy &R) {
+                                       StringRef SymbolName, const Elf_Rel &R,
+                                       Optional<int64_t> Addend) {
   // First two fields are bit width dependent. The rest of them are fixed width.
   unsigned Bias = ELFT::Is64Bits ? 8 : 0;
   Field Fields[5] = {0, 10 + Bias, 19 + 2 * Bias, 42 + 2 * Bias, 53 + 2 * Bias};
@@ -3682,20 +3646,20 @@
   for (const Field &F : Fields)
     printField(F);
 
-  std::string Addend;
-  if (Optional<int64_t> A = getAddend<ELFT>(R)) {
-    int64_t RelAddend = *A;
+  std::string A;
+  if (Addend) {
+    int64_t RelAddend = *Addend;
     if (!SymbolName.empty()) {
       if (RelAddend < 0) {
-        Addend = " - ";
+        A = " - ";
         RelAddend = std::abs(RelAddend);
       } else {
-        Addend = " + ";
+        A = " + ";
       }
     }
-    Addend += to_hexString(RelAddend, false);
+    A += to_hexString(RelAddend, false);
   }
-  OS << Addend << "\n";
+  OS << A << "\n";
 }
 
 template <class ELFT> void GNUStyle<ELFT>::printRelocHeader(unsigned SType) {
@@ -4496,10 +4460,11 @@
 } // namespace
 
 template <class ELFT>
-template <class RelTy>
-void GNUStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, const RelTy &R) {
-  RelSymbol<ELFT> S = getSymbolForReloc(Obj, this->FileName, this->dumper(), R);
-  printRelRelaReloc(Obj, S.Sym, S.Name, R);
+void GNUStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, const Elf_Rel &R,
+                                            Optional<int64_t> Addend) {
+  RelSymbol<ELFT> S =
+      getSymbolForReloc<ELFT>(Obj, this->FileName, this->dumper(), R);
+  printRelRelaReloc(Obj, S.Sym, S.Name, R, Addend);
 }
 
 template <class ELFT>
@@ -4558,7 +4523,7 @@
        << " contains " << DynRelaRegion.Size << " bytes:\n";
     printRelocHeader(ELF::SHT_RELA);
     for (const Elf_Rela &Rela : this->dumper()->dyn_relas())
-      printDynamicRelocation(Obj, Rela);
+      printDynamicRelocation(Obj, Rela, /*Addend=*/(int64_t)Rela.r_addend);
   }
   if (DynRelRegion.Size > 0) {
     OS << "\n'REL' relocation section at offset "
@@ -4568,7 +4533,7 @@
        << " contains " << DynRelRegion.Size << " bytes:\n";
     printRelocHeader(ELF::SHT_REL);
     for (const Elf_Rel &Rel : this->dumper()->dyn_rels())
-      printDynamicRelocation(Obj, Rel);
+      printDynamicRelocation(Obj, Rel, /*Addend=*/None);
   }
   if (DynRelrRegion.Size > 0) {
     OS << "\n'RELR' relocation section at offset "
@@ -4581,7 +4546,7 @@
     std::vector<Elf_Rel> RelrRels =
         unwrapOrError(this->FileName, Obj->decode_relrs(Relrs));
     for (const Elf_Rel &R : RelrRels)
-      printDynamicRelocation(Obj, R);
+      printDynamicRelocation(Obj, R, /*Addend=*/None);
   }
   if (DynPLTRelRegion.Size) {
     OS << "\n'PLT' relocation section at offset "
@@ -4593,11 +4558,11 @@
     if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) {
       printRelocHeader(ELF::SHT_RELA);
       for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef<Elf_Rela>())
-        printDynamicRelocation(Obj, Rela);
+        printDynamicRelocation(Obj, Rela, /*Addend=*/(int64_t)Rela.r_addend);
     } else {
       printRelocHeader(ELF::SHT_REL);
       for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef<Elf_Rel>())
-        printDynamicRelocation(Obj, Rel);
+        printDynamicRelocation(Obj, Rel, /*Addend=*/None);
     }
   }
 }
@@ -5590,11 +5555,11 @@
   switch (Sec.sh_type) {
   case ELF::SHT_REL:
     for (const Elf_Rel &R : unwrapOrError(this->FileName, Obj->rels(&Sec)))
-      printRelReloc(Obj, SecNdx, SymTab, R, ++RelNdx);
+      printRelRelaReloc(Obj, SecNdx, SymTab, R, /*Addend=*/None, ++RelNdx);
     break;
   case ELF::SHT_RELA:
     for (const Elf_Rela &R : unwrapOrError(this->FileName, Obj->relas(&Sec)))
-      printRelaReloc(Obj, SecNdx, SymTab, R, ++RelNdx);
+      printRelRelaReloc(Obj, SecNdx, SymTab, R, (int64_t)R.r_addend, ++RelNdx);
     break;
   case ELF::SHT_RELR:
   case ELF::SHT_ANDROID_RELR: {
@@ -5607,14 +5572,14 @@
     std::vector<Elf_Rel> RelrRels =
         unwrapOrError(this->FileName, Obj->decode_relrs(Relrs));
     for (const Elf_Rel &R : RelrRels)
-      printRelReloc(Obj, SecNdx, SymTab, R, ++RelNdx);
+      printRelRelaReloc(Obj, SecNdx, SymTab, R, /*Addend=*/None, ++RelNdx);
     break;
   }
   case ELF::SHT_ANDROID_REL:
   case ELF::SHT_ANDROID_RELA:
     for (const Elf_Rela &R :
          unwrapOrError(this->FileName, Obj->android_relas(&Sec)))
-      printRelaReloc(Obj, SecNdx, SymTab, R, ++RelNdx);
+      printRelRelaReloc(Obj, SecNdx, SymTab, R, (int64_t)R.r_addend, ++RelNdx);
     break;
   }
 }
@@ -6242,29 +6207,16 @@
   }
 }
 
-template <class ELFT>
-void LLVMStyle<ELFT>::printRelReloc(const ELFO *Obj, unsigned SecIndex,
-                                    const Elf_Shdr *SymTab, const Elf_Rel &R,
-                                    unsigned RelIndex) {
-  printRelRelaReloc(Obj, SecIndex, R, RelIndex, SymTab);
-}
-
-template <class ELFT>
-void LLVMStyle<ELFT>::printRelaReloc(const ELFO *Obj, unsigned SecIndex,
-                                     const Elf_Shdr *SymTab, const Elf_Rela &R,
-                                     unsigned RelIndex) {
-  printRelRelaReloc(Obj, SecIndex, R, RelIndex, SymTab);
-}
-
 template <class ELFT> void LLVMStyle<ELFT>::printRelrReloc(const Elf_Relr &R) {
   W.startLine() << W.hex(R) << "\n";
 }
 
 template <class ELFT>
-template <class RelTy>
 void LLVMStyle<ELFT>::printRelRelaReloc(const ELFO *Obj, unsigned SecIndex,
-                                        const RelTy &Rel, unsigned RelIndex,
-                                        const Elf_Shdr *SymTab) {
+                                        const Elf_Shdr *SymTab,
+                                        const Elf_Rel &Rel,
+                                        Optional<int64_t> Addend,
+                                        unsigned RelIndex) {
   Expected<std::pair<const typename ELFT::Sym *, std::string>> Target =
       this->dumper()->getRelocationTarget(SymTab, Rel);
   if (!Target) {
@@ -6278,19 +6230,18 @@
   SmallString<32> RelocName;
   Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
 
-  uintX_t Addend = getAddend<ELFT>(Rel).getValueOr(0);
+  uintX_t A = Addend.getValueOr(0);
   if (opts::ExpandRelocs) {
     DictScope Group(W, "Relocation");
     W.printHex("Offset", Rel.r_offset);
     W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL()));
     W.printNumber("Symbol", !TargetName.empty() ? TargetName : "-",
                   Rel.getSymbol(Obj->isMips64EL()));
-    W.printHex("Addend", Addend);
+    W.printHex("Addend", A);
   } else {
     raw_ostream &OS = W.startLine();
     OS << W.hex(Rel.r_offset) << " " << RelocName << " "
-       << (!TargetName.empty() ? TargetName : "-") << " " << W.hex(Addend)
-       << "\n";
+       << (!TargetName.empty() ? TargetName : "-") << " " << W.hex(A) << "\n";
   }
 }
 
@@ -6490,11 +6441,11 @@
   W.indent();
   if (DynRelaRegion.Size > 0) {
     for (const Elf_Rela &Rela : this->dumper()->dyn_relas())
-      printDynamicRelocation(Obj, Rela);
+      printDynamicRelocation(Obj, Rela, (int64_t)Rela.r_addend);
   }
   if (DynRelRegion.Size > 0) {
     for (const Elf_Rel &Rel : this->dumper()->dyn_rels())
-      printDynamicRelocation(Obj, Rel);
+      printDynamicRelocation(Obj, Rel, /*Addend*/None);
   }
 
   if (DynRelrRegion.Size > 0) {
@@ -6502,39 +6453,38 @@
     std::vector<Elf_Rel> RelrRels =
         unwrapOrError(this->FileName, Obj->decode_relrs(Relrs));
     for (const Elf_Rel &R : RelrRels)
-      printDynamicRelocation(Obj, R);
+      printDynamicRelocation(Obj, R, /*Addend*/None);
   }
   if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela))
     for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef<Elf_Rela>())
-      printDynamicRelocation(Obj, Rela);
+      printDynamicRelocation(Obj, Rela, (int64_t)Rela.r_addend);
   else
     for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef<Elf_Rel>())
-      printDynamicRelocation(Obj, Rel);
+      printDynamicRelocation(Obj, Rel, /*Addend*/None);
 
   W.unindent();
   W.startLine() << "}\n";
 }
 
 template <class ELFT>
- template <class RelTy>
-void LLVMStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, const RelTy& Rel) {
+void LLVMStyle<ELFT>::printDynamicRelocation(const ELFO *Obj, const Elf_Rel &Rel,
+                                             Optional<int64_t> Addend) {
   SmallString<32> RelocName;
   Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName);
   std::string SymbolName =
-      getSymbolForReloc(Obj, this->FileName, this->dumper(), Rel).Name;
+      getSymbolForReloc<ELFT>(Obj, this->FileName, this->dumper(), Rel).Name;
 
-  uintX_t Addend = getAddend<ELFT>(Rel).getValueOr(0);
+  uintX_t A = Addend.getValueOr(0);
   if (opts::ExpandRelocs) {
     DictScope Group(W, "Relocation");
     W.printHex("Offset", Rel.r_offset);
     W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL()));
     W.printString("Symbol", !SymbolName.empty() ? SymbolName : "-");
-    W.printHex("Addend", Addend);
+    W.printHex("Addend", A);
   } else {
     raw_ostream &OS = W.startLine();
     OS << W.hex(Rel.r_offset) << " " << RelocName << " "
-       << (!SymbolName.empty() ? SymbolName : "-") << " " << W.hex(Addend)
-       << "\n";
+       << (!SymbolName.empty() ? SymbolName : "-") << " " << W.hex(A) << "\n";
   }
 }