brintos

brintos / llvm-project-archived public Read only

0
0
Text · 99.7 KiB · 55e106d Raw
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