diff --git a/llvm/test/tools/llvm-readobj/ELF/groups.test b/llvm/test/tools/llvm-readobj/ELF/groups.test --- 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 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -718,6 +718,7 @@ 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, const StringRef SymbolName, @@ -727,6 +728,9 @@ const StringRef RelocName); virtual void printRelocationSectionInfo(const Elf_Shdr &Sec, const StringRef Name, const unsigned SecNdx); + virtual void printSectionGroupMembers(const StringRef Name, + uint64_t Idx) const; + virtual void printEmptyGroupMessage() const; ScopedPrinter &W; }; @@ -740,6 +744,8 @@ 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; @@ -751,6 +757,12 @@ void printRelocationSectionInfo(const Elf_Shdr &Sec, const StringRef Name, const unsigned SecNdx) override; + + void printSectionGroupMembers(const StringRef Name, + uint64_t Idx) const override; + + void printEmptyGroupMessage() const override; + private: std::unique_ptr FileScope; }; @@ -6742,9 +6754,9 @@ 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) @@ -6754,12 +6766,23 @@ 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(const StringRef Name, + uint64_t Idx) const { + W.startLine() << Name << " (" << Idx << ")\n"; } template void LLVMELFDumper::printRelocations() { @@ -6811,6 +6834,11 @@ DictScope D(W,(Twine("Section (") + Twine(SecNdx) +") " + Name).str()); 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) { @@ -7736,3 +7764,20 @@ ListScope D(this->W, "Relocs"); this->printRelocationsHelper(Sec); } + +template +std::string JSONELFDumper::getGroupSectionHeaderName() const { + return "GroupSections"; +} + +template +void JSONELFDumper::printSectionGroupMembers(const 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 +}