Index: llvm/tools/llvm-readobj/ELFDumper.cpp =================================================================== --- llvm/tools/llvm-readobj/ELFDumper.cpp +++ llvm/tools/llvm-readobj/ELFDumper.cpp @@ -733,9 +733,7 @@ template class DumpStyle { public: - using Elf_Shdr = typename ELFT::Shdr; - using Elf_Sym = typename ELFT::Sym; - using Elf_Addr = typename ELFT::Addr; + TYPEDEF_ELF_TYPES(ELFT) DumpStyle(ELFDumper *Dumper) : Dumper(Dumper) { FileName = this->Dumper->getElfObject()->getFileName(); @@ -798,6 +796,23 @@ function_ref OnSectionStart, function_ref OnSectionEntry); + struct Relocation { + enum class RelType { Rel, Rela, Relr }; + Relocation(Elf_Rel R) : Rel(R), Type(RelType::Rel){}; + Relocation(Elf_Rela R) : Rela(R), Type(RelType::Rela){}; + Relocation(Elf_Relr R) : Relr(R), Type(RelType::Relr){}; + RelType Type; + union { + Elf_Rel Rel; + Elf_Rela Rela; + Elf_Relr Relr; + }; + }; + using PrintRelocationFn = function_ref; + void printRelocationsHelper(const ELFFile *Obj, const Elf_Shdr &Sec, + PrintRelocationFn Print); + void reportUniqueWarning(Error Err) const; StringRef FileName; @@ -953,7 +968,6 @@ void printFileHeaders(const ELFO *Obj) override; void printGroupSections(const ELFFile *Obj) override; void printRelocations(const ELFO *Obj) override; - void printRelocations(const Elf_Shdr *Sec, const ELFO *Obj); void printSectionHeaders(const ELFO *Obj) override; void printSymbols(const ELFO *Obj, bool PrintSymbols, bool PrintDynamicSymbols) override; @@ -3697,73 +3711,54 @@ OS << "\n"; } +template +static bool isRelocationSec(const typename ELFT::Shdr &Sec) { + return Sec.sh_type == ELF::SHT_REL || Sec.sh_type == ELF::SHT_RELA || + Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_ANDROID_REL || + Sec.sh_type == ELF::SHT_ANDROID_RELA || + Sec.sh_type == ELF::SHT_ANDROID_RELR; +} + template void GNUStyle::printRelocations(const ELFO *Obj) { bool HasRelocSections = false; for (const Elf_Shdr &Sec : cantFail(Obj->sections())) { - if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA && - Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_REL && - Sec.sh_type != ELF::SHT_ANDROID_RELA && - Sec.sh_type != ELF::SHT_ANDROID_RELR) + if (!isRelocationSec(Sec)) continue; HasRelocSections = true; + StringRef Name = unwrapOrError(this->FileName, Obj->getSectionName(&Sec)); - unsigned Entries = Sec.getEntityCount(); - std::vector AndroidRelas; + unsigned Entries; + // Android's packed relocation section needs to be unpacked first + // to get the actual number of entries. if (Sec.sh_type == ELF::SHT_ANDROID_REL || Sec.sh_type == ELF::SHT_ANDROID_RELA) { - // Android's packed relocation section needs to be unpacked first - // to get the actual number of entries. - AndroidRelas = unwrapOrError(this->FileName, Obj->android_relas(&Sec)); - Entries = AndroidRelas.size(); - } - 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. + Entries = unwrapOrError(this->FileName, Obj->android_relas(&Sec)).size(); + } else if (!opts::RawRelr && (Sec.sh_type == ELF::SHT_RELR || + Sec.sh_type == ELF::SHT_ANDROID_RELR)) { Elf_Relr_Range Relrs = unwrapOrError(this->FileName, Obj->relrs(&Sec)); - RelrRels = unwrapOrError(this->FileName, Obj->decode_relrs(Relrs)); - Entries = RelrRels.size(); + Entries = unwrapOrError(this->FileName, Obj->decode_relrs(Relrs)).size(); + } else { + Entries = Sec.getEntityCount(); } + uintX_t Offset = Sec.sh_offset; OS << "\nRelocation section '" << Name << "' at offset 0x" << to_hexString(Offset, false) << " contains " << Entries << " entries:\n"; printRelocHeader(Sec.sh_type); - const Elf_Shdr *SymTab = - unwrapOrError(this->FileName, Obj->getSection(Sec.sh_link)); - unsigned SecNdx = &Sec - &cantFail(Obj->sections()).front(); - unsigned RelNdx = 0; - - switch (Sec.sh_type) { - case ELF::SHT_REL: - for (const Elf_Rel &R : unwrapOrError(this->FileName, Obj->rels(&Sec))) - printRelocation(Obj, SecNdx, SymTab, R, ++RelNdx); - break; - case ELF::SHT_RELA: - 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 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 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 Elf_Rela &R : AndroidRelas) - printRelocation(Obj, SecNdx, SymTab, R, ++RelNdx); - break; - } + this->printRelocationsHelper( + Obj, Sec, + [&](const ELFO *Obj, unsigned SecIndex, unsigned RelIndex, + const Elf_Shdr *SymTab, const Relocation &R) { + if (R.Type == Relocation::RelType::Rel) + printRelocation(Obj, SecIndex, SymTab, R.Rel, RelIndex); + else if (R.Type == Relocation::RelType::Rela) + printRelocation(Obj, SecIndex, SymTab, R.Rela, RelIndex); + else + OS << to_string( + format_hex_no_prefix(R.Relr, ELFT::Is64Bits ? 16 : 8)) + << "\n"; + }); } if (!HasRelocSections) OS << "\nThere are no relocations in this file.\n"; @@ -5596,6 +5591,47 @@ } } +template +void DumpStyle::printRelocationsHelper(const ELFFile *Obj, + const Elf_Shdr &Sec, + PrintRelocationFn Print) { + const Elf_Shdr *SymTab = + unwrapOrError(this->FileName, Obj->getSection(Sec.sh_link)); + unsigned SecNdx = &Sec - &cantFail(Obj->sections()).front(); + unsigned RelNdx = 0; + + switch (Sec.sh_type) { + case ELF::SHT_REL: + for (const Elf_Rel &R : unwrapOrError(this->FileName, Obj->rels(&Sec))) + Print(Obj, SecNdx, ++RelNdx, SymTab, Relocation(R)); + break; + case ELF::SHT_RELA: + for (const Elf_Rela &R : unwrapOrError(this->FileName, Obj->relas(&Sec))) + Print(Obj, SecNdx, ++RelNdx, SymTab, Relocation(R)); + break; + case ELF::SHT_RELR: + case ELF::SHT_ANDROID_RELR: { + Elf_Relr_Range Relrs = unwrapOrError(this->FileName, Obj->relrs(&Sec)); + if (opts::RawRelr) { + for (const Elf_Relr &R : Relrs) + Print(Obj, SecNdx, ++RelNdx, SymTab, Relocation(R)); + break; + } + std::vector RelrRels = + unwrapOrError(this->FileName, Obj->decode_relrs(Relrs)); + for (const Elf_Rel &R : RelrRels) + Print(Obj, SecNdx, ++RelNdx, SymTab, Relocation(R)); + break; + } + case ELF::SHT_ANDROID_REL: + case ELF::SHT_ANDROID_RELA: + for (const Elf_Rela &R : + unwrapOrError(this->FileName, Obj->android_relas(&Sec))) + Print(Obj, SecNdx, ++RelNdx, SymTab, Relocation(R)); + break; + } +} + template void GNUStyle::printDependentLibs(const ELFFile *Obj) { bool SectionStarted = false; @@ -6192,67 +6228,30 @@ template void LLVMStyle::printRelocations(const ELFO *Obj) { ListScope D(W, "Relocations"); - int SectionNumber = -1; for (const Elf_Shdr &Sec : cantFail(Obj->sections())) { - ++SectionNumber; - - if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA && - Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_REL && - Sec.sh_type != ELF::SHT_ANDROID_RELA && - Sec.sh_type != ELF::SHT_ANDROID_RELR) + if (!isRelocationSec(Sec)) continue; StringRef Name = unwrapOrError(this->FileName, Obj->getSectionName(&Sec)); - - W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n"; + unsigned SecNdx = &Sec - &cantFail(Obj->sections()).front(); + W.startLine() << "Section (" << SecNdx << ") " << Name << " {\n"; W.indent(); - - printRelocations(&Sec, Obj); - + this->printRelocationsHelper( + Obj, Sec, + [&](const ELFO *Obj, unsigned SecIndex, unsigned RelIndex, + const Elf_Shdr *SymTab, const Relocation &R) { + if (R.Type == Relocation::RelType::Rel) + printRelocation(Obj, SecIndex, R.Rel, RelIndex, SymTab); + else if (R.Type == Relocation::RelType::Rela) + printRelocation(Obj, SecIndex, R.Rela, RelIndex, SymTab); + else + W.startLine() << W.hex(R.Relr) << "\n"; + }); W.unindent(); W.startLine() << "}\n"; } } -template -void LLVMStyle::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) { - const Elf_Shdr *SymTab = - unwrapOrError(this->FileName, Obj->getSection(Sec->sh_link)); - unsigned SecNdx = Sec - &cantFail(Obj->sections()).front(); - unsigned RelNdx = 0; - - switch (Sec->sh_type) { - case ELF::SHT_REL: - 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))) - printRelocation(Obj, SecNdx, R, ++RelNdx, SymTab); - break; - case ELF::SHT_RELR: - case ELF::SHT_ANDROID_RELR: { - Elf_Relr_Range Relrs = unwrapOrError(this->FileName, Obj->relrs(Sec)); - if (opts::RawRelr) { - for (const Elf_Relr &R : Relrs) - W.startLine() << W.hex(R) << "\n"; - } else { - std::vector RelrRels = - unwrapOrError(this->FileName, Obj->decode_relrs(Relrs)); - for (const Elf_Rel &R : RelrRels) - printRelocation(Obj, SecNdx, R, ++RelNdx, SymTab); - } - break; - } - case ELF::SHT_ANDROID_REL: - case ELF::SHT_ANDROID_RELA: - for (const Elf_Rela &R : - unwrapOrError(this->FileName, Obj->android_relas(Sec))) - printRelocation(Obj, SecNdx, R, ++RelNdx, SymTab); - break; - } -} - template template void LLVMStyle::printRelocation(const ELFO *Obj, unsigned SecIndex, @@ -6320,7 +6319,17 @@ if (opts::SectionRelocations) { ListScope D(W, "Relocations"); - printRelocations(&Sec, Obj); + this->printRelocationsHelper( + Obj, Sec, + [&](const ELFO *Obj, unsigned SecIndex, unsigned RelIndex, + const Elf_Shdr *SymTab, const Relocation &R) { + if (R.Type == Relocation::RelType::Rel) + printRelocation(Obj, SecIndex, R.Rel, RelIndex, SymTab); + else if (R.Type == Relocation::RelType::Rela) + printRelocation(Obj, SecIndex, R.Rela, RelIndex, SymTab); + else + W.startLine() << W.hex(R.Relr) << "\n"; + }); } if (opts::SectionSymbols) {