From 14f292d00e26cb99909e4d192bc78d7e715ecc8c Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Sat, 18 Mar 2023 01:36:40 +0000 Subject: [PATCH] [llvm-readobj] Output valid JSON for GroupSections The current implementation output the LLVM formatted heading for group sections, which was not valid JSON. This patch provides two small customization points that allow the heading to vary between the two implementations, and another that allows the section members to be output as valid JSON objects. Reviewed By: jhenderson Differential Revision: https://reviews.llvm.org/D137095 --- llvm/test/tools/llvm-readobj/ELF/groups.test | 52 ++++++++++++++++++++++++++++ llvm/tools/llvm-readobj/ELFDumper.cpp | 49 +++++++++++++++++++++++--- 2 files changed, 97 insertions(+), 4 deletions(-) diff --git a/llvm/test/tools/llvm-readobj/ELF/groups.test b/llvm/test/tools/llvm-readobj/ELF/groups.test index afa5fb0..8bb80c0 100644 --- a/llvm/test/tools/llvm-readobj/ELF/groups.test +++ b/llvm/test/tools/llvm-readobj/ELF/groups.test @@ -4,6 +4,7 @@ # RUN: yaml2obj %s -o %t.o # RUN: llvm-readobj -g %t.o | FileCheck %s # RUN: llvm-readobj --elf-section-groups %t.o | FileCheck %s +# RUN: llvm-readobj --elf-section-groups %t.o --elf-output-style=JSON --pretty-print | FileCheck %s --check-prefix=JSON # RUN: llvm-readelf -g %t.o | FileCheck --check-prefix=GNU %s # CHECK: Groups { @@ -41,6 +42,57 @@ # GNU-NEXT: [ 5] .text.bar # GNU-NEXT: [ 6] .rela.text.bar +# JSON: "Groups": { +# JSON-NEXT: "Group": { +# JSON-NEXT: "Name": { +# JSON-NEXT: "Name": ".group", +# JSON-NEXT: "Value": 16 +# JSON-NEXT: }, +# JSON-NEXT: "Index": 1, +# JSON-NEXT: "Link": 7, +# JSON-NEXT: "Info": 1, +# JSON-NEXT: "Type": { +# JSON-NEXT: "Name": "COMDAT", +# JSON-NEXT: "Value": 1 +# JSON-NEXT: }, +# JSON-NEXT: "Signature": "foo", +# JSON-NEXT: "GroupSections": [ +# JSON-NEXT: { +# JSON-NEXT: "Name": ".text.foo", +# JSON-NEXT: "Index": 3 +# JSON-NEXT: }, +# JSON-NEXT: { +# JSON-NEXT: "Name": ".rela.text.foo", +# JSON-NEXT: "Index": 4 +# JSON-NEXT: } +# JSON-NEXT: ] +# JSON-NEXT: }, +# JSON-NEXT: "Group": { +# JSON-NEXT: "Name": { +# JSON-NEXT: "Name": ".group1", +# JSON-NEXT: "Value": 64 +# JSON-NEXT: }, +# JSON-NEXT: "Index": 2, +# JSON-NEXT: "Link": 7, +# JSON-NEXT: "Info": 2, +# JSON-NEXT: "Type": { +# JSON-NEXT: "Name": "COMDAT", +# JSON-NEXT: "Value": 1 +# JSON-NEXT: }, +# JSON-NEXT: "Signature": "bar", +# JSON-NEXT: "GroupSections": [ +# JSON-NEXT: { +# JSON-NEXT: "Name": ".text.bar", +# JSON-NEXT: "Index": 5 +# JSON-NEXT: }, +# JSON-NEXT: { +# JSON-NEXT: "Name": ".rela.text.bar", +# JSON-NEXT: "Index": 6 +# JSON-NEXT: } +# JSON-NEXT: ] +# JSON-NEXT: } +# JSON-NEXT: } + --- !ELF FileHeader: Class: ELFCLASS64 diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 7ff1435..2434aa7 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -712,6 +712,7 @@ private: virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const; protected: + virtual std::string getGroupSectionHeaderName() const; void printSymbolOtherField(const Elf_Sym &Symbol) const; virtual void printExpandedRelRelaReloc(const Relocation &R, StringRef SymbolName, @@ -721,6 +722,8 @@ protected: StringRef RelocName); virtual void printRelocationSectionInfo(const Elf_Shdr &Sec, StringRef Name, const unsigned SecNdx); + virtual void printSectionGroupMembers(StringRef Name, uint64_t Idx) const; + virtual void printEmptyGroupMessage() const; ScopedPrinter &W; }; @@ -734,6 +737,8 @@ public: JSONELFDumper(const object::ELFObjectFile &ObjF, ScopedPrinter &Writer) : LLVMELFDumper(ObjF, Writer) {} + std::string getGroupSectionHeaderName() const override; + void printFileSummary(StringRef FileStr, ObjectFile &Obj, ArrayRef InputFilenames, const Archive *A) override; @@ -746,6 +751,10 @@ public: void printRelocationSectionInfo(const Elf_Shdr &Sec, StringRef Name, const unsigned SecNdx) override; + void printSectionGroupMembers(StringRef Name, uint64_t Idx) const override; + + void printEmptyGroupMessage() const override; + private: std::unique_ptr FileScope; }; @@ -6717,9 +6726,9 @@ template void LLVMELFDumper::printGroupSections() { W.printNumber("Link", G.Link); W.printNumber("Info", G.Info); W.printHex("Type", getGroupType(G.Type), G.Type); - W.startLine() << "Signature: " << G.Signature << "\n"; + W.printString("Signature", G.Signature); - ListScope L(W, "Section(s) in group"); + ListScope L(W, getGroupSectionHeaderName()); for (const GroupMember &GM : G.Members) { const GroupSection *MainGroup = Map[GM.Index]; if (MainGroup != &G) @@ -6729,12 +6738,23 @@ template void LLVMELFDumper::printGroupSections() { Twine(MainGroup->Index) + ", was also found in the group section with index " + Twine(G.Index)); - W.startLine() << GM.Name << " (" << GM.Index << ")\n"; + printSectionGroupMembers(GM.Name, GM.Index); } } if (V.empty()) - W.startLine() << "There are no group sections in the file.\n"; + printEmptyGroupMessage(); +} + +template +std::string LLVMELFDumper::getGroupSectionHeaderName() const { + return "Section(s) in group"; +} + +template +void LLVMELFDumper::printSectionGroupMembers(StringRef Name, + uint64_t Idx) const { + W.startLine() << Name << " (" << Idx << ")\n"; } template void LLVMELFDumper::printRelocations() { @@ -6787,6 +6807,10 @@ void LLVMELFDumper::printRelocationSectionInfo(const Elf_Shdr &Sec, this->printRelocationsHelper(Sec); } +template void LLVMELFDumper::printEmptyGroupMessage() const { + W.startLine() << "There are no group sections in the file.\n"; +} + template void LLVMELFDumper::printRelRelaReloc(const Relocation &R, const RelSymbol &RelSym) { @@ -7733,3 +7757,20 @@ void JSONELFDumper::printRelocationSectionInfo(const Elf_Shdr &Sec, ListScope D(this->W, "Relocs"); this->printRelocationsHelper(Sec); } + +template +std::string JSONELFDumper::getGroupSectionHeaderName() const { + return "GroupSections"; +} + +template +void JSONELFDumper::printSectionGroupMembers(StringRef Name, + uint64_t Idx) const { + DictScope Grp(this->W); + this->W.printString("Name", Name); + this->W.printNumber("Index", Idx); +} + +template void JSONELFDumper::printEmptyGroupMessage() const { + // JSON output does not need to print anything for empty groups +} -- 2.7.4