Skip to content

Commit

Permalink
[llvm-readobj] Output valid JSON for GroupSections
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ilovepi committed Mar 18, 2023
1 parent 4e844a1 commit 14f292d
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 4 deletions.
52 changes: 52 additions & 0 deletions llvm/test/tools/llvm-readobj/ELF/groups.test
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
49 changes: 45 additions & 4 deletions llvm/tools/llvm-readobj/ELFDumper.cpp
Expand Up @@ -712,6 +712,7 @@ template <typename ELFT> class LLVMELFDumper : public ELFDumper<ELFT> {
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<ELFT> &R,
StringRef SymbolName,
Expand All @@ -721,6 +722,8 @@ template <typename ELFT> class LLVMELFDumper : public ELFDumper<ELFT> {
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;
};
Expand All @@ -734,6 +737,8 @@ template <typename ELFT> class JSONELFDumper : public LLVMELFDumper<ELFT> {
JSONELFDumper(const object::ELFObjectFile<ELFT> &ObjF, ScopedPrinter &Writer)
: LLVMELFDumper<ELFT>(ObjF, Writer) {}

std::string getGroupSectionHeaderName() const override;

void printFileSummary(StringRef FileStr, ObjectFile &Obj,
ArrayRef<std::string> InputFilenames,
const Archive *A) override;
Expand All @@ -746,6 +751,10 @@ template <typename ELFT> class JSONELFDumper : public LLVMELFDumper<ELFT> {
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<DictScope> FileScope;
};
Expand Down Expand Up @@ -6717,9 +6726,9 @@ template <class ELFT> void LLVMELFDumper<ELFT>::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)
Expand All @@ -6729,12 +6738,23 @@ template <class ELFT> void LLVMELFDumper<ELFT>::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 <class ELFT>
std::string LLVMELFDumper<ELFT>::getGroupSectionHeaderName() const {
return "Section(s) in group";
}

template <class ELFT>
void LLVMELFDumper<ELFT>::printSectionGroupMembers(StringRef Name,
uint64_t Idx) const {
W.startLine() << Name << " (" << Idx << ")\n";
}

template <class ELFT> void LLVMELFDumper<ELFT>::printRelocations() {
Expand Down Expand Up @@ -6787,6 +6807,10 @@ void LLVMELFDumper<ELFT>::printRelocationSectionInfo(const Elf_Shdr &Sec,
this->printRelocationsHelper(Sec);
}

template <class ELFT> void LLVMELFDumper<ELFT>::printEmptyGroupMessage() const {
W.startLine() << "There are no group sections in the file.\n";
}

template <class ELFT>
void LLVMELFDumper<ELFT>::printRelRelaReloc(const Relocation<ELFT> &R,
const RelSymbol<ELFT> &RelSym) {
Expand Down Expand Up @@ -7733,3 +7757,20 @@ void JSONELFDumper<ELFT>::printRelocationSectionInfo(const Elf_Shdr &Sec,
ListScope D(this->W, "Relocs");
this->printRelocationsHelper(Sec);
}

template <class ELFT>
std::string JSONELFDumper<ELFT>::getGroupSectionHeaderName() const {
return "GroupSections";
}

template <class ELFT>
void JSONELFDumper<ELFT>::printSectionGroupMembers(StringRef Name,
uint64_t Idx) const {
DictScope Grp(this->W);
this->W.printString("Name", Name);
this->W.printNumber("Index", Idx);
}

template <class ELFT> void JSONELFDumper<ELFT>::printEmptyGroupMessage() const {
// JSON output does not need to print anything for empty groups
}

0 comments on commit 14f292d

Please sign in to comment.