From 0af663f80da0009f6fd879cf4d41743d4c88a2db Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 14 Jul 2023 12:44:41 -0700 Subject: [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, 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 --- llvm/tools/llvm-objdump/llvm-objdump.cpp | 46 ++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 20 deletions(-) (limited to 'llvm/tools/llvm-objdump/llvm-objdump.cpp') diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index 052b7f1..4d2e59d 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -256,6 +256,22 @@ void Dumper::reportUniqueWarning(const Twine &Msg) { reportWarning(Msg, O.getFileName()); } +static Expected> createDumper(const ObjectFile &Obj) { + if (const auto *O = dyn_cast(&Obj)) + return createCOFFDumper(*O); + if (const auto *O = dyn_cast(&Obj)) + return createELFDumper(*O); + if (const auto *O = dyn_cast(&Obj)) + return createMachODumper(*O); + if (const auto *O = dyn_cast(&Obj)) + return createWasmDumper(*O); + if (const auto *O = dyn_cast(&Obj)) + return createXCOFFDumper(*O); + + return createStringError(errc::invalid_argument, + "unsupported object file format"); +} + namespace { struct FilterResult { // True if the section should not be skipped. @@ -2697,24 +2713,8 @@ static void printFaultMaps(const ObjectFile *Obj) { outs() << FMP; } -static void printPrivateFileHeaders(const ObjectFile *O, bool OnlyFirst) { - if (O->isELF()) { - printELFFileHeader(O); - printELFDynamicSection(O); - printELFSymbolVersionInfo(O); - return; - } - if (O->isCOFF()) - return printCOFFFileHeader(cast(*O)); - if (O->isWasm()) - return printWasmFileHeader(O); - if (O->isMachO()) { - printMachOFileHeader(O); - if (!OnlyFirst) - printMachOLoadCommands(O); - return; - } - reportError(O->getFileName(), "Invalid/Unsupported object file format"); +void Dumper::printPrivateHeaders(bool) { + reportError(O.getFileName(), "Invalid/Unsupported object file format"); } static void printFileHeaders(const ObjectFile *O) { @@ -2817,7 +2817,13 @@ static void checkForInvalidStartStopAddress(ObjectFile *Obj, static void dumpObject(ObjectFile *O, const Archive *A = nullptr, const Archive::Child *C = nullptr) { - Dumper D(*O); + Expected> DumperOrErr = createDumper(*O); + if (!DumperOrErr) { + reportError(DumperOrErr.takeError(), O->getFileName(), + A ? A->getFileName() : ""); + return; + } + Dumper &D = **DumperOrErr; // Avoid other output when using a raw option. if (!RawClangAST) { @@ -2842,7 +2848,7 @@ static void dumpObject(ObjectFile *O, const Archive *A = nullptr, if (FileHeaders) printFileHeaders(O); if (PrivateHeaders || FirstPrivateHeader) - printPrivateFileHeaders(O, FirstPrivateHeader); + D.printPrivateHeaders(FirstPrivateHeader); if (SectionHeaders) printSectionHeaders(*O); if (SymbolTable) -- cgit v1.1