From: Hemant Kulkarni Date: Thu, 25 Feb 2016 20:47:07 +0000 (+0000) Subject: Reverts change r261907 and r261918 X-Git-Tag: llvmorg-3.9.0-rc1~13206 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=de1152f4447649bb07e4c34fa9559f8475dbdf15;p=platform%2Fupstream%2Fllvm.git Reverts change r261907 and r261918 llvm-svn: 261927 --- diff --git a/llvm/test/tools/llvm-readobj/gnu-relocations.test b/llvm/test/tools/llvm-readobj/gnu-relocations.test deleted file mode 100644 index 5b269e0..0000000 --- a/llvm/test/tools/llvm-readobj/gnu-relocations.test +++ /dev/null @@ -1,28 +0,0 @@ -RUN: llvm-readobj -r %p/Inputs/relocs.obj.elf-i386 --elf-output-style=GNU \ -RUN: | FileCheck %s -check-prefix ELF32 -RUN: llvm-readobj -r %p/Inputs/relocs.obj.elf-x86_64 --elf-output-style=GNU \ -RUN: | FileCheck %s -check-prefix ELF64 - -ELF32: Relocation section '.rel.text' at offset 0x318 contains 41 entries: -ELF32-NEXT: Offset Info Type Sym. Value Symbol's Name -ELF32-NEXT: 00000002 00000500 R_386_NONE 00000000 sym -ELF32-NEXT: 00000008 00000501 R_386_32 00000000 sym -ELF32-NEXT: 0000000e 00000502 R_386_PC32 00000000 sym -ELF32-NEXT: 00000014 00000503 R_386_GOT32 00000000 sym -ELF32-NEXT: 0000001a 00000504 R_386_PLT32 00000000 sym -ELF32-NEXT: 00000020 00000505 R_386_COPY 00000000 sym -ELF32-NEXT: 00000026 00000506 R_386_GLOB_DAT 00000000 sym -ELF32-NEXT: 0000002c 00000507 R_386_JUMP_SLOT 00000000 sym -ELF32-NEXT: 00000032 00000508 R_386_RELATIVE 00000000 sym -ELF32-NEXT: 00000038 00000509 R_386_GOTOFF 00000000 sym - -ELF64: Relocation section '.rela.text' at offset 0x430 contains 38 entries: -ELF64-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend -ELF64-NEXT: 0000000000000003 0000000500000000 R_X86_64_NONE 0000000000000000 sym - 4 -ELF64-NEXT: 000000000000000a 0000000500000001 R_X86_64_64 0000000000000000 sym - 4 -ELF64-NEXT: 0000000000000011 0000000500000002 R_X86_64_PC32 0000000000000000 sym - 4 -ELF64-NEXT: 0000000000000018 0000000500000003 R_X86_64_GOT32 0000000000000000 sym - 4 -ELF64-NEXT: 000000000000001f 0000000500000004 R_X86_64_PLT32 0000000000000000 sym - 4 -ELF64-NEXT: 0000000000000026 0000000500000005 R_X86_64_COPY 0000000000000000 sym - 4 -ELF64-NEXT: 000000000000002d 0000000500000006 R_X86_64_GLOB_DAT 0000000000000000 sym - 4 -ELF64-NEXT: 0000000000000034 0000000500000007 R_X86_64_JUMP_SLOT 0000000000000000 sym - 4 diff --git a/llvm/test/tools/llvm-readobj/gnu-sections.test b/llvm/test/tools/llvm-readobj/gnu-sections.test deleted file mode 100644 index fb90ce4..0000000 --- a/llvm/test/tools/llvm-readobj/gnu-sections.test +++ /dev/null @@ -1,35 +0,0 @@ -RUN: llvm-readobj -s %p/Inputs/relocs.obj.elf-i386 --elf-output-style=GNU \ -RUN: | FileCheck %s -check-prefix ELF32 -RUN: llvm-readobj -s %p/Inputs/relocs.obj.elf-x86_64 --elf-output-style=GNU \ -RUN: | FileCheck %s -check-prefix ELF64 - -ELF32: Section Headers: -ELF32-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al -ELF32-NEXT: [ 0] NULL 00000000 000000 000000 00 0 0 0 -ELF32-NEXT: [ 1] .text PROGBITS 00000000 000034 0000f6 00 AX 0 0 4 -ELF32-NEXT: [ 2] .rel.text REL 00000000 000318 000148 08 6 1 4 -ELF32-NEXT: [ 3] .data PROGBITS 00000000 00012c 000000 00 WA 0 0 4 -ELF32-NEXT: [ 4] .bss NOBITS 00000000 00012c 000000 00 WA 0 0 4 -ELF32-NEXT: [ 5] .shstrtab STRTAB 00000000 00012c 000030 00 0 0 1 -ELF32-NEXT: [ 6] .symtab SYMTAB 00000000 00029c 000060 10 7 4 4 -ELF32-NEXT: [ 7] .strtab STRTAB 00000000 0002fc 00001b 00 0 0 1 -ELF32-NEXT: Key to Flags: -ELF32-NEXT: W (write), A (alloc), X (execute), M (merge), S (strings), l (large) -ELF32-NEXT: I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) -ELF32-NEXT: O (extra OS processing required) o (OS specific), p (processor specific) - -ELF64: There are 8 section headers, starting at offset 0x180: -ELF64: Section Headers: -ELF64-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al -ELF64-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 0 0 -ELF64-NEXT: [ 1] .text PROGBITS 0000000000000000 000040 00010a 00 AX 0 0 4 -ELF64-NEXT: [ 2] .rela.text RELA 0000000000000000 000430 000390 18 6 1 8 -ELF64-NEXT: [ 3] .data PROGBITS 0000000000000000 00014c 000000 00 WA 0 0 4 -ELF64-NEXT: [ 4] .bss NOBITS 0000000000000000 00014c 000000 00 WA 0 0 4 -ELF64-NEXT: [ 5] .shstrtab STRTAB 0000000000000000 00014c 000031 00 0 0 1 -ELF64-NEXT: [ 6] .symtab SYMTAB 0000000000000000 000380 000090 18 7 4 8 -ELF64-NEXT: [ 7] .strtab STRTAB 0000000000000000 000410 00001b 00 0 0 1 -ELF64-NEXT: Key to Flags: -ELF64-NEXT: W (write), A (alloc), X (execute), M (merge), S (strings), l (large) -ELF64-NEXT: I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) -ELF64-NEXT: O (extra OS processing required) o (OS specific), p (processor specific) diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 33dcefd..ae924cd 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -44,21 +44,6 @@ using namespace ELF; #define ENUM_ENT_1(enum) \ { #enum, #enum, ELF::enum } -#define TYPEDEF_ELF_TYPES(ELFT) \ - typedef ELFFile ELFO; \ - typedef typename ELFO::Elf_Shdr Elf_Shdr; \ - typedef typename ELFO::Elf_Sym Elf_Sym; \ - typedef typename ELFO::Elf_Dyn Elf_Dyn; \ - typedef typename ELFO::Elf_Dyn_Range Elf_Dyn_Range; \ - typedef typename ELFO::Elf_Rel Elf_Rel; \ - typedef typename ELFO::Elf_Rela Elf_Rela; \ - typedef typename ELFO::Elf_Rela_Range Elf_Rela_Range; \ - typedef typename ELFO::Elf_Phdr Elf_Phdr; \ - typedef typename ELFO::Elf_Half Elf_Half; \ - typedef typename ELFO::Elf_Ehdr Elf_Ehdr; \ - typedef typename ELFO::Elf_Word Elf_Word; \ - typedef typename ELFO::uintX_t uintX_t; - namespace { template class DumpStyle; @@ -159,15 +144,21 @@ private: void parseDynamicTable(ArrayRef LoadSegments); + void printSymbolsHelper(bool IsDynamic); void printSymbol(const Elf_Sym *Symbol, const Elf_Sym *FirstSym, StringRef StrTable, bool IsDynamic); + void printDynamicRelocation(Elf_Rela Rel); + void printRelocations(const Elf_Shdr *Sec); + void printRelocation(Elf_Rela Rel, const Elf_Shdr *SymTab); void printValue(uint64_t Type, uint64_t Value); + Elf_Rel_Range dyn_rels() const; + Elf_Rela_Range dyn_relas() const; StringRef getDynamicString(uint64_t Offset) const; StringRef getSymbolVersion(StringRef StrTab, const Elf_Sym *symb, - bool &IsDefault) const; - void LoadVersionMap() const; + bool &IsDefault); + void LoadVersionMap(); void LoadVersionNeeds(const Elf_Shdr *ec) const; void LoadVersionDefs(const Elf_Shdr *sec) const; @@ -220,99 +211,45 @@ public: return DynSymRegion.getAsRange(); } - Elf_Rel_Range dyn_rels() const; - Elf_Rela_Range dyn_relas() const; std::string getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable, - bool IsDynamic) const; + bool IsDynamic); const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; } - ArrayRef getShndxTable() const { return ShndxTable; } + ArrayRef getShndxTable() { return ShndxTable; } StringRef getDynamicStringTable() const { return DynamicStringTable; } - const DynRegionInfo &getDynRelRegion() const { return DynRelRegion; } - const DynRegionInfo &getDynRelaRegion()const { return DynRelaRegion; } - const DynRegionInfo &getDynPLTRelRegion()const { return DynPLTRelRegion; } }; template class DumpStyle { public: - TYPEDEF_ELF_TYPES(ELFT) - virtual void printFileHeaders(const ELFO *Obj) = 0; + virtual void printFileHeaders(const ELFFile *Obj) = 0; virtual ~DumpStyle() { } - DumpStyle(ELFDumper *Dumper) : Dumper(Dumper) {} - virtual void printRelocations(const ELFO *Obj) = 0; - virtual void printSections(const ELFO *Obj) = 0; - virtual void printSymbols(const ELFO *Obj) = 0; - virtual void printDynamicSymbols(const ELFO *Obj) = 0; - virtual void printDynamicRelocations(const ELFO *Obj) = 0; - const ELFDumper *dumper() const { return Dumper; } - -private: - const ELFDumper *Dumper; }; template class GNUStyle : public DumpStyle { formatted_raw_ostream OS; + public: - TYPEDEF_ELF_TYPES(ELFT) - GNUStyle(StreamWriter &W, ELFDumper *Dumper) - : DumpStyle(Dumper), OS(W.getOStream()) {} - void printFileHeaders(const ELFO *Obj) override; - void printRelocations(const ELFO *Obj) override; - void printSections(const ELFO *Obj) override; - void printSymbols(const ELFO *Obj) override; - void printDynamicSymbols(const ELFO *Obj) override; - void printDynamicRelocations(const ELFO *Obj) override; + typedef typename ELFFile::Elf_Ehdr Elf_Ehdr; + GNUStyle(StreamWriter &W) : OS(W.getOStream()) {} + void printFileHeaders(const ELFFile *Obj) override; private: - struct Field { - StringRef Str; - unsigned Column; - Field(StringRef S, unsigned Col) : Str(S), Column(Col) {} - Field(unsigned Col) : Str(""), Column(Col) {} - Field &operator=(StringRef S) { - Str = S; - return *this; - } - }; - template std::string printEnum(T Value, ArrayRef> EnumValues) { for (const auto &EnumItem : EnumValues) if (EnumItem.Value == Value) return EnumItem.AltName; - return to_hexString(Value, false); + return to_hexString(Value); } - formatted_raw_ostream &printField(struct Field F) { - if (F.Column != 0) - OS.PadToColumn(F.Column); - OS << F.Str; - OS.flush(); - return OS; - } - void printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, - const Elf_Rela &R, bool IsRela); }; template class LLVMStyle : public DumpStyle { public: - TYPEDEF_ELF_TYPES(ELFT) - LLVMStyle(StreamWriter &W, ELFDumper *Dumper) - : DumpStyle(Dumper), W(W) {} - - void printFileHeaders(const ELFO *Obj) override; - void printRelocations(const ELFO *Obj) override; - void printRelocations(const Elf_Shdr *Sec, const ELFO *Obj); - void printSections(const ELFO *Obj) override; - void printSymbolsHelper(const ELFO *Obj, bool IsDynamic); - void printSymbols(const ELFO *Obj) override; - void printDynamicSymbols(const ELFO *Obj) override; - void printDynamicRelocations(const ELFO *Obj) override; + typedef typename ELFFile::Elf_Ehdr Elf_Ehdr; + LLVMStyle(StreamWriter &W) : W(W) {} -private: - void printRelocation(const ELFO* Obj, Elf_Rela Rel, const Elf_Shdr *SymTab); - void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First, - StringRef StrTable, bool IsDynamic); - void printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel); + void printFileHeaders(const ELFFile *Obj) override; +private: StreamWriter &W; }; @@ -411,7 +348,7 @@ void ELFDumper::LoadVersionDefs(const Elf_Shdr *sec) const { } } -template void ELFDumper::LoadVersionMap() const { +template void ELFDumper::LoadVersionMap() { // If there is no dynamic symtab or version table, there is nothing to do. if (!DynSymRegion.Addr || !dot_gnu_version_sec) return; @@ -520,7 +457,7 @@ template void ELFDumper::printVersionInfo() { template StringRef ELFDumper::getSymbolVersion(StringRef StrTab, const Elf_Sym *symb, - bool &IsDefault) const { + bool &IsDefault) { // This is a dynamic symbol. Look in the GNU symbol version table. if (!dot_gnu_version_sec) { // No version table. @@ -569,7 +506,7 @@ StringRef ELFDumper::getSymbolVersion(StringRef StrTab, template std::string ELFDumper::getFullSymbolName(const Elf_Sym *Symbol, StringRef StrTable, - bool IsDynamic) const { + bool IsDynamic) { StringRef SymbolName = unwrapOrError(Symbol->getName(StrTable)); if (!IsDynamic) return SymbolName; @@ -956,56 +893,6 @@ static const EnumEntry ElfX86_64SectionFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, SHF_X86_64_LARGE) }; -static std::string getGNUFlags(uint64_t flags) { - std::string str; - for (auto entry : ElfSectionFlags) { - uint64_t flag = entry.Value & flags; - switch (flag) { - case ELF::SHF_WRITE: - str += "W"; - break; - case ELF::SHF_ALLOC: - str += "A"; - break; - case ELF::SHF_EXECINSTR: - str += "X"; - break; - case ELF::SHF_MERGE: - str += "M"; - break; - case ELF::SHF_STRINGS: - str += "S"; - break; - case ELF::SHF_INFO_LINK: - str += "I"; - break; - case ELF::SHF_LINK_ORDER: - str += "L"; - break; - case ELF::SHF_OS_NONCONFORMING: - str += "O"; - break; - case ELF::SHF_GROUP: - str += "G"; - break; - case ELF::SHF_TLS: - str += "T"; - break; - case ELF::SHF_EXCLUDE: - str += "E"; - break; - default: - if (flags & ELF::SHF_MASKOS) - str += "o"; - else if (flags & ELF::SHF_MASKPROC) - str += "p"; - else if (flag) - str += "x"; - } - } - return str; -} - static const char *getElfSegmentType(unsigned Arch, unsigned Type) { // Check potentially overlapped processor-specific // program header type. @@ -1153,9 +1040,9 @@ ELFDumper::ELFDumper(const ELFFile *Obj, StreamWriter &Writer) parseDynamicTable(LoadSegments); if (opts::Output == opts::GNU) - ELFDumperStyle.reset(new GNUStyle(Writer, this)); + ELFDumperStyle.reset(new GNUStyle(Writer)); else - ELFDumperStyle.reset(new LLVMStyle(Writer, this)); + ELFDumperStyle.reset(new LLVMStyle(Writer)); } template @@ -1258,29 +1145,261 @@ void ELFDumper::printFileHeaders() { template void ELFDumper::printSections() { - ELFDumperStyle->printSections(Obj); + ListScope SectionsD(W, "Sections"); + + int SectionIndex = -1; + for (const Elf_Shdr &Sec : Obj->sections()) { + ++SectionIndex; + + StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); + + DictScope SectionD(W, "Section"); + W.printNumber("Index", SectionIndex); + W.printNumber("Name", Name, Sec.sh_name); + W.printHex("Type", + getElfSectionType(Obj->getHeader()->e_machine, Sec.sh_type), + Sec.sh_type); + std::vector> SectionFlags(std::begin(ElfSectionFlags), + std::end(ElfSectionFlags)); + switch (Obj->getHeader()->e_machine) { + case EM_AMDGPU: + SectionFlags.insert(SectionFlags.end(), std::begin(ElfAMDGPUSectionFlags), + std::end(ElfAMDGPUSectionFlags)); + break; + case EM_HEXAGON: + SectionFlags.insert(SectionFlags.end(), + std::begin(ElfHexagonSectionFlags), + std::end(ElfHexagonSectionFlags)); + break; + case EM_MIPS: + SectionFlags.insert(SectionFlags.end(), std::begin(ElfMipsSectionFlags), + std::end(ElfMipsSectionFlags)); + break; + case EM_X86_64: + SectionFlags.insert(SectionFlags.end(), std::begin(ElfX86_64SectionFlags), + std::end(ElfX86_64SectionFlags)); + break; + default: + // Nothing to do. + break; + } + W.printFlags("Flags", Sec.sh_flags, makeArrayRef(SectionFlags)); + W.printHex("Address", Sec.sh_addr); + W.printHex("Offset", 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) { + ListScope D(W, "Relocations"); + printRelocations(&Sec); + } + + if (opts::SectionSymbols) { + ListScope D(W, "Symbols"); + const Elf_Shdr *Symtab = DotSymtabSec; + StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab)); + + for (const Elf_Sym &Sym : Obj->symbols(Symtab)) { + const Elf_Shdr *SymSec = + unwrapOrError(Obj->getSection(&Sym, Symtab, ShndxTable)); + if (SymSec == &Sec) + printSymbol(&Sym, Obj->symbol_begin(Symtab), StrTable, false); + } + } + + if (opts::SectionData && Sec.sh_type != ELF::SHT_NOBITS) { + ArrayRef Data = unwrapOrError(Obj->getSectionContents(&Sec)); + W.printBinaryBlock("SectionData", + StringRef((const char *)Data.data(), Data.size())); + } + } } template void ELFDumper::printRelocations() { - ELFDumperStyle->printRelocations(Obj); + ListScope D(W, "Relocations"); + + int SectionNumber = -1; + for (const Elf_Shdr &Sec : Obj->sections()) { + ++SectionNumber; + + if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA) + continue; + + StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); + + W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n"; + W.indent(); + + printRelocations(&Sec); + + W.unindent(); + W.startLine() << "}\n"; + } } template void ELFDumper::printDynamicRelocations() { - ELFDumperStyle->printDynamicRelocations(Obj); + if (DynRelRegion.Size && DynRelaRegion.Size) + report_fatal_error("There are both REL and RELA dynamic relocations"); + W.startLine() << "Dynamic Relocations {\n"; + W.indent(); + if (DynRelaRegion.Size > 0) + for (const Elf_Rela &Rela : dyn_relas()) + printDynamicRelocation(Rela); + else + for (const Elf_Rel &Rel : dyn_rels()) { + Elf_Rela Rela; + Rela.r_offset = Rel.r_offset; + Rela.r_info = Rel.r_info; + Rela.r_addend = 0; + printDynamicRelocation(Rela); + } + if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) + for (const Elf_Rela &Rela : DynPLTRelRegion.getAsRange()) + printDynamicRelocation(Rela); + else + for (const Elf_Rel &Rel : DynPLTRelRegion.getAsRange()) { + Elf_Rela Rela; + Rela.r_offset = Rel.r_offset; + Rela.r_info = Rel.r_info; + Rela.r_addend = 0; + printDynamicRelocation(Rela); + } + W.unindent(); + W.startLine() << "}\n"; +} + +template +void ELFDumper::printRelocations(const Elf_Shdr *Sec) { + const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec->sh_link)); + + switch (Sec->sh_type) { + case ELF::SHT_REL: + for (const Elf_Rel &R : Obj->rels(Sec)) { + Elf_Rela Rela; + Rela.r_offset = R.r_offset; + Rela.r_info = R.r_info; + Rela.r_addend = 0; + printRelocation(Rela, SymTab); + } + break; + case ELF::SHT_RELA: + for (const Elf_Rela &R : Obj->relas(Sec)) + printRelocation(R, SymTab); + break; + } } +template +void ELFDumper::printRelocation(Elf_Rela Rel, const Elf_Shdr *SymTab) { + SmallString<32> RelocName; + Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); + StringRef TargetName; + const Elf_Sym *Sym = Obj->getRelocationSymbol(&Rel, SymTab); + if (Sym && Sym->getType() == ELF::STT_SECTION) { + const Elf_Shdr *Sec = + unwrapOrError(Obj->getSection(Sym, SymTab, ShndxTable)); + TargetName = unwrapOrError(Obj->getSectionName(Sec)); + } else if (Sym) { + StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab)); + TargetName = unwrapOrError(Sym->getName(StrTable)); + } + + if (opts::ExpandRelocs) { + DictScope Group(W, "Relocation"); + W.printHex("Offset", Rel.r_offset); + W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); + W.printNumber("Symbol", TargetName.size() > 0 ? TargetName : "-", + Rel.getSymbol(Obj->isMips64EL())); + W.printHex("Addend", Rel.r_addend); + } else { + raw_ostream& OS = W.startLine(); + OS << W.hex(Rel.r_offset) << " " << RelocName << " " + << (TargetName.size() > 0 ? TargetName : "-") << " " + << W.hex(Rel.r_addend) << "\n"; + } +} + +template +void ELFDumper::printDynamicRelocation(Elf_Rela Rel) { + SmallString<32> RelocName; + Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); + StringRef SymbolName; + uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL()); + const Elf_Sym *Sym = dynamic_symbols().begin() + SymIndex; + SymbolName = unwrapOrError(Sym->getName(DynamicStringTable)); + if (opts::ExpandRelocs) { + DictScope Group(W, "Relocation"); + W.printHex("Offset", Rel.r_offset); + W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); + W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); + W.printHex("Addend", Rel.r_addend); + } else { + raw_ostream &OS = W.startLine(); + OS << W.hex(Rel.r_offset) << " " << RelocName << " " + << (SymbolName.size() > 0 ? SymbolName : "-") << " " + << W.hex(Rel.r_addend) << "\n"; + } +} + +template +void ELFDumper::printSymbolsHelper(bool IsDynamic) { + StringRef StrTable; + Elf_Sym_Range Syms(nullptr, nullptr); + + if (IsDynamic) { + StrTable = DynamicStringTable; + Syms = dynamic_symbols(); + } else { + if (!DotSymtabSec) + return; + StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec)); + Syms = Obj->symbols(DotSymtabSec); + } + for (const Elf_Sym &Sym : Syms) + printSymbol(&Sym, Syms.begin(), StrTable, IsDynamic); +} template void ELFDumper::printSymbols() { - ELFDumperStyle->printSymbols(Obj); + ListScope Group(W, "Symbols"); + printSymbolsHelper(false); } template void ELFDumper::printDynamicSymbols() { - ELFDumperStyle->printDynamicSymbols(Obj); + ListScope Group(W, "DynamicSymbols"); + printSymbolsHelper(true); } +template +void ELFDumper::printSymbol(const Elf_Sym *Symbol, + const Elf_Sym *FirstSym, StringRef StrTable, + bool IsDynamic) { + unsigned SectionIndex = 0; + StringRef SectionName; + getSectionNameIndex(*Obj, Symbol, FirstSym, ShndxTable, SectionName, + SectionIndex); + std::string FullSymbolName = getFullSymbolName(Symbol, StrTable, IsDynamic); + unsigned char SymbolType = Symbol->getType(); + + DictScope D(W, "Symbol"); + W.printNumber("Name", FullSymbolName, Symbol->st_name); + W.printHex ("Value", Symbol->st_value); + W.printNumber("Size", Symbol->st_size); + W.printEnum ("Binding", Symbol->getBinding(), + makeArrayRef(ElfSymbolBindings)); + if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU && + SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) + W.printEnum ("Type", SymbolType, makeArrayRef(AMDGPUSymbolTypes)); + else + W.printEnum ("Type", SymbolType, makeArrayRef(ElfSymbolTypes)); + W.printNumber("Other", Symbol->st_other); + W.printHex("Section", SectionName, SectionIndex); +} #define LLVM_READOBJ_TYPE_CASE(name) \ case DT_##name: return #name @@ -2173,7 +2292,8 @@ static inline void printFields(formatted_raw_ostream &OS, StringRef Str1, OS.flush(); } -template void GNUStyle::printFileHeaders(const ELFO *Obj) { +template +void GNUStyle::printFileHeaders(const ELFFile *Obj) { const Elf_Ehdr *e = Obj->getHeader(); OS << "ELF Header:\n"; OS << " Magic: "; @@ -2226,275 +2346,7 @@ template void GNUStyle::printFileHeaders(const ELFO *Obj) { } template -void GNUStyle::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, - const Elf_Rela &R, bool IsRela) { - std::string r_offset, r_info, r_addend = "", s_value; - SmallString<32> RelocName; - StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab)); - StringRef TargetName; - const Elf_Sym *Sym = nullptr; - unsigned bias; - const char *FmtCharHex; - if (ELFT::Is64Bits) { - bias = 8; - FmtCharHex = "%016" PRIx64; - } else { - bias = 0; - FmtCharHex = "%08" PRIx32; - } - Field fields[5] = {0, 10 + bias, 19 + 2 * bias, 42 + 2 * bias, 53 + 2 * bias}; - Obj->getRelocationTypeName(R.getType(Obj->isMips64EL()), RelocName); - Sym = Obj->getRelocationSymbol(&R, SymTab); - if (Sym && Sym->getType() == ELF::STT_SECTION) { - const Elf_Shdr *Sec = unwrapOrError( - Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable())); - TargetName = unwrapOrError(Obj->getSectionName(Sec)); - } else if (Sym) { - TargetName = unwrapOrError(Sym->getName(StrTable)); - } - - if (Sym && IsRela) { - if (R.r_addend < 0) - r_addend = " - "; - else - r_addend = " + "; - } - r_offset = to_hexString(format(FmtCharHex, R.r_offset)); - r_info = to_hexString(format(FmtCharHex, R.r_info)); - if (IsRela) - r_addend += - R.r_addend == 0 ? std::string("0") : to_hexString(std::abs(R.r_addend), false); - if (Sym) - s_value = to_hexString(format(FmtCharHex, Sym->getValue())); - - fields[0] = r_offset; - fields[1] = r_info; - fields[2] = RelocName; - fields[3] = s_value; - fields[4] = TargetName; - for (auto &field : fields) - printField(field); - if (IsRela) - OS << r_addend; - OS << "\n"; -} - -template void GNUStyle::printRelocations(const ELFO *Obj) { - bool hasRelocSections = false; - for (const Elf_Shdr &Sec : Obj->sections()) { - if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA) - continue; - hasRelocSections = true; - StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); - unsigned entries = Sec.getEntityCount(); - uintX_t offset = Sec.sh_offset; - OS << "\nRelocation section '" << Name << "' at offset 0x" - << to_hexString(offset, false) << " contains " << to_string(entries) - << " entries:\n"; - if (ELFT::Is64Bits) - OS << " Offset Info Type" - << " Symbol's Value Symbol's Name"; - else - OS << " Offset Info Type Sym. Value " - << "Symbol's Name"; - OS << ((Sec.sh_type == ELF::SHT_RELA) ? " + Addend" : "") << "\n"; - - const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec.sh_link)); - if (Sec.sh_type == ELF::SHT_REL) { - for (const auto &R : Obj->rels(&Sec)) { - Elf_Rela Rela; - Rela.r_offset = R.r_offset; - Rela.r_info = R.r_info; - Rela.r_addend = 0; - printRelocation(Obj, SymTab, Rela, false); - } - } else { - for (const auto &R : Obj->relas(&Sec)) - printRelocation(Obj, SymTab, R, true); - } - } - if (!hasRelocSections) - OS << "\nThere are no relocations in this file.\n"; -} - -std::string getSectiontypeString(unsigned arch, unsigned type) { - using namespace ELF; - switch (arch) { - case EM_ARM: - switch (type) { - case SHT_ARM_EXIDX: - return "ARM_EXIDX"; - case SHT_ARM_PREEMPTMAP: - return "ARM_PREEMPTMAP"; - case SHT_ARM_ATTRIBUTES: - return "ARM_ATTRIBUTES"; - case SHT_ARM_DEBUGOVERLAY: - return "ARM_DEBUGOVERLAY"; - case SHT_ARM_OVERLAYSECTION: - return "ARM_OVERLAYSECTION"; - } - case EM_X86_64: - switch (type) { - case SHT_X86_64_UNWIND: - return "X86_64_UNWIND"; - } - case EM_MIPS: - case EM_MIPS_RS3_LE: - switch (type) { - case SHT_MIPS_REGINFO: - return "MIPS_REGINFO"; - case SHT_MIPS_OPTIONS: - return "MIPS_OPTIONS"; - case SHT_MIPS_ABIFLAGS: - return "MIPS_ABIFLAGS"; - } - } - switch (type) { - case SHT_NULL: - return "NULL"; - case SHT_PROGBITS: - return "PROGBITS"; - case SHT_SYMTAB: - return "SYMTAB"; - case SHT_STRTAB: - return "STRTAB"; - case SHT_RELA: - return "RELA"; - case SHT_HASH: - return "HASH"; - case SHT_DYNAMIC: - return "DYNAMIC"; - case SHT_NOTE: - return "NOTE"; - case SHT_NOBITS: - return "NOBITS"; - case SHT_REL: - return "REL"; - case SHT_SHLIB: - return "SHLIB"; - case SHT_DYNSYM: - return "DYNSYM"; - case SHT_INIT_ARRAY: - return "INIT_ARRAY"; - case SHT_FINI_ARRAY: - return "FINI_ARRAY"; - case SHT_PREINIT_ARRAY: - return "PREINIT_ARRAY"; - case SHT_GROUP: - return "GROUP"; - case SHT_SYMTAB_SHNDX: - return "SYMTAB SECTION INDICES"; - // FIXME: Parse processor specific GNU attributes - case SHT_GNU_ATTRIBUTES: - return "ATTRIBUTES"; - case SHT_GNU_HASH: - return "GNU_HASH"; - case SHT_GNU_verdef: - return "VERDEF"; - case SHT_GNU_verneed: - return "VERNEED"; - case SHT_GNU_versym: - return "VERSYM"; - default: - return ""; - } - return ""; -} - -template void GNUStyle::printSections(const ELFO *Obj) { - size_t sectionIndex = 0; - std::string number, type, size, address, offset, flags, link, info, entrysize, - alignment; - unsigned bias; - const char *FmtChar; - - if (ELFT::Is64Bits) { - bias = 0; - FmtChar = "%016" PRIx64; - } else { - bias = 8; - FmtChar = "%08" PRIx32; - } - OS << "There are " << to_string(Obj->getHeader()->e_shnum) - << " section headers, starting at offset " - << "0x" << to_hexString(Obj->getHeader()->e_shoff, false) << ":\n\n"; - OS << "Section Headers:\n"; - Field fields[11] = {{"[Nr]", 2}, - {"Name", 7}, - {"Type", 25}, - {"Address", 41}, - {"Off", 58 - bias}, - {"Size", 65 - bias}, - {"ES", 72 - bias}, - {"Flg", 75 - bias}, - {"Lk", 79 - bias}, - {"Inf", 82 - bias}, - {"Al", 86 - bias}}; - for (auto &f : fields) - printField(f); - OS << "\n"; - - for (const Elf_Shdr &Sec : Obj->sections()) { - number = to_string(sectionIndex); - fields[0] = number; - fields[1] = unwrapOrError(Obj->getSectionName(&Sec)); - type = getSectiontypeString(Obj->getHeader()->e_machine, Sec.sh_type); - fields[2] = type; - address = to_hexString(format(FmtChar, Sec.sh_addr)); - fields[3] = address; - offset = to_hexString(format("%6.6x", Sec.sh_offset)); - fields[4] = offset; - size = to_hexString(format("%6.6x", Sec.sh_size)); - fields[5] = size; - entrysize = to_hexString(format("%2.2x", Sec.sh_entsize)); - fields[6] = entrysize; - flags = getGNUFlags(Sec.sh_flags); - fields[7] = flags; - link = to_string(Sec.sh_link); - fields[8] = link; - info = to_string(Sec.sh_info); - fields[9] = info; - alignment = to_string(Sec.sh_addralign); - fields[10] = alignment; - OS.PadToColumn(fields[0].Column); - OS << "[" << right_justify(fields[0].Str, 2) << "]"; - for (int i = 1; i < 7; i++) - printField(fields[i]); - OS.PadToColumn(fields[7].Column); - OS << right_justify(fields[7].Str, 3); - OS.PadToColumn(fields[8].Column); - OS << right_justify(fields[8].Str, 2); - OS.PadToColumn(fields[9].Column); - OS << right_justify(fields[9].Str, 3); - OS.PadToColumn(fields[10].Column); - OS << right_justify(fields[10].Str, 2); - OS << "\n"; - ++sectionIndex; - } - OS << "Key to Flags:\n" - << " W (write), A (alloc), X (execute), M (merge), S (strings), l " - "(large)\n" - << " I (info), L (link order), G (group), T (TLS), E (exclude),\ - x (unknown)\n" - << " O (extra OS processing required) o (OS specific),\ - p (processor specific)\n"; -} - -template void GNUStyle::printSymbols(const ELFO *Obj) { - OS << "GNU style symbols not implemented!\n"; -} - -template -void GNUStyle::printDynamicSymbols(const ELFO *Obj) { - OS << "GNU style dynamic symbols not implemented!\n"; -} - -template -void GNUStyle::printDynamicRelocations(const ELFO *Obj) { - OS << "GNU style dynamic relocations not implemented!\n"; -} - -template void LLVMStyle::printFileHeaders(const ELFO *Obj) { +void LLVMStyle::printFileHeaders(const ELFFile *Obj) { const Elf_Ehdr *e = Obj->getHeader(); { DictScope D(W, "ElfHeader"); @@ -2537,264 +2389,3 @@ template void LLVMStyle::printFileHeaders(const ELFO *Obj) { W.printNumber("StringTableSectionIndex", e->e_shstrndx); } } - -template void LLVMStyle::printRelocations(const ELFO *Obj) { - ListScope D(W, "Relocations"); - - int SectionNumber = -1; - for (const Elf_Shdr &Sec : Obj->sections()) { - ++SectionNumber; - - if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA) - continue; - - StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); - - W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n"; - W.indent(); - - printRelocations(&Sec, Obj); - - W.unindent(); - W.startLine() << "}\n"; - } -} - -template -void LLVMStyle::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) { - const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec->sh_link)); - - switch (Sec->sh_type) { - case ELF::SHT_REL: - for (const Elf_Rel &R : Obj->rels(Sec)) { - Elf_Rela Rela; - Rela.r_offset = R.r_offset; - Rela.r_info = R.r_info; - Rela.r_addend = 0; - printRelocation(Obj, Rela, SymTab); - } - break; - case ELF::SHT_RELA: - for (const Elf_Rela &R : Obj->relas(Sec)) - printRelocation(Obj, R, SymTab); - break; - } -} - -template -void LLVMStyle::printRelocation(const ELFO *Obj, Elf_Rela Rel, - const Elf_Shdr *SymTab) { - SmallString<32> RelocName; - Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); - StringRef TargetName; - const Elf_Sym *Sym = Obj->getRelocationSymbol(&Rel, SymTab); - if (Sym && Sym->getType() == ELF::STT_SECTION) { - const Elf_Shdr *Sec = unwrapOrError( - Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable())); - TargetName = unwrapOrError(Obj->getSectionName(Sec)); - } else if (Sym) { - StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*SymTab)); - TargetName = unwrapOrError(Sym->getName(StrTable)); - } - - if (opts::ExpandRelocs) { - DictScope Group(W, "Relocation"); - W.printHex("Offset", Rel.r_offset); - W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); - W.printNumber("Symbol", TargetName.size() > 0 ? TargetName : "-", - Rel.getSymbol(Obj->isMips64EL())); - W.printHex("Addend", Rel.r_addend); - } else { - raw_ostream &OS = W.startLine(); - OS << W.hex(Rel.r_offset) << " " << RelocName << " " - << (TargetName.size() > 0 ? TargetName : "-") << " " - << W.hex(Rel.r_addend) << "\n"; - } -} - -template void LLVMStyle::printSections(const ELFO *Obj) { - ListScope SectionsD(W, "Sections"); - - int SectionIndex = -1; - for (const Elf_Shdr &Sec : Obj->sections()) { - ++SectionIndex; - - StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); - - DictScope SectionD(W, "Section"); - W.printNumber("Index", SectionIndex); - W.printNumber("Name", Name, Sec.sh_name); - W.printHex("Type", - getElfSectionType(Obj->getHeader()->e_machine, Sec.sh_type), - Sec.sh_type); - std::vector> SectionFlags(std::begin(ElfSectionFlags), - std::end(ElfSectionFlags)); - switch (Obj->getHeader()->e_machine) { - case EM_AMDGPU: - SectionFlags.insert(SectionFlags.end(), std::begin(ElfAMDGPUSectionFlags), - std::end(ElfAMDGPUSectionFlags)); - break; - case EM_HEXAGON: - SectionFlags.insert(SectionFlags.end(), - std::begin(ElfHexagonSectionFlags), - std::end(ElfHexagonSectionFlags)); - break; - case EM_MIPS: - SectionFlags.insert(SectionFlags.end(), std::begin(ElfMipsSectionFlags), - std::end(ElfMipsSectionFlags)); - break; - case EM_X86_64: - SectionFlags.insert(SectionFlags.end(), std::begin(ElfX86_64SectionFlags), - std::end(ElfX86_64SectionFlags)); - break; - default: - // Nothing to do. - break; - } - W.printFlags("Flags", Sec.sh_flags, makeArrayRef(SectionFlags)); - W.printHex("Address", Sec.sh_addr); - W.printHex("Offset", 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) { - ListScope D(W, "Relocations"); - printRelocations(&Sec, Obj); - } - - if (opts::SectionSymbols) { - ListScope D(W, "Symbols"); - const Elf_Shdr *Symtab = this->dumper()->getDotSymtabSec(); - StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab)); - - for (const Elf_Sym &Sym : Obj->symbols(Symtab)) { - const Elf_Shdr *SymSec = unwrapOrError( - Obj->getSection(&Sym, Symtab, this->dumper()->getShndxTable())); - if (SymSec == &Sec) - printSymbol(Obj, &Sym, Obj->symbol_begin(Symtab), StrTable, false); - } - } - - if (opts::SectionData && Sec.sh_type != ELF::SHT_NOBITS) { - ArrayRef Data = unwrapOrError(Obj->getSectionContents(&Sec)); - W.printBinaryBlock("SectionData", - StringRef((const char *)Data.data(), Data.size())); - } - } -} - -template -void LLVMStyle::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, - const Elf_Sym *First, StringRef StrTable, - bool IsDynamic) { - unsigned SectionIndex = 0; - StringRef SectionName; - getSectionNameIndex(*Obj, Symbol, First, this->dumper()->getShndxTable(), - SectionName, SectionIndex); - std::string FullSymbolName = - this->dumper()->getFullSymbolName(Symbol, StrTable, IsDynamic); - unsigned char SymbolType = Symbol->getType(); - - DictScope D(W, "Symbol"); - W.printNumber("Name", FullSymbolName, Symbol->st_name); - W.printHex("Value", Symbol->st_value); - W.printNumber("Size", Symbol->st_size); - W.printEnum("Binding", Symbol->getBinding(), makeArrayRef(ElfSymbolBindings)); - if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU && - SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) - W.printEnum("Type", SymbolType, makeArrayRef(AMDGPUSymbolTypes)); - else - W.printEnum("Type", SymbolType, makeArrayRef(ElfSymbolTypes)); - W.printNumber("Other", Symbol->st_other); - W.printHex("Section", SectionName, SectionIndex); -} - -template -void LLVMStyle::printSymbolsHelper(const ELFO *Obj, bool IsDynamic) { - StringRef StrTable; - typename ELFO::Elf_Sym_Range Syms(nullptr, nullptr); - if (IsDynamic) { - StrTable = this->dumper()->getDynamicStringTable(); - Syms = this->dumper()->dynamic_symbols(); - } else { - if (!this->dumper()->getDotSymtabSec()) - return; - const auto DotSymtabSec = this->dumper()->getDotSymtabSec(); - StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec)); - Syms = Obj->symbols(DotSymtabSec); - } - for (const Elf_Sym &Sym : Syms) - printSymbol(Obj, &Sym, Syms.begin(), StrTable, IsDynamic); -} - -template void LLVMStyle::printSymbols(const ELFO *Obj) { - ListScope Group(W, "Symbols"); - printSymbolsHelper(Obj, false); -} - -template -void LLVMStyle::printDynamicSymbols(const ELFO *Obj) { - ListScope Group(W, "DynamicSymbols"); - printSymbolsHelper(Obj, true); -} - -template -void LLVMStyle::printDynamicRelocations(const ELFO *Obj) { - const DynRegionInfo &DynRelRegion = this->dumper()->getDynRelRegion(); - const DynRegionInfo &DynRelaRegion = this->dumper()->getDynRelaRegion(); - const DynRegionInfo &DynPLTRelRegion = this->dumper()->getDynPLTRelRegion(); - if (DynRelRegion.Size && DynRelaRegion.Size) - report_fatal_error("There are both REL and RELA dynamic relocations"); - W.startLine() << "Dynamic Relocations {\n"; - W.indent(); - if (DynRelaRegion.Size > 0) - for (const Elf_Rela &Rela : this->dumper()->dyn_relas()) - printDynamicRelocation(Obj, Rela); - else - for (const Elf_Rel &Rel : this->dumper()->dyn_rels()) { - Elf_Rela Rela; - Rela.r_offset = Rel.r_offset; - Rela.r_info = Rel.r_info; - Rela.r_addend = 0; - printDynamicRelocation(Obj, Rela); - } - if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) - for (const Elf_Rela &Rela : DynPLTRelRegion.getAsRange()) - printDynamicRelocation(Obj, Rela); - else - for (const Elf_Rel &Rel : DynPLTRelRegion.getAsRange()) { - Elf_Rela Rela; - Rela.r_offset = Rel.r_offset; - Rela.r_info = Rel.r_info; - Rela.r_addend = 0; - printDynamicRelocation(Obj, Rela); - } - W.unindent(); - W.startLine() << "}\n"; -} - -template -void LLVMStyle::printDynamicRelocation(const ELFO *Obj, Elf_Rela Rel) { - SmallString<32> RelocName; - Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); - StringRef SymbolName; - uint32_t SymIndex = Rel.getSymbol(Obj->isMips64EL()); - const Elf_Sym *Sym = this->dumper()->dynamic_symbols().begin() + SymIndex; - SymbolName = - unwrapOrError(Sym->getName(this->dumper()->getDynamicStringTable())); - if (opts::ExpandRelocs) { - DictScope Group(W, "Relocation"); - W.printHex("Offset", Rel.r_offset); - W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); - W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); - W.printHex("Addend", Rel.r_addend); - } else { - raw_ostream &OS = W.startLine(); - OS << W.hex(Rel.r_offset) << " " << RelocName << " " - << (SymbolName.size() > 0 ? SymbolName : "-") << " " - << W.hex(Rel.r_addend) << "\n"; - } -} diff --git a/llvm/tools/llvm-readobj/StreamWriter.cpp b/llvm/tools/llvm-readobj/StreamWriter.cpp index 0b0be59..390b05e 100644 --- a/llvm/tools/llvm-readobj/StreamWriter.cpp +++ b/llvm/tools/llvm-readobj/StreamWriter.cpp @@ -26,13 +26,6 @@ const std::string to_string(uint64_t Value) { return stream.str(); } -const std::string to_hexString(const format_object_base &obj) { - std::string number; - llvm::raw_string_ostream stream(number); - stream << obj; - return stream.str(); -} - void StreamWriter::printBinaryImpl(StringRef Label, StringRef Str, ArrayRef Data, bool Block) { if (Data.size() > 16) diff --git a/llvm/tools/llvm-readobj/StreamWriter.h b/llvm/tools/llvm-readobj/StreamWriter.h index d745f8d..c1567d4 100644 --- a/llvm/tools/llvm-readobj/StreamWriter.h +++ b/llvm/tools/llvm-readobj/StreamWriter.h @@ -62,7 +62,6 @@ raw_ostream &operator<<(raw_ostream &OS, const HexNumber& Value); const std::string to_hexString(uint64_t Value, bool UpperCase = true); const std::string to_string(uint64_t Value); -const std::string to_hexString(const format_object_base &obj); class StreamWriter { public: StreamWriter(raw_ostream &OS)