diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h index b44dd3f486614..f4979ac065039 100644 --- a/llvm/include/llvm/Object/ELF.h +++ b/llvm/include/llvm/Object/ELF.h @@ -196,7 +196,7 @@ class ELFFile { return getSectionContentsAsArray(Sec); } - Expected> decode_relrs(Elf_Relr_Range relrs) const; + Expected> decode_relrs(Elf_Relr_Range relrs) const; Expected> android_relas(const Elf_Shdr *Sec) const; diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp index 2515695095a1c..7a675944bb440 100644 --- a/llvm/lib/Object/ELF.cpp +++ b/llvm/lib/Object/ELF.cpp @@ -278,7 +278,7 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) { } template -Expected> +Expected> ELFFile::decode_relrs(Elf_Relr_Range relrs) const { // This function decodes the contents of an SHT_RELR packed relocation // section. @@ -310,11 +310,10 @@ ELFFile::decode_relrs(Elf_Relr_Range relrs) const { // even means address, odd means bitmap. // 2. Just a simple list of addresses is a valid encoding. - Elf_Rela Rela; - Rela.r_info = 0; - Rela.r_addend = 0; - Rela.setType(getRelativeRelocationType(), false); - std::vector Relocs; + Elf_Rel Rel; + Rel.r_info = 0; + Rel.setType(getRelativeRelocationType(), false); + std::vector Relocs; // Word type: uint32_t for Elf32, and uint64_t for Elf64. typedef typename ELFT::uint Word; @@ -331,8 +330,8 @@ ELFFile::decode_relrs(Elf_Relr_Range relrs) const { Word Entry = R; if ((Entry&1) == 0) { // Even entry: encodes the offset for next relocation. - Rela.r_offset = Entry; - Relocs.push_back(Rela); + Rel.r_offset = Entry; + Relocs.push_back(Rel); // Set base offset for subsequent bitmap entries. Base = Entry + WordSize; continue; @@ -343,8 +342,8 @@ ELFFile::decode_relrs(Elf_Relr_Range relrs) const { while (Entry != 0) { Entry >>= 1; if ((Entry&1) != 0) { - Rela.r_offset = Offset; - Relocs.push_back(Rela); + Rel.r_offset = Offset; + Relocs.push_back(Rel); } Offset += WordSize; } diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 6b28044d7d902..a21e80d080fd7 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -372,8 +372,9 @@ template class ELFDumper : public ObjDumper { Expected> getVersionDependencies(const Elf_Shdr *Sec) const; + template Expected> - getRelocationTarget(const Elf_Shdr *SymTab, const Elf_Rela &R) const; + getRelocationTarget(const Elf_Shdr *SymTab, const RelTy &R) const; std::function WarningHandler; void reportUniqueWarning(Error Err) const; @@ -908,17 +909,20 @@ template class GNUStyle : public DumpStyle { void printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym, uint32_t Sym, StringRef StrTable, uint32_t Bucket); void printRelocHeader(unsigned SType); + template void printRelocation(const ELFO *Obj, unsigned SecIndex, - const Elf_Shdr *SymTab, const Elf_Rela &R, - unsigned RelIndex, bool IsRela); + const Elf_Shdr *SymTab, const RelTy &R, + unsigned RelIndex); + template void printRelocation(const ELFO *Obj, const Elf_Sym *Sym, - StringRef SymbolName, const Elf_Rela &R, bool IsRela); + StringRef SymbolName, const RelTy &R); void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First, Optional StrTable, bool IsDynamic, bool NonVisibilityBitsUsed) override; std::string getSymbolSectionNdx(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *FirstSym); - void printDynamicRelocation(const ELFO *Obj, Elf_Rela R, bool IsRela); + template + void printDynamicRelocation(const ELFO *Obj, const RelTy &R); void printProgramHeaders(const ELFO *Obj); void printSectionMapping(const ELFO *Obj); void printGNUVersionSectionProlog(const ELFFile *Obj, @@ -976,9 +980,12 @@ template class LLVMStyle : public DumpStyle { void printMipsABIFlags(const ELFObjectFile *Obj) override; private: - void printRelocation(const ELFO *Obj, unsigned SecIndex, Elf_Rela Rel, + template + void printRelocation(const ELFO *Obj, unsigned SecIndex, const RelTy &Rel, unsigned RelIndex, const Elf_Shdr *SymTab); - void printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel); + template + void printDynamicRelocation(const ELFO *Obj, const RelTy& Rel); + void printSymbols(const ELFO *Obj); void printDynamicSymbols(const ELFO *Obj); void printSymbolSection(const Elf_Sym *Symbol, const Elf_Sym *First); @@ -1095,9 +1102,10 @@ Expected ELFDumper::getSymbolVersion(const Elf_Sym *Sym, } template +template Expected> ELFDumper::getRelocationTarget(const Elf_Shdr *SymTab, - const Elf_Rela &R) const { + const RelTy &R) const { const ELFFile *Obj = ObjF->getELFFile(); Expected SymOrErr = Obj->getRelocationSymbol(&R, SymTab); if (!SymOrErr) @@ -3605,9 +3613,10 @@ template void GNUStyle::printGroupSections(const ELFO *Obj) { } template +template void GNUStyle::printRelocation(const ELFO *Obj, unsigned SecIndex, - const Elf_Shdr *SymTab, const Elf_Rela &R, - unsigned RelIndex, bool IsRela) { + const Elf_Shdr *SymTab, const RelTy &R, + unsigned RelIndex) { Expected> Target = this->dumper()->getRelocationTarget(SymTab, R); if (!Target) @@ -3615,14 +3624,23 @@ void GNUStyle::printRelocation(const ELFO *Obj, unsigned SecIndex, "unable to print relocation " + Twine(RelIndex) + " in section " + Twine(SecIndex) + ": " + toString(Target.takeError()))); else - printRelocation(Obj, /*Sym=*/Target->first, /*Name=*/Target->second, R, - IsRela); + printRelocation(Obj, /*Sym=*/Target->first, /*Name=*/Target->second, R); +} + +template +static Optional getAddend(const typename ELFT::Rela &R) { + return (int64_t)R.r_addend; +} + +template +static Optional getAddend(const typename ELFT::Rel &) { + return None; } template +template void GNUStyle::printRelocation(const ELFO *Obj, const Elf_Sym *Sym, - StringRef SymbolName, const Elf_Rela &R, - bool IsRela) { + StringRef SymbolName, const RelTy &R) { // 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}; @@ -3643,16 +3661,16 @@ void GNUStyle::printRelocation(const ELFO *Obj, const Elf_Sym *Sym, printField(F); std::string Addend; - if (IsRela) { - int64_t RelAddend = R.r_addend; + if (Optional A = getAddend(R)) { + int64_t RelAddend = *A; if (!SymbolName.empty()) { - if (R.r_addend < 0) { + if (RelAddend < 0) { Addend = " - "; RelAddend = std::abs(RelAddend); - } else + } else { Addend = " + "; + } } - Addend += to_hexString(RelAddend, false); } OS << Addend << "\n"; @@ -3698,14 +3716,14 @@ template void GNUStyle::printRelocations(const ELFO *Obj) { AndroidRelas = unwrapOrError(this->FileName, Obj->android_relas(&Sec)); Entries = AndroidRelas.size(); } - std::vector RelrRelas; + std::vector RelrRels; if (!opts::RawRelr && (Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_ANDROID_RELR)) { // .relr.dyn relative relocation section needs to be unpacked first // to get the actual number of entries. Elf_Relr_Range Relrs = unwrapOrError(this->FileName, Obj->relrs(&Sec)); - RelrRelas = unwrapOrError(this->FileName, Obj->decode_relrs(Relrs)); - Entries = RelrRelas.size(); + RelrRels = unwrapOrError(this->FileName, Obj->decode_relrs(Relrs)); + Entries = RelrRels.size(); } uintX_t Offset = Sec.sh_offset; OS << "\nRelocation section '" << Name << "' at offset 0x" @@ -3719,33 +3737,31 @@ template void GNUStyle::printRelocations(const ELFO *Obj) { switch (Sec.sh_type) { case ELF::SHT_REL: - for (const auto &R : unwrapOrError(this->FileName, Obj->rels(&Sec))) { - Elf_Rela Rela; - Rela.r_offset = R.r_offset; - Rela.r_info = R.r_info; - Rela.r_addend = 0; - printRelocation(Obj, SecNdx, SymTab, Rela, ++RelNdx, false); - } + for (const Elf_Rel &R : unwrapOrError(this->FileName, Obj->rels(&Sec))) + printRelocation(Obj, SecNdx, SymTab, R, ++RelNdx); break; case ELF::SHT_RELA: - for (const auto &R : unwrapOrError(this->FileName, Obj->relas(&Sec))) - printRelocation(Obj, SecNdx, SymTab, R, ++RelNdx, true); + for (const Elf_Rela &R : unwrapOrError(this->FileName, Obj->relas(&Sec))) + printRelocation(Obj, SecNdx, SymTab, R, ++RelNdx); break; case ELF::SHT_RELR: case ELF::SHT_ANDROID_RELR: if (opts::RawRelr) - for (const auto &R : unwrapOrError(this->FileName, Obj->relrs(&Sec))) + for (const Elf_Relr &R : + unwrapOrError(this->FileName, Obj->relrs(&Sec))) OS << to_string(format_hex_no_prefix(R, ELFT::Is64Bits ? 16 : 8)) << "\n"; else - for (const auto &R : RelrRelas) - printRelocation(Obj, SecNdx, SymTab, R, ++RelNdx, false); + for (const Elf_Rel &R : RelrRels) + printRelocation(Obj, SecNdx, SymTab, R, ++RelNdx); break; case ELF::SHT_ANDROID_REL: + for (const Elf_Rela &R : AndroidRelas) + printRelocation(Obj, SecNdx, SymTab, (const Elf_Rel &)R, ++RelNdx); + break; case ELF::SHT_ANDROID_RELA: - for (const auto &R : AndroidRelas) - printRelocation(Obj, SecNdx, SymTab, R, ++RelNdx, - Sec.sh_type == ELF::SHT_ANDROID_RELA); + for (const Elf_Rela &R : AndroidRelas) + printRelocation(Obj, SecNdx, SymTab, R, ++RelNdx); break; } } @@ -4451,10 +4467,10 @@ template struct RelSymbol { std::string Name; }; -template +template RelSymbol getSymbolForReloc(const ELFFile *Obj, StringRef FileName, const ELFDumper *Dumper, - const typename ELFT::Rela &Reloc) { + const RelTy &Reloc) { uint32_t SymIndex = Reloc.getSymbol(Obj->isMips64EL()); auto WarnAndReturn = [&](const typename ELFT::Sym *Sym, const Twine &Reason) -> RelSymbol { @@ -4489,10 +4505,10 @@ RelSymbol getSymbolForReloc(const ELFFile *Obj, StringRef FileName, } // namespace template -void GNUStyle::printDynamicRelocation(const ELFO *Obj, Elf_Rela R, - bool IsRela) { +template +void GNUStyle::printDynamicRelocation(const ELFO *Obj, const RelTy &R) { RelSymbol S = getSymbolForReloc(Obj, this->FileName, this->dumper(), R); - printRelocation(Obj, S.Sym, S.Name, R, IsRela); + printRelocation(Obj, S.Sym, S.Name, R); } template @@ -4551,7 +4567,7 @@ void GNUStyle::printDynamicRelocations(const ELFO *Obj) { << " contains " << DynRelaRegion.Size << " bytes:\n"; printRelocHeader(ELF::SHT_RELA); for (const Elf_Rela &Rela : this->dumper()->dyn_relas()) - printDynamicRelocation(Obj, Rela, true); + printDynamicRelocation(Obj, Rela); } if (DynRelRegion.Size > 0) { OS << "\n'REL' relocation section at offset " @@ -4560,13 +4576,8 @@ void GNUStyle::printDynamicRelocations(const ELFO *Obj) { 1) << " contains " << DynRelRegion.Size << " bytes:\n"; printRelocHeader(ELF::SHT_REL); - for (const Elf_Rel &Rel : this->dumper()->dyn_rels()) { - Elf_Rela Rela; - Rela.r_offset = Rel.r_offset; - Rela.r_info = Rel.r_info; - Rela.r_addend = 0; - printDynamicRelocation(Obj, Rela, false); - } + for (const Elf_Rel &Rel : this->dumper()->dyn_rels()) + printDynamicRelocation(Obj, Rel); } if (DynRelrRegion.Size > 0) { OS << "\n'RELR' relocation section at offset " @@ -4576,11 +4587,10 @@ void GNUStyle::printDynamicRelocations(const ELFO *Obj) { << " contains " << DynRelrRegion.Size << " bytes:\n"; printRelocHeader(ELF::SHT_REL); Elf_Relr_Range Relrs = this->dumper()->dyn_relrs(); - std::vector RelrRelas = + std::vector RelrRels = unwrapOrError(this->FileName, Obj->decode_relrs(Relrs)); - for (const Elf_Rela &Rela : RelrRelas) { - printDynamicRelocation(Obj, Rela, false); - } + for (const Elf_Rel &R : RelrRels) + printDynamicRelocation(Obj, R); } if (DynPLTRelRegion.Size) { OS << "\n'PLT' relocation section at offset " @@ -4592,16 +4602,11 @@ void GNUStyle::printDynamicRelocations(const ELFO *Obj) { if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) { printRelocHeader(ELF::SHT_RELA); for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef()) - printDynamicRelocation(Obj, Rela, true); + printDynamicRelocation(Obj, Rela); } else { printRelocHeader(ELF::SHT_REL); - for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef()) { - Elf_Rela Rela; - Rela.r_offset = Rel.r_offset; - Rela.r_info = Rel.r_info; - Rela.r_addend = 0; - printDynamicRelocation(Obj, Rela, false); - } + for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef()) + printDynamicRelocation(Obj, Rel); } } } @@ -6233,13 +6238,8 @@ void LLVMStyle::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) { switch (Sec->sh_type) { case ELF::SHT_REL: - for (const Elf_Rel &R : unwrapOrError(this->FileName, Obj->rels(Sec))) { - Elf_Rela Rela; - Rela.r_offset = R.r_offset; - Rela.r_info = R.r_info; - Rela.r_addend = 0; - printRelocation(Obj, SecNdx, Rela, ++RelNdx, SymTab); - } + for (const Elf_Rel &R : unwrapOrError(this->FileName, Obj->rels(Sec))) + printRelocation(Obj, SecNdx, R, ++RelNdx, SymTab); break; case ELF::SHT_RELA: for (const Elf_Rela &R : unwrapOrError(this->FileName, Obj->relas(Sec))) @@ -6252,9 +6252,9 @@ void LLVMStyle::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) { for (const Elf_Relr &R : Relrs) W.startLine() << W.hex(R) << "\n"; } else { - std::vector RelrRelas = + std::vector RelrRels = unwrapOrError(this->FileName, Obj->decode_relrs(Relrs)); - for (const Elf_Rela &R : RelrRelas) + for (const Elf_Rel &R : RelrRels) printRelocation(Obj, SecNdx, R, ++RelNdx, SymTab); } break; @@ -6269,8 +6269,9 @@ void LLVMStyle::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) { } template +template void LLVMStyle::printRelocation(const ELFO *Obj, unsigned SecIndex, - Elf_Rela Rel, unsigned RelIndex, + const RelTy &Rel, unsigned RelIndex, const Elf_Shdr *SymTab) { Expected> Target = this->dumper()->getRelocationTarget(SymTab, Rel); @@ -6285,17 +6286,18 @@ void LLVMStyle::printRelocation(const ELFO *Obj, unsigned SecIndex, SmallString<32> RelocName; Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); + uintX_t Addend = getAddend(Rel).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", Rel.r_addend); + W.printHex("Addend", Addend); } else { raw_ostream &OS = W.startLine(); OS << W.hex(Rel.r_offset) << " " << RelocName << " " - << (!TargetName.empty() ? TargetName : "-") << " " << W.hex(Rel.r_addend) + << (!TargetName.empty() ? TargetName : "-") << " " << W.hex(Addend) << "\n"; } } @@ -6499,54 +6501,47 @@ void LLVMStyle::printDynamicRelocations(const ELFO *Obj) { printDynamicRelocation(Obj, Rela); } if (DynRelRegion.Size > 0) { - for (const Elf_Rel &Rel : this->dumper()->dyn_rels()) { - Elf_Rela Rela; - Rela.r_offset = Rel.r_offset; - Rela.r_info = Rel.r_info; - Rela.r_addend = 0; - printDynamicRelocation(Obj, Rela); - } + for (const Elf_Rel &Rel : this->dumper()->dyn_rels()) + printDynamicRelocation(Obj, Rel); } if (DynRelrRegion.Size > 0) { Elf_Relr_Range Relrs = this->dumper()->dyn_relrs(); - std::vector RelrRelas = + std::vector RelrRels = unwrapOrError(this->FileName, Obj->decode_relrs(Relrs)); - for (const Elf_Rela &Rela : RelrRelas) - printDynamicRelocation(Obj, Rela); + for (const Elf_Rel &R : RelrRels) + printDynamicRelocation(Obj, R); } if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef()) printDynamicRelocation(Obj, Rela); else - for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef()) { - Elf_Rela Rela; - Rela.r_offset = Rel.r_offset; - Rela.r_info = Rel.r_info; - Rela.r_addend = 0; - printDynamicRelocation(Obj, Rela); - } + for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef()) + printDynamicRelocation(Obj, Rel); + W.unindent(); W.startLine() << "}\n"; } template -void LLVMStyle::printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel) { + template +void LLVMStyle::printDynamicRelocation(const ELFO *Obj, const RelTy& Rel) { SmallString<32> RelocName; Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); std::string SymbolName = getSymbolForReloc(Obj, this->FileName, this->dumper(), Rel).Name; + uintX_t Addend = getAddend(Rel).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", Rel.r_addend); + W.printHex("Addend", Addend); } else { raw_ostream &OS = W.startLine(); OS << W.hex(Rel.r_offset) << " " << RelocName << " " - << (!SymbolName.empty() ? SymbolName : "-") << " " << W.hex(Rel.r_addend) + << (!SymbolName.empty() ? SymbolName : "-") << " " << W.hex(Addend) << "\n"; } }