[llvm] 824eef2 - [llvm-readobj] Add JSONScopedPrinter to llvm-readelf
Jayson Yan via llvm-commits
llvm-commits at lists.llvm.org
Fri Dec 10 10:58:11 PST 2021
Author: Jayson Yan
Date: 2021-12-10T18:57:34Z
New Revision: 824eef231a853d7054d55010c16654f6f20e0394
URL: https://github.com/llvm/llvm-project/commit/824eef231a853d7054d55010c16654f6f20e0394
DIFF: https://github.com/llvm/llvm-project/commit/824eef231a853d7054d55010c16654f6f20e0394.diff
LOG: [llvm-readobj] Add JSONScopedPrinter to llvm-readelf
Adds JSONScopedPrinter to llvm-readelf. It includes an empty
JSONELFDumper class which will be used to override any LLVMELFDumper
methods which utilize startLine() which JSONScopedPrinter cannot
provide.
Reviewed By: jhenderson
Differential Revision: https://reviews.llvm.org/D114225
Added:
llvm/test/tools/llvm-readobj/ELF/file-summary-json.test
llvm/test/tools/llvm-readobj/ELF/pretty-print.test
Modified:
llvm/docs/CommandGuide/llvm-readelf.rst
llvm/docs/CommandGuide/llvm-readobj.rst
llvm/test/tools/llvm-readobj/ELF/output-style.test
llvm/tools/llvm-readobj/ELFDumper.cpp
llvm/tools/llvm-readobj/ObjDumper.cpp
llvm/tools/llvm-readobj/ObjDumper.h
llvm/tools/llvm-readobj/Opts.td
llvm/tools/llvm-readobj/llvm-readobj.cpp
llvm/tools/llvm-readobj/llvm-readobj.h
Removed:
################################################################################
diff --git a/llvm/docs/CommandGuide/llvm-readelf.rst b/llvm/docs/CommandGuide/llvm-readelf.rst
index d83d566b2f82..dd4d82190eb5 100644
--- a/llvm/docs/CommandGuide/llvm-readelf.rst
+++ b/llvm/docs/CommandGuide/llvm-readelf.rst
@@ -72,9 +72,10 @@ OPTIONS
.. option:: --elf-output-style=<value>
- Format ELF information in the specified style. Valid options are ``LLVM`` and
- ``GNU``. ``LLVM`` output is an expanded and structured format, whilst ``GNU``
- (the default) output mimics the equivalent GNU :program:`readelf` output.
+ Format ELF information in the specified style. Valid options are ``LLVM``,
+ ``GNU``, and ``JSON``. ``LLVM`` output is an expanded and structured format.
+ ``GNU`` (the default) output mimics the equivalent GNU :program:`readelf`
+ output. ``JSON`` is JSON formatted output intended for machine consumption.
.. option:: --section-groups, -g
@@ -127,6 +128,11 @@ OPTIONS
Display all notes.
+.. option:: --pretty-print
+
+ When used with :option:`--elf-output-style`, JSON output will be formatted in
+ a more readable format.
+
.. option:: --program-headers, --segments, -l
Display the program headers.
diff --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst
index e7e6c73b3148..ef2ea3eb0e58 100644
--- a/llvm/docs/CommandGuide/llvm-readobj.rst
+++ b/llvm/docs/CommandGuide/llvm-readobj.rst
@@ -183,9 +183,10 @@ The following options are implemented only for the ELF file format.
.. option:: --elf-output-style=<value>
- Format ELF information in the specified style. Valid options are ``LLVM`` and
- ``GNU``. ``LLVM`` output (the default) is an expanded and structured format,
- whilst ``GNU`` output mimics the equivalent GNU :program:`readelf` output.
+ Format ELF information in the specified style. Valid options are ``LLVM``,
+ ``GNU``, and ``JSON``. ``LLVM`` output (the default) is an expanded and
+ structured format. ``GNU`` output mimics the equivalent GNU :program:`readelf`
+ output. ``JSON`` is JSON formatted output intended for machine consumption.
.. option:: --section-groups, -g
@@ -207,6 +208,11 @@ The following options are implemented only for the ELF file format.
Display all notes.
+.. option:: --pretty-print
+
+ When used with :option:`--elf-output-style`, JSON output will be formatted in
+ a more readable format.
+
.. option:: --program-headers, --segments, -l
Display the program headers.
diff --git a/llvm/test/tools/llvm-readobj/ELF/file-summary-json.test b/llvm/test/tools/llvm-readobj/ELF/file-summary-json.test
new file mode 100644
index 000000000000..81ea6d86b7a7
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/file-summary-json.test
@@ -0,0 +1,114 @@
+## Test how we output JSON file summaries.
+
+# RUN: rm -rf %t.dir
+# RUN: mkdir -p %t.dir
+# RUN: yaml2obj %s -o %t.dir/obj
+
+## Test outputting file summary for a single file.
+# RUN: llvm-readobj --elf-output-style=JSON --pretty-print %t.dir/obj | \
+# RUN: FileCheck %s -DFILE="%t.dir/obj" --check-prefix=SINGLE \
+# RUN: --match-full-lines --strict-whitespace --implicit-check-not={{.}}
+
+# SINGLE:[
+# SINGLE-NEXT: {
+# SINGLE-NEXT: "[[FILE]]": {
+# SINGLE-NEXT: "FileSummary": {
+# SINGLE-NEXT: "File": "[[FILE]]",
+# SINGLE-NEXT: "Format": "elf64-x86-64",
+# SINGLE-NEXT: "Arch": "x86_64",
+# SINGLE-NEXT: "AddressSize": "64bit",
+# SINGLE-NEXT: "LoadName": "<Not found>"
+# SINGLE-NEXT: }
+# SINGLE-NEXT: }
+# SINGLE-NEXT: }
+# SINGLE-NEXT:]
+
+## Test outputting file summary for multiple files.
+# RUN: llvm-readobj --elf-output-style=JSON --pretty-print %t.dir/obj %t.dir/obj | \
+# RUN: FileCheck %s -DFILE="%t.dir/obj" --check-prefix=MULTI \
+# RUN: --match-full-lines --strict-whitespace --implicit-check-not={{.}}
+
+# MULTI:[
+# MULTI-NEXT: {
+# MULTI-NEXT: "[[FILE]]": {
+# MULTI-NEXT: "FileSummary": {
+# MULTI-NEXT: "File": "[[FILE]]",
+# MULTI-NEXT: "Format": "elf64-x86-64",
+# MULTI-NEXT: "Arch": "x86_64",
+# MULTI-NEXT: "AddressSize": "64bit",
+# MULTI-NEXT: "LoadName": "<Not found>"
+# MULTI-NEXT: }
+# MULTI-NEXT: }
+# MULTI-NEXT: },
+# MULTI-NEXT: {
+# MULTI-NEXT: "[[FILE]]": {
+# MULTI-NEXT: "FileSummary": {
+# MULTI-NEXT: "File": "[[FILE]]",
+# MULTI-NEXT: "Format": "elf64-x86-64",
+# MULTI-NEXT: "Arch": "x86_64",
+# MULTI-NEXT: "AddressSize": "64bit",
+# MULTI-NEXT: "LoadName": "<Not found>"
+# MULTI-NEXT: }
+# MULTI-NEXT: }
+# MULTI-NEXT: }
+# MULTI-NEXT:]
+
+## Test outputting file summary for an archive with a single file.
+# RUN: rm -f %t.archive-single
+# RUN: llvm-ar rc %t.archive-single %t.dir/obj
+# RUN: llvm-readobj --elf-output-style=JSON --pretty-print %t.archive-single | \
+# RUN: FileCheck %s -DARFILE="%t.archive-single" --check-prefix=ARCH-SINGLE \
+# RUN: --match-full-lines --strict-whitespace --implicit-check-not={{.}}
+
+# ARCH-SINGLE:[
+# ARCH-SINGLE-NEXT: {
+# ARCH-SINGLE-NEXT: "[[ARFILE]](obj)": {
+# ARCH-SINGLE-NEXT: "FileSummary": {
+# ARCH-SINGLE-NEXT: "File": "[[ARFILE]](obj)",
+# ARCH-SINGLE-NEXT: "Format": "elf64-x86-64",
+# ARCH-SINGLE-NEXT: "Arch": "x86_64",
+# ARCH-SINGLE-NEXT: "AddressSize": "64bit",
+# ARCH-SINGLE-NEXT: "LoadName": "<Not found>"
+# ARCH-SINGLE-NEXT: }
+# ARCH-SINGLE-NEXT: }
+# ARCH-SINGLE-NEXT: }
+# ARCH-SINGLE-NEXT:]
+
+## Test outputting file summary for an archive with multiple files.
+# RUN: rm -f %t.archive-multiple
+# RUN: llvm-ar rc %t.archive-multiple %t.dir/obj %t.dir/obj
+# RUN: llvm-readobj --elf-output-style=JSON --pretty-print %t.archive-multiple | \
+# RUN: FileCheck %s -DARFILE="%t.archive-multiple" --check-prefix=ARCH-MULTI \
+# RUN: --match-full-lines --strict-whitespace --implicit-check-not={{.}}
+
+# ARCH-MULTI:[
+# ARCH-MULTI-NEXT: {
+# ARCH-MULTI-NEXT: "[[ARFILE]](obj)": {
+# ARCH-MULTI-NEXT: "FileSummary": {
+# ARCH-MULTI-NEXT: "File": "[[ARFILE]](obj)",
+# ARCH-MULTI-NEXT: "Format": "elf64-x86-64",
+# ARCH-MULTI-NEXT: "Arch": "x86_64",
+# ARCH-MULTI-NEXT: "AddressSize": "64bit",
+# ARCH-MULTI-NEXT: "LoadName": "<Not found>"
+# ARCH-MULTI-NEXT: }
+# ARCH-MULTI-NEXT: }
+# ARCH-MULTI-NEXT: },
+# ARCH-MULTI-NEXT: {
+# ARCH-MULTI-NEXT: "[[ARFILE]](obj)": {
+# ARCH-MULTI-NEXT: "FileSummary": {
+# ARCH-MULTI-NEXT: "File": "[[ARFILE]](obj)",
+# ARCH-MULTI-NEXT: "Format": "elf64-x86-64",
+# ARCH-MULTI-NEXT: "Arch": "x86_64",
+# ARCH-MULTI-NEXT: "AddressSize": "64bit",
+# ARCH-MULTI-NEXT: "LoadName": "<Not found>"
+# ARCH-MULTI-NEXT: }
+# ARCH-MULTI-NEXT: }
+# ARCH-MULTI-NEXT: }
+# ARCH-MULTI-NEXT:]
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
diff --git a/llvm/test/tools/llvm-readobj/ELF/output-style.test b/llvm/test/tools/llvm-readobj/ELF/output-style.test
index 1ad347a08170..a79c6e993399 100644
--- a/llvm/test/tools/llvm-readobj/ELF/output-style.test
+++ b/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', but was 'unknown'
diff --git a/llvm/test/tools/llvm-readobj/ELF/pretty-print.test b/llvm/test/tools/llvm-readobj/ELF/pretty-print.test
new file mode 100644
index 000000000000..844d73af5d40
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/pretty-print.test
@@ -0,0 +1,48 @@
+## Test the JSON pretty-print flag.
+#
+# RUN: yaml2obj %s -o %t.pretty
+
+## Test JSON with pretty-print off.
+# RUN: llvm-readobj --elf-output-style=JSON %t.pretty | \
+# RUN: FileCheck %s -DFILE="%t.pretty" --check-prefix=NO-PRETTY \
+# RUN: --strict-whitespace --implicit-check-not={{.}}
+
+# NO-PRETTY:[
+# NO-PRETTY-SAME:{
+# NO-PRETTY-SAME:"[[FILE]]":{
+# NO-PRETTY-SAME:"FileSummary":{
+# NO-PRETTY-SAME:"File":"[[FILE]]",
+# NO-PRETTY-SAME:"Format":"elf64-x86-64",
+# NO-PRETTY-SAME:"Arch":"x86_64",
+# NO-PRETTY-SAME:"AddressSize":"64bit",
+# NO-PRETTY-SAME:"LoadName":"<Not found>"
+# NO-PRETTY-SAME:}
+# NO-PRETTY-SAME:}
+# NO-PRETTY-SAME:}
+# NO-PRETTY-SAME:]
+
+## Test JSON with pretty-print on.
+# RUN: llvm-readobj --elf-output-style=JSON --pretty-print %t.pretty | \
+# RUN: FileCheck %s -DFILE="%t.pretty" --check-prefix=PRETTY \
+# RUN: --match-full-lines --strict-whitespace --implicit-check-not={{.}}
+
+# PRETTY:[
+# PRETTY-NEXT: {
+# PRETTY-NEXT: "[[FILE]]": {
+# PRETTY-NEXT: "FileSummary": {
+# PRETTY-NEXT: "File": "[[FILE]]",
+# PRETTY-NEXT: "Format": "elf64-x86-64",
+# PRETTY-NEXT: "Arch": "x86_64",
+# PRETTY-NEXT: "AddressSize": "64bit",
+# PRETTY-NEXT: "LoadName": "<Not found>"
+# PRETTY-NEXT: }
+# PRETTY-NEXT: }
+# PRETTY-NEXT: }
+# PRETTY-NEXT:]
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 431b20f77a58..2f64b079d612 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -31,6 +31,7 @@
#include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Demangle/Demangle.h"
+#include "llvm/Object/Archive.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/ELFTypes.h"
@@ -548,6 +549,9 @@ template <typename ELFT> class GNUELFDumper : public ELFDumper<ELFT> {
assert(&this->W.getOStream() == &llvm::fouts());
}
+ void printFileSummary(StringRef FileStr, ObjectFile &Obj,
+ ArrayRef<std::string> InputFilenames,
+ const Archive *A) override;
void printFileHeaders() override;
void printGroupSections() override;
void printRelocations() override;
@@ -697,9 +701,27 @@ template <typename ELFT> class LLVMELFDumper : public ELFDumper<ELFT> {
void printMipsPLT(const MipsGOTParser<ELFT> &Parser) override;
void printMipsABIFlags() override;
+protected:
ScopedPrinter &W;
};
+// JSONELFDumper shares most of the same implementation as LLVMELFDumper except
+// it uses a JSONScopedPrinter.
+template <typename ELFT> class JSONELFDumper : public LLVMELFDumper<ELFT> {
+public:
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
+
+ JSONELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer)
+ : LLVMELFDumper<ELFT>(ObjF, Writer) {}
+
+ void printFileSummary(StringRef FileStr, ObjectFile &Obj,
+ ArrayRef<std::string> InputFilenames,
+ const Archive *A) override;
+
+private:
+ std::unique_ptr<DictScope> FileScope;
+};
+
} // end anonymous namespace
namespace llvm {
@@ -709,6 +731,8 @@ static std::unique_ptr<ObjDumper>
createELFDumper(const ELFObjectFile<ELFT> &Obj, ScopedPrinter &Writer) {
if (opts::Output == opts::GNU)
return std::make_unique<GNUELFDumper<ELFT>>(Obj, Writer);
+ else if (opts::Output == opts::JSON)
+ return std::make_unique<JSONELFDumper<ELFT>>(Obj, Writer);
return std::make_unique<LLVMELFDumper<ELFT>>(Obj, Writer);
}
@@ -3225,6 +3249,16 @@ static const EnumEntry<unsigned> *getObjectFileEnumEntry(unsigned Type) {
return nullptr;
}
+template <class ELFT>
+void GNUELFDumper<ELFT>::printFileSummary(StringRef FileStr, ObjectFile &Obj,
+ ArrayRef<std::string> InputFilenames,
+ const Archive *A) {
+ if (InputFilenames.size() > 1 || A) {
+ this->W.startLine() << "\n";
+ this->W.printString("File", FileStr);
+ }
+}
+
template <class ELFT> void GNUELFDumper<ELFT>::printFileHeaders() {
const Elf_Ehdr &e = this->Obj.getHeader();
OS << "ELF Header:\n";
@@ -7306,3 +7340,18 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printMipsABIFlags() {
W.printFlags("Flags 1", Flags->flags1, makeArrayRef(ElfMipsFlags1));
W.printHex("Flags 2", Flags->flags2);
}
+
+template <class ELFT>
+void JSONELFDumper<ELFT>::printFileSummary(StringRef FileStr, ObjectFile &Obj,
+ ArrayRef<std::string> InputFilenames,
+ const Archive *A) {
+ FileScope = std::make_unique<DictScope>(this->W, FileStr);
+ DictScope D(this->W, "FileSummary");
+ this->W.printString("File", FileStr);
+ this->W.printString("Format", Obj.getFileFormatName());
+ this->W.printString("Arch", Triple::getArchTypeName(Obj.getArch()));
+ this->W.printString(
+ "AddressSize",
+ std::string(formatv("{0}bit", 8 * Obj.getBytesInAddress())));
+ this->printLoadName();
+}
diff --git a/llvm/tools/llvm-readobj/ObjDumper.cpp b/llvm/tools/llvm-readobj/ObjDumper.cpp
index dc4a3031f914..6dde3725b4d6 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.cpp
+++ b/llvm/tools/llvm-readobj/ObjDumper.cpp
@@ -13,6 +13,7 @@
#include "ObjDumper.h"
#include "llvm-readobj.h"
+#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatVariadic.h"
@@ -85,6 +86,18 @@ void ObjDumper::printAsStringList(StringRef StringContent,
}
}
+void ObjDumper::printFileSummary(StringRef FileStr, object::ObjectFile &Obj,
+ ArrayRef<std::string> InputFilenames,
+ const object::Archive *A) {
+ W.startLine() << "\n";
+ W.printString("File", FileStr);
+ W.printString("Format", Obj.getFileFormatName());
+ W.printString("Arch", Triple::getArchTypeName(Obj.getArch()));
+ W.printString("AddressSize",
+ std::string(formatv("{0}bit", 8 * Obj.getBytesInAddress())));
+ this->printLoadName();
+}
+
static std::vector<object::SectionRef>
getSectionRefsByNameOrIndex(const object::ObjectFile &Obj,
ArrayRef<std::string> Sections) {
diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h
index b395a95f3cb4..a09a243d381e 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/llvm/tools/llvm-readobj/ObjDumper.h
@@ -20,6 +20,7 @@
namespace llvm {
namespace object {
+class Archive;
class COFFImportFile;
class ObjectFile;
class XCOFFObjectFile;
@@ -39,6 +40,9 @@ class ObjDumper {
virtual bool canDumpContent() { return true; }
+ virtual void printFileSummary(StringRef FileStr, object::ObjectFile &Obj,
+ ArrayRef<std::string> InputFilenames,
+ const object::Archive *A);
virtual void printFileHeaders() = 0;
virtual void printSectionHeaders() = 0;
virtual void printRelocations() = 0;
diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td
index 7723691e8225..d0f273fa60c7 100644
--- a/llvm/tools/llvm-readobj/Opts.td
+++ b/llvm/tools/llvm-readobj/Opts.td
@@ -28,6 +28,7 @@ def expand_relocs : FF<"expand-relocs", "Expand each shown relocation to multipl
def file_header : FF<"file-header", "Display file header">;
def headers : FF<"headers", "Equivalent to setting: --file-header, --program-headers, --section-headers">;
defm hex_dump : Eq<"hex-dump", "Display the specified section(s) as hexadecimal bytes">, MetaVarName<"<name or index>">;
+def pretty_print : FF<"pretty-print", "Pretty print JSON output">;
def relocs : FF<"relocs", "Display the relocation entries in the file">;
def section_data : FF<"section-data", "Display section data for each section shown. This option has no effect for GNU style output">;
def section_details : FF<"section-details", "Display the section details">;
@@ -47,7 +48,7 @@ def unwind : FF<"unwind", "Display unwind information">;
def grp_elf : OptionGroup<"kind">, HelpText<"OPTIONS (ELF specific)">;
def dynamic_table : FF<"dynamic-table", "Display the dynamic section table">, Group<grp_elf>;
def elf_linker_options : FF<"elf-linker-options", "Display the .linker-options section">, Group<grp_elf>;
-defm elf_output_style : Eq<"elf-output-style", "Specify ELF dump style: LLVM or GNU">, Group<grp_elf>;
+defm elf_output_style : Eq<"elf-output-style", "Specify ELF dump style: LLVM, GNU, JSON">, Group<grp_elf>;
def histogram : FF<"histogram", "Display bucket list histogram for hash sections">, Group<grp_elf>;
def section_groups : FF<"section-groups", "Display section groups">, Group<grp_elf>;
def gnu_hash_table : FF<"gnu-hash-table", "Display the GNU hash table for dynamic symbols">, Group<grp_elf>;
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index a598e2c28832..46862bbad7cb 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -99,6 +99,7 @@ static bool DynamicSymbols;
static bool FileHeaders;
static bool Headers;
static std::vector<std::string> HexDump;
+static bool PrettyPrint;
static bool PrintStackMap;
static bool PrintStackSizes;
static bool Relocations;
@@ -230,13 +231,17 @@ static void parseOptions(const opt::InputArgList &Args) {
opts::DynamicTable = Args.hasArg(OPT_dynamic_table);
opts::ELFLinkerOptions = Args.hasArg(OPT_elf_linker_options);
if (Arg *A = Args.getLastArg(OPT_elf_output_style_EQ)) {
- StringRef V(A->getValue());
- if (V == "LLVM")
- opts::Output = opts::OutputStyleTy::LLVM;
- else if (V == "GNU")
- opts::Output = opts::OutputStyleTy::GNU;
- else
- error("--elf-output-style value should be either 'LLVM' or 'GNU'");
+ std::string OutputStyleChoice = A->getValue();
+ opts::Output = StringSwitch<opts::OutputStyleTy>(OutputStyleChoice)
+ .Case("LLVM", opts::OutputStyleTy::LLVM)
+ .Case("GNU", opts::OutputStyleTy::GNU)
+ .Case("JSON", opts::OutputStyleTy::JSON)
+ .Default(opts::OutputStyleTy::UNKNOWN);
+ if (opts::Output == opts::OutputStyleTy::UNKNOWN) {
+ error("--elf-output-style value should be either 'LLVM', 'GNU', or "
+ "'JSON', but was '" +
+ OutputStyleChoice + "'");
+ }
}
opts::GnuHashTable = Args.hasArg(OPT_gnu_hash_table);
opts::HashSymbols = Args.hasArg(OPT_hash_symbols);
@@ -244,6 +249,7 @@ static void parseOptions(const opt::InputArgList &Args) {
opts::HashHistogram = Args.hasArg(OPT_histogram);
opts::NeededLibraries = Args.hasArg(OPT_needed_libs);
opts::Notes = Args.hasArg(OPT_notes);
+ opts::PrettyPrint = Args.hasArg(OPT_pretty_print);
opts::ProgramHeaders = Args.hasArg(OPT_program_headers);
opts::RawRelr = Args.hasArg(OPT_raw_relr);
opts::SectionGroups = Args.hasArg(OPT_section_groups);
@@ -333,18 +339,7 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
reportError(DumperOrErr.takeError(), FileStr);
Dumper = (*DumperOrErr).get();
- if (opts::Output == opts::LLVM || opts::InputFilenames.size() > 1 || A) {
- Writer.startLine() << "\n";
- Writer.printString("File", FileStr);
- }
- if (opts::Output == opts::LLVM) {
- Writer.printString("Format", Obj.getFileFormatName());
- Writer.printString("Arch", Triple::getArchTypeName(Obj.getArch()));
- Writer.printString(
- "AddressSize",
- std::string(formatv("{0}bit", 8 * Obj.getBytesInAddress())));
- Dumper->printLoadName();
- }
+ Dumper->printFileSummary(FileStr, Obj, opts::InputFilenames, A);
if (opts::FileHeaders)
Dumper->printFileHeaders();
@@ -550,6 +545,13 @@ static void dumpInput(StringRef File, ScopedPrinter &Writer) {
OwningBinary<Binary>(std::move(Bin), std::move(Buffer)));
}
+std::unique_ptr<ScopedPrinter> createWriter() {
+ if (opts::Output == opts::JSON)
+ return std::make_unique<JSONScopedPrinter>(
+ fouts(), opts::PrettyPrint ? 2 : 0, std::make_unique<ListScope>());
+ return std::make_unique<ScopedPrinter>(fouts());
+}
+
int main(int argc, char *argv[]) {
InitLLVM X(argc, argv);
BumpPtrAllocator A;
@@ -610,16 +612,17 @@ int main(int argc, char *argv[]) {
opts::SectionHeaders = true;
}
- ScopedPrinter Writer(fouts());
+ std::unique_ptr<ScopedPrinter> Writer = createWriter();
+
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());
}
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.h b/llvm/tools/llvm-readobj/llvm-readobj.h
index 7672da5c0aae..0ea695d1673d 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.h
+++ b/llvm/tools/llvm-readobj/llvm-readobj.h
@@ -39,7 +39,7 @@ extern bool ExpandRelocs;
extern bool RawRelr;
extern bool CodeViewSubsectionBytes;
extern bool Demangle;
-enum OutputStyleTy { LLVM, GNU };
+enum OutputStyleTy { LLVM, GNU, JSON, UNKNOWN };
extern OutputStyleTy Output;
} // namespace opts
More information about the llvm-commits
mailing list