Index: llvm/tools/llvm-readobj/ELFDumper.cpp =================================================================== --- llvm/tools/llvm-readobj/ELFDumper.cpp +++ llvm/tools/llvm-readobj/ELFDumper.cpp @@ -69,6 +69,8 @@ #include #include +#include + using namespace llvm; using namespace llvm::object; using namespace ELF; @@ -776,6 +778,7 @@ 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, Optional StrTable, bool IsDynamic, @@ -791,8 +794,42 @@ void printMipsGOT(const MipsGOTParser &Parser) override; void printMipsPLT(const MipsGOTParser &Parser) override; void printMipsABIFlags() override; -}; + template + void printFlags(StringRef Label, T Value, ArrayRef> EnumValues, + TEnum EnumMask1 = {}, TEnum EnumMask2 = {}, + TEnum EnumMask3 = {}) const { + W.printList(Label, [&]() { + for (const EnumEntry &Flag : EnumValues) { + if (Flag.Value == 0) + continue; + TEnum EnumMask{}; + if (Flag.Value & EnumMask1) + EnumMask = EnumMask1; + else if (Flag.Value & EnumMask2) + EnumMask = EnumMask2; + else if (Flag.Value & EnumMask3) + EnumMask = EnumMask3; + bool IsEnum = (Flag.Value & EnumMask) != 0; + if ((!IsEnum && (Value & Flag.Value) == Flag.Value) || + (IsEnum && (Value & EnumMask) == Flag.Value)) { + W.printValue(Flag.Name); + } + } + }); + } + + template + void printEnum(StringRef Label, T Value, ArrayRef> EnumValues) const { + for (const EnumEntry &EnumItem : EnumValues) { + if (EnumItem.Value == Value) { + W.printString(Label, EnumItem.AltName); + return; + } + } + W.printString(Label, "0x" + to_hexString(Value)); + } +}; } // end anonymous namespace namespace llvm { @@ -7465,7 +7502,65 @@ } template void JSONELFDumper::printSectionHeaders() { - // TODO: Implement + int SectionIndex = -1; + std::vector> FlagsList = + getSectionFlagsForTarget(this->Obj.getHeader().e_machine); + + W.printList("SectionHeaders", [&]() { + for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) { + W.objectBegin(); + W.printNumber("Index", ++SectionIndex); + W.printString("Name", this->getPrintableSectionName(Sec)); + /* W.printNumber("Name", this->getPrintableSectionName(Sec), Sec.sh_name); + */ + W.printString("Type", object::getELFSectionTypeName( + this->Obj.getHeader().e_machine, Sec.sh_type)); + printFlags("Flags", Sec.sh_flags, makeArrayRef(FlagsList)); + W.printString("Address", "0x" + to_hexString(Sec.sh_addr)); + W.printString("Offset", "0x" + to_hexString(Sec.sh_offset)); + W.printNumber("Size", Sec.sh_size); + W.printNumber("Link", Sec.sh_link); + W.printNumber("Info", Sec.sh_info); + W.printNumber("AddressAlignment", Sec.sh_addralign); + W.printNumber("EntrySize", Sec.sh_entsize); + + if (opts::SectionRelocations) { + W.printList("Relocations", [&]() { + this->printRelocationsHelper(Sec); + }); + } + + if (opts::SectionSymbols) { + W.printList("Symbols", [&]() { + if (this->DotSymtabSec) { + StringRef StrTable = unwrapOrError( + this->FileName, + this->Obj.getStringTableForSymtab(*this->DotSymtabSec)); + ArrayRef ShndxTable = + this->getShndxTable(this->DotSymtabSec); + + typename ELFT::SymRange Symbols = unwrapOrError( + this->FileName, this->Obj.symbols(this->DotSymtabSec)); + for (const Elf_Sym &Sym : Symbols) { + const Elf_Shdr *SymSec = unwrapOrError( + this->FileName, + this->Obj.getSection(Sym, this->DotSymtabSec, ShndxTable)); + if (SymSec == &Sec) { + printSymbol(Sym, &Sym - &Symbols[0], ShndxTable, StrTable, false, + false); + } + } + } + }); + } + if (opts::SectionData && Sec.sh_type != ELF::SHT_NOBITS) { + ArrayRef Data = + unwrapOrError(this->FileName, this->Obj.getSectionContents(Sec)); + // TODO: print binary block + } + W.objectEnd(); + } + }); } template @@ -7594,13 +7689,82 @@ template void JSONELFDumper::printRelrReloc(const Elf_Relr &R) { - // TODO: Implement + W.printValue(to_hexString(R)); } template void JSONELFDumper::printRelRelaReloc(const Relocation &R, const RelSymbol &RelSym) { - // TODO: Implement + StringRef SymbolName = RelSym.Name; + SmallString<32> RelocName; + this->Obj.getRelocationTypeName(R.Type, RelocName); + + if (opts::ExpandRelocs) { + W.objectBegin(); + W.printString("Offset", "0x" + to_hexString(R.Offset)); + W.printString("Type", RelocName); + W.printString("Symbol", !SymbolName.empty() ? SymbolName : "-"); + if (R.Addend) + W.printString("Addend", "0x" + to_hexString((uintX_t)*R.Addend)); + W.objectEnd(); + } else { + std::string Reloc = (to_hexString(R.Offset) + " " + RelocName + " " + (!SymbolName.empty() ? SymbolName : "-")).str(); + if (R.Addend) + Reloc += " " + to_hexString((uintX_t)*R.Addend); + W.printValue(Reloc); + } +} + +template +void JSONELFDumper::printSymbolSection( + const Elf_Sym &Symbol, unsigned SymIndex, + DataRegion ShndxTable) const { + auto GetSectionSpecialType = [&]() -> Optional { + if (Symbol.isUndefined()) + return StringRef("Undefined"); + if (Symbol.isProcessorSpecific()) + return StringRef("Processor Specific"); + if (Symbol.isOSSpecific()) + return StringRef("Operating System Specific"); + if (Symbol.isAbsolute()) + return StringRef("Absolute"); + if (Symbol.isCommon()) + return StringRef("Common"); + if (Symbol.isReserved() && Symbol.st_shndx != SHN_XINDEX) + return StringRef("Reserved"); + return None; + }; + + if (Optional Type = GetSectionSpecialType()) { + W.printString("Section", *Type); + return; + } + + Expected SectionIndex = + this->getSymbolSectionIndex(Symbol, SymIndex, ShndxTable); + if (!SectionIndex) { + assert(Symbol.st_shndx == SHN_XINDEX && + "getSymbolSectionIndex should only fail due to an invalid " + "SHT_SYMTAB_SHNDX table/reference"); + this->reportUniqueWarning(SectionIndex.takeError()); + W.printString("Section", to_hexString(SHN_XINDEX)); + /* W.printHex("Section", "Reserved", SHN_XINDEX); */ + return; + } + + Expected SectionName = + this->getSymbolSectionName(Symbol, *SectionIndex); + if (!SectionName) { + // Don't report an invalid section name if the section headers are missing. + // In such situations, all sections will be "invalid". + if (!this->ObjF.sections().empty()) + this->reportUniqueWarning(SectionName.takeError()); + else + consumeError(SectionName.takeError()); + W.printHex("Section", "", *SectionIndex); + } else { + W.printHex("Section", *SectionName, *SectionIndex); + } } template @@ -7609,7 +7773,52 @@ Optional StrTable, bool IsDynamic, bool NonVisibilityBitsUsed) const { - // TODO: Implement + std::string FullSymbolName = this->getFullSymbolName( + Symbol, SymIndex, ShndxTable, StrTable, IsDynamic); + unsigned char SymbolType = Symbol.getType(); + + W.printObject("Symbol", [&]() { + W.printString("Name", FullSymbolName); + W.printString("Value", "0x" + to_hexString(Symbol.st_value)); + W.printNumber("Size", Symbol.st_size); + printEnum("Binding", Symbol.getBinding(), makeArrayRef(ElfSymbolBindings)); + if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU && + SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) + printEnum("Type", SymbolType, makeArrayRef(AMDGPUSymbolTypes)); + else + printEnum("Type", SymbolType, makeArrayRef(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(std::begin(ElfSymOtherFlags), + std::end(ElfSymOtherFlags)); + if (this->Obj.getHeader().e_machine == EM_MIPS) { + // Someones in their infinite wisdom decided to make STO_MIPS_MIPS16 + // flag overlapped with other ST_MIPS_xxx flags. So consider both + // cases separately. + if ((Symbol.st_other & STO_MIPS_MIPS16) == STO_MIPS_MIPS16) + SymOtherFlags.insert(SymOtherFlags.end(), + std::begin(ElfMips16SymOtherFlags), + std::end(ElfMips16SymOtherFlags)); + else + SymOtherFlags.insert(SymOtherFlags.end(), + std::begin(ElfMipsSymOtherFlags), + std::end(ElfMipsSymOtherFlags)); + } else if (this->Obj.getHeader().e_machine == EM_AARCH64) { + SymOtherFlags.insert(SymOtherFlags.end(), + std::begin(ElfAArch64SymOtherFlags), + std::end(ElfAArch64SymOtherFlags)); + } else if (this->Obj.getHeader().e_machine == EM_RISCV) { + SymOtherFlags.insert(SymOtherFlags.end(), + std::begin(ElfRISCVSymOtherFlags), + std::end(ElfRISCVSymOtherFlags)); + } + printFlags("Other", Symbol.st_other, makeArrayRef(SymOtherFlags), 0x3u); + } + printSymbolSection(Symbol, SymIndex, ShndxTable); + }); } template