diff options
Diffstat (limited to 'contrib/llvm/tools/llvm-readobj/COFFDumper.cpp')
-rw-r--r-- | contrib/llvm/tools/llvm-readobj/COFFDumper.cpp | 428 |
1 files changed, 339 insertions, 89 deletions
diff --git a/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp b/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp index 7842cd4..156e39a 100644 --- a/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/contrib/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -20,6 +20,7 @@ #include "Win64EHDumper.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Object/COFF.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/COFF.h" @@ -49,35 +50,50 @@ public: cacheRelocations(); } - virtual void printFileHeaders() override; - virtual void printSections() override; - virtual void printRelocations() override; - virtual void printSymbols() override; - virtual void printDynamicSymbols() override; - virtual void printUnwindInfo() override; + void printFileHeaders() override; + void printSections() override; + void printRelocations() override; + void printSymbols() override; + void printDynamicSymbols() override; + void printUnwindInfo() override; + void printCOFFImports() override; + void printCOFFExports() override; + void printCOFFDirectives() override; + void printCOFFBaseReloc() override; private: void printSymbol(const SymbolRef &Sym); void printRelocation(const SectionRef &Section, const RelocationRef &Reloc); void printDataDirectory(uint32_t Index, const std::string &FieldName); + void printDOSHeader(const dos_header *DH); template <class PEHeader> void printPEHeader(const PEHeader *Hdr); void printBaseOfDataField(const pe32_header *Hdr); void printBaseOfDataField(const pe32plus_header *Hdr); void printCodeViewLineTables(const SectionRef &Section); + void printCodeViewSymbolsSubsection(StringRef Subsection, + const SectionRef &Section, + uint32_t Offset); + void cacheRelocations(); std::error_code resolveSymbol(const coff_section *Section, uint64_t Offset, SymbolRef &Sym); std::error_code resolveSymbolName(const coff_section *Section, uint64_t Offset, StringRef &Name); + void printImportedSymbols(iterator_range<imported_symbol_iterator> Range); + void printDelayImportedSymbols( + const DelayImportDirectoryEntryRef &I, + iterator_range<imported_symbol_iterator> Range); typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy; const llvm::object::COFFObjectFile *Obj; RelocMapTy RelocMap; + StringRef CVFileIndexToStringOffsetTable; + StringRef CVStringTable; }; } // namespace @@ -313,9 +329,10 @@ WeakExternalCharacteristics[] = { template <typename T> static std::error_code getSymbolAuxData(const COFFObjectFile *Obj, - const coff_symbol *Symbol, - const T *&Aux) { + COFFSymbolRef Symbol, + uint8_t AuxSymbolIdx, const T *&Aux) { ArrayRef<uint8_t> AuxData = Obj->getSymbolAuxData(Symbol); + AuxData = AuxData.slice(AuxSymbolIdx * Obj->getSymbolTableEntrySize()); Aux = reinterpret_cast<const T*>(AuxData.data()); return readobj_error::success; } @@ -342,25 +359,20 @@ void COFFDumper::printDataDirectory(uint32_t Index, const std::string &FieldName } void COFFDumper::printFileHeaders() { - // Print COFF header - const coff_file_header *COFFHeader = nullptr; - if (error(Obj->getCOFFHeader(COFFHeader))) - return; - - time_t TDS = COFFHeader->TimeDateStamp; + time_t TDS = Obj->getTimeDateStamp(); char FormattedTime[20] = { }; strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS)); { DictScope D(W, "ImageFileHeader"); - W.printEnum ("Machine", COFFHeader->Machine, + W.printEnum ("Machine", Obj->getMachine(), makeArrayRef(ImageFileMachineType)); - W.printNumber("SectionCount", COFFHeader->NumberOfSections); - W.printHex ("TimeDateStamp", FormattedTime, COFFHeader->TimeDateStamp); - W.printHex ("PointerToSymbolTable", COFFHeader->PointerToSymbolTable); - W.printNumber("SymbolCount", COFFHeader->NumberOfSymbols); - W.printNumber("OptionalHeaderSize", COFFHeader->SizeOfOptionalHeader); - W.printFlags ("Characteristics", COFFHeader->Characteristics, + W.printNumber("SectionCount", Obj->getNumberOfSections()); + W.printHex ("TimeDateStamp", FormattedTime, Obj->getTimeDateStamp()); + W.printHex ("PointerToSymbolTable", Obj->getPointerToSymbolTable()); + W.printNumber("SymbolCount", Obj->getNumberOfSymbols()); + W.printNumber("OptionalHeaderSize", Obj->getSizeOfOptionalHeader()); + W.printFlags ("Characteristics", Obj->getCharacteristics(), makeArrayRef(ImageFileCharacteristics)); } @@ -377,6 +389,30 @@ void COFFDumper::printFileHeaders() { return; if (PEPlusHeader) printPEHeader<pe32plus_header>(PEPlusHeader); + + if (const dos_header *DH = Obj->getDOSHeader()) + printDOSHeader(DH); +} + +void COFFDumper::printDOSHeader(const dos_header *DH) { + DictScope D(W, "DOSHeader"); + W.printString("Magic", StringRef(DH->Magic, sizeof(DH->Magic))); + W.printNumber("UsedBytesInTheLastPage", DH->UsedBytesInTheLastPage); + W.printNumber("FileSizeInPages", DH->FileSizeInPages); + W.printNumber("NumberOfRelocationItems", DH->NumberOfRelocationItems); + W.printNumber("HeaderSizeInParagraphs", DH->HeaderSizeInParagraphs); + W.printNumber("MinimumExtraParagraphs", DH->MinimumExtraParagraphs); + W.printNumber("MaximumExtraParagraphs", DH->MaximumExtraParagraphs); + W.printNumber("InitialRelativeSS", DH->InitialRelativeSS); + W.printNumber("InitialSP", DH->InitialSP); + W.printNumber("Checksum", DH->Checksum); + W.printNumber("InitialIP", DH->InitialIP); + W.printNumber("InitialRelativeCS", DH->InitialRelativeCS); + W.printNumber("AddressOfRelocationTable", DH->AddressOfRelocationTable); + W.printNumber("OverlayNumber", DH->OverlayNumber); + W.printNumber("OEMid", DH->OEMid); + W.printNumber("OEMinfo", DH->OEMinfo); + W.printNumber("AddressOfNewExeHeader", DH->AddressOfNewExeHeader); } template <class PEHeader> @@ -404,7 +440,7 @@ void COFFDumper::printPEHeader(const PEHeader *Hdr) { W.printNumber("SizeOfImage", Hdr->SizeOfImage); W.printNumber("SizeOfHeaders", Hdr->SizeOfHeaders); W.printEnum ("Subsystem", Hdr->Subsystem, makeArrayRef(PEWindowsSubsystem)); - W.printFlags ("Subsystem", Hdr->DLLCharacteristics, + W.printFlags ("Characteristics", Hdr->DLLCharacteristics, makeArrayRef(PEDLLCharacteristics)); W.printNumber("SizeOfStackReserve", Hdr->SizeOfStackReserve); W.printNumber("SizeOfStackCommit", Hdr->SizeOfStackCommit); @@ -440,11 +476,10 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { SmallVector<StringRef, 10> FunctionNames; StringMap<StringRef> FunctionLineTables; - StringRef FileIndexToStringOffsetTable; - StringRef StringTable; ListScope D(W, "CodeViewLineTables"); { + // FIXME: Add more offset correctness checks. DataExtractor DE(Data, true, 4); uint32_t Offset = 0, Magic = DE.getU32(&Offset); @@ -474,6 +509,9 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { W.printBinaryBlock("Contents", Contents); switch (SubSectionType) { + case COFF::DEBUG_SYMBOL_SUBSECTION: + printCodeViewSymbolsSubsection(Contents, Section, Offset); + break; case COFF::DEBUG_LINE_TABLE_SUBSECTION: { // Holds a PC to file:line table. Some data to parse this subsection is // stored in the other subsections, so just check sanity and store the @@ -502,25 +540,25 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { break; } case COFF::DEBUG_STRING_TABLE_SUBSECTION: - if (PayloadSize == 0 || StringTable.data() != nullptr || + if (PayloadSize == 0 || CVStringTable.data() != nullptr || Contents.back() != '\0') { // Empty or duplicate or non-null-terminated subsection. error(object_error::parse_failed); return; } - StringTable = Contents; + CVStringTable = Contents; break; case COFF::DEBUG_INDEX_SUBSECTION: // Holds the translation table from file indices // to offsets in the string table. if (PayloadSize == 0 || - FileIndexToStringOffsetTable.data() != nullptr) { + CVFileIndexToStringOffsetTable.data() != nullptr) { // Empty or duplicate subsection. error(object_error::parse_failed); return; } - FileIndexToStringOffsetTable = Contents; + CVFileIndexToStringOffsetTable = Contents; break; } Offset += PayloadSize; @@ -555,7 +593,7 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { uint32_t FilenameOffset; { - DataExtractor SDE(FileIndexToStringOffsetTable, true, 4); + DataExtractor SDE(CVFileIndexToStringOffsetTable, true, 4); uint32_t OffsetInSDE = OffsetInIndex; if (!SDE.isValidOffset(OffsetInSDE)) { error(object_error::parse_failed); @@ -564,15 +602,15 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { FilenameOffset = SDE.getU32(&OffsetInSDE); } - if (FilenameOffset == 0 || FilenameOffset + 1 >= StringTable.size() || - StringTable.data()[FilenameOffset - 1] != '\0') { + if (FilenameOffset == 0 || FilenameOffset + 1 >= CVStringTable.size() || + CVStringTable.data()[FilenameOffset - 1] != '\0') { // Each string in an F3 subsection should be preceded by a null // character. error(object_error::parse_failed); return; } - StringRef Filename(StringTable.data() + FilenameOffset); + StringRef Filename(CVStringTable.data() + FilenameOffset); ListScope S(W, "FilenameSegment"); W.printString("Filename", Filename); for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset); @@ -593,6 +631,80 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { } } +void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, + const SectionRef &Section, + uint32_t OffsetInSection) { + if (Subsection.size() == 0) { + error(object_error::parse_failed); + return; + } + DataExtractor DE(Subsection, true, 4); + uint32_t Offset = 0; + + // Function-level subsections have "procedure start" and "procedure end" + // commands that should come in pairs and surround relevant info. + bool InFunctionScope = false; + while (DE.isValidOffset(Offset)) { + // Read subsection segments one by one. + uint16_t Size = DE.getU16(&Offset); + // The section size includes the size of the type identifier. + if (Size < 2 || !DE.isValidOffsetForDataOfSize(Offset, Size)) { + error(object_error::parse_failed); + return; + } + Size -= 2; + uint16_t Type = DE.getU16(&Offset); + switch (Type) { + case COFF::DEBUG_SYMBOL_TYPE_PROC_START: { + DictScope S(W, "ProcStart"); + if (InFunctionScope || Size < 36) { + error(object_error::parse_failed); + return; + } + InFunctionScope = true; + + // We're currently interested in a limited subset of fields in this + // segment, just ignore the rest of the fields for now. + uint8_t Unused[12]; + DE.getU8(&Offset, Unused, 12); + uint32_t CodeSize = DE.getU32(&Offset); + DE.getU8(&Offset, Unused, 12); + StringRef SectionName; + if (error(resolveSymbolName(Obj->getCOFFSection(Section), + OffsetInSection + Offset, SectionName))) + return; + Offset += 4; + DE.getU8(&Offset, Unused, 3); + StringRef DisplayName = DE.getCStr(&Offset); + if (!DE.isValidOffset(Offset)) { + error(object_error::parse_failed); + return; + } + W.printString("DisplayName", DisplayName); + W.printString("Section", SectionName); + W.printHex("CodeSize", CodeSize); + + break; + } + case COFF::DEBUG_SYMBOL_TYPE_PROC_END: { + W.startLine() << "ProcEnd\n"; + if (!InFunctionScope || Size > 0) { + error(object_error::parse_failed); + return; + } + InFunctionScope = false; + break; + } + default: + Offset += Size; + break; + } + } + + if (InFunctionScope) + error(object_error::parse_failed); +} + void COFFDumper::printSections() { ListScope SectionsD(W, "Sections"); int SectionNumber = 0; @@ -628,8 +740,7 @@ void COFFDumper::printSections() { if (opts::SectionSymbols) { ListScope D(W, "Symbols"); for (const SymbolRef &Symbol : Obj->symbols()) { - bool Contained = false; - if (Sec.containsSymbol(Symbol, Contained) || !Contained) + if (!Sec.containsSymbol(Symbol)) continue; printSymbol(Symbol); @@ -639,7 +750,8 @@ void COFFDumper::printSections() { if (Name == ".debug$S" && opts::CodeViewLineTables) printCodeViewLineTables(Sec); - if (opts::SectionData) { + if (opts::SectionData && + !(Section->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) { StringRef Data; if (error(Sec.getContents(Data))) break; @@ -683,7 +795,6 @@ void COFFDumper::printRelocation(const SectionRef &Section, uint64_t RelocType; SmallString<32> RelocName; StringRef SymbolName; - StringRef Contents; if (error(Reloc.getOffset(Offset))) return; if (error(Reloc.getType(RelocType))) @@ -691,21 +802,19 @@ void COFFDumper::printRelocation(const SectionRef &Section, if (error(Reloc.getTypeName(RelocName))) return; symbol_iterator Symbol = Reloc.getSymbol(); - if (error(Symbol->getName(SymbolName))) - return; - if (error(Section.getContents(Contents))) + if (Symbol != Obj->symbol_end() && error(Symbol->getName(SymbolName))) return; if (opts::ExpandRelocs) { DictScope Group(W, "Relocation"); W.printHex("Offset", Offset); W.printNumber("Type", RelocName, RelocType); - W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); + W.printString("Symbol", SymbolName.empty() ? "-" : SymbolName); } else { raw_ostream& OS = W.startLine(); OS << W.hex(Offset) << " " << RelocName - << " " << (SymbolName.size() > 0 ? SymbolName : "-") + << " " << (SymbolName.empty() ? "-" : SymbolName) << "\n"; } } @@ -719,12 +828,30 @@ void COFFDumper::printSymbols() { void COFFDumper::printDynamicSymbols() { ListScope Group(W, "DynamicSymbols"); } +static ErrorOr<StringRef> +getSectionName(const llvm::object::COFFObjectFile *Obj, int32_t SectionNumber, + const coff_section *Section) { + if (Section) { + StringRef SectionName; + if (std::error_code EC = Obj->getSectionName(Section, SectionName)) + return EC; + return SectionName; + } + if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG) + return StringRef("IMAGE_SYM_DEBUG"); + if (SectionNumber == llvm::COFF::IMAGE_SYM_ABSOLUTE) + return StringRef("IMAGE_SYM_ABSOLUTE"); + if (SectionNumber == llvm::COFF::IMAGE_SYM_UNDEFINED) + return StringRef("IMAGE_SYM_UNDEFINED"); + return StringRef(""); +} + void COFFDumper::printSymbol(const SymbolRef &Sym) { DictScope D(W, "Symbol"); - const coff_symbol *Symbol = Obj->getCOFFSymbol(Sym); + COFFSymbolRef Symbol = Obj->getCOFFSymbol(Sym); const coff_section *Section; - if (std::error_code EC = Obj->getSection(Symbol->SectionNumber, Section)) { + if (std::error_code EC = Obj->getSection(Symbol.getSectionNumber(), Section)) { W.startLine() << "Invalid section number: " << EC.message() << "\n"; W.flush(); return; @@ -735,23 +862,25 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { SymbolName = ""; StringRef SectionName = ""; - if (Section) - Obj->getSectionName(Section, SectionName); + ErrorOr<StringRef> Res = + getSectionName(Obj, Symbol.getSectionNumber(), Section); + if (Res) + SectionName = *Res; W.printString("Name", SymbolName); - W.printNumber("Value", Symbol->Value); - W.printNumber("Section", SectionName, Symbol->SectionNumber); - W.printEnum ("BaseType", Symbol->getBaseType(), makeArrayRef(ImageSymType)); - W.printEnum ("ComplexType", Symbol->getComplexType(), + W.printNumber("Value", Symbol.getValue()); + W.printNumber("Section", SectionName, Symbol.getSectionNumber()); + W.printEnum ("BaseType", Symbol.getBaseType(), makeArrayRef(ImageSymType)); + W.printEnum ("ComplexType", Symbol.getComplexType(), makeArrayRef(ImageSymDType)); - W.printEnum ("StorageClass", Symbol->StorageClass, + W.printEnum ("StorageClass", Symbol.getStorageClass(), makeArrayRef(ImageSymClass)); - W.printNumber("AuxSymbolCount", Symbol->NumberOfAuxSymbols); + W.printNumber("AuxSymbolCount", Symbol.getNumberOfAuxSymbols()); - for (unsigned I = 0; I < Symbol->NumberOfAuxSymbols; ++I) { - if (Symbol->isFunctionDefinition()) { + for (uint8_t I = 0; I < Symbol.getNumberOfAuxSymbols(); ++I) { + if (Symbol.isFunctionDefinition()) { const coff_aux_function_definition *Aux; - if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) + if (error(getSymbolAuxData(Obj, Symbol, I, Aux))) break; DictScope AS(W, "AuxFunctionDef"); @@ -759,18 +888,16 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { W.printNumber("TotalSize", Aux->TotalSize); W.printHex("PointerToLineNumber", Aux->PointerToLinenumber); W.printHex("PointerToNextFunction", Aux->PointerToNextFunction); - W.printBinary("Unused", makeArrayRef(Aux->Unused)); - } else if (Symbol->isWeakExternal()) { + } else if (Symbol.isAnyUndefined()) { const coff_aux_weak_external *Aux; - if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) + if (error(getSymbolAuxData(Obj, Symbol, I, Aux))) break; - const coff_symbol *Linked; + ErrorOr<COFFSymbolRef> Linked = Obj->getSymbol(Aux->TagIndex); StringRef LinkedName; - std::error_code EC; - if ((EC = Obj->getSymbol(Aux->TagIndex, Linked)) || - (EC = Obj->getSymbolName(Linked, LinkedName))) { + std::error_code EC = Linked.getError(); + if (EC || (EC = Obj->getSymbolName(*Linked, LinkedName))) { LinkedName = ""; error(EC); } @@ -779,56 +906,60 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { W.printNumber("Linked", LinkedName, Aux->TagIndex); W.printEnum ("Search", Aux->Characteristics, makeArrayRef(WeakExternalCharacteristics)); - W.printBinary("Unused", makeArrayRef(Aux->Unused)); - } else if (Symbol->isFileRecord()) { - const coff_aux_file *Aux; - if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) + } else if (Symbol.isFileRecord()) { + const char *FileName; + if (error(getSymbolAuxData(Obj, Symbol, I, FileName))) break; DictScope AS(W, "AuxFileRecord"); - StringRef Name(Aux->FileName, - Symbol->NumberOfAuxSymbols * COFF::SymbolSize); + StringRef Name(FileName, Symbol.getNumberOfAuxSymbols() * + Obj->getSymbolTableEntrySize()); W.printString("FileName", Name.rtrim(StringRef("\0", 1))); break; - } else if (Symbol->isSectionDefinition()) { + } else if (Symbol.isSectionDefinition()) { const coff_aux_section_definition *Aux; - if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) + if (error(getSymbolAuxData(Obj, Symbol, I, Aux))) break; + int32_t AuxNumber = Aux->getNumber(Symbol.isBigObj()); + DictScope AS(W, "AuxSectionDef"); W.printNumber("Length", Aux->Length); W.printNumber("RelocationCount", Aux->NumberOfRelocations); W.printNumber("LineNumberCount", Aux->NumberOfLinenumbers); W.printHex("Checksum", Aux->CheckSum); - W.printNumber("Number", Aux->Number); + W.printNumber("Number", AuxNumber); W.printEnum("Selection", Aux->Selection, makeArrayRef(ImageCOMDATSelect)); - W.printBinary("Unused", makeArrayRef(Aux->Unused)); if (Section && Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT && Aux->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { const coff_section *Assoc; - StringRef AssocName; - std::error_code EC; - if ((EC = Obj->getSection(Aux->Number, Assoc)) || - (EC = Obj->getSectionName(Assoc, AssocName))) { + StringRef AssocName = ""; + std::error_code EC = Obj->getSection(AuxNumber, Assoc); + ErrorOr<StringRef> Res = getSectionName(Obj, AuxNumber, Assoc); + if (Res) + AssocName = *Res; + if (!EC) + EC = Res.getError(); + if (EC) { AssocName = ""; error(EC); } - W.printNumber("AssocSection", AssocName, Aux->Number); + W.printNumber("AssocSection", AssocName, AuxNumber); } - } else if (Symbol->isCLRToken()) { + } else if (Symbol.isCLRToken()) { const coff_aux_clr_token *Aux; - if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) + if (error(getSymbolAuxData(Obj, Symbol, I, Aux))) break; - const coff_symbol *ReferredSym; + ErrorOr<COFFSymbolRef> ReferredSym = + Obj->getSymbol(Aux->SymbolTableIndex); StringRef ReferredName; - std::error_code EC; - if ((EC = Obj->getSymbol(Aux->SymbolTableIndex, ReferredSym)) || - (EC = Obj->getSymbolName(ReferredSym, ReferredName))) { + std::error_code EC = ReferredSym.getError(); + if (EC || (EC = Obj->getSymbolName(*ReferredSym, ReferredName))) { ReferredName = ""; error(EC); } @@ -837,7 +968,6 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { W.printNumber("AuxType", Aux->AuxType); W.printNumber("Reserved", Aux->Reserved); W.printNumber("SymbolTableIndex", ReferredName, Aux->SymbolTableIndex); - W.printBinary("Unused", makeArrayRef(Aux->Unused)); } else { W.startLine() << "<unhandled auxiliary record>\n"; @@ -846,12 +976,8 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { } void COFFDumper::printUnwindInfo() { - const coff_file_header *Header; - if (error(Obj->getCOFFHeader(Header))) - return; - ListScope D(W, "UnwindInformation"); - switch (Header->Machine) { + switch (Obj->getMachine()) { case COFF::IMAGE_FILE_MACHINE_AMD64: { Win64EH::Dumper Dumper(W); Win64EH::Dumper::SymbolResolver @@ -870,9 +996,133 @@ void COFFDumper::printUnwindInfo() { break; } default: - W.printEnum("unsupported Image Machine", Header->Machine, + W.printEnum("unsupported Image Machine", Obj->getMachine(), makeArrayRef(ImageFileMachineType)); break; } } +void COFFDumper::printImportedSymbols( + iterator_range<imported_symbol_iterator> Range) { + for (const ImportedSymbolRef &I : Range) { + StringRef Sym; + if (error(I.getSymbolName(Sym))) return; + uint16_t Ordinal; + if (error(I.getOrdinal(Ordinal))) return; + W.printNumber("Symbol", Sym, Ordinal); + } +} + +void COFFDumper::printDelayImportedSymbols( + const DelayImportDirectoryEntryRef &I, + iterator_range<imported_symbol_iterator> Range) { + int Index = 0; + for (const ImportedSymbolRef &S : Range) { + DictScope Import(W, "Import"); + StringRef Sym; + if (error(S.getSymbolName(Sym))) return; + uint16_t Ordinal; + if (error(S.getOrdinal(Ordinal))) return; + W.printNumber("Symbol", Sym, Ordinal); + uint64_t Addr; + if (error(I.getImportAddress(Index++, Addr))) return; + W.printHex("Address", Addr); + } +} + +void COFFDumper::printCOFFImports() { + // Regular imports + for (const ImportDirectoryEntryRef &I : Obj->import_directories()) { + DictScope Import(W, "Import"); + StringRef Name; + if (error(I.getName(Name))) return; + W.printString("Name", Name); + uint32_t Addr; + if (error(I.getImportLookupTableRVA(Addr))) return; + W.printHex("ImportLookupTableRVA", Addr); + if (error(I.getImportAddressTableRVA(Addr))) return; + W.printHex("ImportAddressTableRVA", Addr); + printImportedSymbols(I.imported_symbols()); + } + + // Delay imports + for (const DelayImportDirectoryEntryRef &I : Obj->delay_import_directories()) { + DictScope Import(W, "DelayImport"); + StringRef Name; + if (error(I.getName(Name))) return; + W.printString("Name", Name); + const delay_import_directory_table_entry *Table; + if (error(I.getDelayImportTable(Table))) return; + W.printHex("Attributes", Table->Attributes); + W.printHex("ModuleHandle", Table->ModuleHandle); + W.printHex("ImportAddressTable", Table->DelayImportAddressTable); + W.printHex("ImportNameTable", Table->DelayImportNameTable); + W.printHex("BoundDelayImportTable", Table->BoundDelayImportTable); + W.printHex("UnloadDelayImportTable", Table->UnloadDelayImportTable); + printDelayImportedSymbols(I, I.imported_symbols()); + } +} + +void COFFDumper::printCOFFExports() { + for (const ExportDirectoryEntryRef &E : Obj->export_directories()) { + DictScope Export(W, "Export"); + + StringRef Name; + uint32_t Ordinal, RVA; + + if (error(E.getSymbolName(Name))) + continue; + if (error(E.getOrdinal(Ordinal))) + continue; + if (error(E.getExportRVA(RVA))) + continue; + + W.printNumber("Ordinal", Ordinal); + W.printString("Name", Name); + W.printHex("RVA", RVA); + } +} + +void COFFDumper::printCOFFDirectives() { + for (const SectionRef &Section : Obj->sections()) { + StringRef Contents; + StringRef Name; + + if (error(Section.getName(Name))) + continue; + if (Name != ".drectve") + continue; + + if (error(Section.getContents(Contents))) + return; + + W.printString("Directive(s)", Contents); + } +} + +static StringRef getBaseRelocTypeName(uint8_t Type) { + switch (Type) { + case COFF::IMAGE_REL_BASED_ABSOLUTE: return "ABSOLUTE"; + case COFF::IMAGE_REL_BASED_HIGH: return "HIGH"; + case COFF::IMAGE_REL_BASED_LOW: return "LOW"; + case COFF::IMAGE_REL_BASED_HIGHLOW: return "HIGHLOW"; + case COFF::IMAGE_REL_BASED_HIGHADJ: return "HIGHADJ"; + case COFF::IMAGE_REL_BASED_DIR64: return "DIR64"; + default: return "unknown (" + llvm::utostr(Type) + ")"; + } +} + +void COFFDumper::printCOFFBaseReloc() { + ListScope D(W, "BaseReloc"); + for (const BaseRelocRef &I : Obj->base_relocs()) { + uint8_t Type; + uint32_t RVA; + if (error(I.getRVA(RVA))) + continue; + if (error(I.getType(Type))) + continue; + DictScope Import(W, "Entry"); + W.printString("Type", getBaseRelocTypeName(Type)); + W.printHex("Address", RVA); + } +} |