2561 lines · cpp
1//===-- COFFDumper.cpp - COFF-specific dumper -------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file implements the COFF-specific dumper for llvm-readobj.11///12//===----------------------------------------------------------------------===//13 14#include "ARMWinEHPrinter.h"15#include "ObjDumper.h"16#include "StackMapPrinter.h"17#include "Win64EHDumper.h"18#include "llvm-readobj.h"19#include "llvm/ADT/DenseMap.h"20#include "llvm/ADT/SmallString.h"21#include "llvm/ADT/StringExtras.h"22#include "llvm/BinaryFormat/COFF.h"23#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"24#include "llvm/DebugInfo/CodeView/CodeView.h"25#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"26#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"27#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"28#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"29#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"30#include "llvm/DebugInfo/CodeView/Formatters.h"31#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"32#include "llvm/DebugInfo/CodeView/Line.h"33#include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"34#include "llvm/DebugInfo/CodeView/RecordSerialization.h"35#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"36#include "llvm/DebugInfo/CodeView/SymbolDumper.h"37#include "llvm/DebugInfo/CodeView/SymbolRecord.h"38#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"39#include "llvm/DebugInfo/CodeView/TypeHashing.h"40#include "llvm/DebugInfo/CodeView/TypeIndex.h"41#include "llvm/DebugInfo/CodeView/TypeRecord.h"42#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"43#include "llvm/DebugInfo/CodeView/TypeTableCollection.h"44#include "llvm/Object/COFF.h"45#include "llvm/Object/ObjectFile.h"46#include "llvm/Object/WindowsResource.h"47#include "llvm/Support/BinaryStreamReader.h"48#include "llvm/Support/Casting.h"49#include "llvm/Support/Compiler.h"50#include "llvm/Support/ConvertUTF.h"51#include "llvm/Support/FormatVariadic.h"52#include "llvm/Support/LEB128.h"53#include "llvm/Support/ScopedPrinter.h"54#include "llvm/Support/Win64EH.h"55#include "llvm/Support/raw_ostream.h"56#include <ctime>57 58using namespace llvm;59using namespace llvm::object;60using namespace llvm::codeview;61using namespace llvm::support;62using namespace llvm::Win64EH;63 64namespace {65 66struct LoadConfigTables {67 uint64_t SEHTableVA = 0;68 uint64_t SEHTableCount = 0;69 uint32_t GuardFlags = 0;70 uint64_t GuardFidTableVA = 0;71 uint64_t GuardFidTableCount = 0;72 uint64_t GuardIatTableVA = 0;73 uint64_t GuardIatTableCount = 0;74 uint64_t GuardLJmpTableVA = 0;75 uint64_t GuardLJmpTableCount = 0;76 uint64_t GuardEHContTableVA = 0;77 uint64_t GuardEHContTableCount = 0;78};79 80class COFFDumper : public ObjDumper {81public:82 friend class COFFObjectDumpDelegate;83 COFFDumper(const llvm::object::COFFObjectFile *Obj, ScopedPrinter &Writer)84 : ObjDumper(Writer, Obj->getFileName()), Obj(Obj), Writer(Writer),85 Types(100) {}86 87 void printFileHeaders() override;88 void printSectionHeaders() override;89 void printRelocations() override;90 void printUnwindInfo() override;91 92 void printNeededLibraries() override;93 94 void printCOFFImports() override;95 void printCOFFExports() override;96 void printCOFFDirectives() override;97 void printCOFFBaseReloc() override;98 void printCOFFPseudoReloc() override;99 void printCOFFDebugDirectory() override;100 void printCOFFTLSDirectory() override;101 void printCOFFResources() override;102 void printCOFFLoadConfig() override;103 void printCodeViewDebugInfo() override;104 void mergeCodeViewTypes(llvm::codeview::MergingTypeTableBuilder &CVIDs,105 llvm::codeview::MergingTypeTableBuilder &CVTypes,106 llvm::codeview::GlobalTypeTableBuilder &GlobalCVIDs,107 llvm::codeview::GlobalTypeTableBuilder &GlobalCVTypes,108 bool GHash) override;109 void printStackMap() const override;110 void printAddrsig() override;111 void printCGProfile() override;112 void printStringTable() override;113 114private:115 StringRef getSymbolName(uint32_t Index);116 void printSymbols(bool ExtraSymInfo) override;117 void printDynamicSymbols() override;118 void printSymbol(const SymbolRef &Sym);119 void printRelocation(const SectionRef &Section, const RelocationRef &Reloc,120 uint64_t Bias = 0);121 void printDataDirectory(uint32_t Index, const std::string &FieldName);122 123 void printDOSHeader(const dos_header *DH);124 template <class PEHeader> void printPEHeader(const PEHeader *Hdr);125 void printBaseOfDataField(const pe32_header *Hdr);126 void printBaseOfDataField(const pe32plus_header *Hdr);127 template <typename T>128 void printCOFFLoadConfig(const T *Conf, LoadConfigTables &Tables);129 template <typename IntTy>130 void printCOFFTLSDirectory(const coff_tls_directory<IntTy> *TlsTable);131 typedef void (*PrintExtraCB)(raw_ostream &, const uint8_t *);132 void printRVATable(uint64_t TableVA, uint64_t Count, uint64_t EntrySize,133 PrintExtraCB PrintExtra = nullptr);134 135 void printCodeViewSymbolSection(StringRef SectionName, const SectionRef &Section);136 void printCodeViewTypeSection(StringRef SectionName, const SectionRef &Section);137 StringRef getFileNameForFileOffset(uint32_t FileOffset);138 void printFileNameForOffset(StringRef Label, uint32_t FileOffset);139 void printTypeIndex(StringRef FieldName, TypeIndex TI) {140 // Forward to CVTypeDumper for simplicity.141 codeview::printTypeIndex(Writer, FieldName, TI, Types);142 }143 144 void printCodeViewSymbolsSubsection(StringRef Subsection,145 const SectionRef &Section,146 StringRef SectionContents);147 148 void printCodeViewFileChecksums(StringRef Subsection);149 150 void printCodeViewInlineeLines(StringRef Subsection);151 152 void printRelocatedField(StringRef Label, const coff_section *Sec,153 uint32_t RelocOffset, uint32_t Offset,154 StringRef *RelocSym = nullptr);155 156 uint32_t countTotalTableEntries(ResourceSectionRef RSF,157 const coff_resource_dir_table &Table,158 StringRef Level);159 160 void printResourceDirectoryTable(ResourceSectionRef RSF,161 const coff_resource_dir_table &Table,162 StringRef Level);163 164 void printBinaryBlockWithRelocs(StringRef Label, const SectionRef &Sec,165 StringRef SectionContents, StringRef Block);166 167 /// Given a .debug$S section, find the string table and file checksum table.168 void initializeFileAndStringTables(BinaryStreamReader &Reader);169 170 void cacheRelocations();171 172 std::error_code resolveSymbol(const coff_section *Section, uint64_t Offset,173 SymbolRef &Sym);174 std::error_code resolveSymbolName(const coff_section *Section,175 uint64_t Offset, StringRef &Name);176 std::error_code resolveSymbolName(const coff_section *Section,177 StringRef SectionContents,178 const void *RelocPtr, StringRef &Name);179 void printImportedSymbols(iterator_range<imported_symbol_iterator> Range);180 void printDelayImportedSymbols(181 const DelayImportDirectoryEntryRef &I,182 iterator_range<imported_symbol_iterator> Range);183 184 typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy;185 186 const llvm::object::COFFObjectFile *Obj;187 bool RelocCached = false;188 RelocMapTy RelocMap;189 190 DebugChecksumsSubsectionRef CVFileChecksumTable;191 192 DebugStringTableSubsectionRef CVStringTable;193 194 /// Track the compilation CPU type. S_COMPILE3 symbol records typically come195 /// first, but if we don't see one, just assume an X64 CPU type. It is common.196 CPUType CompilationCPUType = CPUType::X64;197 198 ScopedPrinter &Writer;199 LazyRandomTypeCollection Types;200};201 202class COFFObjectDumpDelegate : public SymbolDumpDelegate {203public:204 COFFObjectDumpDelegate(COFFDumper &CD, const SectionRef &SR,205 const COFFObjectFile *Obj, StringRef SectionContents)206 : CD(CD), SR(SR), SectionContents(SectionContents) {207 Sec = Obj->getCOFFSection(SR);208 }209 210 uint32_t getRecordOffset(BinaryStreamReader Reader) override {211 ArrayRef<uint8_t> Data;212 if (auto EC = Reader.readLongestContiguousChunk(Data)) {213 llvm::consumeError(std::move(EC));214 return 0;215 }216 return Data.data() - SectionContents.bytes_begin();217 }218 219 void printRelocatedField(StringRef Label, uint32_t RelocOffset,220 uint32_t Offset, StringRef *RelocSym) override {221 CD.printRelocatedField(Label, Sec, RelocOffset, Offset, RelocSym);222 }223 224 void printBinaryBlockWithRelocs(StringRef Label,225 ArrayRef<uint8_t> Block) override {226 StringRef SBlock(reinterpret_cast<const char *>(Block.data()),227 Block.size());228 if (opts::CodeViewSubsectionBytes)229 CD.printBinaryBlockWithRelocs(Label, SR, SectionContents, SBlock);230 }231 232 StringRef getFileNameForFileOffset(uint32_t FileOffset) override {233 return CD.getFileNameForFileOffset(FileOffset);234 }235 236 DebugStringTableSubsectionRef getStringTable() override {237 return CD.CVStringTable;238 }239 240private:241 COFFDumper &CD;242 const SectionRef &SR;243 const coff_section *Sec;244 StringRef SectionContents;245};246 247} // end namespace248 249namespace llvm {250 251std::unique_ptr<ObjDumper> createCOFFDumper(const object::COFFObjectFile &Obj,252 ScopedPrinter &Writer) {253 return std::make_unique<COFFDumper>(&Obj, Writer);254}255 256} // namespace llvm257 258// Given a section and an offset into this section the function returns the259// symbol used for the relocation at the offset.260std::error_code COFFDumper::resolveSymbol(const coff_section *Section,261 uint64_t Offset, SymbolRef &Sym) {262 cacheRelocations();263 const auto &Relocations = RelocMap[Section];264 auto SymI = Obj->symbol_end();265 for (const auto &Relocation : Relocations) {266 uint64_t RelocationOffset = Relocation.getOffset();267 268 if (RelocationOffset == Offset) {269 SymI = Relocation.getSymbol();270 break;271 }272 }273 if (SymI == Obj->symbol_end())274 return inconvertibleErrorCode();275 Sym = *SymI;276 return std::error_code();277}278 279// Given a section and an offset into this section the function returns the name280// of the symbol used for the relocation at the offset.281std::error_code COFFDumper::resolveSymbolName(const coff_section *Section,282 uint64_t Offset,283 StringRef &Name) {284 SymbolRef Symbol;285 if (std::error_code EC = resolveSymbol(Section, Offset, Symbol))286 return EC;287 Expected<StringRef> NameOrErr = Symbol.getName();288 if (!NameOrErr)289 return errorToErrorCode(NameOrErr.takeError());290 Name = *NameOrErr;291 return std::error_code();292}293 294// Helper for when you have a pointer to real data and you want to know about295// relocations against it.296std::error_code COFFDumper::resolveSymbolName(const coff_section *Section,297 StringRef SectionContents,298 const void *RelocPtr,299 StringRef &Name) {300 assert(SectionContents.data() < RelocPtr &&301 RelocPtr < SectionContents.data() + SectionContents.size() &&302 "pointer to relocated object is not in section");303 uint64_t Offset = ptrdiff_t(reinterpret_cast<const char *>(RelocPtr) -304 SectionContents.data());305 return resolveSymbolName(Section, Offset, Name);306}307 308void COFFDumper::printRelocatedField(StringRef Label, const coff_section *Sec,309 uint32_t RelocOffset, uint32_t Offset,310 StringRef *RelocSym) {311 StringRef SymStorage;312 StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;313 if (!resolveSymbolName(Sec, RelocOffset, Symbol))314 W.printSymbolOffset(Label, Symbol, Offset);315 else316 W.printHex(Label, RelocOffset);317}318 319void COFFDumper::printBinaryBlockWithRelocs(StringRef Label,320 const SectionRef &Sec,321 StringRef SectionContents,322 StringRef Block) {323 W.printBinaryBlock(Label, Block);324 325 assert(SectionContents.begin() < Block.begin() &&326 SectionContents.end() >= Block.end() &&327 "Block is not contained in SectionContents");328 uint64_t OffsetStart = Block.data() - SectionContents.data();329 uint64_t OffsetEnd = OffsetStart + Block.size();330 331 W.flush();332 cacheRelocations();333 ListScope D(W, "BlockRelocations");334 const coff_section *Section = Obj->getCOFFSection(Sec);335 const auto &Relocations = RelocMap[Section];336 for (const auto &Relocation : Relocations) {337 uint64_t RelocationOffset = Relocation.getOffset();338 if (OffsetStart <= RelocationOffset && RelocationOffset < OffsetEnd)339 printRelocation(Sec, Relocation, OffsetStart);340 }341}342 343const EnumEntry<COFF::MachineTypes> ImageFileMachineType[] = {344 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_UNKNOWN ),345 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AM33 ),346 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AMD64 ),347 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM ),348 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64 ),349 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64EC ),350 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64X ),351 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARMNT ),352 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_EBC ),353 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_I386 ),354 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_IA64 ),355 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_M32R ),356 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPS16 ),357 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU ),358 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU16),359 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPC ),360 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPCFP),361 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_R4000 ),362 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3 ),363 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3DSP ),364 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH4 ),365 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH5 ),366 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_THUMB ),367 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_WCEMIPSV2)368};369 370const EnumEntry<COFF::Characteristics> ImageFileCharacteristics[] = {371 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_RELOCS_STRIPPED ),372 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_EXECUTABLE_IMAGE ),373 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LINE_NUMS_STRIPPED ),374 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LOCAL_SYMS_STRIPPED ),375 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_AGGRESSIVE_WS_TRIM ),376 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LARGE_ADDRESS_AWARE ),377 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_BYTES_REVERSED_LO ),378 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_32BIT_MACHINE ),379 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_DEBUG_STRIPPED ),380 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP),381 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_NET_RUN_FROM_SWAP ),382 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_SYSTEM ),383 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_DLL ),384 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_UP_SYSTEM_ONLY ),385 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_BYTES_REVERSED_HI )386};387 388const EnumEntry<COFF::WindowsSubsystem> PEWindowsSubsystem[] = {389 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_UNKNOWN ),390 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_NATIVE ),391 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_GUI ),392 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CUI ),393 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_POSIX_CUI ),394 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI ),395 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_APPLICATION ),396 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER),397 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER ),398 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_ROM ),399 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_XBOX ),400};401 402const EnumEntry<COFF::DLLCharacteristics> PEDLLCharacteristics[] = {403 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA ),404 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE ),405 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY ),406 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT ),407 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION ),408 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_SEH ),409 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_BIND ),410 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_APPCONTAINER ),411 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER ),412 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_GUARD_CF ),413 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE),414};415 416// clang-format off417static const EnumEntry<COFF::ExtendedDLLCharacteristics>418 PEExtendedDLLCharacteristics[] = {419 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT ),420 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_COMPAT_STRICT_MODE ),421 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_SET_CONTEXT_IP_VALIDATION_RELAXED_MODE),422 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_DYNAMIC_APIS_ALLOW_IN_PROC_ONLY ),423 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_1 ),424 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_CET_RESERVED_2 ),425 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_FORWARD_CFI_COMPAT ),426 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_EX_HOTPATCH_COMPATIBLE ),427};428// clang-format on429 430static const EnumEntry<COFF::SectionCharacteristics>431ImageSectionCharacteristics[] = {432 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NOLOAD ),433 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NO_PAD ),434 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_CODE ),435 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_INITIALIZED_DATA ),436 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_UNINITIALIZED_DATA),437 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_OTHER ),438 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_INFO ),439 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_REMOVE ),440 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_COMDAT ),441 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_GPREL ),442 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_PURGEABLE ),443 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_16BIT ),444 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_LOCKED ),445 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_PRELOAD ),446 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1BYTES ),447 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2BYTES ),448 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4BYTES ),449 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8BYTES ),450 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_16BYTES ),451 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_32BYTES ),452 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_64BYTES ),453 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_128BYTES ),454 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_256BYTES ),455 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_512BYTES ),456 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1024BYTES ),457 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2048BYTES ),458 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4096BYTES ),459 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8192BYTES ),460 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_NRELOC_OVFL ),461 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_DISCARDABLE ),462 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_CACHED ),463 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_PAGED ),464 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_SHARED ),465 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_EXECUTE ),466 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_READ ),467 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_WRITE )468};469 470const EnumEntry<COFF::SymbolBaseType> ImageSymType[] = {471 { "Null" , COFF::IMAGE_SYM_TYPE_NULL },472 { "Void" , COFF::IMAGE_SYM_TYPE_VOID },473 { "Char" , COFF::IMAGE_SYM_TYPE_CHAR },474 { "Short" , COFF::IMAGE_SYM_TYPE_SHORT },475 { "Int" , COFF::IMAGE_SYM_TYPE_INT },476 { "Long" , COFF::IMAGE_SYM_TYPE_LONG },477 { "Float" , COFF::IMAGE_SYM_TYPE_FLOAT },478 { "Double", COFF::IMAGE_SYM_TYPE_DOUBLE },479 { "Struct", COFF::IMAGE_SYM_TYPE_STRUCT },480 { "Union" , COFF::IMAGE_SYM_TYPE_UNION },481 { "Enum" , COFF::IMAGE_SYM_TYPE_ENUM },482 { "MOE" , COFF::IMAGE_SYM_TYPE_MOE },483 { "Byte" , COFF::IMAGE_SYM_TYPE_BYTE },484 { "Word" , COFF::IMAGE_SYM_TYPE_WORD },485 { "UInt" , COFF::IMAGE_SYM_TYPE_UINT },486 { "DWord" , COFF::IMAGE_SYM_TYPE_DWORD }487};488 489const EnumEntry<COFF::SymbolComplexType> ImageSymDType[] = {490 { "Null" , COFF::IMAGE_SYM_DTYPE_NULL },491 { "Pointer" , COFF::IMAGE_SYM_DTYPE_POINTER },492 { "Function", COFF::IMAGE_SYM_DTYPE_FUNCTION },493 { "Array" , COFF::IMAGE_SYM_DTYPE_ARRAY }494};495 496const EnumEntry<COFF::SymbolStorageClass> ImageSymClass[] = {497 { "EndOfFunction" , COFF::IMAGE_SYM_CLASS_END_OF_FUNCTION },498 { "Null" , COFF::IMAGE_SYM_CLASS_NULL },499 { "Automatic" , COFF::IMAGE_SYM_CLASS_AUTOMATIC },500 { "External" , COFF::IMAGE_SYM_CLASS_EXTERNAL },501 { "Static" , COFF::IMAGE_SYM_CLASS_STATIC },502 { "Register" , COFF::IMAGE_SYM_CLASS_REGISTER },503 { "ExternalDef" , COFF::IMAGE_SYM_CLASS_EXTERNAL_DEF },504 { "Label" , COFF::IMAGE_SYM_CLASS_LABEL },505 { "UndefinedLabel" , COFF::IMAGE_SYM_CLASS_UNDEFINED_LABEL },506 { "MemberOfStruct" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_STRUCT },507 { "Argument" , COFF::IMAGE_SYM_CLASS_ARGUMENT },508 { "StructTag" , COFF::IMAGE_SYM_CLASS_STRUCT_TAG },509 { "MemberOfUnion" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_UNION },510 { "UnionTag" , COFF::IMAGE_SYM_CLASS_UNION_TAG },511 { "TypeDefinition" , COFF::IMAGE_SYM_CLASS_TYPE_DEFINITION },512 { "UndefinedStatic", COFF::IMAGE_SYM_CLASS_UNDEFINED_STATIC },513 { "EnumTag" , COFF::IMAGE_SYM_CLASS_ENUM_TAG },514 { "MemberOfEnum" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_ENUM },515 { "RegisterParam" , COFF::IMAGE_SYM_CLASS_REGISTER_PARAM },516 { "BitField" , COFF::IMAGE_SYM_CLASS_BIT_FIELD },517 { "Block" , COFF::IMAGE_SYM_CLASS_BLOCK },518 { "Function" , COFF::IMAGE_SYM_CLASS_FUNCTION },519 { "EndOfStruct" , COFF::IMAGE_SYM_CLASS_END_OF_STRUCT },520 { "File" , COFF::IMAGE_SYM_CLASS_FILE },521 { "Section" , COFF::IMAGE_SYM_CLASS_SECTION },522 { "WeakExternal" , COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL },523 { "CLRToken" , COFF::IMAGE_SYM_CLASS_CLR_TOKEN }524};525 526const EnumEntry<COFF::COMDATType> ImageCOMDATSelect[] = {527 { "NoDuplicates", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES },528 { "Any" , COFF::IMAGE_COMDAT_SELECT_ANY },529 { "SameSize" , COFF::IMAGE_COMDAT_SELECT_SAME_SIZE },530 { "ExactMatch" , COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH },531 { "Associative" , COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE },532 { "Largest" , COFF::IMAGE_COMDAT_SELECT_LARGEST },533 { "Newest" , COFF::IMAGE_COMDAT_SELECT_NEWEST }534};535 536const EnumEntry<COFF::DebugType> ImageDebugType[] = {537 {"Unknown", COFF::IMAGE_DEBUG_TYPE_UNKNOWN},538 {"COFF", COFF::IMAGE_DEBUG_TYPE_COFF},539 {"CodeView", COFF::IMAGE_DEBUG_TYPE_CODEVIEW},540 {"FPO", COFF::IMAGE_DEBUG_TYPE_FPO},541 {"Misc", COFF::IMAGE_DEBUG_TYPE_MISC},542 {"Exception", COFF::IMAGE_DEBUG_TYPE_EXCEPTION},543 {"Fixup", COFF::IMAGE_DEBUG_TYPE_FIXUP},544 {"OmapToSrc", COFF::IMAGE_DEBUG_TYPE_OMAP_TO_SRC},545 {"OmapFromSrc", COFF::IMAGE_DEBUG_TYPE_OMAP_FROM_SRC},546 {"Borland", COFF::IMAGE_DEBUG_TYPE_BORLAND},547 {"Reserved10", COFF::IMAGE_DEBUG_TYPE_RESERVED10},548 {"CLSID", COFF::IMAGE_DEBUG_TYPE_CLSID},549 {"VCFeature", COFF::IMAGE_DEBUG_TYPE_VC_FEATURE},550 {"POGO", COFF::IMAGE_DEBUG_TYPE_POGO},551 {"ILTCG", COFF::IMAGE_DEBUG_TYPE_ILTCG},552 {"MPX", COFF::IMAGE_DEBUG_TYPE_MPX},553 {"Repro", COFF::IMAGE_DEBUG_TYPE_REPRO},554 {"ExtendedDLLCharacteristics",555 COFF::IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS},556};557 558static const EnumEntry<COFF::WeakExternalCharacteristics>559WeakExternalCharacteristics[] = {560 { "NoLibrary" , COFF::IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY },561 { "Library" , COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY },562 { "Alias" , COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS },563 { "AntiDependency" , COFF::IMAGE_WEAK_EXTERN_ANTI_DEPENDENCY },564};565 566const EnumEntry<uint32_t> SubSectionTypes[] = {567 LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, Symbols),568 LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, Lines),569 LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, StringTable),570 LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, FileChecksums),571 LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, FrameData),572 LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, InlineeLines),573 LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, CrossScopeImports),574 LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, CrossScopeExports),575 LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, ILLines),576 LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, FuncMDTokenMap),577 LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, TypeMDTokenMap),578 LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, MergedAssemblyInput),579 LLVM_READOBJ_ENUM_CLASS_ENT(DebugSubsectionKind, CoffSymbolRVA),580};581 582const EnumEntry<uint32_t> FrameDataFlags[] = {583 LLVM_READOBJ_ENUM_ENT(FrameData, HasSEH),584 LLVM_READOBJ_ENUM_ENT(FrameData, HasEH),585 LLVM_READOBJ_ENUM_ENT(FrameData, IsFunctionStart),586};587 588const EnumEntry<uint8_t> FileChecksumKindNames[] = {589 LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, None),590 LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, MD5),591 LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, SHA1),592 LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, SHA256),593};594 595const EnumEntry<uint32_t> PELoadConfigGuardFlags[] = {596 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, CF_INSTRUMENTED),597 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, CFW_INSTRUMENTED),598 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, CF_FUNCTION_TABLE_PRESENT),599 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, SECURITY_COOKIE_UNUSED),600 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, PROTECT_DELAYLOAD_IAT),601 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,602 DELAYLOAD_IAT_IN_ITS_OWN_SECTION),603 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,604 CF_EXPORT_SUPPRESSION_INFO_PRESENT),605 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, CF_ENABLE_EXPORT_SUPPRESSION),606 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, CF_LONGJUMP_TABLE_PRESENT),607 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,608 EH_CONTINUATION_TABLE_PRESENT),609 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,610 CF_FUNCTION_TABLE_SIZE_5BYTES),611 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,612 CF_FUNCTION_TABLE_SIZE_6BYTES),613 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,614 CF_FUNCTION_TABLE_SIZE_7BYTES),615 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,616 CF_FUNCTION_TABLE_SIZE_8BYTES),617 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,618 CF_FUNCTION_TABLE_SIZE_9BYTES),619 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,620 CF_FUNCTION_TABLE_SIZE_10BYTES),621 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,622 CF_FUNCTION_TABLE_SIZE_11BYTES),623 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,624 CF_FUNCTION_TABLE_SIZE_12BYTES),625 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,626 CF_FUNCTION_TABLE_SIZE_13BYTES),627 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,628 CF_FUNCTION_TABLE_SIZE_14BYTES),629 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,630 CF_FUNCTION_TABLE_SIZE_15BYTES),631 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,632 CF_FUNCTION_TABLE_SIZE_16BYTES),633 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,634 CF_FUNCTION_TABLE_SIZE_17BYTES),635 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,636 CF_FUNCTION_TABLE_SIZE_18BYTES),637 LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,638 CF_FUNCTION_TABLE_SIZE_19BYTES),639};640 641template <typename T>642static std::error_code getSymbolAuxData(const COFFObjectFile *Obj,643 COFFSymbolRef Symbol,644 uint8_t AuxSymbolIdx, const T *&Aux) {645 ArrayRef<uint8_t> AuxData = Obj->getSymbolAuxData(Symbol);646 AuxData = AuxData.slice(AuxSymbolIdx * Obj->getSymbolTableEntrySize());647 Aux = reinterpret_cast<const T*>(AuxData.data());648 return std::error_code();649}650 651void COFFDumper::cacheRelocations() {652 if (RelocCached)653 return;654 RelocCached = true;655 656 for (const SectionRef &S : Obj->sections()) {657 const coff_section *Section = Obj->getCOFFSection(S);658 659 auto &RM = RelocMap[Section];660 append_range(RM, S.relocations());661 662 // Sort relocations by address.663 llvm::sort(RM, [](RelocationRef L, RelocationRef R) {664 return L.getOffset() < R.getOffset();665 });666 }667}668 669void COFFDumper::printDataDirectory(uint32_t Index,670 const std::string &FieldName) {671 const data_directory *Data = Obj->getDataDirectory(Index);672 if (!Data)673 return;674 W.printHex(FieldName + "RVA", Data->RelativeVirtualAddress);675 W.printHex(FieldName + "Size", Data->Size);676}677 678void COFFDumper::printFileHeaders() {679 time_t TDS = Obj->getTimeDateStamp();680 char FormattedTime[20] = { };681 strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS));682 683 {684 DictScope D(W, "ImageFileHeader");685 W.printEnum("Machine", Obj->getMachine(), ArrayRef(ImageFileMachineType));686 W.printNumber("SectionCount", Obj->getNumberOfSections());687 W.printHex ("TimeDateStamp", FormattedTime, Obj->getTimeDateStamp());688 W.printHex ("PointerToSymbolTable", Obj->getPointerToSymbolTable());689 W.printNumber("SymbolCount", Obj->getNumberOfSymbols());690 W.printNumber("StringTableSize", Obj->getStringTableSize());691 W.printNumber("OptionalHeaderSize", Obj->getSizeOfOptionalHeader());692 W.printFlags("Characteristics", Obj->getCharacteristics(),693 ArrayRef(ImageFileCharacteristics));694 }695 696 // Print PE header. This header does not exist if this is an object file and697 // not an executable.698 if (const pe32_header *PEHeader = Obj->getPE32Header())699 printPEHeader<pe32_header>(PEHeader);700 701 if (const pe32plus_header *PEPlusHeader = Obj->getPE32PlusHeader())702 printPEHeader<pe32plus_header>(PEPlusHeader);703 704 if (const dos_header *DH = Obj->getDOSHeader())705 printDOSHeader(DH);706}707 708void COFFDumper::printDOSHeader(const dos_header *DH) {709 DictScope D(W, "DOSHeader");710 W.printString("Magic", StringRef(DH->Magic, sizeof(DH->Magic)));711 W.printNumber("UsedBytesInTheLastPage", DH->UsedBytesInTheLastPage);712 W.printNumber("FileSizeInPages", DH->FileSizeInPages);713 W.printNumber("NumberOfRelocationItems", DH->NumberOfRelocationItems);714 W.printNumber("HeaderSizeInParagraphs", DH->HeaderSizeInParagraphs);715 W.printNumber("MinimumExtraParagraphs", DH->MinimumExtraParagraphs);716 W.printNumber("MaximumExtraParagraphs", DH->MaximumExtraParagraphs);717 W.printNumber("InitialRelativeSS", DH->InitialRelativeSS);718 W.printNumber("InitialSP", DH->InitialSP);719 W.printNumber("Checksum", DH->Checksum);720 W.printNumber("InitialIP", DH->InitialIP);721 W.printNumber("InitialRelativeCS", DH->InitialRelativeCS);722 W.printNumber("AddressOfRelocationTable", DH->AddressOfRelocationTable);723 W.printNumber("OverlayNumber", DH->OverlayNumber);724 W.printNumber("OEMid", DH->OEMid);725 W.printNumber("OEMinfo", DH->OEMinfo);726 W.printNumber("AddressOfNewExeHeader", DH->AddressOfNewExeHeader);727}728 729template <class PEHeader>730void COFFDumper::printPEHeader(const PEHeader *Hdr) {731 DictScope D(W, "ImageOptionalHeader");732 W.printHex ("Magic", Hdr->Magic);733 W.printNumber("MajorLinkerVersion", Hdr->MajorLinkerVersion);734 W.printNumber("MinorLinkerVersion", Hdr->MinorLinkerVersion);735 W.printNumber("SizeOfCode", Hdr->SizeOfCode);736 W.printNumber("SizeOfInitializedData", Hdr->SizeOfInitializedData);737 W.printNumber("SizeOfUninitializedData", Hdr->SizeOfUninitializedData);738 W.printHex ("AddressOfEntryPoint", Hdr->AddressOfEntryPoint);739 W.printHex ("BaseOfCode", Hdr->BaseOfCode);740 printBaseOfDataField(Hdr);741 W.printHex ("ImageBase", Hdr->ImageBase);742 W.printNumber("SectionAlignment", Hdr->SectionAlignment);743 W.printNumber("FileAlignment", Hdr->FileAlignment);744 W.printNumber("MajorOperatingSystemVersion",745 Hdr->MajorOperatingSystemVersion);746 W.printNumber("MinorOperatingSystemVersion",747 Hdr->MinorOperatingSystemVersion);748 W.printNumber("MajorImageVersion", Hdr->MajorImageVersion);749 W.printNumber("MinorImageVersion", Hdr->MinorImageVersion);750 W.printNumber("MajorSubsystemVersion", Hdr->MajorSubsystemVersion);751 W.printNumber("MinorSubsystemVersion", Hdr->MinorSubsystemVersion);752 W.printNumber("SizeOfImage", Hdr->SizeOfImage);753 W.printNumber("SizeOfHeaders", Hdr->SizeOfHeaders);754 W.printHex ("CheckSum", Hdr->CheckSum);755 W.printEnum("Subsystem", Hdr->Subsystem, ArrayRef(PEWindowsSubsystem));756 W.printFlags("Characteristics", Hdr->DLLCharacteristics,757 ArrayRef(PEDLLCharacteristics));758 W.printNumber("SizeOfStackReserve", Hdr->SizeOfStackReserve);759 W.printNumber("SizeOfStackCommit", Hdr->SizeOfStackCommit);760 W.printNumber("SizeOfHeapReserve", Hdr->SizeOfHeapReserve);761 W.printNumber("SizeOfHeapCommit", Hdr->SizeOfHeapCommit);762 W.printNumber("NumberOfRvaAndSize", Hdr->NumberOfRvaAndSize);763 764 if (Hdr->NumberOfRvaAndSize > 0) {765 DictScope D(W, "DataDirectory");766 static const char * const directory[] = {767 "ExportTable", "ImportTable", "ResourceTable", "ExceptionTable",768 "CertificateTable", "BaseRelocationTable", "Debug", "Architecture",769 "GlobalPtr", "TLSTable", "LoadConfigTable", "BoundImport", "IAT",770 "DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"771 };772 773 for (uint32_t i = 0; i < Hdr->NumberOfRvaAndSize; ++i)774 if (i < std::size(directory))775 printDataDirectory(i, directory[i]);776 else777 printDataDirectory(i, "Unknown");778 }779}780 781void COFFDumper::printCOFFDebugDirectory() {782 ListScope LS(W, "DebugDirectory");783 for (const debug_directory &D : Obj->debug_directories()) {784 char FormattedTime[20] = {};785 time_t TDS = D.TimeDateStamp;786 strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS));787 DictScope S(W, "DebugEntry");788 W.printHex("Characteristics", D.Characteristics);789 W.printHex("TimeDateStamp", FormattedTime, D.TimeDateStamp);790 W.printHex("MajorVersion", D.MajorVersion);791 W.printHex("MinorVersion", D.MinorVersion);792 W.printEnum("Type", D.Type, ArrayRef(ImageDebugType));793 W.printHex("SizeOfData", D.SizeOfData);794 W.printHex("AddressOfRawData", D.AddressOfRawData);795 W.printHex("PointerToRawData", D.PointerToRawData);796 // Ideally, if D.AddressOfRawData == 0, we should try to load the payload797 // using D.PointerToRawData instead.798 if (D.AddressOfRawData == 0)799 continue;800 if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) {801 const codeview::DebugInfo *DebugInfo;802 StringRef PDBFileName;803 if (Error E = Obj->getDebugPDBInfo(&D, DebugInfo, PDBFileName))804 reportError(std::move(E), Obj->getFileName());805 806 DictScope PDBScope(W, "PDBInfo");807 W.printHex("PDBSignature", DebugInfo->Signature.CVSignature);808 if (DebugInfo->Signature.CVSignature == OMF::Signature::PDB70) {809 W.printString(810 "PDBGUID",811 formatv("{0}", fmt_guid(DebugInfo->PDB70.Signature)).str());812 W.printNumber("PDBAge", DebugInfo->PDB70.Age);813 W.printString("PDBFileName", PDBFileName);814 }815 } else if (D.SizeOfData != 0) {816 // FIXME: Data visualization for IMAGE_DEBUG_TYPE_VC_FEATURE and817 // IMAGE_DEBUG_TYPE_POGO?818 ArrayRef<uint8_t> RawData;819 if (Error E = Obj->getRvaAndSizeAsBytes(D.AddressOfRawData,820 D.SizeOfData, RawData))821 reportError(std::move(E), Obj->getFileName());822 if (D.Type == COFF::IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS) {823 // FIXME right now the only possible value would fit in 8 bits,824 // but that might change in the future825 uint16_t Characteristics = RawData[0];826 W.printFlags("ExtendedCharacteristics", Characteristics,827 ArrayRef(PEExtendedDLLCharacteristics));828 }829 W.printBinaryBlock("RawData", RawData);830 }831 }832}833 834void COFFDumper::printRVATable(uint64_t TableVA, uint64_t Count,835 uint64_t EntrySize, PrintExtraCB PrintExtra) {836 uintptr_t TableStart, TableEnd;837 if (Error E = Obj->getVaPtr(TableVA, TableStart))838 reportError(std::move(E), Obj->getFileName());839 if (Error E =840 Obj->getVaPtr(TableVA + Count * EntrySize - 1, TableEnd))841 reportError(std::move(E), Obj->getFileName());842 TableEnd++;843 for (uintptr_t I = TableStart; I < TableEnd; I += EntrySize) {844 uint32_t RVA = *reinterpret_cast<const ulittle32_t *>(I);845 raw_ostream &OS = W.startLine();846 OS << W.hex(Obj->getImageBase() + RVA);847 if (PrintExtra)848 PrintExtra(OS, reinterpret_cast<const uint8_t *>(I));849 OS << '\n';850 }851}852 853void COFFDumper::printCOFFLoadConfig() {854 LoadConfigTables Tables;855 if (Obj->is64())856 printCOFFLoadConfig(Obj->getLoadConfig64(), Tables);857 else858 printCOFFLoadConfig(Obj->getLoadConfig32(), Tables);859 860 if (auto CHPE = Obj->getCHPEMetadata()) {861 ListScope LS(W, "CHPEMetadata");862 W.printHex("Version", CHPE->Version);863 864 if (CHPE->CodeMapCount) {865 ListScope CMLS(W, "CodeMap");866 867 uintptr_t CodeMapInt;868 if (Error E = Obj->getRvaPtr(CHPE->CodeMap, CodeMapInt))869 reportError(std::move(E), Obj->getFileName());870 auto CodeMap = reinterpret_cast<const chpe_range_entry *>(CodeMapInt);871 for (uint32_t i = 0; i < CHPE->CodeMapCount; i++) {872 uint32_t Start = CodeMap[i].getStart();873 W.startLine() << W.hex(Start) << " - "874 << W.hex(Start + CodeMap[i].Length) << " ";875 switch (CodeMap[i].getType()) {876 case chpe_range_type::Arm64:877 W.getOStream() << "ARM64\n";878 break;879 case chpe_range_type::Arm64EC:880 W.getOStream() << "ARM64EC\n";881 break;882 case chpe_range_type::Amd64:883 W.getOStream() << "X64\n";884 break;885 default:886 W.getOStream() << W.hex(CodeMap[i].StartOffset & 3) << "\n";887 break;888 }889 }890 } else {891 W.printNumber("CodeMap", CHPE->CodeMap);892 }893 894 if (CHPE->CodeRangesToEntryPointsCount) {895 ListScope CRLS(W, "CodeRangesToEntryPoints");896 897 uintptr_t CodeRangesInt;898 if (Error E =899 Obj->getRvaPtr(CHPE->CodeRangesToEntryPoints, CodeRangesInt))900 reportError(std::move(E), Obj->getFileName());901 auto CodeRanges =902 reinterpret_cast<const chpe_code_range_entry *>(CodeRangesInt);903 for (uint32_t i = 0; i < CHPE->CodeRangesToEntryPointsCount; i++) {904 W.startLine() << W.hex(CodeRanges[i].StartRva) << " - "905 << W.hex(CodeRanges[i].EndRva) << " -> "906 << W.hex(CodeRanges[i].EntryPoint) << "\n";907 }908 } else {909 W.printNumber("CodeRangesToEntryPoints", CHPE->CodeRangesToEntryPoints);910 }911 912 if (CHPE->RedirectionMetadataCount) {913 ListScope RMLS(W, "RedirectionMetadata");914 915 uintptr_t RedirMetadataInt;916 if (Error E = Obj->getRvaPtr(CHPE->RedirectionMetadata, RedirMetadataInt))917 reportError(std::move(E), Obj->getFileName());918 auto RedirMetadata =919 reinterpret_cast<const chpe_redirection_entry *>(RedirMetadataInt);920 for (uint32_t i = 0; i < CHPE->RedirectionMetadataCount; i++) {921 W.startLine() << W.hex(RedirMetadata[i].Source) << " -> "922 << W.hex(RedirMetadata[i].Destination) << "\n";923 }924 } else {925 W.printNumber("RedirectionMetadata", CHPE->RedirectionMetadata);926 }927 928 W.printHex("__os_arm64x_dispatch_call_no_redirect",929 CHPE->__os_arm64x_dispatch_call_no_redirect);930 W.printHex("__os_arm64x_dispatch_ret", CHPE->__os_arm64x_dispatch_ret);931 W.printHex("__os_arm64x_dispatch_call", CHPE->__os_arm64x_dispatch_call);932 W.printHex("__os_arm64x_dispatch_icall", CHPE->__os_arm64x_dispatch_icall);933 W.printHex("__os_arm64x_dispatch_icall_cfg",934 CHPE->__os_arm64x_dispatch_icall_cfg);935 W.printHex("AlternateEntryPoint", CHPE->AlternateEntryPoint);936 W.printHex("AuxiliaryIAT", CHPE->AuxiliaryIAT);937 W.printHex("GetX64InformationFunctionPointer",938 CHPE->GetX64InformationFunctionPointer);939 W.printHex("SetX64InformationFunctionPointer",940 CHPE->SetX64InformationFunctionPointer);941 W.printHex("ExtraRFETable", CHPE->ExtraRFETable);942 W.printHex("ExtraRFETableSize", CHPE->ExtraRFETableSize);943 W.printHex("__os_arm64x_dispatch_fptr", CHPE->__os_arm64x_dispatch_fptr);944 W.printHex("AuxiliaryIATCopy", CHPE->AuxiliaryIATCopy);945 946 if (CHPE->Version >= 2) {947 W.printHex("AuxiliaryDelayloadIAT", CHPE->AuxiliaryDelayloadIAT);948 W.printHex("AuxiliaryDelayloadIATCopy", CHPE->AuxiliaryDelayloadIATCopy);949 W.printHex("HybridImageInfoBitfield", CHPE->HybridImageInfoBitfield);950 }951 }952 953 if (Tables.SEHTableVA) {954 ListScope LS(W, "SEHTable");955 printRVATable(Tables.SEHTableVA, Tables.SEHTableCount, 4);956 }957 958 auto PrintGuardFlags = [](raw_ostream &OS, const uint8_t *Entry) {959 uint8_t Flags = *reinterpret_cast<const uint8_t *>(Entry + 4);960 if (Flags)961 OS << " flags " << utohexstr(Flags);962 };963 964 // The stride gives the number of extra bytes in addition to the 4-byte965 // RVA of each entry in the table. As of writing only a 1-byte extra flag966 // has been defined.967 uint32_t Stride = Tables.GuardFlags >> 28;968 PrintExtraCB PrintExtra = Stride == 1 ? +PrintGuardFlags : nullptr;969 970 if (Tables.GuardFidTableVA) {971 ListScope LS(W, "GuardFidTable");972 printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount,973 4 + Stride, PrintExtra);974 }975 976 if (Tables.GuardIatTableVA) {977 ListScope LS(W, "GuardIatTable");978 printRVATable(Tables.GuardIatTableVA, Tables.GuardIatTableCount,979 4 + Stride, PrintExtra);980 }981 982 if (Tables.GuardLJmpTableVA) {983 ListScope LS(W, "GuardLJmpTable");984 printRVATable(Tables.GuardLJmpTableVA, Tables.GuardLJmpTableCount,985 4 + Stride, PrintExtra);986 }987 988 if (Tables.GuardEHContTableVA) {989 ListScope LS(W, "GuardEHContTable");990 printRVATable(Tables.GuardEHContTableVA, Tables.GuardEHContTableCount,991 4 + Stride, PrintExtra);992 }993 994 if (const coff_dynamic_reloc_table *DynRelocTable =995 Obj->getDynamicRelocTable()) {996 ListScope LS(W, "DynamicRelocations");997 W.printHex("Version", DynRelocTable->Version);998 for (auto reloc : Obj->dynamic_relocs()) {999 switch (reloc.getType()) {1000 case COFF::IMAGE_DYNAMIC_RELOCATION_ARM64X: {1001 ListScope TLS(W, "Arm64X");1002 for (auto Arm64XReloc : reloc.arm64x_relocs()) {1003 ListScope ELS(W, "Entry");1004 W.printHex("RVA", Arm64XReloc.getRVA());1005 switch (Arm64XReloc.getType()) {1006 case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_ZEROFILL:1007 W.printString("Type", "ZEROFILL");1008 W.printHex("Size", Arm64XReloc.getSize());1009 break;1010 case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE:1011 W.printString("Type", "VALUE");1012 W.printHex("Size", Arm64XReloc.getSize());1013 W.printHex("Value", Arm64XReloc.getValue());1014 break;1015 case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA:1016 W.printString("Type", "DELTA");1017 W.printNumber("Value",1018 static_cast<int32_t>(Arm64XReloc.getValue()));1019 break;1020 }1021 }1022 break;1023 }1024 default:1025 W.printHex("Type", reloc.getType());1026 break;1027 }1028 }1029 }1030}1031 1032template <typename T>1033void COFFDumper::printCOFFLoadConfig(const T *Conf, LoadConfigTables &Tables) {1034 if (!Conf)1035 return;1036 1037 ListScope LS(W, "LoadConfig");1038 char FormattedTime[20] = {};1039 time_t TDS = Conf->TimeDateStamp;1040 strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS));1041 W.printHex("Size", Conf->Size);1042 1043 // Print everything before SecurityCookie. The vast majority of images today1044 // have all these fields.1045 if (Conf->Size < offsetof(T, SEHandlerTable))1046 return;1047 W.printHex("TimeDateStamp", FormattedTime, TDS);1048 W.printHex("MajorVersion", Conf->MajorVersion);1049 W.printHex("MinorVersion", Conf->MinorVersion);1050 W.printHex("GlobalFlagsClear", Conf->GlobalFlagsClear);1051 W.printHex("GlobalFlagsSet", Conf->GlobalFlagsSet);1052 W.printHex("CriticalSectionDefaultTimeout",1053 Conf->CriticalSectionDefaultTimeout);1054 W.printHex("DeCommitFreeBlockThreshold", Conf->DeCommitFreeBlockThreshold);1055 W.printHex("DeCommitTotalFreeThreshold", Conf->DeCommitTotalFreeThreshold);1056 W.printHex("LockPrefixTable", Conf->LockPrefixTable);1057 W.printHex("MaximumAllocationSize", Conf->MaximumAllocationSize);1058 W.printHex("VirtualMemoryThreshold", Conf->VirtualMemoryThreshold);1059 W.printHex("ProcessHeapFlags", Conf->ProcessHeapFlags);1060 W.printHex("ProcessAffinityMask", Conf->ProcessAffinityMask);1061 W.printHex("CSDVersion", Conf->CSDVersion);1062 W.printHex("DependentLoadFlags", Conf->DependentLoadFlags);1063 W.printHex("EditList", Conf->EditList);1064 W.printHex("SecurityCookie", Conf->SecurityCookie);1065 1066 // Print the safe SEH table if present.1067 if (Conf->Size < offsetof(T, GuardCFCheckFunction))1068 return;1069 W.printHex("SEHandlerTable", Conf->SEHandlerTable);1070 W.printNumber("SEHandlerCount", Conf->SEHandlerCount);1071 1072 Tables.SEHTableVA = Conf->SEHandlerTable;1073 Tables.SEHTableCount = Conf->SEHandlerCount;1074 1075 // Print everything before CodeIntegrity. (2015)1076 if (Conf->Size < offsetof(T, CodeIntegrity))1077 return;1078 W.printHex("GuardCFCheckFunction", Conf->GuardCFCheckFunction);1079 W.printHex("GuardCFCheckDispatch", Conf->GuardCFCheckDispatch);1080 W.printHex("GuardCFFunctionTable", Conf->GuardCFFunctionTable);1081 W.printNumber("GuardCFFunctionCount", Conf->GuardCFFunctionCount);1082 W.printFlags("GuardFlags", Conf->GuardFlags, ArrayRef(PELoadConfigGuardFlags),1083 (uint32_t)COFF::GuardFlags::CF_FUNCTION_TABLE_SIZE_MASK);1084 1085 Tables.GuardFidTableVA = Conf->GuardCFFunctionTable;1086 Tables.GuardFidTableCount = Conf->GuardCFFunctionCount;1087 Tables.GuardFlags = Conf->GuardFlags;1088 1089 // Print everything before Reserved3. (2017)1090 if (Conf->Size < offsetof(T, Reserved3))1091 return;1092 W.printHex("GuardAddressTakenIatEntryTable",1093 Conf->GuardAddressTakenIatEntryTable);1094 W.printNumber("GuardAddressTakenIatEntryCount",1095 Conf->GuardAddressTakenIatEntryCount);1096 W.printHex("GuardLongJumpTargetTable", Conf->GuardLongJumpTargetTable);1097 W.printNumber("GuardLongJumpTargetCount", Conf->GuardLongJumpTargetCount);1098 W.printHex("DynamicValueRelocTable", Conf->DynamicValueRelocTable);1099 W.printHex("CHPEMetadataPointer", Conf->CHPEMetadataPointer);1100 W.printHex("GuardRFFailureRoutine", Conf->GuardRFFailureRoutine);1101 W.printHex("GuardRFFailureRoutineFunctionPointer",1102 Conf->GuardRFFailureRoutineFunctionPointer);1103 W.printHex("DynamicValueRelocTableOffset",1104 Conf->DynamicValueRelocTableOffset);1105 W.printNumber("DynamicValueRelocTableSection",1106 Conf->DynamicValueRelocTableSection);1107 W.printHex("GuardRFVerifyStackPointerFunctionPointer",1108 Conf->GuardRFVerifyStackPointerFunctionPointer);1109 W.printHex("HotPatchTableOffset", Conf->HotPatchTableOffset);1110 1111 Tables.GuardIatTableVA = Conf->GuardAddressTakenIatEntryTable;1112 Tables.GuardIatTableCount = Conf->GuardAddressTakenIatEntryCount;1113 1114 Tables.GuardLJmpTableVA = Conf->GuardLongJumpTargetTable;1115 Tables.GuardLJmpTableCount = Conf->GuardLongJumpTargetCount;1116 1117 // Print the rest. (2019)1118 if (Conf->Size < sizeof(T))1119 return;1120 W.printHex("EnclaveConfigurationPointer", Conf->EnclaveConfigurationPointer);1121 W.printHex("VolatileMetadataPointer", Conf->VolatileMetadataPointer);1122 W.printHex("GuardEHContinuationTable", Conf->GuardEHContinuationTable);1123 W.printNumber("GuardEHContinuationCount", Conf->GuardEHContinuationCount);1124 1125 Tables.GuardEHContTableVA = Conf->GuardEHContinuationTable;1126 Tables.GuardEHContTableCount = Conf->GuardEHContinuationCount;1127}1128 1129void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) {1130 W.printHex("BaseOfData", Hdr->BaseOfData);1131}1132 1133void COFFDumper::printBaseOfDataField(const pe32plus_header *) {}1134 1135void COFFDumper::printCodeViewDebugInfo() {1136 // Print types first to build CVUDTNames, then print symbols.1137 for (const SectionRef &S : Obj->sections()) {1138 StringRef SectionName = unwrapOrError(Obj->getFileName(), S.getName());1139 // .debug$T is a standard CodeView type section, while .debug$P is the same1140 // format but used for MSVC precompiled header object files.1141 if (SectionName == ".debug$T" || SectionName == ".debug$P")1142 printCodeViewTypeSection(SectionName, S);1143 }1144 for (const SectionRef &S : Obj->sections()) {1145 StringRef SectionName = unwrapOrError(Obj->getFileName(), S.getName());1146 if (SectionName == ".debug$S")1147 printCodeViewSymbolSection(SectionName, S);1148 }1149}1150 1151void COFFDumper::initializeFileAndStringTables(BinaryStreamReader &Reader) {1152 while (Reader.bytesRemaining() > 0 &&1153 (!CVFileChecksumTable.valid() || !CVStringTable.valid())) {1154 // The section consists of a number of subsection in the following format:1155 // |SubSectionType|SubSectionSize|Contents...|1156 uint32_t SubType, SubSectionSize;1157 1158 if (Error E = Reader.readInteger(SubType))1159 reportError(std::move(E), Obj->getFileName());1160 if (Error E = Reader.readInteger(SubSectionSize))1161 reportError(std::move(E), Obj->getFileName());1162 1163 StringRef Contents;1164 if (Error E = Reader.readFixedString(Contents, SubSectionSize))1165 reportError(std::move(E), Obj->getFileName());1166 1167 BinaryStreamRef ST(Contents, llvm::endianness::little);1168 switch (DebugSubsectionKind(SubType)) {1169 case DebugSubsectionKind::FileChecksums:1170 if (Error E = CVFileChecksumTable.initialize(ST))1171 reportError(std::move(E), Obj->getFileName());1172 break;1173 case DebugSubsectionKind::StringTable:1174 if (Error E = CVStringTable.initialize(ST))1175 reportError(std::move(E), Obj->getFileName());1176 break;1177 default:1178 break;1179 }1180 1181 uint32_t PaddedSize = alignTo(SubSectionSize, 4);1182 if (Error E = Reader.skip(PaddedSize - SubSectionSize))1183 reportError(std::move(E), Obj->getFileName());1184 }1185}1186 1187void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,1188 const SectionRef &Section) {1189 StringRef SectionContents =1190 unwrapOrError(Obj->getFileName(), Section.getContents());1191 StringRef Data = SectionContents;1192 1193 SmallVector<StringRef, 10> FunctionNames;1194 StringMap<StringRef> FunctionLineTables;1195 1196 ListScope D(W, "CodeViewDebugInfo");1197 // Print the section to allow correlation with printSectionHeaders.1198 W.printNumber("Section", SectionName, Obj->getSectionID(Section));1199 1200 uint32_t Magic;1201 if (Error E = consume(Data, Magic))1202 reportError(std::move(E), Obj->getFileName());1203 1204 W.printHex("Magic", Magic);1205 if (Magic != COFF::DEBUG_SECTION_MAGIC)1206 reportError(errorCodeToError(object_error::parse_failed),1207 Obj->getFileName());1208 1209 BinaryStreamReader FSReader(Data, llvm::endianness::little);1210 initializeFileAndStringTables(FSReader);1211 1212 // TODO: Convert this over to using ModuleSubstreamVisitor.1213 while (!Data.empty()) {1214 // The section consists of a number of subsection in the following format:1215 // |SubSectionType|SubSectionSize|Contents...|1216 uint32_t SubType, SubSectionSize;1217 if (Error E = consume(Data, SubType))1218 reportError(std::move(E), Obj->getFileName());1219 if (Error E = consume(Data, SubSectionSize))1220 reportError(std::move(E), Obj->getFileName());1221 1222 ListScope S(W, "Subsection");1223 // Dump the subsection as normal even if the ignore bit is set.1224 if (SubType & SubsectionIgnoreFlag) {1225 W.printHex("IgnoredSubsectionKind", SubType);1226 SubType &= ~SubsectionIgnoreFlag;1227 }1228 W.printEnum("SubSectionType", SubType, ArrayRef(SubSectionTypes));1229 W.printHex("SubSectionSize", SubSectionSize);1230 1231 // Get the contents of the subsection.1232 if (SubSectionSize > Data.size())1233 return reportError(errorCodeToError(object_error::parse_failed),1234 Obj->getFileName());1235 StringRef Contents = Data.substr(0, SubSectionSize);1236 1237 // Add SubSectionSize to the current offset and align that offset to find1238 // the next subsection.1239 size_t SectionOffset = Data.data() - SectionContents.data();1240 size_t NextOffset = SectionOffset + SubSectionSize;1241 NextOffset = alignTo(NextOffset, 4);1242 if (NextOffset > SectionContents.size())1243 return reportError(errorCodeToError(object_error::parse_failed),1244 Obj->getFileName());1245 Data = SectionContents.drop_front(NextOffset);1246 1247 // Optionally print the subsection bytes in case our parsing gets confused1248 // later.1249 if (opts::CodeViewSubsectionBytes)1250 printBinaryBlockWithRelocs("SubSectionContents", Section, SectionContents,1251 Contents);1252 1253 switch (DebugSubsectionKind(SubType)) {1254 case DebugSubsectionKind::Symbols:1255 printCodeViewSymbolsSubsection(Contents, Section, SectionContents);1256 break;1257 1258 case DebugSubsectionKind::InlineeLines:1259 printCodeViewInlineeLines(Contents);1260 break;1261 1262 case DebugSubsectionKind::FileChecksums:1263 printCodeViewFileChecksums(Contents);1264 break;1265 1266 case DebugSubsectionKind::Lines: {1267 // Holds a PC to file:line table. Some data to parse this subsection is1268 // stored in the other subsections, so just check sanity and store the1269 // pointers for deferred processing.1270 1271 if (SubSectionSize < 12) {1272 // There should be at least three words to store two function1273 // relocations and size of the code.1274 reportError(errorCodeToError(object_error::parse_failed),1275 Obj->getFileName());1276 return;1277 }1278 1279 StringRef LinkageName;1280 if (std::error_code EC = resolveSymbolName(Obj->getCOFFSection(Section),1281 SectionOffset, LinkageName))1282 reportError(errorCodeToError(EC), Obj->getFileName());1283 1284 W.printString("LinkageName", LinkageName);1285 auto [It, Inserted] =1286 FunctionLineTables.try_emplace(LinkageName, Contents);1287 if (!Inserted) {1288 // Saw debug info for this function already?1289 reportError(errorCodeToError(object_error::parse_failed),1290 Obj->getFileName());1291 return;1292 }1293 1294 FunctionNames.push_back(LinkageName);1295 break;1296 }1297 case DebugSubsectionKind::FrameData: {1298 // First four bytes is a relocation against the function.1299 BinaryStreamReader SR(Contents, llvm::endianness::little);1300 1301 DebugFrameDataSubsectionRef FrameData;1302 if (Error E = FrameData.initialize(SR))1303 reportError(std::move(E), Obj->getFileName());1304 1305 StringRef LinkageName;1306 if (std::error_code EC =1307 resolveSymbolName(Obj->getCOFFSection(Section), SectionContents,1308 FrameData.getRelocPtr(), LinkageName))1309 reportError(errorCodeToError(EC), Obj->getFileName());1310 W.printString("LinkageName", LinkageName);1311 1312 // To find the active frame description, search this array for the1313 // smallest PC range that includes the current PC.1314 for (const auto &FD : FrameData) {1315 StringRef FrameFunc = unwrapOrError(1316 Obj->getFileName(), CVStringTable.getString(FD.FrameFunc));1317 1318 DictScope S(W, "FrameData");1319 W.printHex("RvaStart", FD.RvaStart);1320 W.printHex("CodeSize", FD.CodeSize);1321 W.printHex("LocalSize", FD.LocalSize);1322 W.printHex("ParamsSize", FD.ParamsSize);1323 W.printHex("MaxStackSize", FD.MaxStackSize);1324 W.printHex("PrologSize", FD.PrologSize);1325 W.printHex("SavedRegsSize", FD.SavedRegsSize);1326 W.printFlags("Flags", FD.Flags, ArrayRef(FrameDataFlags));1327 1328 // The FrameFunc string is a small RPN program. It can be broken up into1329 // statements that end in the '=' operator, which assigns the value on1330 // the top of the stack to the previously pushed variable. Variables can1331 // be temporary values ($T0) or physical registers ($esp). Print each1332 // assignment on its own line to make these programs easier to read.1333 {1334 ListScope FFS(W, "FrameFunc");1335 while (!FrameFunc.empty()) {1336 size_t EqOrEnd = FrameFunc.find('=');1337 if (EqOrEnd == StringRef::npos)1338 EqOrEnd = FrameFunc.size();1339 else1340 ++EqOrEnd;1341 StringRef Stmt = FrameFunc.substr(0, EqOrEnd);1342 W.printString(Stmt);1343 FrameFunc = FrameFunc.drop_front(EqOrEnd).trim();1344 }1345 }1346 }1347 break;1348 }1349 1350 // Do nothing for unrecognized subsections.1351 default:1352 break;1353 }1354 W.flush();1355 }1356 1357 // Dump the line tables now that we've read all the subsections and know all1358 // the required information.1359 for (unsigned I = 0, E = FunctionNames.size(); I != E; ++I) {1360 StringRef Name = FunctionNames[I];1361 ListScope S(W, "FunctionLineTable");1362 W.printString("LinkageName", Name);1363 1364 BinaryStreamReader Reader(FunctionLineTables[Name],1365 llvm::endianness::little);1366 1367 DebugLinesSubsectionRef LineInfo;1368 if (Error E = LineInfo.initialize(Reader))1369 reportError(std::move(E), Obj->getFileName());1370 1371 W.printHex("Flags", LineInfo.header()->Flags);1372 W.printHex("CodeSize", LineInfo.header()->CodeSize);1373 for (const auto &Entry : LineInfo) {1374 1375 ListScope S(W, "FilenameSegment");1376 printFileNameForOffset("Filename", Entry.NameIndex);1377 uint32_t ColumnIndex = 0;1378 for (const auto &Line : Entry.LineNumbers) {1379 if (Line.Offset >= LineInfo.header()->CodeSize) {1380 reportError(errorCodeToError(object_error::parse_failed),1381 Obj->getFileName());1382 return;1383 }1384 1385 std::string PC = std::string(formatv("+{0:X}", uint32_t(Line.Offset)));1386 ListScope PCScope(W, PC);1387 codeview::LineInfo LI(Line.Flags);1388 1389 if (LI.isAlwaysStepInto())1390 W.printString("StepInto", StringRef("Always"));1391 else if (LI.isNeverStepInto())1392 W.printString("StepInto", StringRef("Never"));1393 else1394 W.printNumber("LineNumberStart", LI.getStartLine());1395 W.printNumber("LineNumberEndDelta", LI.getLineDelta());1396 W.printBoolean("IsStatement", LI.isStatement());1397 if (LineInfo.hasColumnInfo()) {1398 W.printNumber("ColStart", Entry.Columns[ColumnIndex].StartColumn);1399 W.printNumber("ColEnd", Entry.Columns[ColumnIndex].EndColumn);1400 ++ColumnIndex;1401 }1402 }1403 }1404 }1405}1406 1407void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,1408 const SectionRef &Section,1409 StringRef SectionContents) {1410 ArrayRef<uint8_t> BinaryData(Subsection.bytes_begin(),1411 Subsection.bytes_end());1412 auto CODD = std::make_unique<COFFObjectDumpDelegate>(*this, Section, Obj,1413 SectionContents);1414 CVSymbolDumper CVSD(W, Types, CodeViewContainer::ObjectFile, std::move(CODD),1415 CompilationCPUType, opts::CodeViewSubsectionBytes);1416 CVSymbolArray Symbols;1417 BinaryStreamReader Reader(BinaryData, llvm::endianness::little);1418 if (Error E = Reader.readArray(Symbols, Reader.getLength())) {1419 W.flush();1420 reportError(std::move(E), Obj->getFileName());1421 }1422 1423 if (Error E = CVSD.dump(Symbols)) {1424 W.flush();1425 reportError(std::move(E), Obj->getFileName());1426 }1427 CompilationCPUType = CVSD.getCompilationCPUType();1428 W.flush();1429}1430 1431void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) {1432 BinaryStreamRef Stream(Subsection, llvm::endianness::little);1433 DebugChecksumsSubsectionRef Checksums;1434 if (Error E = Checksums.initialize(Stream))1435 reportError(std::move(E), Obj->getFileName());1436 1437 for (auto &FC : Checksums) {1438 DictScope S(W, "FileChecksum");1439 1440 StringRef Filename = unwrapOrError(1441 Obj->getFileName(), CVStringTable.getString(FC.FileNameOffset));1442 W.printHex("Filename", Filename, FC.FileNameOffset);1443 W.printHex("ChecksumSize", FC.Checksum.size());1444 W.printEnum("ChecksumKind", uint8_t(FC.Kind),1445 ArrayRef(FileChecksumKindNames));1446 1447 W.printBinary("ChecksumBytes", FC.Checksum);1448 }1449}1450 1451void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {1452 BinaryStreamReader SR(Subsection, llvm::endianness::little);1453 DebugInlineeLinesSubsectionRef Lines;1454 if (Error E = Lines.initialize(SR))1455 reportError(std::move(E), Obj->getFileName());1456 1457 for (auto &Line : Lines) {1458 DictScope S(W, "InlineeSourceLine");1459 printTypeIndex("Inlinee", Line.Header->Inlinee);1460 printFileNameForOffset("FileID", Line.Header->FileID);1461 W.printNumber("SourceLineNum", Line.Header->SourceLineNum);1462 1463 if (Lines.hasExtraFiles()) {1464 W.printNumber("ExtraFileCount", Line.ExtraFiles.size());1465 ListScope ExtraFiles(W, "ExtraFiles");1466 for (const auto &FID : Line.ExtraFiles) {1467 printFileNameForOffset("FileID", FID);1468 }1469 }1470 }1471}1472 1473StringRef COFFDumper::getFileNameForFileOffset(uint32_t FileOffset) {1474 // The file checksum subsection should precede all references to it.1475 if (!CVFileChecksumTable.valid() || !CVStringTable.valid())1476 reportError(errorCodeToError(object_error::parse_failed),1477 Obj->getFileName());1478 1479 auto Iter = CVFileChecksumTable.getArray().at(FileOffset);1480 1481 // Check if the file checksum table offset is valid.1482 if (Iter == CVFileChecksumTable.end())1483 reportError(errorCodeToError(object_error::parse_failed),1484 Obj->getFileName());1485 1486 return unwrapOrError(Obj->getFileName(),1487 CVStringTable.getString(Iter->FileNameOffset));1488}1489 1490void COFFDumper::printFileNameForOffset(StringRef Label, uint32_t FileOffset) {1491 W.printHex(Label, getFileNameForFileOffset(FileOffset), FileOffset);1492}1493 1494void COFFDumper::mergeCodeViewTypes(MergingTypeTableBuilder &CVIDs,1495 MergingTypeTableBuilder &CVTypes,1496 GlobalTypeTableBuilder &GlobalCVIDs,1497 GlobalTypeTableBuilder &GlobalCVTypes,1498 bool GHash) {1499 for (const SectionRef &S : Obj->sections()) {1500 StringRef SectionName = unwrapOrError(Obj->getFileName(), S.getName());1501 if (SectionName == ".debug$T") {1502 StringRef Data = unwrapOrError(Obj->getFileName(), S.getContents());1503 uint32_t Magic;1504 if (Error E = consume(Data, Magic))1505 reportError(std::move(E), Obj->getFileName());1506 1507 if (Magic != 4)1508 reportError(errorCodeToError(object_error::parse_failed),1509 Obj->getFileName());1510 1511 CVTypeArray Types;1512 BinaryStreamReader Reader(Data, llvm::endianness::little);1513 if (auto EC = Reader.readArray(Types, Reader.getLength())) {1514 consumeError(std::move(EC));1515 W.flush();1516 reportError(errorCodeToError(object_error::parse_failed),1517 Obj->getFileName());1518 }1519 SmallVector<TypeIndex, 128> SourceToDest;1520 std::optional<PCHMergerInfo> PCHInfo;1521 if (GHash) {1522 std::vector<GloballyHashedType> Hashes =1523 GloballyHashedType::hashTypes(Types);1524 if (Error E =1525 mergeTypeAndIdRecords(GlobalCVIDs, GlobalCVTypes, SourceToDest,1526 Types, Hashes, PCHInfo))1527 return reportError(std::move(E), Obj->getFileName());1528 } else {1529 if (Error E = mergeTypeAndIdRecords(CVIDs, CVTypes, SourceToDest, Types,1530 PCHInfo))1531 return reportError(std::move(E), Obj->getFileName());1532 }1533 }1534 }1535}1536 1537void COFFDumper::printCodeViewTypeSection(StringRef SectionName,1538 const SectionRef &Section) {1539 ListScope D(W, "CodeViewTypes");1540 W.printNumber("Section", SectionName, Obj->getSectionID(Section));1541 1542 StringRef Data = unwrapOrError(Obj->getFileName(), Section.getContents());1543 if (opts::CodeViewSubsectionBytes)1544 W.printBinaryBlock("Data", Data);1545 1546 uint32_t Magic;1547 if (Error E = consume(Data, Magic))1548 reportError(std::move(E), Obj->getFileName());1549 1550 W.printHex("Magic", Magic);1551 if (Magic != COFF::DEBUG_SECTION_MAGIC)1552 reportError(errorCodeToError(object_error::parse_failed),1553 Obj->getFileName());1554 1555 Types.reset(Data, 100);1556 1557 TypeDumpVisitor TDV(Types, &W, opts::CodeViewSubsectionBytes);1558 if (Error E = codeview::visitTypeStream(Types, TDV))1559 reportError(std::move(E), Obj->getFileName());1560 1561 W.flush();1562}1563 1564void COFFDumper::printSectionHeaders() {1565 ListScope SectionsD(W, "Sections");1566 int SectionNumber = 0;1567 for (const SectionRef &Sec : Obj->sections()) {1568 ++SectionNumber;1569 const coff_section *Section = Obj->getCOFFSection(Sec);1570 1571 StringRef Name = unwrapOrError(Obj->getFileName(), Sec.getName());1572 1573 DictScope D(W, "Section");1574 W.printNumber("Number", SectionNumber);1575 W.printBinary("Name", Name, Section->Name);1576 W.printHex ("VirtualSize", Section->VirtualSize);1577 W.printHex ("VirtualAddress", Section->VirtualAddress);1578 W.printNumber("RawDataSize", Section->SizeOfRawData);1579 W.printHex ("PointerToRawData", Section->PointerToRawData);1580 W.printHex ("PointerToRelocations", Section->PointerToRelocations);1581 W.printHex ("PointerToLineNumbers", Section->PointerToLinenumbers);1582 W.printNumber("RelocationCount", Section->NumberOfRelocations);1583 W.printNumber("LineNumberCount", Section->NumberOfLinenumbers);1584 W.printFlags("Characteristics", Section->Characteristics,1585 ArrayRef(ImageSectionCharacteristics),1586 COFF::SectionCharacteristics(0x00F00000));1587 1588 if (opts::SectionRelocations) {1589 ListScope D(W, "Relocations");1590 for (const RelocationRef &Reloc : Sec.relocations())1591 printRelocation(Sec, Reloc);1592 }1593 1594 if (opts::SectionSymbols) {1595 ListScope D(W, "Symbols");1596 for (const SymbolRef &Symbol : Obj->symbols()) {1597 if (!Sec.containsSymbol(Symbol))1598 continue;1599 1600 printSymbol(Symbol);1601 }1602 }1603 1604 if (opts::SectionData &&1605 !(Section->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) {1606 StringRef Data = unwrapOrError(Obj->getFileName(), Sec.getContents());1607 W.printBinaryBlock("SectionData", Data);1608 }1609 }1610}1611 1612void COFFDumper::printRelocations() {1613 ListScope D(W, "Relocations");1614 1615 int SectionNumber = 0;1616 for (const SectionRef &Section : Obj->sections()) {1617 ++SectionNumber;1618 StringRef Name = unwrapOrError(Obj->getFileName(), Section.getName());1619 1620 bool PrintedGroup = false;1621 for (const RelocationRef &Reloc : Section.relocations()) {1622 if (!PrintedGroup) {1623 W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";1624 W.indent();1625 PrintedGroup = true;1626 }1627 1628 printRelocation(Section, Reloc);1629 }1630 1631 if (PrintedGroup) {1632 W.unindent();1633 W.startLine() << "}\n";1634 }1635 }1636}1637 1638void COFFDumper::printRelocation(const SectionRef &Section,1639 const RelocationRef &Reloc, uint64_t Bias) {1640 uint64_t Offset = Reloc.getOffset() - Bias;1641 uint64_t RelocType = Reloc.getType();1642 SmallString<32> RelocName;1643 StringRef SymbolName;1644 Reloc.getTypeName(RelocName);1645 symbol_iterator Symbol = Reloc.getSymbol();1646 int64_t SymbolIndex = -1;1647 if (Symbol != Obj->symbol_end()) {1648 Expected<StringRef> SymbolNameOrErr = Symbol->getName();1649 if (!SymbolNameOrErr)1650 reportError(SymbolNameOrErr.takeError(), Obj->getFileName());1651 1652 SymbolName = *SymbolNameOrErr;1653 SymbolIndex = Obj->getSymbolIndex(Obj->getCOFFSymbol(*Symbol));1654 }1655 1656 if (opts::ExpandRelocs) {1657 DictScope Group(W, "Relocation");1658 W.printHex("Offset", Offset);1659 W.printNumber("Type", RelocName, RelocType);1660 W.printString("Symbol", SymbolName.empty() ? "-" : SymbolName);1661 W.printNumber("SymbolIndex", SymbolIndex);1662 } else {1663 raw_ostream& OS = W.startLine();1664 OS << W.hex(Offset)1665 << " " << RelocName1666 << " " << (SymbolName.empty() ? "-" : SymbolName)1667 << " (" << SymbolIndex << ")"1668 << "\n";1669 }1670}1671 1672void COFFDumper::printSymbols(bool /*ExtraSymInfo*/) {1673 ListScope Group(W, "Symbols");1674 1675 for (const SymbolRef &Symbol : Obj->symbols())1676 printSymbol(Symbol);1677}1678 1679void COFFDumper::printDynamicSymbols() { ListScope Group(W, "DynamicSymbols"); }1680 1681static Expected<StringRef>1682getSectionName(const llvm::object::COFFObjectFile *Obj, int32_t SectionNumber,1683 const coff_section *Section) {1684 if (Section)1685 return Obj->getSectionName(Section);1686 if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG)1687 return StringRef("IMAGE_SYM_DEBUG");1688 if (SectionNumber == llvm::COFF::IMAGE_SYM_ABSOLUTE)1689 return StringRef("IMAGE_SYM_ABSOLUTE");1690 if (SectionNumber == llvm::COFF::IMAGE_SYM_UNDEFINED)1691 return StringRef("IMAGE_SYM_UNDEFINED");1692 return StringRef("");1693}1694 1695void COFFDumper::printSymbol(const SymbolRef &Sym) {1696 DictScope D(W, "Symbol");1697 1698 COFFSymbolRef Symbol = Obj->getCOFFSymbol(Sym);1699 Expected<const coff_section *> SecOrErr =1700 Obj->getSection(Symbol.getSectionNumber());1701 if (!SecOrErr) {1702 W.startLine() << "Invalid section number: " << Symbol.getSectionNumber()1703 << "\n";1704 W.flush();1705 consumeError(SecOrErr.takeError());1706 return;1707 }1708 const coff_section *Section = *SecOrErr;1709 1710 StringRef SymbolName;1711 if (Expected<StringRef> SymNameOrErr = Obj->getSymbolName(Symbol))1712 SymbolName = *SymNameOrErr;1713 1714 StringRef SectionName;1715 if (Expected<StringRef> SecNameOrErr =1716 getSectionName(Obj, Symbol.getSectionNumber(), Section))1717 SectionName = *SecNameOrErr;1718 1719 W.printString("Name", SymbolName);1720 W.printNumber("Value", Symbol.getValue());1721 W.printNumber("Section", SectionName, Symbol.getSectionNumber());1722 W.printEnum("BaseType", Symbol.getBaseType(), ArrayRef(ImageSymType));1723 W.printEnum("ComplexType", Symbol.getComplexType(), ArrayRef(ImageSymDType));1724 W.printEnum("StorageClass", Symbol.getStorageClass(),1725 ArrayRef(ImageSymClass));1726 W.printNumber("AuxSymbolCount", Symbol.getNumberOfAuxSymbols());1727 1728 for (uint8_t I = 0; I < Symbol.getNumberOfAuxSymbols(); ++I) {1729 if (Symbol.isFunctionDefinition()) {1730 const coff_aux_function_definition *Aux;1731 if (std::error_code EC = getSymbolAuxData(Obj, Symbol, I, Aux))1732 reportError(errorCodeToError(EC), Obj->getFileName());1733 1734 DictScope AS(W, "AuxFunctionDef");1735 W.printNumber("TagIndex", Aux->TagIndex);1736 W.printNumber("TotalSize", Aux->TotalSize);1737 W.printHex("PointerToLineNumber", Aux->PointerToLinenumber);1738 W.printHex("PointerToNextFunction", Aux->PointerToNextFunction);1739 1740 } else if (Symbol.isAnyUndefined()) {1741 const coff_aux_weak_external *Aux;1742 if (std::error_code EC = getSymbolAuxData(Obj, Symbol, I, Aux))1743 reportError(errorCodeToError(EC), Obj->getFileName());1744 1745 DictScope AS(W, "AuxWeakExternal");1746 W.printNumber("Linked", getSymbolName(Aux->TagIndex), Aux->TagIndex);1747 W.printEnum("Search", Aux->Characteristics,1748 ArrayRef(WeakExternalCharacteristics));1749 1750 } else if (Symbol.isFileRecord()) {1751 const char *FileName;1752 if (std::error_code EC = getSymbolAuxData(Obj, Symbol, I, FileName))1753 reportError(errorCodeToError(EC), Obj->getFileName());1754 DictScope AS(W, "AuxFileRecord");1755 1756 StringRef Name(FileName, Symbol.getNumberOfAuxSymbols() *1757 Obj->getSymbolTableEntrySize());1758 W.printString("FileName", Name.rtrim(StringRef("\0", 1)));1759 break;1760 } else if (Symbol.isSectionDefinition()) {1761 const coff_aux_section_definition *Aux;1762 if (std::error_code EC = getSymbolAuxData(Obj, Symbol, I, Aux))1763 reportError(errorCodeToError(EC), Obj->getFileName());1764 1765 int32_t AuxNumber = Aux->getNumber(Symbol.isBigObj());1766 1767 DictScope AS(W, "AuxSectionDef");1768 W.printNumber("Length", Aux->Length);1769 W.printNumber("RelocationCount", Aux->NumberOfRelocations);1770 W.printNumber("LineNumberCount", Aux->NumberOfLinenumbers);1771 W.printHex("Checksum", Aux->CheckSum);1772 W.printNumber("Number", AuxNumber);1773 W.printEnum("Selection", Aux->Selection, ArrayRef(ImageCOMDATSelect));1774 1775 if (Section && Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT1776 && Aux->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {1777 Expected<const coff_section *> Assoc = Obj->getSection(AuxNumber);1778 if (!Assoc)1779 reportError(Assoc.takeError(), Obj->getFileName());1780 Expected<StringRef> AssocName = getSectionName(Obj, AuxNumber, *Assoc);1781 if (!AssocName)1782 reportError(AssocName.takeError(), Obj->getFileName());1783 1784 W.printNumber("AssocSection", *AssocName, AuxNumber);1785 }1786 } else if (Symbol.isCLRToken()) {1787 const coff_aux_clr_token *Aux;1788 if (std::error_code EC = getSymbolAuxData(Obj, Symbol, I, Aux))1789 reportError(errorCodeToError(EC), Obj->getFileName());1790 1791 DictScope AS(W, "AuxCLRToken");1792 W.printNumber("AuxType", Aux->AuxType);1793 W.printNumber("Reserved", Aux->Reserved);1794 W.printNumber("SymbolTableIndex", getSymbolName(Aux->SymbolTableIndex),1795 Aux->SymbolTableIndex);1796 1797 } else {1798 W.startLine() << "<unhandled auxiliary record>\n";1799 }1800 }1801}1802 1803void COFFDumper::printUnwindInfo() {1804 ListScope D(W, "UnwindInformation");1805 switch (Obj->getMachine()) {1806 case COFF::IMAGE_FILE_MACHINE_AMD64: {1807 Win64EH::Dumper Dumper(W);1808 Win64EH::Dumper::SymbolResolver1809 Resolver = [](const object::coff_section *Section, uint64_t Offset,1810 SymbolRef &Symbol, void *user_data) -> std::error_code {1811 COFFDumper *Dumper = reinterpret_cast<COFFDumper *>(user_data);1812 return Dumper->resolveSymbol(Section, Offset, Symbol);1813 };1814 Win64EH::Dumper::Context Ctx(*Obj, Resolver, this);1815 Dumper.printData(Ctx);1816 break;1817 }1818 case COFF::IMAGE_FILE_MACHINE_ARM64:1819 case COFF::IMAGE_FILE_MACHINE_ARM64EC:1820 case COFF::IMAGE_FILE_MACHINE_ARM64X:1821 case COFF::IMAGE_FILE_MACHINE_ARMNT: {1822 ARM::WinEH::Decoder Decoder(W, Obj->getMachine() !=1823 COFF::IMAGE_FILE_MACHINE_ARMNT);1824 // TODO Propagate the error.1825 consumeError(Decoder.dumpProcedureData(*Obj));1826 break;1827 }1828 default:1829 W.printEnum("unsupported Image Machine", Obj->getMachine(),1830 ArrayRef(ImageFileMachineType));1831 break;1832 }1833}1834 1835void COFFDumper::printNeededLibraries() {1836 ListScope D(W, "NeededLibraries");1837 1838 using LibsTy = std::vector<StringRef>;1839 LibsTy Libs;1840 1841 for (const ImportDirectoryEntryRef &DirRef : Obj->import_directories()) {1842 StringRef Name;1843 if (!DirRef.getName(Name))1844 Libs.push_back(Name);1845 }1846 1847 llvm::stable_sort(Libs);1848 1849 for (const auto &L : Libs) {1850 W.startLine() << L << "\n";1851 }1852}1853 1854void COFFDumper::printImportedSymbols(1855 iterator_range<imported_symbol_iterator> Range) {1856 for (const ImportedSymbolRef &I : Range) {1857 StringRef Sym;1858 if (Error E = I.getSymbolName(Sym))1859 reportError(std::move(E), Obj->getFileName());1860 uint16_t Ordinal;1861 if (Error E = I.getOrdinal(Ordinal))1862 reportError(std::move(E), Obj->getFileName());1863 W.printNumber("Symbol", Sym, Ordinal);1864 }1865}1866 1867void COFFDumper::printDelayImportedSymbols(1868 const DelayImportDirectoryEntryRef &I,1869 iterator_range<imported_symbol_iterator> Range) {1870 int Index = 0;1871 for (const ImportedSymbolRef &S : Range) {1872 DictScope Import(W, "Import");1873 StringRef Sym;1874 if (Error E = S.getSymbolName(Sym))1875 reportError(std::move(E), Obj->getFileName());1876 1877 uint16_t Ordinal;1878 if (Error E = S.getOrdinal(Ordinal))1879 reportError(std::move(E), Obj->getFileName());1880 W.printNumber("Symbol", Sym, Ordinal);1881 1882 uint64_t Addr;1883 if (Error E = I.getImportAddress(Index++, Addr))1884 reportError(std::move(E), Obj->getFileName());1885 W.printHex("Address", Addr);1886 }1887}1888 1889void COFFDumper::printCOFFImports() {1890 // Regular imports1891 for (const ImportDirectoryEntryRef &I : Obj->import_directories()) {1892 DictScope Import(W, "Import");1893 StringRef Name;1894 if (Error E = I.getName(Name))1895 reportError(std::move(E), Obj->getFileName());1896 W.printString("Name", Name);1897 uint32_t ILTAddr;1898 if (Error E = I.getImportLookupTableRVA(ILTAddr))1899 reportError(std::move(E), Obj->getFileName());1900 W.printHex("ImportLookupTableRVA", ILTAddr);1901 uint32_t IATAddr;1902 if (Error E = I.getImportAddressTableRVA(IATAddr))1903 reportError(std::move(E), Obj->getFileName());1904 W.printHex("ImportAddressTableRVA", IATAddr);1905 // The import lookup table can be missing with certain older linkers, so1906 // fall back to the import address table in that case.1907 if (ILTAddr)1908 printImportedSymbols(I.lookup_table_symbols());1909 else1910 printImportedSymbols(I.imported_symbols());1911 }1912 1913 // Delay imports1914 for (const DelayImportDirectoryEntryRef &I : Obj->delay_import_directories()) {1915 DictScope Import(W, "DelayImport");1916 StringRef Name;1917 if (Error E = I.getName(Name))1918 reportError(std::move(E), Obj->getFileName());1919 W.printString("Name", Name);1920 const delay_import_directory_table_entry *Table;1921 if (Error E = I.getDelayImportTable(Table))1922 reportError(std::move(E), Obj->getFileName());1923 W.printHex("Attributes", Table->Attributes);1924 W.printHex("ModuleHandle", Table->ModuleHandle);1925 W.printHex("ImportAddressTable", Table->DelayImportAddressTable);1926 W.printHex("ImportNameTable", Table->DelayImportNameTable);1927 W.printHex("BoundDelayImportTable", Table->BoundDelayImportTable);1928 W.printHex("UnloadDelayImportTable", Table->UnloadDelayImportTable);1929 printDelayImportedSymbols(I, I.imported_symbols());1930 }1931}1932 1933void COFFDumper::printCOFFExports() {1934 for (const ExportDirectoryEntryRef &Exp : Obj->export_directories()) {1935 DictScope Export(W, "Export");1936 1937 StringRef Name;1938 uint32_t Ordinal;1939 bool IsForwarder;1940 1941 if (Error E = Exp.getSymbolName(Name))1942 reportError(std::move(E), Obj->getFileName());1943 if (Error E = Exp.getOrdinal(Ordinal))1944 reportError(std::move(E), Obj->getFileName());1945 if (Error E = Exp.isForwarder(IsForwarder))1946 reportError(std::move(E), Obj->getFileName());1947 1948 W.printNumber("Ordinal", Ordinal);1949 W.printString("Name", Name);1950 StringRef ForwardTo;1951 if (IsForwarder) {1952 if (Error E = Exp.getForwardTo(ForwardTo))1953 reportError(std::move(E), Obj->getFileName());1954 W.printString("ForwardedTo", ForwardTo);1955 } else {1956 uint32_t RVA;1957 if (Error E = Exp.getExportRVA(RVA))1958 reportError(std::move(E), Obj->getFileName());1959 W.printHex("RVA", RVA);1960 }1961 }1962}1963 1964void COFFDumper::printCOFFDirectives() {1965 for (const SectionRef &Section : Obj->sections()) {1966 StringRef Name = unwrapOrError(Obj->getFileName(), Section.getName());1967 if (Name != ".drectve")1968 continue;1969 1970 StringRef Contents =1971 unwrapOrError(Obj->getFileName(), Section.getContents());1972 W.printString("Directive(s)", Contents);1973 }1974}1975 1976static std::string getBaseRelocTypeName(uint8_t Type) {1977 switch (Type) {1978 case COFF::IMAGE_REL_BASED_ABSOLUTE: return "ABSOLUTE";1979 case COFF::IMAGE_REL_BASED_HIGH: return "HIGH";1980 case COFF::IMAGE_REL_BASED_LOW: return "LOW";1981 case COFF::IMAGE_REL_BASED_HIGHLOW: return "HIGHLOW";1982 case COFF::IMAGE_REL_BASED_HIGHADJ: return "HIGHADJ";1983 case COFF::IMAGE_REL_BASED_ARM_MOV32T: return "ARM_MOV32(T)";1984 case COFF::IMAGE_REL_BASED_DIR64: return "DIR64";1985 default: return "unknown (" + llvm::utostr(Type) + ")";1986 }1987}1988 1989void COFFDumper::printCOFFBaseReloc() {1990 ListScope D(W, "BaseReloc");1991 for (const BaseRelocRef &I : Obj->base_relocs()) {1992 uint8_t Type;1993 uint32_t RVA;1994 if (Error E = I.getRVA(RVA))1995 reportError(std::move(E), Obj->getFileName());1996 if (Error E = I.getType(Type))1997 reportError(std::move(E), Obj->getFileName());1998 DictScope Import(W, "Entry");1999 W.printString("Type", getBaseRelocTypeName(Type));2000 W.printHex("Address", RVA);2001 }2002}2003 2004void COFFDumper::printCOFFPseudoReloc() {2005 ListScope D(W, "PseudoReloc");2006 2007 // Pseudo-relocations are only meaningful with PE image files.2008 if (!Obj->getDOSHeader())2009 return;2010 2011 const StringRef RelocBeginName = Obj->getArch() == Triple::x862012 ? "___RUNTIME_PSEUDO_RELOC_LIST__"2013 : "__RUNTIME_PSEUDO_RELOC_LIST__";2014 const StringRef RelocEndName = Obj->getArch() == Triple::x862015 ? "___RUNTIME_PSEUDO_RELOC_LIST_END__"2016 : "__RUNTIME_PSEUDO_RELOC_LIST_END__";2017 2018 const uint32_t Count = Obj->getNumberOfSymbols();2019 // Skip if no symbol was found (maybe stripped).2020 if (Count == 0)2021 return;2022 2023 struct SymbolEntry {2024 uint32_t RVA;2025 COFFSymbolRef Symbol;2026 const coff_section *Section;2027 StringRef SymbolName;2028 };2029 SmallVector<SymbolEntry> RVASymbolMap;2030 COFFSymbolRef RelocBegin, RelocEnd;2031 for (uint32_t i = 0; i < Count; ++i) {2032 COFFSymbolRef Sym;2033 if (Expected<COFFSymbolRef> SymOrErr = Obj->getSymbol(i)) {2034 Sym = *SymOrErr;2035 } else {2036 reportUniqueWarning(SymOrErr.takeError());2037 continue;2038 }2039 2040 i += Sym.getNumberOfAuxSymbols();2041 2042 if (Sym.getSectionNumber() <= 0)2043 continue;2044 2045 StringRef Name;2046 if (Expected<StringRef> NameOrErr = Obj->getSymbolName(Sym)) {2047 Name = *NameOrErr;2048 } else {2049 reportUniqueWarning(NameOrErr.takeError());2050 continue;2051 }2052 2053 if (Name == RelocBeginName)2054 RelocBegin = Sym;2055 else if (Name == RelocEndName)2056 RelocEnd = Sym;2057 2058 const coff_section *Sec = nullptr;2059 if (Expected<const coff_section *> SecOrErr =2060 Obj->getSection(Sym.getSectionNumber())) {2061 Sec = *SecOrErr;2062 } else {2063 reportUniqueWarning(SecOrErr.takeError());2064 continue;2065 }2066 2067 RVASymbolMap.push_back(2068 {Sec->VirtualAddress + Sym.getValue(), Sym, Sec, Name});2069 }2070 2071 if (!RelocBegin.getRawPtr() || !RelocEnd.getRawPtr()) {2072 reportUniqueWarning(createStringError(2073 "the marker symbols for runtime pseudo-relocation were not found"));2074 return;2075 }2076 2077 const coff_section *Section = nullptr;2078 if (Expected<const coff_section *> SecOrErr =2079 Obj->getSection(RelocBegin.getSectionNumber())) {2080 Section = *SecOrErr;2081 } else {2082 reportUniqueWarning(SecOrErr.takeError());2083 return;2084 }2085 2086 if (RelocBegin.getSectionNumber() != RelocEnd.getSectionNumber()) {2087 reportUniqueWarning(createStringError(2088 "the end marker symbol for runtime pseudo-relocation must "2089 "point to the same section where the begin marker points to: "2090 "expected %d, but got %d",2091 RelocBegin.getSectionNumber(), RelocEnd.getSectionNumber()));2092 return;2093 }2094 2095 // Skip if the relocation list is empty.2096 if (RelocBegin.getValue() == RelocEnd.getValue())2097 return;2098 2099 if (RelocEnd.getValue() < RelocBegin.getValue()) {2100 reportUniqueWarning(createStringError(2101 "the end marker symbol for runtime pseudo-relocation must point "2102 "to a higher address than where the begin marker points to: "2103 "expected >=0x%x, but got 0x%x",2104 RelocBegin.getValue(), RelocEnd.getValue()));2105 return;2106 }2107 2108 ArrayRef<uint8_t> Data;2109 if (auto E = Obj->getSectionContents(Section, Data)) {2110 reportUniqueWarning(std::move(E));2111 return;2112 }2113 2114 if (const uint32_t Begin = RelocBegin.getValue(), End = RelocEnd.getValue();2115 Begin >= Data.size() || End > Data.size()) {2116 reportUniqueWarning(2117 createStringError("the marker symbol of runtime pseudo-relocation "2118 "points past the end of the section 0x%x: got 0x%x",2119 Data.size(), Begin >= Data.size() ? Begin : End));2120 return;2121 }2122 2123 const ArrayRef<uint8_t> RawRelocs =2124 Data.take_front(RelocEnd.getValue()).drop_front(RelocBegin.getValue());2125 struct alignas(4) PseudoRelocationHeader {2126 PseudoRelocationHeader(uint32_t Signature)2127 : Zero1(0), Zero2(0), Signature(Signature) {}2128 support::ulittle32_t Zero1;2129 support::ulittle32_t Zero2;2130 support::ulittle32_t Signature;2131 };2132 const PseudoRelocationHeader HeaderV2(1);2133 if (RawRelocs.size() < sizeof(HeaderV2) ||2134 (memcmp(RawRelocs.data(), &HeaderV2, sizeof(HeaderV2)) != 0)) {2135 reportUniqueWarning(2136 createStringError("invalid runtime pseudo-relocation records"));2137 return;2138 }2139 2140 struct alignas(4) PseudoRelocationRecord {2141 support::ulittle32_t Symbol;2142 support::ulittle32_t Target;2143 support::ulittle32_t BitSize;2144 };2145 ArrayRef<PseudoRelocationRecord> RelocRecords(2146 reinterpret_cast<const PseudoRelocationRecord *>(2147 RawRelocs.data() + sizeof(PseudoRelocationHeader)),2148 (RawRelocs.size() - sizeof(PseudoRelocationHeader)) /2149 sizeof(PseudoRelocationRecord));2150 2151 struct CachingImportedSymbolLookup {2152 struct SizedImportDirectoryEntry {2153 uint32_t StartRVA;2154 uint32_t EndRVA;2155 ImportDirectoryEntryRef EntryRef;2156 };2157 2158 CachingImportedSymbolLookup(const COFFObjectFile *Obj) : Obj(Obj) {2159 for (auto D : Obj->import_directories()) {2160 auto &Entry = ImportDirectories.emplace_back();2161 Entry.EntryRef = D;2162 Entry.EndRVA = 0;2163 if (auto E = D.getImportAddressTableRVA(Entry.StartRVA))2164 reportError(std::move(E), Obj->getFileName());2165 }2166 if (ImportDirectories.empty())2167 return;2168 llvm::sort(ImportDirectories, [](const auto &x, const auto &y) {2169 return x.StartRVA < y.StartRVA;2170 });2171 }2172 2173 Expected<StringRef> find(COFFDumper *Self, uint32_t EntryRVA) {2174 static constexpr char Msg[] =2175 "the address referenced by pseudo-relocation is not a valid import "2176 "entry: 0x%x";2177 if (auto Ite = ImportedSymbols.find(EntryRVA);2178 Ite != ImportedSymbols.end())2179 return Ite->second;2180 2181 auto Ite = llvm::upper_bound(2182 ImportDirectories, EntryRVA,2183 [](uint32_t RVA, const auto &D) { return RVA < D.StartRVA; });2184 if (Ite == ImportDirectories.begin())2185 return createStringError(Msg, EntryRVA);2186 2187 --Ite;2188 uint32_t RVA = Ite->StartRVA;2189 if (Ite->EndRVA != 0 && Ite->EndRVA <= RVA)2190 return createStringError(Msg, EntryRVA);2191 // Search with linear iteration to care if padding or garbage exist2192 // between ImportDirectoryEntry.2193 for (auto S : Ite->EntryRef.imported_symbols()) {2194 if (RVA == EntryRVA) {2195 StringRef &NameDst = ImportedSymbols[RVA];2196 if (auto E = S.getSymbolName(NameDst)) {2197 Self->reportUniqueWarning(std::move(E));2198 NameDst = "(no symbol)";2199 }2200 return NameDst;2201 }2202 RVA += Obj->is64() ? 8 : 4;2203 if (EntryRVA < RVA)2204 return createStringError(Msg, EntryRVA);2205 }2206 Ite->EndRVA = RVA;2207 2208 return createStringError(Msg, EntryRVA);2209 }2210 2211 private:2212 const COFFObjectFile *Obj;2213 SmallVector<SizedImportDirectoryEntry> ImportDirectories;2214 DenseMap<uint32_t, StringRef> ImportedSymbols;2215 };2216 CachingImportedSymbolLookup ImportedSymbols(Obj);2217 llvm::stable_sort(RVASymbolMap,2218 [](const auto &x, const auto &y) { return x.RVA < y.RVA; });2219 RVASymbolMap.erase(2220 llvm::unique(RVASymbolMap,2221 [](const auto &x, const auto &y) { return x.RVA == y.RVA; }),2222 RVASymbolMap.end());2223 2224 for (const auto &Reloc : RelocRecords) {2225 DictScope Entry(W, "Entry");2226 2227 W.printHex("Symbol", Reloc.Symbol);2228 if (Expected<StringRef> SymOrErr =2229 ImportedSymbols.find(this, Reloc.Symbol)) {2230 W.printString("SymbolName", *SymOrErr);2231 } else {2232 reportUniqueWarning(SymOrErr.takeError());2233 W.printString("SymbolName", "(missing)");2234 }2235 2236 W.printHex("Target", Reloc.Target);2237 if (auto Ite = llvm::upper_bound(2238 RVASymbolMap, Reloc.Target.value(),2239 [](uint32_t RVA, const auto &Sym) { return RVA < Sym.RVA; });2240 Ite == RVASymbolMap.begin()) {2241 W.printSymbolOffset("TargetSymbol", "(base)", Reloc.Target);2242 } else if (const uint32_t Offset = Reloc.Target.value() - (--Ite)->RVA;2243 Offset == 0) {2244 W.printString("TargetSymbol", Ite->SymbolName);2245 } else if (Offset < Ite->Section->VirtualSize) {2246 W.printSymbolOffset("TargetSymbol", Ite->SymbolName, Offset);2247 } else if (++Ite == RVASymbolMap.end()) {2248 W.printSymbolOffset("TargetSymbol", "(base)", Reloc.Target);2249 } else if (Expected<StringRef> NameOrErr =2250 Obj->getSectionName(Ite->Section)) {2251 W.printSymbolOffset("TargetSymbol", *NameOrErr,2252 Reloc.Target - Ite->Section->VirtualAddress);2253 } else {2254 reportUniqueWarning(NameOrErr.takeError());2255 W.printSymbolOffset("TargetSymbol", "(base)", Reloc.Target);2256 }2257 2258 W.printNumber("BitWidth", Reloc.BitSize);2259 }2260}2261 2262void COFFDumper::printCOFFResources() {2263 ListScope ResourcesD(W, "Resources");2264 for (const SectionRef &S : Obj->sections()) {2265 StringRef Name = unwrapOrError(Obj->getFileName(), S.getName());2266 if (!Name.starts_with(".rsrc"))2267 continue;2268 2269 StringRef Ref = unwrapOrError(Obj->getFileName(), S.getContents());2270 2271 if ((Name == ".rsrc") || (Name == ".rsrc$01")) {2272 ResourceSectionRef RSF;2273 Error E = RSF.load(Obj, S);2274 if (E)2275 reportError(std::move(E), Obj->getFileName());2276 auto &BaseTable = unwrapOrError(Obj->getFileName(), RSF.getBaseTable());2277 W.printNumber("Total Number of Resources",2278 countTotalTableEntries(RSF, BaseTable, "Type"));2279 W.printHex("Base Table Address",2280 Obj->getCOFFSection(S)->PointerToRawData);2281 W.startLine() << "\n";2282 printResourceDirectoryTable(RSF, BaseTable, "Type");2283 }2284 if (opts::SectionData)2285 W.printBinaryBlock(Name.str() + " Data", Ref);2286 }2287}2288 2289uint32_t2290COFFDumper::countTotalTableEntries(ResourceSectionRef RSF,2291 const coff_resource_dir_table &Table,2292 StringRef Level) {2293 uint32_t TotalEntries = 0;2294 for (int i = 0; i < Table.NumberOfNameEntries + Table.NumberOfIDEntries;2295 i++) {2296 auto Entry = unwrapOrError(Obj->getFileName(), RSF.getTableEntry(Table, i));2297 if (Entry.Offset.isSubDir()) {2298 StringRef NextLevel;2299 if (Level == "Name")2300 NextLevel = "Language";2301 else2302 NextLevel = "Name";2303 auto &NextTable =2304 unwrapOrError(Obj->getFileName(), RSF.getEntrySubDir(Entry));2305 TotalEntries += countTotalTableEntries(RSF, NextTable, NextLevel);2306 } else {2307 TotalEntries += 1;2308 }2309 }2310 return TotalEntries;2311}2312 2313void COFFDumper::printResourceDirectoryTable(2314 ResourceSectionRef RSF, const coff_resource_dir_table &Table,2315 StringRef Level) {2316 2317 W.printNumber("Number of String Entries", Table.NumberOfNameEntries);2318 W.printNumber("Number of ID Entries", Table.NumberOfIDEntries);2319 2320 // Iterate through level in resource directory tree.2321 for (int i = 0; i < Table.NumberOfNameEntries + Table.NumberOfIDEntries;2322 i++) {2323 auto Entry = unwrapOrError(Obj->getFileName(), RSF.getTableEntry(Table, i));2324 StringRef Name;2325 SmallString<20> IDStr;2326 raw_svector_ostream OS(IDStr);2327 if (i < Table.NumberOfNameEntries) {2328 ArrayRef<UTF16> RawEntryNameString =2329 unwrapOrError(Obj->getFileName(), RSF.getEntryNameString(Entry));2330 std::vector<UTF16> EndianCorrectedNameString;2331 if (llvm::sys::IsBigEndianHost) {2332 EndianCorrectedNameString.resize(RawEntryNameString.size() + 1);2333 llvm::copy(RawEntryNameString, EndianCorrectedNameString.begin() + 1);2334 EndianCorrectedNameString[0] = UNI_UTF16_BYTE_ORDER_MARK_SWAPPED;2335 RawEntryNameString = ArrayRef(EndianCorrectedNameString);2336 }2337 std::string EntryNameString;2338 if (!llvm::convertUTF16ToUTF8String(RawEntryNameString, EntryNameString))2339 reportError(errorCodeToError(object_error::parse_failed),2340 Obj->getFileName());2341 OS << ": ";2342 OS << EntryNameString;2343 } else {2344 if (Level == "Type") {2345 OS << ": ";2346 printResourceTypeName(Entry.Identifier.ID, OS);2347 } else {2348 OS << ": (ID " << Entry.Identifier.ID << ")";2349 }2350 }2351 Name = IDStr;2352 ListScope ResourceType(W, Level.str() + Name.str());2353 if (Entry.Offset.isSubDir()) {2354 W.printHex("Table Offset", Entry.Offset.value());2355 StringRef NextLevel;2356 if (Level == "Name")2357 NextLevel = "Language";2358 else2359 NextLevel = "Name";2360 auto &NextTable =2361 unwrapOrError(Obj->getFileName(), RSF.getEntrySubDir(Entry));2362 printResourceDirectoryTable(RSF, NextTable, NextLevel);2363 } else {2364 W.printHex("Entry Offset", Entry.Offset.value());2365 char FormattedTime[20] = {};2366 time_t TDS = time_t(Table.TimeDateStamp);2367 strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS));2368 W.printHex("Time/Date Stamp", FormattedTime, Table.TimeDateStamp);2369 W.printNumber("Major Version", Table.MajorVersion);2370 W.printNumber("Minor Version", Table.MinorVersion);2371 W.printNumber("Characteristics", Table.Characteristics);2372 ListScope DataScope(W, "Data");2373 auto &DataEntry =2374 unwrapOrError(Obj->getFileName(), RSF.getEntryData(Entry));2375 W.printHex("DataRVA", DataEntry.DataRVA);2376 W.printNumber("DataSize", DataEntry.DataSize);2377 W.printNumber("Codepage", DataEntry.Codepage);2378 W.printNumber("Reserved", DataEntry.Reserved);2379 StringRef Contents =2380 unwrapOrError(Obj->getFileName(), RSF.getContents(DataEntry));2381 W.printBinaryBlock("Data", Contents);2382 }2383 }2384}2385 2386void COFFDumper::printStackMap() const {2387 SectionRef StackMapSection;2388 for (auto Sec : Obj->sections()) {2389 StringRef Name;2390 if (Expected<StringRef> NameOrErr = Sec.getName())2391 Name = *NameOrErr;2392 else2393 consumeError(NameOrErr.takeError());2394 2395 if (Name == ".llvm_stackmaps") {2396 StackMapSection = Sec;2397 break;2398 }2399 }2400 2401 if (StackMapSection == SectionRef())2402 return;2403 2404 StringRef StackMapContents =2405 unwrapOrError(Obj->getFileName(), StackMapSection.getContents());2406 ArrayRef<uint8_t> StackMapContentsArray =2407 arrayRefFromStringRef(StackMapContents);2408 2409 if (Obj->isLittleEndian())2410 prettyPrintStackMap(2411 W, StackMapParser<llvm::endianness::little>(StackMapContentsArray));2412 else2413 prettyPrintStackMap(2414 W, StackMapParser<llvm::endianness::big>(StackMapContentsArray));2415}2416 2417void COFFDumper::printAddrsig() {2418 SectionRef AddrsigSection;2419 for (auto Sec : Obj->sections()) {2420 StringRef Name;2421 if (Expected<StringRef> NameOrErr = Sec.getName())2422 Name = *NameOrErr;2423 else2424 consumeError(NameOrErr.takeError());2425 2426 if (Name == ".llvm_addrsig") {2427 AddrsigSection = Sec;2428 break;2429 }2430 }2431 2432 if (AddrsigSection == SectionRef())2433 return;2434 2435 StringRef AddrsigContents =2436 unwrapOrError(Obj->getFileName(), AddrsigSection.getContents());2437 ArrayRef<uint8_t> AddrsigContentsArray(AddrsigContents.bytes_begin(),2438 AddrsigContents.size());2439 2440 ListScope L(W, "Addrsig");2441 const uint8_t *Cur = AddrsigContents.bytes_begin();2442 const uint8_t *End = AddrsigContents.bytes_end();2443 while (Cur != End) {2444 unsigned Size;2445 const char *Err = nullptr;2446 uint64_t SymIndex = decodeULEB128(Cur, &Size, End, &Err);2447 if (Err)2448 reportError(createError(Err), Obj->getFileName());2449 2450 W.printNumber("Sym", getSymbolName(SymIndex), SymIndex);2451 Cur += Size;2452 }2453}2454 2455void COFFDumper::printCGProfile() {2456 SectionRef CGProfileSection;2457 for (SectionRef Sec : Obj->sections()) {2458 StringRef Name = unwrapOrError(Obj->getFileName(), Sec.getName());2459 if (Name == ".llvm.call-graph-profile") {2460 CGProfileSection = Sec;2461 break;2462 }2463 }2464 2465 if (CGProfileSection == SectionRef())2466 return;2467 2468 StringRef CGProfileContents =2469 unwrapOrError(Obj->getFileName(), CGProfileSection.getContents());2470 BinaryStreamReader Reader(CGProfileContents, llvm::endianness::little);2471 2472 ListScope L(W, "CGProfile");2473 while (!Reader.empty()) {2474 uint32_t FromIndex, ToIndex;2475 uint64_t Count;2476 if (Error Err = Reader.readInteger(FromIndex))2477 reportError(std::move(Err), Obj->getFileName());2478 if (Error Err = Reader.readInteger(ToIndex))2479 reportError(std::move(Err), Obj->getFileName());2480 if (Error Err = Reader.readInteger(Count))2481 reportError(std::move(Err), Obj->getFileName());2482 2483 DictScope D(W, "CGProfileEntry");2484 W.printNumber("From", getSymbolName(FromIndex), FromIndex);2485 W.printNumber("To", getSymbolName(ToIndex), ToIndex);2486 W.printNumber("Weight", Count);2487 }2488}2489 2490void COFFDumper::printStringTable() {2491 DictScope DS(W, "StringTable");2492 StringRef StrTable = Obj->getStringTable();2493 uint32_t StrTabSize = StrTable.size();2494 W.printNumber("Length", StrTabSize);2495 // Print strings from the fifth byte, since the first four bytes contain the2496 // length (in bytes) of the string table (including the length field).2497 if (StrTabSize > 4)2498 printAsStringList(StrTable, 4);2499}2500 2501StringRef COFFDumper::getSymbolName(uint32_t Index) {2502 Expected<COFFSymbolRef> Sym = Obj->getSymbol(Index);2503 if (!Sym)2504 reportError(Sym.takeError(), Obj->getFileName());2505 2506 Expected<StringRef> SymName = Obj->getSymbolName(*Sym);2507 if (!SymName)2508 reportError(SymName.takeError(), Obj->getFileName());2509 2510 return *SymName;2511}2512 2513void llvm::dumpCodeViewMergedTypes(ScopedPrinter &Writer,2514 ArrayRef<ArrayRef<uint8_t>> IpiRecords,2515 ArrayRef<ArrayRef<uint8_t>> TpiRecords) {2516 TypeTableCollection TpiTypes(TpiRecords);2517 {2518 ListScope S(Writer, "MergedTypeStream");2519 TypeDumpVisitor TDV(TpiTypes, &Writer, opts::CodeViewSubsectionBytes);2520 if (Error Err = codeview::visitTypeStream(TpiTypes, TDV))2521 reportError(std::move(Err), "<?>");2522 Writer.flush();2523 }2524 2525 // Flatten the id stream and print it next. The ID stream refers to names from2526 // the type stream.2527 TypeTableCollection IpiTypes(IpiRecords);2528 {2529 ListScope S(Writer, "MergedIDStream");2530 TypeDumpVisitor TDV(TpiTypes, &Writer, opts::CodeViewSubsectionBytes);2531 TDV.setIpiTypes(IpiTypes);2532 if (Error Err = codeview::visitTypeStream(IpiTypes, TDV))2533 reportError(std::move(Err), "<?>");2534 Writer.flush();2535 }2536}2537 2538void COFFDumper::printCOFFTLSDirectory() {2539 if (Obj->is64())2540 printCOFFTLSDirectory(Obj->getTLSDirectory64());2541 else2542 printCOFFTLSDirectory(Obj->getTLSDirectory32());2543}2544 2545template <typename IntTy>2546void COFFDumper::printCOFFTLSDirectory(2547 const coff_tls_directory<IntTy> *TlsTable) {2548 DictScope D(W, "TLSDirectory");2549 if (!TlsTable)2550 return;2551 2552 W.printHex("StartAddressOfRawData", TlsTable->StartAddressOfRawData);2553 W.printHex("EndAddressOfRawData", TlsTable->EndAddressOfRawData);2554 W.printHex("AddressOfIndex", TlsTable->AddressOfIndex);2555 W.printHex("AddressOfCallBacks", TlsTable->AddressOfCallBacks);2556 W.printHex("SizeOfZeroFill", TlsTable->SizeOfZeroFill);2557 W.printFlags("Characteristics", TlsTable->Characteristics,2558 ArrayRef(ImageSectionCharacteristics),2559 COFF::SectionCharacteristics(COFF::IMAGE_SCN_ALIGN_MASK));2560}2561