diff --git a/llvm/test/tools/llvm-readobj/ELF/aarch64-symbols-stother.test b/llvm/test/tools/llvm-readobj/ELF/aarch64-symbols-stother.test --- a/llvm/test/tools/llvm-readobj/ELF/aarch64-symbols-stother.test +++ b/llvm/test/tools/llvm-readobj/ELF/aarch64-symbols-stother.test @@ -2,6 +2,7 @@ # RUN: yaml2obj %s -o %t.o # RUN: llvm-readobj --symbols %t.o | FileCheck %s --check-prefix=LLVM +# RUN: llvm-readobj --symbols %t.o --elf-output-style=JSON --pretty-print | FileCheck %s --check-prefix=JSON # RUN: llvm-readelf --symbols %t.o | FileCheck %s --check-prefix=GNU # LLVM: Name: foo1 @@ -28,6 +29,54 @@ # GNU-NEXT: 3: 0000000000000000 0 NOTYPE LOCAL PROTECTED [VARIANT_PCS] UND foo3 # GNU-NEXT: 4: 0000000000000000 0 NOTYPE LOCAL PROTECTED UND foo4 +# JSON: "Value": "foo1", +# JSON: "Other": { +# JSON-NEXT: "RawFlags": 128, +# JSON-NEXT: "Flags": [ +# JSON-NEXT: { +# JSON-NEXT: "Name": "STO_AARCH64_VARIANT_PCS", +# JSON-NEXT: "Value": 128 +# JSON-NEXT: } +# JSON-NEXT: ] +# JSON-NEXT:}, + +# JSON: "Value": "foo2", +# JSON: "Other": { +# JSON-NEXT: "RawFlags": 192, +# JSON-NEXT: "Flags": [ +# JSON-NEXT: { +# JSON-NEXT: "Name": "STO_AARCH64_VARIANT_PCS", +# JSON-NEXT: "Value": 128 +# JSON-NEXT: } +# JSON-NEXT: ] +# JSON-NEXT:}, + +# JSON: "Value": "foo3", +# JSON: "Other": { +# JSON-NEXT: "RawFlags": 131, +# JSON-NEXT: "Flags": [ +# JSON-NEXT: { +# JSON-NEXT: "Name": "STO_AARCH64_VARIANT_PCS", +# JSON-NEXT: "Value": 128 +# JSON-NEXT: }, +# JSON-NEXT: { +# JSON-NEXT: "Name": "STV_PROTECTED", +# JSON-NEXT: "Value": 3 +# JSON-NEXT: } +# JSON-NEXT: ] +# JSON-NEXT:}, + +# JSON: "Value": "foo4", +# JSON: "Other": { +# JSON-NEXT: "RawFlags": 3, +# JSON-NEXT: "Flags": [ +# JSON-NEXT: { +# JSON-NEXT: "Name": "STV_PROTECTED", +# JSON-NEXT: "Value": 3 +# JSON-NEXT: } +# JSON-NEXT: ] +# JSON-NEXT:}, + --- !ELF FileHeader: Class: ELFCLASS64 diff --git a/llvm/test/tools/llvm-readobj/ELF/mips-symbols-stother.test b/llvm/test/tools/llvm-readobj/ELF/mips-symbols-stother.test --- a/llvm/test/tools/llvm-readobj/ELF/mips-symbols-stother.test +++ b/llvm/test/tools/llvm-readobj/ELF/mips-symbols-stother.test @@ -2,6 +2,7 @@ # RUN: yaml2obj %s -o %t.o # RUN: llvm-readobj --symbols %t.o | FileCheck %s --strict-whitespace --check-prefix=MIPS-LLVM +# RUN: llvm-readobj --symbols %t.o --elf-output-style=JSON --pretty-print | FileCheck %s --check-prefix=MIPS-JSON # RUN: llvm-readelf --symbols %t.o | FileCheck %s --strict-whitespace --check-prefix=MIPS-GNU # MIPS-LLVM:Name: foo @@ -23,6 +24,39 @@ # MIPS-GNU-NEXT: 1: 00000000 0 NOTYPE LOCAL DEFAULT [] UND foo # MIPS-GNU-NEXT: 2: 00000000 0 NOTYPE LOCAL DEFAULT [] UND bar +# MIPS-JSON: "Value": "foo", +# MIPS-JSON: "Other": { +# MIPS-JSON-NEXT: "RawFlags": 172, +# MIPS-JSON-NEXT: "Flags": [ +# MIPS-JSON-NEXT: { +# MIPS-JSON-NEXT: "Name": "STO_MIPS_MICROMIPS", +# MIPS-JSON-NEXT: "Value": 128 +# MIPS-JSON-NEXT: }, +# MIPS-JSON-NEXT: { +# MIPS-JSON-NEXT: "Name": "STO_MIPS_OPTIONAL", +# MIPS-JSON-NEXT: "Value": 4 +# MIPS-JSON-NEXT: }, +# MIPS-JSON-NEXT: { +# MIPS-JSON-NEXT: "Name": "STO_MIPS_PIC", +# MIPS-JSON-NEXT: "Value": 32 +# MIPS-JSON-NEXT: }, +# MIPS-JSON-NEXT: { +# MIPS-JSON-NEXT: "Name": "STO_MIPS_PLT", +# MIPS-JSON-NEXT: "Value": 8 +# MIPS-JSON-NEXT: } +# MIPS-JSON-NEXT: ] +# MIPS-JSON-NEXT: }, +# MIPS-JSON: "Value": "bar", +# MIPS-JSON: "Other": { +# MIPS-JSON-NEXT: "RawFlags": 240, +# MIPS-JSON-NEXT: "Flags": [ +# MIPS-JSON-NEXT: { +# MIPS-JSON-NEXT: "Name": "STO_MIPS_MIPS16", +# MIPS-JSON-NEXT: "Value": 240 +# MIPS-JSON-NEXT: } +# MIPS-JSON-NEXT: ] +# MIPS-JSON-NEXT: }, + --- !ELF FileHeader: Class: ELFCLASS32 diff --git a/llvm/test/tools/llvm-readobj/ELF/symbol-visibility.test b/llvm/test/tools/llvm-readobj/ELF/symbol-visibility.test --- a/llvm/test/tools/llvm-readobj/ELF/symbol-visibility.test +++ b/llvm/test/tools/llvm-readobj/ELF/symbol-visibility.test @@ -7,6 +7,7 @@ # RUN: yaml2obj --docnum=1 %s -o %t1.o # RUN: llvm-readobj --symbols %t1.o | FileCheck %s --check-prefix=LLVM # RUN: llvm-readelf --symbols %t1.o | FileCheck %s --strict-whitespace --check-prefix=GNU +# RUN: llvm-readobj --symbols --pretty-print --elf-output-style=JSON %t1.o | FileCheck %s --check-prefix=JSON # LLVM: Name: default # LLVM: Other: 0 @@ -30,6 +31,45 @@ # GNU-NEXT: HIDDEN UND hidden # GNU-NEXT: PROTECTED UND protected +# JSON: "Value": "default", +# JSON: "Other": { +# JSON-NEXT: "RawFlags": 0, +# JSON-NEXT: "Flags": [] +# JSON-NEXT: }, + +# JSON: "Value": "internal", +# JSON: "Other": { +# JSON-NEXT: "RawFlags": 1, +# JSON-NEXT: "Flags": [ +# JSON-NEXT: { +# JSON-NEXT: "Name": "STV_INTERNAL", +# JSON-NEXT: "Value": 1 +# JSON-NEXT: } +# JSON-NEXT: ] +# JSON-NEXT: }, + +# JSON: "Value": "hidden", +# JSON: "Other": { +# JSON-NEXT: "RawFlags": 2, +# JSON-NEXT: "Flags": [ +# JSON-NEXT: { +# JSON-NEXT: "Name": "STV_HIDDEN", +# JSON-NEXT: "Value": 2 +# JSON-NEXT: } +# JSON-NEXT: ] +# JSON-NEXT: }, + +# JSON: "Value": "protected", +# JSON: "Other": { +# JSON-NEXT: "RawFlags": 3, +# JSON-NEXT: "Flags": [ +# JSON-NEXT: { +# JSON-NEXT: "Name": "STV_PROTECTED", +# JSON-NEXT: "Value": 3 +# JSON-NEXT: } +# JSON-NEXT: ] +# JSON-NEXT: }, + --- !ELF FileHeader: Class: ELFCLASS32 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 @@ -695,14 +695,14 @@ void printMemtag( const ArrayRef> DynamicEntries, const ArrayRef AndroidNoteDesc) override; + void printSymbolSection(const Elf_Sym &Symbol, unsigned SymIndex, + DataRegion ShndxTable) const; private: void printRelrReloc(const Elf_Relr &R) override; void printRelRelaReloc(const Relocation &R, const RelSymbol &RelSym) override; - void printSymbolSection(const Elf_Sym &Symbol, unsigned SymIndex, - DataRegion ShndxTable) const; void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex, DataRegion ShndxTable, std::optional StrTable, bool IsDynamic, @@ -715,8 +715,10 @@ void printMipsGOT(const MipsGOTParser &Parser) override; void printMipsPLT(const MipsGOTParser &Parser) override; void printMipsABIFlags() override; + virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const; protected: + void printSymbolOtherField(const Elf_Sym &Symbol) const; ScopedPrinter &W; }; @@ -732,6 +734,7 @@ void printFileSummary(StringRef FileStr, ObjectFile &Obj, ArrayRef InputFilenames, const Archive *A) override; + virtual void printZeroSymbolOtherField(const Elf_Sym &Symbol) const override; private: std::unique_ptr FileScope; @@ -6901,6 +6904,22 @@ } } +template +void LLVMELFDumper::printSymbolOtherField(const Elf_Sym &Symbol) const { + std::vector> SymOtherFlags = + this->getOtherFlagsFromSymbol(this->Obj.getHeader(), Symbol); + W.printFlags("Other", Symbol.st_other, ArrayRef(SymOtherFlags), 0x3u); +} + +template +void LLVMELFDumper::printZeroSymbolOtherField( + const Elf_Sym &Symbol) const { + assert(Symbol.st_other == 0 && "non-zero Other Field"); + // Usually st_other flag is zero. Do not pollute the output + // by flags enumeration in that case. + W.printNumber("Other", 0); +} + template void LLVMELFDumper::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex, DataRegion ShndxTable, @@ -6922,14 +6941,9 @@ else W.printEnum("Type", SymbolType, ArrayRef(ElfSymbolTypes)); if (Symbol.st_other == 0) - // Usually st_other flag is zero. Do not pollute the output - // by flags enumeration in that case. - W.printNumber("Other", 0); - else { - std::vector> SymOtherFlags = - this->getOtherFlagsFromSymbol(this->Obj.getHeader(), Symbol); - W.printFlags("Other", Symbol.st_other, ArrayRef(SymOtherFlags), 0x3u); - } + printZeroSymbolOtherField(Symbol); + else + printSymbolOtherField(Symbol); printSymbolSection(Symbol, SymIndex, ShndxTable); } @@ -7667,3 +7681,11 @@ std::string(formatv("{0}bit", 8 * Obj.getBytesInAddress()))); this->printLoadName(); } + +template +void JSONELFDumper::printZeroSymbolOtherField( + const Elf_Sym &Symbol) const { + // We want the JSON format to be uniform, since it is machine readable, so + // always print the `Other` field the same way. + this->printSymbolOtherField(Symbol); +}