Index: llvm/test/tools/llvm-readobj/ELF/output-style.test =================================================================== --- llvm/test/tools/llvm-readobj/ELF/output-style.test +++ llvm/test/tools/llvm-readobj/ELF/output-style.test @@ -1,4 +1,4 @@ ## Error for an unknown output style. RUN: not llvm-readobj --elf-output-style=unknown 2>&1 | FileCheck %s -CHECK: error: --elf-output-style value should be either 'LLVM' or 'GNU' +CHECK: error: --elf-output-style value should be either 'LLVM', 'GNU', or 'JSON' Index: llvm/tools/llvm-readobj/ELFDumper.cpp =================================================================== --- llvm/tools/llvm-readobj/ELFDumper.cpp +++ llvm/tools/llvm-readobj/ELFDumper.cpp @@ -705,9 +705,18 @@ void printMipsPLT(const MipsGOTParser &Parser) override; void printMipsABIFlags() override; +protected: ScopedPrinter &W; }; +template class JSONELFDumper : public LLVMELFDumper { +public: + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + + JSONELFDumper(const object::ELFObjectFile &ObjF, ScopedPrinter &Writer) + : LLVMELFDumper(ObjF, Writer) {} +}; + } // end anonymous namespace namespace llvm { @@ -717,6 +726,8 @@ createELFDumper(const ELFObjectFile &Obj, ScopedPrinter &Writer) { if (opts::Output == opts::GNU) return std::make_unique>(Obj, Writer); + else if (opts::Output == opts::JSON) + return std::make_unique>(Obj, Writer); return std::make_unique>(Obj, Writer); } Index: llvm/tools/llvm-readobj/llvm-readobj.h =================================================================== --- llvm/tools/llvm-readobj/llvm-readobj.h +++ llvm/tools/llvm-readobj/llvm-readobj.h @@ -39,7 +39,7 @@ extern bool RawRelr; extern bool CodeViewSubsectionBytes; extern bool Demangle; -enum OutputStyleTy { LLVM, GNU }; +enum OutputStyleTy { LLVM, GNU, JSON }; extern OutputStyleTy Output; } // namespace opts Index: llvm/tools/llvm-readobj/llvm-readobj.cpp =================================================================== --- llvm/tools/llvm-readobj/llvm-readobj.cpp +++ llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -235,8 +235,11 @@ opts::Output = opts::OutputStyleTy::LLVM; else if (V == "GNU") opts::Output = opts::OutputStyleTy::GNU; + else if (V == "JSON") + opts::Output = opts::OutputStyleTy::JSON; else - error("--elf-output-style value should be either 'LLVM' or 'GNU'"); + error( + "--elf-output-style value should be either 'LLVM', 'GNU', or 'JSON'"); } opts::GnuHashTable = Args.hasArg(OPT_gnu_hash_table); opts::HashSymbols = Args.hasArg(OPT_hash_symbols); @@ -333,7 +336,11 @@ reportError(DumperOrErr.takeError(), FileStr); Dumper = (*DumperOrErr).get(); - if (opts::Output == opts::LLVM || opts::InputFilenames.size() > 1 || A) { + std::unique_ptr D; + if (opts::Output == opts::JSON) { + D = std::make_unique(Writer, FileStr); + } else if (opts::Output == opts::LLVM || opts::InputFilenames.size() > 1 || + A) { Writer.startLine() << "\n"; Writer.printString("File", FileStr); } @@ -550,6 +557,13 @@ OwningBinary(std::move(Bin), std::move(Buffer))); } +std::unique_ptr createWriter() { + if (opts::Output == opts::JSON) { + return std::make_unique(fouts()); + } + return std::make_unique(fouts()); +} + int main(int argc, char *argv[]) { InitLLVM X(argc, argv); BumpPtrAllocator A; @@ -610,16 +624,20 @@ opts::SectionHeaders = true; } - ScopedPrinter Writer(fouts()); + std::unique_ptr Writer = createWriter(); + std::unique_ptr D; + if (opts::Output == opts::JSON) + D = std::make_unique(*Writer.get()); + for (const std::string &I : opts::InputFilenames) - dumpInput(I, Writer); + dumpInput(I, *Writer.get()); if (opts::CodeViewMergedTypes) { if (opts::CodeViewEnableGHash) - dumpCodeViewMergedTypes(Writer, CVTypes.GlobalIDTable.records(), + dumpCodeViewMergedTypes(*Writer.get(), CVTypes.GlobalIDTable.records(), CVTypes.GlobalTypeTable.records()); else - dumpCodeViewMergedTypes(Writer, CVTypes.IDTable.records(), + dumpCodeViewMergedTypes(*Writer.get(), CVTypes.IDTable.records(), CVTypes.TypeTable.records()); }