diff --git a/llvm/test/tools/llvm-readobj/ELF/llvm-vs-json-format.test b/llvm/test/tools/llvm-readobj/ELF/llvm-vs-json-format.test --- a/llvm/test/tools/llvm-readobj/ELF/llvm-vs-json-format.test +++ b/llvm/test/tools/llvm-readobj/ELF/llvm-vs-json-format.test @@ -327,8 +327,6 @@ # JSON-EXPAND-64-NEXT: } # JSON-EXPAND-64-NEXT:] - - --- !ELF FileHeader: Class: ELFCLASS64 @@ -413,3 +411,139 @@ Value: 0xFFFFFFFFFFFFFFFF +## Check that group sections are consistent between LLVM and JSON formats + +# RUN: yaml2obj %s --docnum=3 -o %t-sg.o +# RUN: llvm-readobj --elf-section-groups %t-sg.o | FileCheck %s --check-prefix=LLVM-SG +# RUN: llvm-readobj --elf-section-groups %t-sg.o --elf-output-style=JSON --pretty-print | FileCheck %s --check-prefix=JSON-SG + +# LLVM-SG: Groups { +# LLVM-SG-NEXT: Group { +# LLVM-SG-NEXT: Name: .group +# LLVM-SG-NEXT: Index: 1 +# LLVM-SG-NEXT: Link: 7 +# LLVM-SG-NEXT: Info: 1 +# LLVM-SG-NEXT: Type: COMDAT +# LLVM-SG-NEXT: Signature: foo +# LLVM-SG-NEXT: Section(s) in group [ +# LLVM-SG-NEXT: .text.foo +# LLVM-SG-NEXT: .rela.text.foo +# LLVM-SG-NEXT: ] +# LLVM-SG-NEXT: } +# LLVM-SG-NEXT: Group { +# LLVM-SG-NEXT: Name: .group1 +# LLVM-SG-NEXT: Index: 2 +# LLVM-SG-NEXT: Link: 7 +# LLVM-SG-NEXT: Info: 2 +# LLVM-SG-NEXT: Type: COMDAT +# LLVM-SG-NEXT: Signature: bar +# LLVM-SG-NEXT: Section(s) in group [ +# LLVM-SG-NEXT: .text.bar +# LLVM-SG-NEXT: .rela.text.bar +# LLVM-SG-NEXT: ] +# LLVM-SG-NEXT: } + +# JSON-SG: "Groups": { +# JSON-SG-NEXT: "Group": { +# JSON-SG-NEXT: "Name": { +# JSON-SG-NEXT: "Name": ".group", +# JSON-SG-NEXT: "Value": 16 +# JSON-SG-NEXT: }, +# JSON-SG-NEXT: "Index": 1, +# JSON-SG-NEXT: "Link": 7, +# JSON-SG-NEXT: "Info": 1, +# JSON-SG-NEXT: "Type": { +# JSON-SG-NEXT: "Name": "COMDAT", +# JSON-SG-NEXT: "Value": 1 +# JSON-SG-NEXT: }, +# JSON-SG-NEXT: "Signature": "foo", +# JSON-SG-NEXT: "GroupSections": [ +# JSON-SG-NEXT: { +# JSON-SG-NEXT: "Name": ".text.foo", +# JSON-SG-NEXT: "Index": 3 +# JSON-SG-NEXT: }, +# JSON-SG-NEXT: { +# JSON-SG-NEXT: "Name": ".rela.text.foo", +# JSON-SG-NEXT: "Index": 4 +# JSON-SG-NEXT: } +# JSON-SG-NEXT: ] +# JSON-SG-NEXT: }, +# JSON-SG-NEXT: "Group": { +# JSON-SG-NEXT: "Name": { +# JSON-SG-NEXT: "Name": ".group1", +# JSON-SG-NEXT: "Value": 64 +# JSON-SG-NEXT: }, +# JSON-SG-NEXT: "Index": 2, +# JSON-SG-NEXT: "Link": 7, +# JSON-SG-NEXT: "Info": 2, +# JSON-SG-NEXT: "Type": { +# JSON-SG-NEXT: "Name": "COMDAT", +# JSON-SG-NEXT: "Value": 1 +# JSON-SG-NEXT: }, +# JSON-SG-NEXT: "Signature": "bar", +# JSON-SG-NEXT: "GroupSections": [ +# JSON-SG-NEXT: { +# JSON-SG-NEXT: "Name": ".text.bar", +# JSON-SG-NEXT: "Index": 5 +# JSON-SG-NEXT: }, +# JSON-SG-NEXT: { +# JSON-SG-NEXT: "Name": ".rela.text.bar", +# JSON-SG-NEXT: "Index": 6 +# JSON-SG-NEXT: } +# JSON-SG-NEXT: ] +# JSON-SG-NEXT: } +# JSON-SG-NEXT: } + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL +Sections: + - Name: .group + Type: SHT_GROUP + Link: [[SYMTAB1=.symtab]] + Info: foo + Members: + - SectionOrType: GRP_COMDAT + - SectionOrType: .text.foo + - SectionOrType: [[MEMBER1=.rela.text.foo]] + ShSize: [[SECSIZE1=]] + ShName: [[GROUP1SHNAME=]] + - Name: .group1 + Type: SHT_GROUP + Link: [[SYMTAB2=.symtab]] + Info: bar + Members: + - SectionOrType: GRP_COMDAT + - SectionOrType: [[MEMBER2=.text.bar]] + - SectionOrType: .rela.text.bar + ShSize: [[SECSIZE2=]] + - Name: .text.foo + Type: SHT_PROGBITS + - Name: .rela.text.foo + Type: SHT_RELA + Link: .symtab + Info: .text.foo + - Name: .text.bar + Type: SHT_PROGBITS + ShName: [[TEXTBARSHNAME=]] + - Name: .rela.text.bar + Type: SHT_RELA + Link: .symtab + Info: .text.bar + - Name: .symtab + Type: SHT_SYMTAB + Link: [[SYMTABLINK=.strtab]] + - Name: .strtab + Type: SHT_STRTAB + Content: [[STRTABCONTENT=]] +Symbols: + - Name: foo + Section: .text.foo + StName: [[SYM1STNAME=]] + - Name: bar + Section: .text.bar + StName: [[SYM2STNAME=]] + + 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 @@ -716,6 +716,10 @@ const StringRef RelocName); virtual void printRelocationInfo(const Elf_Shdr &Sec, const StringRef Name, const unsigned SecNdx); + virtual void printEmptyGroupMessage() const; + virtual void printSectionGroupMembers(const StringRef Name, + uint64_t Idx) const; + virtual std::string getGroupSectionHeaderName() const; ScopedPrinter &W; }; @@ -740,6 +744,11 @@ void printRelocationInfo(const Elf_Shdr &Sec, const StringRef Name, const unsigned SecNdx) override; + void printEmptyGroupMessage() const override; + + void printSectionGroupMembers(const StringRef Name, + uint64_t Idx) const override; + std::string getGroupSectionHeaderName() const override; private: std::unique_ptr FileScope; @@ -6658,9 +6667,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) @@ -6670,12 +6679,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 +void LLVMELFDumper::printSectionGroupMembers(const StringRef Name, + uint64_t Idx) const { + W.startLine() << Name << " (" << Idx << ")\n"; +} + +template +std::string LLVMELFDumper::getGroupSectionHeaderName() const { + return "Section(s) in group"; } template void LLVMELFDumper::printRelocations() { @@ -6728,6 +6748,10 @@ 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) { @@ -7636,3 +7660,20 @@ ListScope D(this->W, "Relocs"); this->printRelocationsHelper(Sec); } + +template void JSONELFDumper::printEmptyGroupMessage() const { + // JSON output does not need to print anything for empty groups +} + +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 +std::string JSONELFDumper::getGroupSectionHeaderName() const { + return "GroupSections"; +}