diff options
Diffstat (limited to 'contrib/llvm/tools/llvm-readobj')
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/ARMEHABIPrinter.h | 36 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/COFFDumper.cpp | 116 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/ELFDumper.cpp | 473 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/Error.cpp | 4 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/MachODumper.cpp | 4 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/ObjDumper.h | 11 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/StackMapPrinter.h | 3 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp | 48 | ||||
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/llvm-readobj.h | 3 |
9 files changed, 523 insertions, 175 deletions
diff --git a/contrib/llvm/tools/llvm-readobj/ARMEHABIPrinter.h b/contrib/llvm/tools/llvm-readobj/ARMEHABIPrinter.h index 59c9b71..903a246 100644 --- a/contrib/llvm/tools/llvm-readobj/ARMEHABIPrinter.h +++ b/contrib/llvm/tools/llvm-readobj/ARMEHABIPrinter.h @@ -349,11 +349,12 @@ template <typename ET> ErrorOr<StringRef> PrinterContext<ET>::FunctionAtAddress(unsigned Section, uint64_t Address) const { - ErrorOr<StringRef> StrTableOrErr = ELF->getStringTableForSymtab(*Symtab); - error(StrTableOrErr.getError()); + auto StrTableOrErr = ELF->getStringTableForSymtab(*Symtab); + if (!StrTableOrErr) + error(StrTableOrErr.takeError()); StringRef StrTable = *StrTableOrErr; - for (const Elf_Sym &Sym : ELF->symbols(Symtab)) + for (const Elf_Sym &Sym : unwrapOrError(ELF->symbols(Symtab))) if (Sym.st_shndx == Section && Sym.st_value == Address && Sym.getType() == ELF::STT_FUNC) { auto NameOrErr = Sym.getName(StrTable); @@ -379,15 +380,16 @@ PrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex, /// handling table. Use this symbol to recover the actual exception handling /// table. - for (const Elf_Shdr &Sec : ELF->sections()) { + for (const Elf_Shdr &Sec : unwrapOrError(ELF->sections())) { if (Sec.sh_type != ELF::SHT_REL || Sec.sh_info != IndexSectionIndex) continue; - ErrorOr<const Elf_Shdr *> SymTabOrErr = ELF->getSection(Sec.sh_link); - error(SymTabOrErr.getError()); + auto SymTabOrErr = ELF->getSection(Sec.sh_link); + if (!SymTabOrErr) + error(SymTabOrErr.takeError()); const Elf_Shdr *SymTab = *SymTabOrErr; - for (const Elf_Rel &R : ELF->rels(&Sec)) { + for (const Elf_Rel &R : unwrapOrError(ELF->rels(&Sec))) { if (R.r_offset != static_cast<unsigned>(IndexTableOffset)) continue; @@ -396,12 +398,12 @@ PrinterContext<ET>::FindExceptionTable(unsigned IndexSectionIndex, RelA.r_info = R.r_info; RelA.r_addend = 0; - const Elf_Sym *Symbol = ELF->getRelocationSymbol(&RelA, SymTab); + const Elf_Sym *Symbol = + unwrapOrError(ELF->getRelocationSymbol(&RelA, SymTab)); - ErrorOr<const Elf_Shdr *> Ret = - ELF->getSection(Symbol, SymTab, ShndxTable); - if (std::error_code EC = Ret.getError()) - report_fatal_error(EC.message()); + auto Ret = ELF->getSection(Symbol, SymTab, ShndxTable); + if (!Ret) + report_fatal_error(errorToErrorCode(Ret.takeError()).message()); return *Ret; } } @@ -412,7 +414,7 @@ template <typename ET> void PrinterContext<ET>::PrintExceptionTable(const Elf_Shdr *IT, const Elf_Shdr *EHT, uint64_t TableEntryOffset) const { - ErrorOr<ArrayRef<uint8_t> > Contents = ELF->getSectionContents(EHT); + Expected<ArrayRef<uint8_t>> Contents = ELF->getSectionContents(EHT); if (!Contents) return; @@ -479,7 +481,7 @@ void PrinterContext<ET>::PrintOpcodes(const uint8_t *Entry, template <typename ET> void PrinterContext<ET>::PrintIndexTable(unsigned SectionIndex, const Elf_Shdr *IT) const { - ErrorOr<ArrayRef<uint8_t> > Contents = ELF->getSectionContents(IT); + Expected<ArrayRef<uint8_t>> Contents = ELF->getSectionContents(IT); if (!Contents) return; @@ -532,7 +534,7 @@ void PrinterContext<ET>::PrintIndexTable(unsigned SectionIndex, const Elf_Shdr *EHT = FindExceptionTable(SectionIndex, Entry * IndexTableEntrySize + 4); - if (ErrorOr<StringRef> Name = ELF->getSectionName(EHT)) + if (auto Name = ELF->getSectionName(EHT)) SW.printString("ExceptionHandlingTable", *Name); uint64_t TableEntryOffset = PREL31(Word1, IT->sh_addr); @@ -548,12 +550,12 @@ void PrinterContext<ET>::PrintUnwindInformation() const { DictScope UI(SW, "UnwindInformation"); int SectionIndex = 0; - for (const Elf_Shdr &Sec : ELF->sections()) { + for (const Elf_Shdr &Sec : unwrapOrError(ELF->sections())) { if (Sec.sh_type == ELF::SHT_ARM_EXIDX) { DictScope UIT(SW, "UnwindIndexTable"); SW.printNumber("SectionIndex", SectionIndex); - if (ErrorOr<StringRef> SectionName = ELF->getSectionName(&Sec)) + if (auto SectionName = ELF->getSectionName(&Sec)) SW.printString("SectionName", *SectionName); SW.printHex("SectionOffset", Sec.sh_offset); diff --git a/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp b/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp index 348f5b4..c83655f 100644 --- a/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -22,18 +22,20 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/DebugInfo/CodeView/ByteStream.h" +#include "llvm/DebugInfo/CodeView/CVTypeDumper.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/Line.h" -#include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h" #include "llvm/DebugInfo/CodeView/RecordSerialization.h" +#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h" #include "llvm/DebugInfo/CodeView/SymbolDumper.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" -#include "llvm/DebugInfo/CodeView/TypeDumper.h" +#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" +#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" +#include "llvm/DebugInfo/MSF/ByteStream.h" #include "llvm/Object/COFF.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/COFF.h" @@ -53,6 +55,7 @@ using namespace llvm; using namespace llvm::object; using namespace llvm::codeview; +using namespace llvm::msf; using namespace llvm::support; using namespace llvm::Win64EH; @@ -62,8 +65,7 @@ class COFFDumper : public ObjDumper { public: friend class COFFObjectDumpDelegate; COFFDumper(const llvm::object::COFFObjectFile *Obj, ScopedPrinter &Writer) - : ObjDumper(Writer), Obj(Obj), - CVTD(&Writer, opts::CodeViewSubsectionBytes) {} + : ObjDumper(Writer), Obj(Obj), Writer(Writer) {} void printFileHeaders() override; void printSections() override; @@ -77,8 +79,7 @@ public: void printCOFFBaseReloc() override; void printCOFFDebugDirectory() override; void printCodeViewDebugInfo() override; - void - mergeCodeViewTypes(llvm::codeview::MemoryTypeTableBuilder &CVTypes) override; + void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVTypes) override; void printStackMap() const override; private: void printSymbol(const SymbolRef &Sym); @@ -98,7 +99,7 @@ private: void printFileNameForOffset(StringRef Label, uint32_t FileOffset); void printTypeIndex(StringRef FieldName, TypeIndex TI) { // Forward to CVTypeDumper for simplicity. - CVTD.printTypeIndex(FieldName, TI); + CVTypeDumper::printTypeIndex(Writer, FieldName, TI, TypeDB); } void printCodeViewSymbolsSubsection(StringRef Subsection, @@ -141,7 +142,8 @@ private: StringRef CVFileChecksumTable; StringRef CVStringTable; - CVTypeDumper CVTD; + ScopedPrinter &Writer; + TypeDatabase TypeDB; }; class COFFObjectDumpDelegate : public SymbolDumpDelegate { @@ -152,8 +154,13 @@ public: Sec = Obj->getCOFFSection(SR); } - uint32_t getRecordOffset(ArrayRef<uint8_t> Record) override { - return Record.data() - SectionContents.bytes_begin(); + uint32_t getRecordOffset(msf::StreamReader Reader) override { + ArrayRef<uint8_t> Data; + if (auto EC = Reader.readLongestContiguousChunk(Data)) { + llvm::consumeError(std::move(EC)); + return 0; + } + return Data.data() - SectionContents.bytes_begin(); } void printRelocatedField(StringRef Label, uint32_t RelocOffset, @@ -669,14 +676,16 @@ void COFFDumper::printCOFFDebugDirectory() { W.printHex("AddressOfRawData", D.AddressOfRawData); W.printHex("PointerToRawData", D.PointerToRawData); if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) { - const debug_pdb_info *PDBInfo; + const codeview::DebugInfo *DebugInfo; StringRef PDBFileName; - error(Obj->getDebugPDBInfo(&D, PDBInfo, PDBFileName)); + error(Obj->getDebugPDBInfo(&D, DebugInfo, PDBFileName)); DictScope PDBScope(W, "PDBInfo"); - W.printHex("PDBSignature", PDBInfo->Signature); - W.printBinary("PDBGUID", makeArrayRef(PDBInfo->Guid)); - W.printNumber("PDBAge", PDBInfo->Age); - W.printString("PDBFileName", PDBFileName); + W.printHex("PDBSignature", DebugInfo->Signature.CVSignature); + if (DebugInfo->Signature.CVSignature == OMF::Signature::PDB70) { + W.printBinary("PDBGUID", makeArrayRef(DebugInfo->PDB70.Signature)); + W.printNumber("PDBAge", DebugInfo->PDB70.Age); + W.printString("PDBFileName", PDBFileName); + } } else { // FIXME: Type values of 12 and 13 are commonly observed but are not in // the documented type enum. Figure out what they mean. @@ -831,8 +840,10 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, } case ModuleSubstreamKind::FrameData: { // First four bytes is a relocation against the function. + msf::ByteStream S(Contents); + msf::StreamReader SR(S); const uint32_t *CodePtr; - error(consumeObject(Contents, CodePtr)); + error(SR.readObject(CodePtr)); StringRef LinkageName; error(resolveSymbolName(Obj->getCOFFSection(Section), SectionContents, CodePtr, LinkageName)); @@ -840,9 +851,9 @@ void COFFDumper::printCodeViewSymbolSection(StringRef SectionName, // To find the active frame description, search this array for the // smallest PC range that includes the current PC. - while (!Contents.empty()) { + while (!SR.empty()) { const FrameData *FD; - error(consumeObject(Contents, FD)); + error(SR.readObject(FD)); if (FD->FrameFunc >= CVStringTable.size()) error(object_error::parse_failed); @@ -952,8 +963,9 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, auto CODD = llvm::make_unique<COFFObjectDumpDelegate>(*this, Section, Obj, SectionContents); - CVSymbolDumper CVSD(W, CVTD, std::move(CODD), opts::CodeViewSubsectionBytes); - ByteStream<> Stream(BinaryData); + CVSymbolDumper CVSD(W, TypeDB, std::move(CODD), + opts::CodeViewSubsectionBytes); + ByteStream Stream(BinaryData); CVSymbolArray Symbols; StreamReader Reader(Stream); if (auto EC = Reader.readArray(Symbols, Reader.getLength())) { @@ -962,19 +974,20 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, error(object_error::parse_failed); } - if (!CVSD.dump(Symbols)) { + if (auto EC = CVSD.dump(Symbols)) { W.flush(); - error(object_error::parse_failed); + error(std::move(EC)); } W.flush(); } void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) { - StringRef Data = Subsection; - while (!Data.empty()) { + msf::ByteStream S(Subsection); + msf::StreamReader SR(S); + while (!SR.empty()) { DictScope S(W, "FileChecksum"); const FileChecksum *FC; - error(consumeObject(Data, FC)); + error(SR.readObject(FC)); if (FC->FileNameOffset >= CVStringTable.size()) error(object_error::parse_failed); StringRef Filename = @@ -983,27 +996,30 @@ void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) { W.printHex("ChecksumSize", FC->ChecksumSize); W.printEnum("ChecksumKind", uint8_t(FC->ChecksumKind), makeArrayRef(FileChecksumKindNames)); - if (FC->ChecksumSize >= Data.size()) + if (FC->ChecksumSize >= SR.bytesRemaining()) error(object_error::parse_failed); - StringRef ChecksumBytes = Data.substr(0, FC->ChecksumSize); + ArrayRef<uint8_t> ChecksumBytes; + error(SR.readBytes(ChecksumBytes, FC->ChecksumSize)); W.printBinary("ChecksumBytes", ChecksumBytes); unsigned PaddedSize = alignTo(FC->ChecksumSize + sizeof(FileChecksum), 4) - sizeof(FileChecksum); - if (PaddedSize > Data.size()) + PaddedSize -= ChecksumBytes.size(); + if (PaddedSize > SR.bytesRemaining()) error(object_error::parse_failed); - Data = Data.drop_front(PaddedSize); + error(SR.skip(PaddedSize)); } } void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) { - StringRef Data = Subsection; + msf::ByteStream S(Subsection); + msf::StreamReader SR(S); uint32_t Signature; - error(consume(Data, Signature)); + error(SR.readInteger(Signature)); bool HasExtraFiles = Signature == unsigned(InlineeLinesSignature::ExtraFiles); - while (!Data.empty()) { + while (!SR.empty()) { const InlineeSourceLine *ISL; - error(consumeObject(Data, ISL)); + error(SR.readObject(ISL)); DictScope S(W, "InlineeSourceLine"); printTypeIndex("Inlinee", ISL->Inlinee); printFileNameForOffset("FileID", ISL->FileID); @@ -1011,12 +1027,12 @@ void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) { if (HasExtraFiles) { uint32_t ExtraFileCount; - error(consume(Data, ExtraFileCount)); + error(SR.readInteger(ExtraFileCount)); W.printNumber("ExtraFileCount", ExtraFileCount); ListScope ExtraFiles(W, "ExtraFiles"); for (unsigned I = 0; I < ExtraFileCount; ++I) { uint32_t FileID; - error(consume(Data, FileID)); + error(SR.readInteger(FileID)); printFileNameForOffset("FileID", FileID); } } @@ -1048,7 +1064,7 @@ void COFFDumper::printFileNameForOffset(StringRef Label, uint32_t FileOffset) { W.printHex(Label, getFileNameForFileOffset(FileOffset), FileOffset); } -void COFFDumper::mergeCodeViewTypes(MemoryTypeTableBuilder &CVTypes) { +void COFFDumper::mergeCodeViewTypes(TypeTableBuilder &CVTypes) { for (const SectionRef &S : Obj->sections()) { StringRef SectionName; error(S.getName(SectionName)); @@ -1061,7 +1077,7 @@ void COFFDumper::mergeCodeViewTypes(MemoryTypeTableBuilder &CVTypes) { error(object_error::parse_failed); ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(Data.data()), Data.size()); - ByteStream<> Stream(Bytes); + ByteStream Stream(Bytes); CVTypeArray Types; StreamReader Reader(Stream); if (auto EC = Reader.readArray(Types, Reader.getLength())) { @@ -1092,7 +1108,9 @@ void COFFDumper::printCodeViewTypeSection(StringRef SectionName, if (Magic != COFF::DEBUG_SECTION_MAGIC) return error(object_error::parse_failed); - if (auto EC = CVTD.dump({Data.bytes_begin(), Data.bytes_end()})) { + CVTypeDumper CVTD(TypeDB); + TypeDumpVisitor TDV(TypeDB, &W, opts::CodeViewSubsectionBytes); + if (auto EC = CVTD.dump({Data.bytes_begin(), Data.bytes_end()}, TDV)) { W.flush(); error(llvm::errorToErrorCode(std::move(EC))); } @@ -1524,22 +1542,26 @@ void COFFDumper::printStackMap() const { if (Obj->isLittleEndian()) prettyPrintStackMap( llvm::outs(), - StackMapV1Parser<support::little>(StackMapContentsArray)); + StackMapV2Parser<support::little>(StackMapContentsArray)); else prettyPrintStackMap(llvm::outs(), - StackMapV1Parser<support::big>(StackMapContentsArray)); + StackMapV2Parser<support::big>(StackMapContentsArray)); } -void llvm::dumpCodeViewMergedTypes( - ScopedPrinter &Writer, llvm::codeview::MemoryTypeTableBuilder &CVTypes) { +void llvm::dumpCodeViewMergedTypes(ScopedPrinter &Writer, + llvm::codeview::TypeTableBuilder &CVTypes) { // Flatten it first, then run our dumper on it. ListScope S(Writer, "MergedTypeStream"); SmallString<0> Buf; - CVTypes.ForEachRecord([&](TypeIndex TI, StringRef Record) { + CVTypes.ForEachRecord([&](TypeIndex TI, ArrayRef<uint8_t> Record) { Buf.append(Record.begin(), Record.end()); }); - CVTypeDumper CVTD(&Writer, opts::CodeViewSubsectionBytes); - if (auto EC = CVTD.dump({Buf.str().bytes_begin(), Buf.str().bytes_end()})) { + + TypeDatabase TypeDB; + CVTypeDumper CVTD(TypeDB); + TypeDumpVisitor TDV(TypeDB, &Writer, opts::CodeViewSubsectionBytes); + if (auto EC = + CVTD.dump({Buf.str().bytes_begin(), Buf.str().bytes_end()}, TDV)) { Writer.flush(); error(llvm::errorToErrorCode(std::move(EC))); } diff --git a/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp b/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp index 06fbe8d..997af56 100644 --- a/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/contrib/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -56,6 +56,7 @@ using namespace ELF; 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_Rel_Range Elf_Rel_Range; \ typedef typename ELFO::Elf_Rela_Range Elf_Rela_Range; \ typedef typename ELFO::Elf_Phdr Elf_Phdr; \ typedef typename ELFO::Elf_Half Elf_Half; \ @@ -63,6 +64,12 @@ using namespace ELF; typedef typename ELFO::Elf_Word Elf_Word; \ typedef typename ELFO::Elf_Hash Elf_Hash; \ typedef typename ELFO::Elf_GnuHash Elf_GnuHash; \ + typedef typename ELFO::Elf_Sym_Range Elf_Sym_Range; \ + typedef typename ELFO::Elf_Versym Elf_Versym; \ + typedef typename ELFO::Elf_Verneed Elf_Verneed; \ + typedef typename ELFO::Elf_Vernaux Elf_Vernaux; \ + typedef typename ELFO::Elf_Verdef Elf_Verdef; \ + typedef typename ELFO::Elf_Verdaux Elf_Verdaux; \ typedef typename ELFO::uintX_t uintX_t; namespace { @@ -122,34 +129,17 @@ public: void printMipsReginfo() override; void printMipsOptions() override; + void printAMDGPURuntimeMD() override; + void printStackMap() const override; void printHashHistogram() override; + void printNotes() override; + private: std::unique_ptr<DumpStyle<ELFT>> ELFDumperStyle; - typedef ELFFile<ELFT> ELFO; - typedef typename ELFO::Elf_Shdr Elf_Shdr; - typedef typename ELFO::Elf_Sym Elf_Sym; - typedef typename ELFO::Elf_Sym_Range Elf_Sym_Range; - 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_Rel_Range Elf_Rel_Range; - 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_Hash Elf_Hash; - typedef typename ELFO::Elf_GnuHash Elf_GnuHash; - typedef typename ELFO::Elf_Ehdr Elf_Ehdr; - typedef typename ELFO::Elf_Word Elf_Word; - typedef typename ELFO::uintX_t uintX_t; - typedef typename ELFO::Elf_Versym Elf_Versym; - typedef typename ELFO::Elf_Verneed Elf_Verneed; - typedef typename ELFO::Elf_Vernaux Elf_Vernaux; - typedef typename ELFO::Elf_Verdef Elf_Verdef; - typedef typename ELFO::Elf_Verdaux Elf_Verdaux; + TYPEDEF_ELF_TYPES(ELFT) DynRegionInfo checkDRI(DynRegionInfo DRI) { if (DRI.Addr < Obj->base() || @@ -258,7 +248,7 @@ void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const { if (!DotSymtabSec) return; StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec)); - Syms = Obj->symbols(DotSymtabSec); + Syms = unwrapOrError(Obj->symbols(DotSymtabSec)); SymtabName = unwrapOrError(Obj->getSectionName(DotSymtabSec)); Entries = DotSymtabSec->getEntityCount(); } @@ -292,6 +282,7 @@ public: bool IsDynamic) = 0; virtual void printProgramHeaders(const ELFFile<ELFT> *Obj) = 0; virtual void printHashHistogram(const ELFFile<ELFT> *Obj) = 0; + virtual void printNotes(const ELFFile<ELFT> *Obj) = 0; const ELFDumper<ELFT> *dumper() const { return Dumper; } private: const ELFDumper<ELFT> *Dumper; @@ -314,6 +305,7 @@ public: size_t Offset) override; void printProgramHeaders(const ELFO *Obj) override; void printHashHistogram(const ELFFile<ELFT> *Obj) override; + void printNotes(const ELFFile<ELFT> *Obj) override; private: struct Field { @@ -338,6 +330,8 @@ private: OS.flush(); return OS; } + void printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym, uint32_t Sym, + StringRef StrTable, uint32_t Bucket); void printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, const Elf_Rela &R, bool IsRela); void printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, const Elf_Sym *First, @@ -367,6 +361,7 @@ public: void printDynamicRelocations(const ELFO *Obj) override; void printProgramHeaders(const ELFO *Obj) override; void printHashHistogram(const ELFFile<ELFT> *Obj) override; + void printNotes(const ELFFile<ELFT> *Obj) override; private: void printRelocation(const ELFO *Obj, Elf_Rela Rel, const Elf_Shdr *SymTab); @@ -656,8 +651,8 @@ StringRef ELFDumper<ELFT>::getSymbolVersion(StringRef StrTab, sizeof(Elf_Sym); // Get the corresponding version index entry - const Elf_Versym *vs = - Obj->template getEntry<Elf_Versym>(dot_gnu_version_sec, entry_index); + const Elf_Versym *vs = unwrapOrError( + Obj->template getEntry<Elf_Versym>(dot_gnu_version_sec, entry_index)); size_t version_index = vs->vs_index & ELF::VERSYM_VERSION; // Special markers for unversioned symbols. @@ -705,11 +700,11 @@ std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol, return FullSymbolName; } -template <typename ELFO> +template <typename ELFT> static void -getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol, - const typename ELFO::Elf_Sym *FirstSym, - ArrayRef<typename ELFO::Elf_Word> ShndxTable, +getSectionNameIndex(const ELFFile<ELFT> &Obj, const typename ELFT::Sym *Symbol, + const typename ELFT::Sym *FirstSym, + ArrayRef<typename ELFT::Word> ShndxTable, StringRef &SectionName, unsigned &SectionIndex) { SectionIndex = Symbol->st_shndx; if (Symbol->isUndefined()) @@ -726,9 +721,9 @@ getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol, SectionName = "Reserved"; else { if (SectionIndex == SHN_XINDEX) - SectionIndex = - Obj.getExtendedSymbolTableIndex(Symbol, FirstSym, ShndxTable); - const typename ELFO::Elf_Shdr *Sec = + SectionIndex = unwrapOrError(object::getExtendedSymbolTableIndex<ELFT>( + Symbol, FirstSym, ShndxTable)); + const typename ELFT::Shdr *Sec = unwrapOrError(Obj.getSection(SectionIndex)); SectionName = unwrapOrError(Obj.getSectionName(Sec)); } @@ -737,7 +732,7 @@ getSectionNameIndex(const ELFO &Obj, const typename ELFO::Elf_Sym *Symbol, template <class ELFO> static const typename ELFO::Elf_Shdr * findNotEmptySectionByAddress(const ELFO *Obj, uint64_t Addr) { - for (const auto &Shdr : Obj->sections()) + for (const auto &Shdr : unwrapOrError(Obj->sections())) if (Shdr.sh_addr == Addr && Shdr.sh_size > 0) return &Shdr; return nullptr; @@ -746,7 +741,7 @@ findNotEmptySectionByAddress(const ELFO *Obj, uint64_t Addr) { template <class ELFO> static const typename ELFO::Elf_Shdr *findSectionByName(const ELFO &Obj, StringRef Name) { - for (const auto &Shdr : Obj.sections()) { + for (const auto &Shdr : unwrapOrError(Obj.sections())) { if (Name == unwrapOrError(Obj.getSectionName(&Shdr))) return &Shdr; } @@ -954,6 +949,7 @@ static const EnumEntry<unsigned> ElfMachineType[] = { ENUM_ENT(EM_78KOR, "EM_78KOR"), ENUM_ENT(EM_56800EX, "EM_56800EX"), ENUM_ENT(EM_AMDGPU, "EM_AMDGPU"), + ENUM_ENT(EM_RISCV, "RISC-V"), ENUM_ENT(EM_WEBASSEMBLY, "EM_WEBASSEMBLY"), ENUM_ENT(EM_LANAI, "EM_LANAI"), ENUM_ENT(EM_BPF, "EM_BPF"), @@ -1073,6 +1069,10 @@ static const EnumEntry<unsigned> ElfAMDGPUSectionFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, SHF_AMDGPU_HSA_AGENT) }; +static const EnumEntry<unsigned> ElfARMSectionFlags[] = { + LLVM_READOBJ_ENUM_ENT(ELF, SHF_ARM_PURECODE) +}; + static const EnumEntry<unsigned> ElfHexagonSectionFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, SHF_HEX_GPREL) }; @@ -1163,6 +1163,11 @@ static const char *getElfSegmentType(unsigned Arch, unsigned Type) { LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_STACK); LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_RELRO); + + LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_RANDOMIZE); + LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_WXNEEDED); + LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA); + default: return ""; } } @@ -1309,7 +1314,7 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, ScopedPrinter &Writer) : ObjDumper(Writer), Obj(Obj) { SmallVector<const Elf_Phdr *, 4> LoadSegments; - for (const Elf_Phdr &Phdr : Obj->program_headers()) { + for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { if (Phdr.p_type == ELF::PT_DYNAMIC) { DynamicTable = createDRIFrom(&Phdr, sizeof(Elf_Dyn)); continue; @@ -1319,7 +1324,7 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile<ELFT> *Obj, ScopedPrinter &Writer) LoadSegments.push_back(&Phdr); } - for (const Elf_Shdr &Sec : Obj->sections()) { + for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { switch (Sec.sh_type) { case ELF::SHT_SYMTAB: if (DotSymtabSec != nullptr) @@ -1491,10 +1496,37 @@ void ELFDumper<ELFT>::printDynamicSymbols() { template <class ELFT> void ELFDumper<ELFT>::printHashHistogram() { ELFDumperStyle->printHashHistogram(Obj); } + +template <class ELFT> void ELFDumper<ELFT>::printNotes() { + ELFDumperStyle->printNotes(Obj); +} + #define LLVM_READOBJ_TYPE_CASE(name) \ case DT_##name: return #name -static const char *getTypeString(uint64_t Type) { +static const char *getTypeString(unsigned Arch, uint64_t Type) { + switch (Arch) { + case EM_HEXAGON: + switch (Type) { + LLVM_READOBJ_TYPE_CASE(HEXAGON_SYMSZ); + LLVM_READOBJ_TYPE_CASE(HEXAGON_VER); + LLVM_READOBJ_TYPE_CASE(HEXAGON_PLT); + } + case EM_MIPS: + switch (Type) { + LLVM_READOBJ_TYPE_CASE(MIPS_RLD_MAP_REL); + LLVM_READOBJ_TYPE_CASE(MIPS_RLD_VERSION); + LLVM_READOBJ_TYPE_CASE(MIPS_FLAGS); + LLVM_READOBJ_TYPE_CASE(MIPS_BASE_ADDRESS); + LLVM_READOBJ_TYPE_CASE(MIPS_LOCAL_GOTNO); + LLVM_READOBJ_TYPE_CASE(MIPS_SYMTABNO); + LLVM_READOBJ_TYPE_CASE(MIPS_UNREFEXTNO); + LLVM_READOBJ_TYPE_CASE(MIPS_GOTSYM); + LLVM_READOBJ_TYPE_CASE(MIPS_RLD_MAP); + LLVM_READOBJ_TYPE_CASE(MIPS_PLTGOT); + LLVM_READOBJ_TYPE_CASE(MIPS_OPTIONS); + } + } switch (Type) { LLVM_READOBJ_TYPE_CASE(BIND_NOW); LLVM_READOBJ_TYPE_CASE(DEBUG); @@ -1540,17 +1572,7 @@ static const char *getTypeString(uint64_t Type) { LLVM_READOBJ_TYPE_CASE(GNU_HASH); LLVM_READOBJ_TYPE_CASE(TLSDESC_PLT); LLVM_READOBJ_TYPE_CASE(TLSDESC_GOT); - LLVM_READOBJ_TYPE_CASE(MIPS_RLD_VERSION); - LLVM_READOBJ_TYPE_CASE(MIPS_RLD_MAP_REL); - LLVM_READOBJ_TYPE_CASE(MIPS_FLAGS); - LLVM_READOBJ_TYPE_CASE(MIPS_BASE_ADDRESS); - LLVM_READOBJ_TYPE_CASE(MIPS_LOCAL_GOTNO); - LLVM_READOBJ_TYPE_CASE(MIPS_SYMTABNO); - LLVM_READOBJ_TYPE_CASE(MIPS_UNREFEXTNO); - LLVM_READOBJ_TYPE_CASE(MIPS_GOTSYM); - LLVM_READOBJ_TYPE_CASE(MIPS_RLD_MAP); - LLVM_READOBJ_TYPE_CASE(MIPS_PLTGOT); - LLVM_READOBJ_TYPE_CASE(MIPS_OPTIONS); + LLVM_READOBJ_TYPE_CASE(AUXILIARY); default: return "unknown"; } } @@ -1656,7 +1678,7 @@ void ELFDumper<ELFT>::printValue(uint64_t Type, uint64_t Value) { OS << "RELA"; break; } - // Fallthrough. + LLVM_FALLTHROUGH; case DT_PLTGOT: case DT_HASH: case DT_STRTAB: @@ -1711,6 +1733,9 @@ void ELFDumper<ELFT>::printValue(uint64_t Type, uint64_t Value) { case DT_SONAME: OS << "LibrarySoname (" << getDynamicString(Value) << ")"; break; + case DT_AUXILIARY: + OS << "Auxiliary library: [" << getDynamicString(Value) << "]"; + break; case DT_RPATH: case DT_RUNPATH: OS << getDynamicString(Value); @@ -1779,7 +1804,7 @@ void ELFDumper<ELFT>::printDynamicTable() { uintX_t Tag = Entry.getTag(); ++I; W.startLine() << " " << format_hex(Tag, Is64 ? 18 : 10, opts::Output != opts::GNU) << " " - << format("%-21s", getTypeString(Tag)); + << format("%-21s", getTypeString(Obj->getHeader()->e_machine, Tag)); printValue(Tag, Entry.getVal()); OS << "\n"; } @@ -1852,7 +1877,7 @@ template <> void ELFDumper<ELFType<support::little, false>>::printAttributes() { } DictScope BA(W, "BuildAttributes"); - for (const ELFO::Elf_Shdr &Sec : Obj->sections()) { + for (const ELFO::Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { if (Sec.sh_type != ELF::SHT_ARM_ATTRIBUTES) continue; @@ -1875,14 +1900,8 @@ template <> void ELFDumper<ELFType<support::little, false>>::printAttributes() { namespace { template <class ELFT> class MipsGOTParser { public: - typedef object::ELFFile<ELFT> ELFO; - typedef typename ELFO::Elf_Shdr Elf_Shdr; - typedef typename ELFO::Elf_Sym Elf_Sym; - typedef typename ELFO::Elf_Dyn_Range Elf_Dyn_Range; + TYPEDEF_ELF_TYPES(ELFT) typedef typename ELFO::Elf_Addr GOTEntry; - typedef typename ELFO::Elf_Rel Elf_Rel; - typedef typename ELFO::Elf_Rela Elf_Rela; - MipsGOTParser(ELFDumper<ELFT> *Dumper, const ELFO *Obj, Elf_Dyn_Range DynTable, ScopedPrinter &W); @@ -2068,19 +2087,21 @@ template <class ELFT> void MipsGOTParser<ELFT>::parsePLT() { switch (PLTRelShdr->sh_type) { case ELF::SHT_REL: - for (const Elf_Rel *RI = Obj->rel_begin(PLTRelShdr), - *RE = Obj->rel_end(PLTRelShdr); - RI != RE && It != PLTEnd; ++RI, ++It) { - const Elf_Sym *Sym = Obj->getRelocationSymbol(&*RI, SymTable); + for (const Elf_Rel &Rel : unwrapOrError(Obj->rels(PLTRelShdr))) { + const Elf_Sym *Sym = + unwrapOrError(Obj->getRelocationSymbol(&Rel, SymTable)); printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, StrTable, Sym); + if (++It == PLTEnd) + break; } break; case ELF::SHT_RELA: - for (const Elf_Rela *RI = Obj->rela_begin(PLTRelShdr), - *RE = Obj->rela_end(PLTRelShdr); - RI != RE && It != PLTEnd; ++RI, ++It) { - const Elf_Sym *Sym = Obj->getRelocationSymbol(&*RI, SymTable); + for (const Elf_Rela &Rel : unwrapOrError(Obj->relas(PLTRelShdr))) { + const Elf_Sym *Sym = + unwrapOrError(Obj->getRelocationSymbol(&Rel, SymTable)); printPLTEntry(PLTShdr->sh_addr, PLTBegin, It, StrTable, Sym); + if (++It == PLTEnd) + break; } break; } @@ -2335,9 +2356,39 @@ template <class ELFT> void ELFDumper<ELFT>::printMipsOptions() { } } +template <class ELFT> void ELFDumper<ELFT>::printAMDGPURuntimeMD() { + const Elf_Shdr *Shdr = findSectionByName(*Obj, ".note"); + if (!Shdr) { + W.startLine() << "There is no .note section in the file.\n"; + return; + } + ArrayRef<uint8_t> Sec = unwrapOrError(Obj->getSectionContents(Shdr)); + + const uint32_t RuntimeMDNoteType = 7; + for (auto I = reinterpret_cast<const Elf_Word *>(&Sec[0]), + E = I + Sec.size()/4; I != E;) { + uint32_t NameSZ = I[0]; + uint32_t DescSZ = I[1]; + uint32_t Type = I[2]; + I += 3; + + StringRef Name; + if (NameSZ) { + Name = StringRef(reinterpret_cast<const char *>(I), NameSZ - 1); + I += alignTo<4>(NameSZ)/4; + } + + if (Name == "AMD" && Type == RuntimeMDNoteType) { + StringRef Desc(reinterpret_cast<const char *>(I), DescSZ); + W.printString(Desc); + } + I += alignTo<4>(DescSZ)/4; + } +} + template <class ELFT> void ELFDumper<ELFT>::printStackMap() const { const Elf_Shdr *StackMapSection = nullptr; - for (const auto &Sec : Obj->sections()) { + for (const auto &Sec : unwrapOrError(Obj->sections())) { StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); if (Name == ".llvm_stackmaps") { StackMapSection = &Sec; @@ -2352,7 +2403,7 @@ template <class ELFT> void ELFDumper<ELFT>::printStackMap() const { ArrayRef<uint8_t> StackMapContentsArray = unwrapOrError(Obj->getSectionContents(StackMapSection)); - prettyPrintStackMap(llvm::outs(), StackMapV1Parser<ELFT::TargetEndianness>( + prettyPrintStackMap(llvm::outs(), StackMapV2Parser<ELFT::TargetEndianness>( StackMapContentsArray)); } @@ -2390,8 +2441,7 @@ template <class ELFT> void GNUStyle<ELFT>::printFileHeaders(const ELFO *Obj) { OS << "\n"; Str = printEnum(e->e_ident[ELF::EI_OSABI], makeArrayRef(ElfOSABI)); printFields(OS, "OS/ABI:", Str); - Str = "0x" + to_hexString(e->e_version); - Str = to_hexString(e->e_ident[ELF::EI_ABIVERSION]); + Str = "0x" + to_hexString(e->e_ident[ELF::EI_ABIVERSION]); printFields(OS, "ABI Version:", Str); Str = printEnum(e->e_type, makeArrayRef(ElfObjectFileType)); printFields(OS, "Type:", Str); @@ -2424,13 +2474,13 @@ template <class ELFT> void GNUStyle<ELFT>::printFileHeaders(const ELFO *Obj) { template <class ELFT> void GNUStyle<ELFT>::printGroupSections(const ELFO *Obj) { uint32_t SectionIndex = 0; bool HasGroups = false; - for (const Elf_Shdr &Sec : Obj->sections()) { + for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { if (Sec.sh_type == ELF::SHT_GROUP) { HasGroups = true; const Elf_Shdr *Symtab = unwrapOrError(Obj->getSection(Sec.sh_link)); StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab)); const Elf_Sym *Signature = - Obj->template getEntry<Elf_Sym>(Symtab, Sec.sh_info); + unwrapOrError(Obj->template getEntry<Elf_Sym>(Symtab, Sec.sh_info)); ArrayRef<Elf_Word> Data = unwrapOrError( Obj->template getSectionContentsAsArray<Elf_Word>(&Sec)); StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); @@ -2467,7 +2517,7 @@ void GNUStyle<ELFT>::printRelocation(const ELFO *Obj, const Elf_Shdr *SymTab, // fixed width. 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); + Sym = unwrapOrError(Obj->getRelocationSymbol(&R, SymTab)); if (Sym && Sym->getType() == ELF::STT_SECTION) { const Elf_Shdr *Sec = unwrapOrError( Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable())); @@ -2518,7 +2568,7 @@ static inline void printRelocHeader(raw_ostream &OS, bool Is64, bool IsRela) { template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) { bool HasRelocSections = false; - for (const Elf_Shdr &Sec : Obj->sections()) { + for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA) continue; HasRelocSections = true; @@ -2531,7 +2581,7 @@ template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) { printRelocHeader(OS, ELFT::Is64Bits, (Sec.sh_type == ELF::SHT_RELA)); const Elf_Shdr *SymTab = unwrapOrError(Obj->getSection(Sec.sh_link)); if (Sec.sh_type == ELF::SHT_REL) { - for (const auto &R : Obj->rels(&Sec)) { + for (const auto &R : unwrapOrError(Obj->rels(&Sec))) { Elf_Rela Rela; Rela.r_offset = R.r_offset; Rela.r_info = R.r_info; @@ -2539,7 +2589,7 @@ template <class ELFT> void GNUStyle<ELFT>::printRelocations(const ELFO *Obj) { printRelocation(Obj, SymTab, Rela, false); } } else { - for (const auto &R : Obj->relas(&Sec)) + for (const auto &R : unwrapOrError(Obj->relas(&Sec))) printRelocation(Obj, SymTab, R, true); } } @@ -2664,7 +2714,7 @@ template <class ELFT> void GNUStyle<ELFT>::printSections(const ELFO *Obj) { printField(f); OS << "\n"; - for (const Elf_Shdr &Sec : Obj->sections()) { + for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { Number = to_string(SectionIndex); Fields[0].Str = Number; Fields[1].Str = unwrapOrError(Obj->getSectionName(&Sec)); @@ -2738,8 +2788,8 @@ std::string GNUStyle<ELFT>::getSymbolSectionNdx(const ELFO *Obj, case ELF::SHN_COMMON: return "COM"; case ELF::SHN_XINDEX: - SectionIndex = Obj->getExtendedSymbolTableIndex( - Symbol, FirstSym, this->dumper()->getShndxTable()); + SectionIndex = unwrapOrError(object::getExtendedSymbolTableIndex<ELFT>( + Symbol, FirstSym, this->dumper()->getShndxTable())); default: // Find if: // Processor specific @@ -2812,15 +2862,120 @@ void GNUStyle<ELFT>::printSymbol(const ELFO *Obj, const Elf_Sym *Symbol, printField(Entry); OS << "\n"; } +template <class ELFT> +void GNUStyle<ELFT>::printHashedSymbol(const ELFO *Obj, const Elf_Sym *FirstSym, + uint32_t Sym, StringRef StrTable, + uint32_t Bucket) { + std::string Num, Buc, Name, Value, Size, Binding, Type, Visibility, Section; + unsigned Width, Bias = 0; + if (ELFT::Is64Bits) { + Bias = 8; + Width = 16; + } else { + Bias = 0; + Width = 8; + } + Field Fields[9] = {0, 6, 11, 20 + Bias, 25 + Bias, + 34 + Bias, 41 + Bias, 49 + Bias, 53 + Bias}; + Num = to_string(format_decimal(Sym, 5)); + Buc = to_string(format_decimal(Bucket, 3)) + ":"; + + const auto Symbol = FirstSym + Sym; + Value = to_string(format_hex_no_prefix(Symbol->st_value, Width)); + Size = to_string(format_decimal(Symbol->st_size, 5)); + unsigned char SymbolType = Symbol->getType(); + if (Obj->getHeader()->e_machine == ELF::EM_AMDGPU && + SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS) + Type = printEnum(SymbolType, makeArrayRef(AMDGPUSymbolTypes)); + else + Type = printEnum(SymbolType, makeArrayRef(ElfSymbolTypes)); + unsigned Vis = Symbol->getVisibility(); + Binding = printEnum(Symbol->getBinding(), makeArrayRef(ElfSymbolBindings)); + Visibility = printEnum(Vis, makeArrayRef(ElfSymbolVisibilities)); + Section = getSymbolSectionNdx(Obj, Symbol, FirstSym); + Name = this->dumper()->getFullSymbolName(Symbol, StrTable, true); + Fields[0].Str = Num; + Fields[1].Str = Buc; + Fields[2].Str = Value; + Fields[3].Str = Size; + Fields[4].Str = Type; + Fields[5].Str = Binding; + Fields[6].Str = Visibility; + Fields[7].Str = Section; + Fields[8].Str = Name; + for (auto &Entry : Fields) + printField(Entry); + OS << "\n"; +} template <class ELFT> void GNUStyle<ELFT>::printSymbols(const ELFO *Obj) { + if (opts::DynamicSymbols) + return; this->dumper()->printSymbolsHelper(true); this->dumper()->printSymbolsHelper(false); } template <class ELFT> void GNUStyle<ELFT>::printDynamicSymbols(const ELFO *Obj) { - this->dumper()->printSymbolsHelper(true); + if (this->dumper()->getDynamicStringTable().size() == 0) + return; + auto StringTable = this->dumper()->getDynamicStringTable(); + auto DynSyms = this->dumper()->dynamic_symbols(); + auto GnuHash = this->dumper()->getGnuHashTable(); + auto SysVHash = this->dumper()->getHashTable(); + + // If no hash or .gnu.hash found, try using symbol table + if (GnuHash == nullptr && SysVHash == nullptr) + this->dumper()->printSymbolsHelper(true); + + // Try printing .hash + if (this->dumper()->getHashTable()) { + OS << "\n Symbol table of .hash for image:\n"; + if (ELFT::Is64Bits) + OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; + else + OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; + OS << "\n"; + + uint32_t NBuckets = SysVHash->nbucket; + uint32_t NChains = SysVHash->nchain; + auto Buckets = SysVHash->buckets(); + auto Chains = SysVHash->chains(); + for (uint32_t Buc = 0; Buc < NBuckets; Buc++) { + if (Buckets[Buc] == ELF::STN_UNDEF) + continue; + for (uint32_t Ch = Buckets[Buc]; Ch < NChains; Ch = Chains[Ch]) { + if (Ch == ELF::STN_UNDEF) + break; + printHashedSymbol(Obj, &DynSyms[0], Ch, StringTable, Buc); + } + } + } + + // Try printing .gnu.hash + if (GnuHash) { + OS << "\n Symbol table of .gnu.hash for image:\n"; + if (ELFT::Is64Bits) + OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; + else + OS << " Num Buc: Value Size Type Bind Vis Ndx Name"; + OS << "\n"; + uint32_t NBuckets = GnuHash->nbuckets; + auto Buckets = GnuHash->buckets(); + for (uint32_t Buc = 0; Buc < NBuckets; Buc++) { + if (Buckets[Buc] == ELF::STN_UNDEF) + continue; + uint32_t Index = Buckets[Buc]; + uint32_t GnuHashable = Index - GnuHash->symndx; + // Print whole chain + while (true) { + printHashedSymbol(Obj, &DynSyms[0], Index++, StringTable, Buc); + // Chain ends at symbol with stopper bit + if ((GnuHash->values(DynSyms.size())[GnuHashable++] & 1) == 1) + break; + } + } + } } static inline std::string printPhdrFlags(unsigned Flag) { @@ -2912,7 +3067,7 @@ void GNUStyle<ELFT>::printProgramHeaders(const ELFO *Obj) { else OS << " Type Offset VirtAddr PhysAddr FileSiz " << "MemSiz Flg Align\n"; - for (const auto &Phdr : Obj->program_headers()) { + for (const auto &Phdr : unwrapOrError(Obj->program_headers())) { Type = getElfPtType(Header->e_machine, Phdr.p_type); Offset = to_string(format_hex(Phdr.p_offset, 8)); VMA = to_string(format_hex(Phdr.p_vaddr, Width)); @@ -2939,10 +3094,10 @@ void GNUStyle<ELFT>::printProgramHeaders(const ELFO *Obj) { } OS << "\n Section to Segment mapping:\n Segment Sections...\n"; int Phnum = 0; - for (const Elf_Phdr &Phdr : Obj->program_headers()) { + for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { std::string Sections; OS << format(" %2.2d ", Phnum++); - for (const Elf_Shdr &Sec : Obj->sections()) { + for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { // Check if each section is in a segment and then print mapping. // readelf additionally makes sure it does not print zero sized sections // at end of segments and for PT_DYNAMIC both start and end of section @@ -3161,6 +3316,125 @@ void GNUStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) { } } +static std::string getGNUNoteTypeName(const uint32_t NT) { + static const struct { + uint32_t ID; + const char *Name; + } Notes[] = { + {ELF::NT_GNU_ABI_TAG, "NT_GNU_ABI_TAG (ABI version tag)"}, + {ELF::NT_GNU_HWCAP, "NT_GNU_HWCAP (DSO-supplied software HWCAP info)"}, + {ELF::NT_GNU_BUILD_ID, "NT_GNU_BUILD_ID (unique build ID bitstring)"}, + {ELF::NT_GNU_GOLD_VERSION, "NT_GNU_GOLD_VERSION (gold version)"}, + }; + + for (const auto &Note : Notes) + if (Note.ID == NT) + return std::string(Note.Name); + + std::string string; + raw_string_ostream OS(string); + OS << format("Unknown note type (0x%08x)", NT); + return string; +} + +template <typename ELFT> +static void printGNUNote(raw_ostream &OS, uint32_t NoteType, + ArrayRef<typename ELFFile<ELFT>::Elf_Word> Words) { + switch (NoteType) { + default: + return; + case ELF::NT_GNU_ABI_TAG: { + static const char *OSNames[] = { + "Linux", "Hurd", "Solaris", "FreeBSD", "NetBSD", "Syllable", "NaCl", + }; + + StringRef OSName = "Unknown"; + if (Words[0] < array_lengthof(OSNames)) + OSName = OSNames[Words[0]]; + uint32_t Major = Words[1], Minor = Words[2], Patch = Words[3]; + + if (Words.size() < 4) + OS << " <corrupt GNU_ABI_TAG>"; + else + OS << " OS: " << OSName << ", ABI: " << Major << "." << Minor << "." + << Patch; + break; + } + case ELF::NT_GNU_BUILD_ID: { + OS << " Build ID: "; + ArrayRef<uint8_t> ID(reinterpret_cast<const uint8_t *>(Words.data()), + Words.size() * 4); + for (const auto &B : ID) + OS << format_hex_no_prefix(B, 2); + break; + } + case ELF::NT_GNU_GOLD_VERSION: + OS << " Version: " + << StringRef(reinterpret_cast<const char *>(Words.data()), + Words.size() * 4); + break; + } + + OS << '\n'; +} + +template <class ELFT> +void GNUStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) { + const Elf_Ehdr *e = Obj->getHeader(); + bool IsCore = e->e_type == ELF::ET_CORE; + + auto process = [&](const typename ELFFile<ELFT>::Elf_Off Offset, + const typename ELFFile<ELFT>::Elf_Addr Size) { + if (Size <= 0) + return; + + const auto *P = static_cast<const uint8_t *>(Obj->base() + Offset); + const auto *E = P + Size; + + OS << "Displaying notes found at file offset " << format_hex(Offset, 10) + << " with length " << format_hex(Size, 10) << ":\n" + << " Owner Data size\tDescription\n"; + + while (P < E) { + const Elf_Word *Words = reinterpret_cast<const Elf_Word *>(&P[0]); + + uint32_t NameSize = Words[0]; + uint32_t DescriptorSize = Words[1]; + uint32_t Type = Words[2]; + + ArrayRef<Elf_Word> Descriptor(&Words[3 + (alignTo<4>(NameSize) / 4)], + alignTo<4>(DescriptorSize) / 4); + + StringRef Name; + if (NameSize) + Name = + StringRef(reinterpret_cast<const char *>(&Words[3]), NameSize - 1); + + OS << " " << Name << std::string(22 - NameSize, ' ') + << format_hex(DescriptorSize, 10) << '\t'; + + if (Name == "GNU") { + OS << getGNUNoteTypeName(Type) << '\n'; + printGNUNote<ELFT>(OS, Type, Descriptor); + } + OS << '\n'; + + P = P + 3 * sizeof(Elf_Word) * alignTo<4>(NameSize) + + alignTo<4>(DescriptorSize); + } + }; + + if (IsCore) { + for (const auto &P : unwrapOrError(Obj->program_headers())) + if (P.p_type == PT_NOTE) + process(P.p_offset, P.p_filesz); + } else { + for (const auto &S : unwrapOrError(Obj->sections())) + if (S.sh_type == SHT_NOTE) + process(S.sh_offset, S.sh_size); + } +} + template <class ELFT> void LLVMStyle<ELFT>::printFileHeaders(const ELFO *Obj) { const Elf_Ehdr *e = Obj->getHeader(); { @@ -3210,12 +3484,13 @@ void LLVMStyle<ELFT>::printGroupSections(const ELFO *Obj) { DictScope Lists(W, "Groups"); uint32_t SectionIndex = 0; bool HasGroups = false; - for (const Elf_Shdr &Sec : Obj->sections()) { + for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { if (Sec.sh_type == ELF::SHT_GROUP) { HasGroups = true; const Elf_Shdr *Symtab = unwrapOrError(Obj->getSection(Sec.sh_link)); StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab)); - const Elf_Sym *Sym = Obj->template getEntry<Elf_Sym>(Symtab, Sec.sh_info); + const Elf_Sym *Sym = + unwrapOrError(Obj->template getEntry<Elf_Sym>(Symtab, Sec.sh_info)); auto Data = unwrapOrError( Obj->template getSectionContentsAsArray<Elf_Word>(&Sec)); DictScope D(W, "Group"); @@ -3244,7 +3519,7 @@ template <class ELFT> void LLVMStyle<ELFT>::printRelocations(const ELFO *Obj) { ListScope D(W, "Relocations"); int SectionNumber = -1; - for (const Elf_Shdr &Sec : Obj->sections()) { + for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { ++SectionNumber; if (Sec.sh_type != ELF::SHT_REL && Sec.sh_type != ELF::SHT_RELA) @@ -3268,7 +3543,7 @@ void LLVMStyle<ELFT>::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) { switch (Sec->sh_type) { case ELF::SHT_REL: - for (const Elf_Rel &R : Obj->rels(Sec)) { + for (const Elf_Rel &R : unwrapOrError(Obj->rels(Sec))) { Elf_Rela Rela; Rela.r_offset = R.r_offset; Rela.r_info = R.r_info; @@ -3277,7 +3552,7 @@ void LLVMStyle<ELFT>::printRelocations(const Elf_Shdr *Sec, const ELFO *Obj) { } break; case ELF::SHT_RELA: - for (const Elf_Rela &R : Obj->relas(Sec)) + for (const Elf_Rela &R : unwrapOrError(Obj->relas(Sec))) printRelocation(Obj, R, SymTab); break; } @@ -3289,7 +3564,7 @@ void LLVMStyle<ELFT>::printRelocation(const ELFO *Obj, Elf_Rela Rel, SmallString<32> RelocName; Obj->getRelocationTypeName(Rel.getType(Obj->isMips64EL()), RelocName); StringRef TargetName; - const Elf_Sym *Sym = Obj->getRelocationSymbol(&Rel, SymTab); + const Elf_Sym *Sym = unwrapOrError(Obj->getRelocationSymbol(&Rel, SymTab)); if (Sym && Sym->getType() == ELF::STT_SECTION) { const Elf_Shdr *Sec = unwrapOrError( Obj->getSection(Sym, SymTab, this->dumper()->getShndxTable())); @@ -3318,7 +3593,7 @@ template <class ELFT> void LLVMStyle<ELFT>::printSections(const ELFO *Obj) { ListScope SectionsD(W, "Sections"); int SectionIndex = -1; - for (const Elf_Shdr &Sec : Obj->sections()) { + for (const Elf_Shdr &Sec : unwrapOrError(Obj->sections())) { ++SectionIndex; StringRef Name = unwrapOrError(Obj->getSectionName(&Sec)); @@ -3336,6 +3611,10 @@ template <class ELFT> void LLVMStyle<ELFT>::printSections(const ELFO *Obj) { SectionFlags.insert(SectionFlags.end(), std::begin(ElfAMDGPUSectionFlags), std::end(ElfAMDGPUSectionFlags)); break; + case EM_ARM: + SectionFlags.insert(SectionFlags.end(), std::begin(ElfARMSectionFlags), + std::end(ElfARMSectionFlags)); + break; case EM_HEXAGON: SectionFlags.insert(SectionFlags.end(), std::begin(ElfHexagonSectionFlags), @@ -3376,11 +3655,12 @@ template <class ELFT> void LLVMStyle<ELFT>::printSections(const ELFO *Obj) { const Elf_Shdr *Symtab = this->dumper()->getDotSymtabSec(); StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*Symtab)); - for (const Elf_Sym &Sym : Obj->symbols(Symtab)) { + for (const Elf_Sym &Sym : unwrapOrError(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); + printSymbol(Obj, &Sym, unwrapOrError(Obj->symbols(Symtab)).begin(), + StrTable, false); } } @@ -3512,7 +3792,7 @@ template <class ELFT> void LLVMStyle<ELFT>::printProgramHeaders(const ELFO *Obj) { ListScope L(W, "ProgramHeaders"); - for (const Elf_Phdr &Phdr : Obj->program_headers()) { + for (const Elf_Phdr &Phdr : unwrapOrError(Obj->program_headers())) { DictScope P(W, "ProgramHeader"); W.printHex("Type", getElfSegmentType(Obj->getHeader()->e_machine, Phdr.p_type), @@ -3526,7 +3806,14 @@ void LLVMStyle<ELFT>::printProgramHeaders(const ELFO *Obj) { W.printNumber("Alignment", Phdr.p_align); } } + template <class ELFT> void LLVMStyle<ELFT>::printHashHistogram(const ELFFile<ELFT> *Obj) { W.startLine() << "Hash Histogram not implemented!\n"; } + +template <class ELFT> +void LLVMStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) { + W.startLine() << "printNotes not implemented!\n"; +} + diff --git a/contrib/llvm/tools/llvm-readobj/Error.cpp b/contrib/llvm/tools/llvm-readobj/Error.cpp index 492eb33..03d3494 100644 --- a/contrib/llvm/tools/llvm-readobj/Error.cpp +++ b/contrib/llvm/tools/llvm-readobj/Error.cpp @@ -22,12 +22,12 @@ namespace { // deal with the Error value directly, rather than converting to error_code. class _readobj_error_category : public std::error_category { public: - const char* name() const LLVM_NOEXCEPT override; + const char* name() const noexcept override; std::string message(int ev) const override; }; } // namespace -const char *_readobj_error_category::name() const LLVM_NOEXCEPT { +const char *_readobj_error_category::name() const noexcept { return "llvm.readobj"; } diff --git a/contrib/llvm/tools/llvm-readobj/MachODumper.cpp b/contrib/llvm/tools/llvm-readobj/MachODumper.cpp index 3773df2..01b0741 100644 --- a/contrib/llvm/tools/llvm-readobj/MachODumper.cpp +++ b/contrib/llvm/tools/llvm-readobj/MachODumper.cpp @@ -669,10 +669,10 @@ void MachODumper::printStackMap() const { if (Obj->isLittleEndian()) prettyPrintStackMap( llvm::outs(), - StackMapV1Parser<support::little>(StackMapContentsArray)); + StackMapV2Parser<support::little>(StackMapContentsArray)); else prettyPrintStackMap(llvm::outs(), - StackMapV1Parser<support::big>(StackMapContentsArray)); + StackMapV2Parser<support::big>(StackMapContentsArray)); } void MachODumper::printMachODataInCode() { diff --git a/contrib/llvm/tools/llvm-readobj/ObjDumper.h b/contrib/llvm/tools/llvm-readobj/ObjDumper.h index a39fc26..c91558e 100644 --- a/contrib/llvm/tools/llvm-readobj/ObjDumper.h +++ b/contrib/llvm/tools/llvm-readobj/ObjDumper.h @@ -19,7 +19,7 @@ class COFFImportFile; class ObjectFile; } namespace codeview { -class MemoryTypeTableBuilder; +class TypeTableBuilder; } class ScopedPrinter; @@ -47,6 +47,7 @@ public: virtual void printVersionInfo() {} virtual void printGroupSections() {} virtual void printHashHistogram() {} + virtual void printNotes() {} // Only implemented for ARM ELF at this time. virtual void printAttributes() { } @@ -57,6 +58,9 @@ public: virtual void printMipsReginfo() { } virtual void printMipsOptions() { } + // Only implemented for AMDGPU ELF at this time. + virtual void printAMDGPURuntimeMD() {} + // Only implemented for PE/COFF. virtual void printCOFFImports() { } virtual void printCOFFExports() { } @@ -64,8 +68,7 @@ public: virtual void printCOFFBaseReloc() { } virtual void printCOFFDebugDirectory() { } virtual void printCodeViewDebugInfo() { } - virtual void - mergeCodeViewTypes(llvm::codeview::MemoryTypeTableBuilder &CVTypes) {} + virtual void mergeCodeViewTypes(llvm::codeview::TypeTableBuilder &CVTypes) {} // Only implemented for MachO. virtual void printMachODataInCode() { } @@ -96,7 +99,7 @@ std::error_code createMachODumper(const object::ObjectFile *Obj, void dumpCOFFImportFile(const object::COFFImportFile *File); void dumpCodeViewMergedTypes(ScopedPrinter &Writer, - llvm::codeview::MemoryTypeTableBuilder &CVTypes); + llvm::codeview::TypeTableBuilder &CVTypes); } // namespace llvm diff --git a/contrib/llvm/tools/llvm-readobj/StackMapPrinter.h b/contrib/llvm/tools/llvm-readobj/StackMapPrinter.h index 92645bc..f4ed68e 100644 --- a/contrib/llvm/tools/llvm-readobj/StackMapPrinter.h +++ b/contrib/llvm/tools/llvm-readobj/StackMapPrinter.h @@ -24,7 +24,8 @@ void prettyPrintStackMap(OStreamT &OS, const StackMapParserT &SMP) { // Functions: for (const auto &F : SMP.functions()) OS << "\n Function address: " << F.getFunctionAddress() - << ", stack size: " << F.getStackSize(); + << ", stack size: " << F.getStackSize() + << ", callsite record count: " << F.getRecordCount(); // Constants: OS << "\nNum Constants: " << SMP.getNumConstants(); diff --git a/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp b/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp index c293919..970e154 100644 --- a/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/contrib/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -22,7 +22,7 @@ #include "llvm-readobj.h" #include "Error.h" #include "ObjDumper.h" -#include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h" +#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" #include "llvm/Object/Archive.h" #include "llvm/Object/COFFImportFile.h" #include "llvm/Object/ELFObjectFile.h" @@ -92,6 +92,10 @@ namespace opts { cl::desc("Alias for --relocations"), cl::aliasopt(Relocations)); + // -notes, -n + cl::opt<bool> Notes("notes", cl::desc("Display the ELF notes in the file")); + cl::alias NotesShort("n", cl::desc("Alias for --notes"), cl::aliasopt(Notes)); + // -dyn-relocations cl::opt<bool> DynRelocs("dyn-relocations", cl::desc("Display the dynamic relocation entries in the file")); @@ -120,6 +124,8 @@ namespace opts { // -dynamic-table cl::opt<bool> DynamicTable("dynamic-table", cl::desc("Display the ELF .dynamic section table")); + cl::alias DynamicTableShort("d", cl::desc("Alias for --dynamic-table"), + cl::aliasopt(DynamicTable)); // -needed-libs cl::opt<bool> NeededLibraries("needed-libs", @@ -128,6 +134,8 @@ namespace opts { // -program-headers cl::opt<bool> ProgramHeaders("program-headers", cl::desc("Display ELF program headers")); + cl::alias ProgramHeadersShort("l", cl::desc("Alias for --program-headers"), + cl::aliasopt(ProgramHeaders)); // -hash-table cl::opt<bool> HashTable("hash-table", @@ -158,7 +166,7 @@ namespace opts { // -arm-attributes, -a cl::opt<bool> ARMAttributes("arm-attributes", cl::desc("Display the ARM attributes section")); - cl::alias ARMAttributesShort("-a", cl::desc("Alias for --arm-attributes"), + cl::alias ARMAttributesShort("a", cl::desc("Alias for --arm-attributes"), cl::aliasopt(ARMAttributes)); // -mips-plt-got @@ -178,6 +186,10 @@ namespace opts { cl::opt<bool> MipsOptions("mips-options", cl::desc("Display the MIPS .MIPS.options section")); + // -amdgpu-runtime-metadata + cl::opt<bool> AMDGPURuntimeMD("amdgpu-runtime-metadata", + cl::desc("Display AMDGPU runtime metadata")); + // -coff-imports cl::opt<bool> COFFImports("coff-imports", cl::desc("Display the PE/COFF import table")); @@ -256,7 +268,7 @@ namespace opts { cl::opt<OutputStyleTy> Output("elf-output-style", cl::desc("Specify ELF dump style"), cl::values(clEnumVal(LLVM, "LLVM default style"), - clEnumVal(GNU, "GNU readelf style"), clEnumValEnd), + clEnumVal(GNU, "GNU readelf style")), cl::init(LLVM)); } // namespace opts @@ -268,10 +280,16 @@ LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg) { exit(1); } -void error(std::error_code EC) { +void error(Error EC) { if (!EC) return; + handleAllErrors(std::move(EC), + [&](const ErrorInfoBase &EI) { reportError(EI.message()); }); +} +void error(std::error_code EC) { + if (!EC) + return; reportError(EC.message()); } @@ -317,8 +335,15 @@ static bool isMipsArch(unsigned Arch) { return false; } } +namespace { +struct ReadObjTypeTableBuilder { + ReadObjTypeTableBuilder() : Allocator(), Builder(Allocator) {} -static llvm::codeview::MemoryTypeTableBuilder CVTypes; + llvm::BumpPtrAllocator Allocator; + llvm::codeview::TypeTableBuilder Builder; +}; +} +static ReadObjTypeTableBuilder CVTypes; /// @brief Creates an format-specific object file dumper. static std::error_code createDumper(const ObjectFile *Obj, @@ -394,10 +419,15 @@ static void dumpObject(const ObjectFile *Obj) { if (opts::MipsOptions) Dumper->printMipsOptions(); } + if (Obj->getArch() == llvm::Triple::amdgcn) + if (opts::AMDGPURuntimeMD) + Dumper->printAMDGPURuntimeMD(); if (opts::SectionGroups) Dumper->printGroupSections(); if (opts::HashHistogram) Dumper->printHashHistogram(); + if (opts::Notes) + Dumper->printNotes(); } if (Obj->isCOFF()) { if (opts::COFFImports) @@ -413,7 +443,7 @@ static void dumpObject(const ObjectFile *Obj) { if (opts::CodeView) Dumper->printCodeViewDebugInfo(); if (opts::CodeViewMergedTypes) - Dumper->mergeCodeViewTypes(CVTypes); + Dumper->mergeCodeViewTypes(CVTypes.Builder); } if (Obj->isMachO()) { if (opts::MachODataInCode) @@ -435,7 +465,7 @@ static void dumpObject(const ObjectFile *Obj) { /// @brief Dumps each object file in \a Arc; static void dumpArchive(const Archive *Arc) { - Error Err; + Error Err = Error::success(); for (auto &Child : Arc->children(Err)) { Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary(); if (!ChildOrErr) { @@ -450,6 +480,8 @@ static void dumpArchive(const Archive *Arc) { } if (ObjectFile *Obj = dyn_cast<ObjectFile>(&*ChildOrErr.get())) dumpObject(Obj); + else if (COFFImportFile *Imp = dyn_cast<COFFImportFile>(&*ChildOrErr.get())) + dumpCOFFImportFile(Imp); else reportError(Arc->getFileName(), readobj_error::unrecognized_file_format); } @@ -516,7 +548,7 @@ int main(int argc, const char *argv[]) { if (opts::CodeViewMergedTypes) { ScopedPrinter W(outs()); - dumpCodeViewMergedTypes(W, CVTypes); + dumpCodeViewMergedTypes(W, CVTypes.Builder); } return 0; diff --git a/contrib/llvm/tools/llvm-readobj/llvm-readobj.h b/contrib/llvm/tools/llvm-readobj/llvm-readobj.h index b169c00..0156920 100644 --- a/contrib/llvm/tools/llvm-readobj/llvm-readobj.h +++ b/contrib/llvm/tools/llvm-readobj/llvm-readobj.h @@ -23,7 +23,8 @@ namespace llvm { // Various helper functions. LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg); - void error(std::error_code ec); + void error(std::error_code EC); + void error(llvm::Error EC); template <class T> T unwrapOrError(ErrorOr<T> EO) { if (EO) return *EO; |