diff options
author | Fangrui Song <i@maskray.me> | 2023-07-14 12:44:41 -0700 |
---|---|---|
committer | Fangrui Song <i@maskray.me> | 2023-07-14 12:44:41 -0700 |
commit | 0af663f80da0009f6fd879cf4d41743d4c88a2db (patch) | |
tree | da617484204f75590d8fc2155d1959312f65c0b7 /llvm/tools/llvm-objdump/ELFDump.cpp | |
parent | 21ca892f698ac59e86ede6e4a2d4d747b0a36ae8 (diff) | |
download | llvm-0af663f80da0009f6fd879cf4d41743d4c88a2db.zip llvm-0af663f80da0009f6fd879cf4d41743d4c88a2db.tar.gz llvm-0af663f80da0009f6fd879cf4d41743d4c88a2db.tar.bz2 |
[llvm-objdump] Create ObjectFile specific dumpers
We pay the one-off boilerplate overhead to create `*Dumper` classes that derive
from objdump::Dumper a la llvm-readobj. This has two primary advantages.
First, a lot object file format specific code can be moved from
llvm-objdump.cpp to *Dump.cpp files. Refactor `printPrivateHeaders` as
an example.
Second, with the introduction of ELFDumper<ELFT>, we can simplify
a few dispatch functions in ELFDump.cpp.
In addition, the ObjectFile specific dumpers contains a ObjectFile specific
reference so that we can remove a lot of `cast<*ObjectFile>(Obj)`.
Reviewed By: mtrofin
Differential Revision: https://reviews.llvm.org/D155045
Diffstat (limited to 'llvm/tools/llvm-objdump/ELFDump.cpp')
-rw-r--r-- | llvm/tools/llvm-objdump/ELFDump.cpp | 88 |
1 files changed, 46 insertions, 42 deletions
diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp index 6e42204..43ab309 100644 --- a/llvm/tools/llvm-objdump/ELFDump.cpp +++ b/llvm/tools/llvm-objdump/ELFDump.cpp @@ -24,6 +24,38 @@ using namespace llvm; using namespace llvm::object; using namespace llvm::objdump; +namespace { +template <typename ELFT> class ELFDumper : public Dumper { +public: + ELFDumper(const ELFObjectFile<ELFT> &O) : Dumper(O), Obj(O) {} + void printPrivateHeaders(bool MachOOnlyFirst) override; + +private: + const ELFObjectFile<ELFT> &Obj; + + const ELFFile<ELFT> &getELFFile() const { return Obj.getELFFile(); } + void printDynamicSection(); + void printProgramHeaders(); + void printSymbolVersion(); +}; +} // namespace + +template <class ELFT> +static std::unique_ptr<Dumper> createDumper(const ELFObjectFile<ELFT> &Obj) { + return std::make_unique<ELFDumper<ELFT>>(Obj); +} + +std::unique_ptr<Dumper> +objdump::createELFDumper(const object::ELFObjectFileBase &Obj) { + if (const auto *O = dyn_cast<ELF32LEObjectFile>(&Obj)) + return createDumper(*O); + if (const auto *O = dyn_cast<ELF32BEObjectFile>(&Obj)) + return createDumper(*O); + if (const auto *O = dyn_cast<ELF64LEObjectFile>(&Obj)) + return createDumper(*O); + return createDumper(cast<ELF64BEObjectFile>(Obj)); +} + template <class ELFT> static Expected<StringRef> getDynamicStrTab(const ELFFile<ELFT> &Elf) { auto DynamicEntriesOrError = Elf.dynamicEntries(); @@ -166,11 +198,11 @@ uint64_t objdump::getELFSectionLMA(const object::ELFSectionRef &Sec) { return getSectionLMA(ELFObj->getELFFile(), Sec); } -template <class ELFT> -static void printDynamicSection(const ELFFile<ELFT> &Elf, StringRef Filename) { +template <class ELFT> void ELFDumper<ELFT>::printDynamicSection() { + const ELFFile<ELFT> &Elf = getELFFile(); auto DynamicEntriesOrErr = Elf.dynamicEntries(); if (!DynamicEntriesOrErr) { - reportWarning(toString(DynamicEntriesOrErr.takeError()), Filename); + reportWarning(toString(DynamicEntriesOrErr.takeError()), Obj.getFileName()); return; } ArrayRef<typename ELFT::Dyn> DynamicEntries = *DynamicEntriesOrErr; @@ -200,21 +232,20 @@ static void printDynamicSection(const ELFFile<ELFT> &Elf, StringRef Filename) { outs() << (Data + Dyn.d_un.d_val) << "\n"; continue; } - reportWarning(toString(StrTabOrErr.takeError()), Filename); + reportWarning(toString(StrTabOrErr.takeError()), Obj.getFileName()); consumeError(StrTabOrErr.takeError()); } outs() << format(Fmt, (uint64_t)Dyn.d_un.d_val); } } -template <class ELFT> -static void printProgramHeaders(const ELFFile<ELFT> &Obj, StringRef FileName) { +template <class ELFT> void ELFDumper<ELFT>::printProgramHeaders() { outs() << "\nProgram Header:\n"; - auto ProgramHeaderOrError = Obj.program_headers(); + auto ProgramHeaderOrError = getELFFile().program_headers(); if (!ProgramHeaderOrError) { reportWarning("unable to read program headers: " + toString(ProgramHeaderOrError.takeError()), - FileName); + Obj.getFileName()); return; } @@ -338,9 +369,9 @@ static void printSymbolVersionDefinition(const typename ELFT::Shdr &Shdr, } } -template <class ELFT> -static void printSymbolVersionInfo(const ELFFile<ELFT> &Elf, - StringRef FileName) { +template <class ELFT> void ELFDumper<ELFT>::printSymbolVersion() { + const ELFFile<ELFT> &Elf = getELFFile(); + StringRef FileName = Obj.getFileName(); ArrayRef<typename ELFT::Shdr> Sections = unwrapOrError(Elf.sections(), FileName); for (const typename ELFT::Shdr &Shdr : Sections) { @@ -361,35 +392,8 @@ static void printSymbolVersionInfo(const ELFFile<ELFT> &Elf, } } -void objdump::printELFFileHeader(const object::ObjectFile *Obj) { - if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) - printProgramHeaders(ELFObj->getELFFile(), Obj->getFileName()); - else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) - printProgramHeaders(ELFObj->getELFFile(), Obj->getFileName()); - else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) - printProgramHeaders(ELFObj->getELFFile(), Obj->getFileName()); - else if (const auto *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) - printProgramHeaders(ELFObj->getELFFile(), Obj->getFileName()); -} - -void objdump::printELFDynamicSection(const object::ObjectFile *Obj) { - if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) - printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); - else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) - printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); - else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) - printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); - else if (const auto *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) - printDynamicSection(ELFObj->getELFFile(), Obj->getFileName()); -} - -void objdump::printELFSymbolVersionInfo(const object::ObjectFile *Obj) { - if (const auto *ELFObj = dyn_cast<ELF32LEObjectFile>(Obj)) - printSymbolVersionInfo(ELFObj->getELFFile(), Obj->getFileName()); - else if (const auto *ELFObj = dyn_cast<ELF32BEObjectFile>(Obj)) - printSymbolVersionInfo(ELFObj->getELFFile(), Obj->getFileName()); - else if (const auto *ELFObj = dyn_cast<ELF64LEObjectFile>(Obj)) - printSymbolVersionInfo(ELFObj->getELFFile(), Obj->getFileName()); - else if (const auto *ELFObj = dyn_cast<ELF64BEObjectFile>(Obj)) - printSymbolVersionInfo(ELFObj->getELFFile(), Obj->getFileName()); +template <class ELFT> void ELFDumper<ELFT>::printPrivateHeaders(bool) { + printProgramHeaders(); + printDynamicSection(); + printSymbolVersion(); } |