Home | History | Annotate | Download | only in llvm-readobj
      1 //===-- COFFDumper.cpp - COFF-specific dumper -------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 /// \brief This file implements the COFF-specific dumper for llvm-readobj.
     12 ///
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "llvm-readobj.h"
     16 #include "ObjDumper.h"
     17 
     18 #include "Error.h"
     19 #include "StreamWriter.h"
     20 
     21 #include "llvm/ADT/DenseMap.h"
     22 #include "llvm/ADT/SmallString.h"
     23 #include "llvm/Object/COFF.h"
     24 #include "llvm/Object/ObjectFile.h"
     25 #include "llvm/Support/Casting.h"
     26 #include "llvm/Support/Compiler.h"
     27 #include "llvm/Support/Format.h"
     28 #include "llvm/Support/SourceMgr.h"
     29 #include "llvm/Support/Win64EH.h"
     30 #include "llvm/Support/raw_ostream.h"
     31 #include "llvm/Support/system_error.h"
     32 
     33 #include <algorithm>
     34 #include <cstring>
     35 #include <time.h>
     36 
     37 using namespace llvm;
     38 using namespace llvm::object;
     39 using namespace llvm::Win64EH;
     40 
     41 namespace {
     42 
     43 class COFFDumper : public ObjDumper {
     44 public:
     45   COFFDumper(const llvm::object::COFFObjectFile *Obj, StreamWriter& Writer)
     46     : ObjDumper(Writer)
     47     , Obj(Obj) {
     48     cacheRelocations();
     49   }
     50 
     51   virtual void printFileHeaders() LLVM_OVERRIDE;
     52   virtual void printSections() LLVM_OVERRIDE;
     53   virtual void printRelocations() LLVM_OVERRIDE;
     54   virtual void printSymbols() LLVM_OVERRIDE;
     55   virtual void printDynamicSymbols() LLVM_OVERRIDE;
     56   virtual void printUnwindInfo() LLVM_OVERRIDE;
     57 
     58 private:
     59   void printSymbol(symbol_iterator SymI);
     60 
     61   void printRelocation(section_iterator SecI, relocation_iterator RelI);
     62 
     63   void printDataDirectory(uint32_t Index, const std::string &FieldName);
     64 
     65   void printX64UnwindInfo();
     66 
     67   void printRuntimeFunction(
     68     const RuntimeFunction& RTF,
     69     uint64_t OffsetInSection,
     70     const std::vector<RelocationRef> &Rels);
     71 
     72   void printUnwindInfo(
     73     const Win64EH::UnwindInfo& UI,
     74     uint64_t OffsetInSection,
     75     const std::vector<RelocationRef> &Rels);
     76 
     77   void printUnwindCode(const Win64EH::UnwindInfo& UI, ArrayRef<UnwindCode> UCs);
     78 
     79   void cacheRelocations();
     80 
     81   error_code getSectionContents(
     82     const std::vector<RelocationRef> &Rels,
     83     uint64_t Offset,
     84     ArrayRef<uint8_t> &Contents,
     85     uint64_t &Addr);
     86 
     87   error_code getSection(
     88     const std::vector<RelocationRef> &Rels,
     89     uint64_t Offset,
     90     const coff_section **Section,
     91     uint64_t *AddrPtr);
     92 
     93   typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy;
     94 
     95   const llvm::object::COFFObjectFile *Obj;
     96   RelocMapTy RelocMap;
     97   std::vector<RelocationRef> EmptyRelocs;
     98 };
     99 
    100 } // namespace
    101 
    102 
    103 namespace llvm {
    104 
    105 error_code createCOFFDumper(const object::ObjectFile *Obj,
    106                             StreamWriter& Writer,
    107                             OwningPtr<ObjDumper> &Result) {
    108   const COFFObjectFile *COFFObj = dyn_cast<COFFObjectFile>(Obj);
    109   if (!COFFObj)
    110     return readobj_error::unsupported_obj_file_format;
    111 
    112   Result.reset(new COFFDumper(COFFObj, Writer));
    113   return readobj_error::success;
    114 }
    115 
    116 } // namespace llvm
    117 
    118 
    119 // Returns the name of the unwind code.
    120 static StringRef getUnwindCodeTypeName(uint8_t Code) {
    121   switch(Code) {
    122   default: llvm_unreachable("Invalid unwind code");
    123   case UOP_PushNonVol: return "PUSH_NONVOL";
    124   case UOP_AllocLarge: return "ALLOC_LARGE";
    125   case UOP_AllocSmall: return "ALLOC_SMALL";
    126   case UOP_SetFPReg: return "SET_FPREG";
    127   case UOP_SaveNonVol: return "SAVE_NONVOL";
    128   case UOP_SaveNonVolBig: return "SAVE_NONVOL_FAR";
    129   case UOP_SaveXMM128: return "SAVE_XMM128";
    130   case UOP_SaveXMM128Big: return "SAVE_XMM128_FAR";
    131   case UOP_PushMachFrame: return "PUSH_MACHFRAME";
    132   }
    133 }
    134 
    135 // Returns the name of a referenced register.
    136 static StringRef getUnwindRegisterName(uint8_t Reg) {
    137   switch(Reg) {
    138   default: llvm_unreachable("Invalid register");
    139   case 0: return "RAX";
    140   case 1: return "RCX";
    141   case 2: return "RDX";
    142   case 3: return "RBX";
    143   case 4: return "RSP";
    144   case 5: return "RBP";
    145   case 6: return "RSI";
    146   case 7: return "RDI";
    147   case 8: return "R8";
    148   case 9: return "R9";
    149   case 10: return "R10";
    150   case 11: return "R11";
    151   case 12: return "R12";
    152   case 13: return "R13";
    153   case 14: return "R14";
    154   case 15: return "R15";
    155   }
    156 }
    157 
    158 // Calculates the number of array slots required for the unwind code.
    159 static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) {
    160   switch (UnwindCode.getUnwindOp()) {
    161   default: llvm_unreachable("Invalid unwind code");
    162   case UOP_PushNonVol:
    163   case UOP_AllocSmall:
    164   case UOP_SetFPReg:
    165   case UOP_PushMachFrame:
    166     return 1;
    167   case UOP_SaveNonVol:
    168   case UOP_SaveXMM128:
    169     return 2;
    170   case UOP_SaveNonVolBig:
    171   case UOP_SaveXMM128Big:
    172     return 3;
    173   case UOP_AllocLarge:
    174     return (UnwindCode.getOpInfo() == 0) ? 2 : 3;
    175   }
    176 }
    177 
    178 // Given a symbol sym this functions returns the address and section of it.
    179 static error_code resolveSectionAndAddress(const COFFObjectFile *Obj,
    180                                            const SymbolRef &Sym,
    181                                            const coff_section *&ResolvedSection,
    182                                            uint64_t &ResolvedAddr) {
    183   if (error_code EC = Sym.getAddress(ResolvedAddr))
    184     return EC;
    185 
    186   section_iterator iter(Obj->begin_sections());
    187   if (error_code EC = Sym.getSection(iter))
    188     return EC;
    189 
    190   ResolvedSection = Obj->getCOFFSection(iter);
    191   return object_error::success;
    192 }
    193 
    194 // Given a vector of relocations for a section and an offset into this section
    195 // the function returns the symbol used for the relocation at the offset.
    196 static error_code resolveSymbol(const std::vector<RelocationRef> &Rels,
    197                                 uint64_t Offset, SymbolRef &Sym) {
    198   for (std::vector<RelocationRef>::const_iterator RelI = Rels.begin(),
    199                                                   RelE = Rels.end();
    200                                                   RelI != RelE; ++RelI) {
    201     uint64_t Ofs;
    202     if (error_code EC = RelI->getOffset(Ofs))
    203       return EC;
    204 
    205     if (Ofs == Offset) {
    206       Sym = *RelI->getSymbol();
    207       return readobj_error::success;
    208     }
    209   }
    210 
    211   return readobj_error::unknown_symbol;
    212 }
    213 
    214 // Given a vector of relocations for a section and an offset into this section
    215 // the function returns the name of the symbol used for the relocation at the
    216 // offset.
    217 static error_code resolveSymbolName(const std::vector<RelocationRef> &Rels,
    218                                     uint64_t Offset, StringRef &Name) {
    219   SymbolRef Sym;
    220   if (error_code EC = resolveSymbol(Rels, Offset, Sym)) return EC;
    221   if (error_code EC = Sym.getName(Name)) return EC;
    222   return object_error::success;
    223 }
    224 
    225 static const EnumEntry<COFF::MachineTypes> ImageFileMachineType[] = {
    226   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_UNKNOWN  ),
    227   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AM33     ),
    228   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AMD64    ),
    229   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM      ),
    230   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARMV7    ),
    231   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_EBC      ),
    232   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_I386     ),
    233   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_IA64     ),
    234   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_M32R     ),
    235   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPS16   ),
    236   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU  ),
    237   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU16),
    238   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPC  ),
    239   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPCFP),
    240   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_R4000    ),
    241   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3      ),
    242   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3DSP   ),
    243   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH4      ),
    244   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH5      ),
    245   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_THUMB    ),
    246   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_WCEMIPSV2)
    247 };
    248 
    249 static const EnumEntry<COFF::Characteristics> ImageFileCharacteristics[] = {
    250   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_RELOCS_STRIPPED        ),
    251   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_EXECUTABLE_IMAGE       ),
    252   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LINE_NUMS_STRIPPED     ),
    253   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LOCAL_SYMS_STRIPPED    ),
    254   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_AGGRESSIVE_WS_TRIM     ),
    255   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LARGE_ADDRESS_AWARE    ),
    256   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_BYTES_REVERSED_LO      ),
    257   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_32BIT_MACHINE          ),
    258   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_DEBUG_STRIPPED         ),
    259   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP),
    260   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_NET_RUN_FROM_SWAP      ),
    261   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_SYSTEM                 ),
    262   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_DLL                    ),
    263   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_UP_SYSTEM_ONLY         ),
    264   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_BYTES_REVERSED_HI      )
    265 };
    266 
    267 static const EnumEntry<COFF::WindowsSubsystem> PEWindowsSubsystem[] = {
    268   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_UNKNOWN                ),
    269   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_NATIVE                 ),
    270   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_GUI            ),
    271   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CUI            ),
    272   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_POSIX_CUI              ),
    273   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI         ),
    274   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_APPLICATION        ),
    275   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER),
    276   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER     ),
    277   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_ROM                ),
    278   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_XBOX                   ),
    279 };
    280 
    281 static const EnumEntry<COFF::DLLCharacteristics> PEDLLCharacteristics[] = {
    282   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE         ),
    283   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY      ),
    284   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT            ),
    285   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION         ),
    286   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_SEH               ),
    287   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_BIND              ),
    288   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER           ),
    289   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE),
    290 };
    291 
    292 static const EnumEntry<COFF::SectionCharacteristics>
    293 ImageSectionCharacteristics[] = {
    294   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NO_PAD           ),
    295   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_CODE              ),
    296   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_INITIALIZED_DATA  ),
    297   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_UNINITIALIZED_DATA),
    298   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_OTHER             ),
    299   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_INFO              ),
    300   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_REMOVE            ),
    301   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_COMDAT            ),
    302   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_GPREL                 ),
    303   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_PURGEABLE         ),
    304   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_16BIT             ),
    305   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_LOCKED            ),
    306   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_PRELOAD           ),
    307   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1BYTES          ),
    308   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2BYTES          ),
    309   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4BYTES          ),
    310   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8BYTES          ),
    311   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_16BYTES         ),
    312   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_32BYTES         ),
    313   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_64BYTES         ),
    314   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_128BYTES        ),
    315   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_256BYTES        ),
    316   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_512BYTES        ),
    317   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1024BYTES       ),
    318   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2048BYTES       ),
    319   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4096BYTES       ),
    320   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8192BYTES       ),
    321   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_NRELOC_OVFL       ),
    322   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_DISCARDABLE       ),
    323   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_CACHED        ),
    324   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_PAGED         ),
    325   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_SHARED            ),
    326   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_EXECUTE           ),
    327   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_READ              ),
    328   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_WRITE             )
    329 };
    330 
    331 static const EnumEntry<COFF::SymbolBaseType> ImageSymType[] = {
    332   { "Null"  , COFF::IMAGE_SYM_TYPE_NULL   },
    333   { "Void"  , COFF::IMAGE_SYM_TYPE_VOID   },
    334   { "Char"  , COFF::IMAGE_SYM_TYPE_CHAR   },
    335   { "Short" , COFF::IMAGE_SYM_TYPE_SHORT  },
    336   { "Int"   , COFF::IMAGE_SYM_TYPE_INT    },
    337   { "Long"  , COFF::IMAGE_SYM_TYPE_LONG   },
    338   { "Float" , COFF::IMAGE_SYM_TYPE_FLOAT  },
    339   { "Double", COFF::IMAGE_SYM_TYPE_DOUBLE },
    340   { "Struct", COFF::IMAGE_SYM_TYPE_STRUCT },
    341   { "Union" , COFF::IMAGE_SYM_TYPE_UNION  },
    342   { "Enum"  , COFF::IMAGE_SYM_TYPE_ENUM   },
    343   { "MOE"   , COFF::IMAGE_SYM_TYPE_MOE    },
    344   { "Byte"  , COFF::IMAGE_SYM_TYPE_BYTE   },
    345   { "Word"  , COFF::IMAGE_SYM_TYPE_WORD   },
    346   { "UInt"  , COFF::IMAGE_SYM_TYPE_UINT   },
    347   { "DWord" , COFF::IMAGE_SYM_TYPE_DWORD  }
    348 };
    349 
    350 static const EnumEntry<COFF::SymbolComplexType> ImageSymDType[] = {
    351   { "Null"    , COFF::IMAGE_SYM_DTYPE_NULL     },
    352   { "Pointer" , COFF::IMAGE_SYM_DTYPE_POINTER  },
    353   { "Function", COFF::IMAGE_SYM_DTYPE_FUNCTION },
    354   { "Array"   , COFF::IMAGE_SYM_DTYPE_ARRAY    }
    355 };
    356 
    357 static const EnumEntry<COFF::SymbolStorageClass> ImageSymClass[] = {
    358   { "EndOfFunction"  , COFF::IMAGE_SYM_CLASS_END_OF_FUNCTION  },
    359   { "Null"           , COFF::IMAGE_SYM_CLASS_NULL             },
    360   { "Automatic"      , COFF::IMAGE_SYM_CLASS_AUTOMATIC        },
    361   { "External"       , COFF::IMAGE_SYM_CLASS_EXTERNAL         },
    362   { "Static"         , COFF::IMAGE_SYM_CLASS_STATIC           },
    363   { "Register"       , COFF::IMAGE_SYM_CLASS_REGISTER         },
    364   { "ExternalDef"    , COFF::IMAGE_SYM_CLASS_EXTERNAL_DEF     },
    365   { "Label"          , COFF::IMAGE_SYM_CLASS_LABEL            },
    366   { "UndefinedLabel" , COFF::IMAGE_SYM_CLASS_UNDEFINED_LABEL  },
    367   { "MemberOfStruct" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_STRUCT },
    368   { "Argument"       , COFF::IMAGE_SYM_CLASS_ARGUMENT         },
    369   { "StructTag"      , COFF::IMAGE_SYM_CLASS_STRUCT_TAG       },
    370   { "MemberOfUnion"  , COFF::IMAGE_SYM_CLASS_MEMBER_OF_UNION  },
    371   { "UnionTag"       , COFF::IMAGE_SYM_CLASS_UNION_TAG        },
    372   { "TypeDefinition" , COFF::IMAGE_SYM_CLASS_TYPE_DEFINITION  },
    373   { "UndefinedStatic", COFF::IMAGE_SYM_CLASS_UNDEFINED_STATIC },
    374   { "EnumTag"        , COFF::IMAGE_SYM_CLASS_ENUM_TAG         },
    375   { "MemberOfEnum"   , COFF::IMAGE_SYM_CLASS_MEMBER_OF_ENUM   },
    376   { "RegisterParam"  , COFF::IMAGE_SYM_CLASS_REGISTER_PARAM   },
    377   { "BitField"       , COFF::IMAGE_SYM_CLASS_BIT_FIELD        },
    378   { "Block"          , COFF::IMAGE_SYM_CLASS_BLOCK            },
    379   { "Function"       , COFF::IMAGE_SYM_CLASS_FUNCTION         },
    380   { "EndOfStruct"    , COFF::IMAGE_SYM_CLASS_END_OF_STRUCT    },
    381   { "File"           , COFF::IMAGE_SYM_CLASS_FILE             },
    382   { "Section"        , COFF::IMAGE_SYM_CLASS_SECTION          },
    383   { "WeakExternal"   , COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL    },
    384   { "CLRToken"       , COFF::IMAGE_SYM_CLASS_CLR_TOKEN        }
    385 };
    386 
    387 static const EnumEntry<COFF::COMDATType> ImageCOMDATSelect[] = {
    388   { "NoDuplicates", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES },
    389   { "Any"         , COFF::IMAGE_COMDAT_SELECT_ANY          },
    390   { "SameSize"    , COFF::IMAGE_COMDAT_SELECT_SAME_SIZE    },
    391   { "ExactMatch"  , COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH  },
    392   { "Associative" , COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE  },
    393   { "Largest"     , COFF::IMAGE_COMDAT_SELECT_LARGEST      },
    394   { "Newest"      , COFF::IMAGE_COMDAT_SELECT_NEWEST       }
    395 };
    396 
    397 static const EnumEntry<COFF::WeakExternalCharacteristics>
    398 WeakExternalCharacteristics[] = {
    399   { "NoLibrary", COFF::IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY },
    400   { "Library"  , COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY   },
    401   { "Alias"    , COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS     }
    402 };
    403 
    404 static const EnumEntry<unsigned> UnwindFlags[] = {
    405   { "ExceptionHandler", Win64EH::UNW_ExceptionHandler },
    406   { "TerminateHandler", Win64EH::UNW_TerminateHandler },
    407   { "ChainInfo"       , Win64EH::UNW_ChainInfo        }
    408 };
    409 
    410 static const EnumEntry<unsigned> UnwindOpInfo[] = {
    411   { "RAX",  0 },
    412   { "RCX",  1 },
    413   { "RDX",  2 },
    414   { "RBX",  3 },
    415   { "RSP",  4 },
    416   { "RBP",  5 },
    417   { "RSI",  6 },
    418   { "RDI",  7 },
    419   { "R8",   8 },
    420   { "R9",   9 },
    421   { "R10", 10 },
    422   { "R11", 11 },
    423   { "R12", 12 },
    424   { "R13", 13 },
    425   { "R14", 14 },
    426   { "R15", 15 }
    427 };
    428 
    429 // Some additional COFF structures not defined by llvm::object.
    430 namespace {
    431   struct coff_aux_function_definition {
    432     support::ulittle32_t TagIndex;
    433     support::ulittle32_t TotalSize;
    434     support::ulittle32_t PointerToLineNumber;
    435     support::ulittle32_t PointerToNextFunction;
    436     uint8_t Unused[2];
    437   };
    438 
    439   struct coff_aux_weak_external_definition {
    440     support::ulittle32_t TagIndex;
    441     support::ulittle32_t Characteristics;
    442     uint8_t Unused[10];
    443   };
    444 
    445   struct coff_aux_file_record {
    446     char FileName[18];
    447   };
    448 
    449   struct coff_aux_clr_token {
    450     support::ulittle8_t AuxType;
    451     support::ulittle8_t Reserved;
    452     support::ulittle32_t SymbolTableIndex;
    453     uint8_t Unused[12];
    454   };
    455 } // namespace
    456 
    457 static uint64_t getOffsetOfLSDA(const Win64EH::UnwindInfo& UI) {
    458   return static_cast<const char*>(UI.getLanguageSpecificData())
    459          - reinterpret_cast<const char*>(&UI);
    460 }
    461 
    462 static uint32_t getLargeSlotValue(ArrayRef<UnwindCode> UCs) {
    463   if (UCs.size() < 3)
    464     return 0;
    465 
    466   return UCs[1].FrameOffset + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16);
    467 }
    468 
    469 template<typename T>
    470 static error_code getSymbolAuxData(const COFFObjectFile *Obj,
    471                                    const coff_symbol *Symbol, const T* &Aux) {
    472   ArrayRef<uint8_t> AuxData = Obj->getSymbolAuxData(Symbol);
    473   Aux = reinterpret_cast<const T*>(AuxData.data());
    474   return readobj_error::success;
    475 }
    476 
    477 static std::string formatSymbol(const std::vector<RelocationRef> &Rels,
    478                                 uint64_t Offset, uint32_t Disp) {
    479   std::string Buffer;
    480   raw_string_ostream Str(Buffer);
    481 
    482   StringRef Sym;
    483   if (resolveSymbolName(Rels, Offset, Sym)) {
    484     Str << format(" (0x%" PRIX64 ")", Offset);
    485     return Str.str();
    486   }
    487 
    488   Str << Sym;
    489   if (Disp > 0) {
    490     Str << format(" +0x%X (0x%" PRIX64 ")", Disp, Offset);
    491   } else {
    492     Str << format(" (0x%" PRIX64 ")", Offset);
    493   }
    494 
    495   return Str.str();
    496 }
    497 
    498 // Given a vector of relocations for a section and an offset into this section
    499 // the function resolves the symbol used for the relocation at the offset and
    500 // returns the section content and the address inside the content pointed to
    501 // by the symbol.
    502 error_code COFFDumper::getSectionContents(
    503     const std::vector<RelocationRef> &Rels, uint64_t Offset,
    504     ArrayRef<uint8_t> &Contents, uint64_t &Addr) {
    505 
    506   SymbolRef Sym;
    507   const coff_section *Section;
    508 
    509   if (error_code EC = resolveSymbol(Rels, Offset, Sym))
    510     return EC;
    511   if (error_code EC = resolveSectionAndAddress(Obj, Sym, Section, Addr))
    512     return EC;
    513   if (error_code EC = Obj->getSectionContents(Section, Contents))
    514     return EC;
    515 
    516   return object_error::success;
    517 }
    518 
    519 error_code COFFDumper::getSection(
    520     const std::vector<RelocationRef> &Rels, uint64_t Offset,
    521     const coff_section **SectionPtr, uint64_t *AddrPtr) {
    522 
    523   SymbolRef Sym;
    524   if (error_code EC = resolveSymbol(Rels, Offset, Sym))
    525     return EC;
    526 
    527   const coff_section *Section;
    528   uint64_t Addr;
    529   if (error_code EC = resolveSectionAndAddress(Obj, Sym, Section, Addr))
    530     return EC;
    531 
    532   if (SectionPtr)
    533     *SectionPtr = Section;
    534   if (AddrPtr)
    535     *AddrPtr = Addr;
    536 
    537   return object_error::success;
    538 }
    539 
    540 void COFFDumper::cacheRelocations() {
    541   error_code EC;
    542   for (section_iterator SecI = Obj->begin_sections(),
    543                         SecE = Obj->end_sections();
    544                         SecI != SecE; SecI.increment(EC)) {
    545     if (error(EC))
    546       break;
    547 
    548     const coff_section *Section = Obj->getCOFFSection(SecI);
    549 
    550     for (relocation_iterator RelI = SecI->begin_relocations(),
    551                              RelE = SecI->end_relocations();
    552                              RelI != RelE; RelI.increment(EC)) {
    553       if (error(EC))
    554         break;
    555 
    556       RelocMap[Section].push_back(*RelI);
    557     }
    558 
    559     // Sort relocations by address.
    560     std::sort(RelocMap[Section].begin(), RelocMap[Section].end(),
    561               relocAddressLess);
    562   }
    563 }
    564 
    565 void COFFDumper::printDataDirectory(uint32_t Index, const std::string &FieldName) {
    566   const data_directory *Data;
    567   if (Obj->getDataDirectory(Index, Data))
    568     return;
    569   W.printHex(FieldName + "RVA", Data->RelativeVirtualAddress);
    570   W.printHex(FieldName + "Size", Data->Size);
    571 }
    572 
    573 void COFFDumper::printFileHeaders() {
    574   // Print COFF header
    575   const coff_file_header *COFFHeader = 0;
    576   if (error(Obj->getCOFFHeader(COFFHeader)))
    577     return;
    578 
    579   time_t TDS = COFFHeader->TimeDateStamp;
    580   char FormattedTime[20] = { };
    581   strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS));
    582 
    583   {
    584     DictScope D(W, "ImageFileHeader");
    585     W.printEnum  ("Machine", COFFHeader->Machine,
    586                     makeArrayRef(ImageFileMachineType));
    587     W.printNumber("SectionCount", COFFHeader->NumberOfSections);
    588     W.printHex   ("TimeDateStamp", FormattedTime, COFFHeader->TimeDateStamp);
    589     W.printHex   ("PointerToSymbolTable", COFFHeader->PointerToSymbolTable);
    590     W.printNumber("SymbolCount", COFFHeader->NumberOfSymbols);
    591     W.printNumber("OptionalHeaderSize", COFFHeader->SizeOfOptionalHeader);
    592     W.printFlags ("Characteristics", COFFHeader->Characteristics,
    593                     makeArrayRef(ImageFileCharacteristics));
    594   }
    595 
    596   // Print PE header. This header does not exist if this is an object file and
    597   // not an executable.
    598   const pe32_header *PEHeader = 0;
    599   if (error(Obj->getPE32Header(PEHeader)))
    600     return;
    601 
    602   if (PEHeader) {
    603     DictScope D(W, "ImageOptionalHeader");
    604     W.printNumber("MajorLinkerVersion", PEHeader->MajorLinkerVersion);
    605     W.printNumber("MinorLinkerVersion", PEHeader->MinorLinkerVersion);
    606     W.printNumber("SizeOfCode", PEHeader->SizeOfCode);
    607     W.printNumber("SizeOfInitializedData", PEHeader->SizeOfInitializedData);
    608     W.printNumber("SizeOfUninitializedData", PEHeader->SizeOfUninitializedData);
    609     W.printHex   ("AddressOfEntryPoint", PEHeader->AddressOfEntryPoint);
    610     W.printHex   ("BaseOfCode", PEHeader->BaseOfCode);
    611     W.printHex   ("BaseOfData", PEHeader->BaseOfData);
    612     W.printHex   ("ImageBase", PEHeader->ImageBase);
    613     W.printNumber("SectionAlignment", PEHeader->SectionAlignment);
    614     W.printNumber("FileAlignment", PEHeader->FileAlignment);
    615     W.printNumber("MajorOperatingSystemVersion",
    616                   PEHeader->MajorOperatingSystemVersion);
    617     W.printNumber("MinorOperatingSystemVersion",
    618                   PEHeader->MinorOperatingSystemVersion);
    619     W.printNumber("MajorImageVersion", PEHeader->MajorImageVersion);
    620     W.printNumber("MinorImageVersion", PEHeader->MinorImageVersion);
    621     W.printNumber("MajorSubsystemVersion", PEHeader->MajorSubsystemVersion);
    622     W.printNumber("MinorSubsystemVersion", PEHeader->MinorSubsystemVersion);
    623     W.printNumber("SizeOfImage", PEHeader->SizeOfImage);
    624     W.printNumber("SizeOfHeaders", PEHeader->SizeOfHeaders);
    625     W.printEnum  ("Subsystem", PEHeader->Subsystem,
    626                     makeArrayRef(PEWindowsSubsystem));
    627     W.printFlags ("Subsystem", PEHeader->DLLCharacteristics,
    628                     makeArrayRef(PEDLLCharacteristics));
    629     W.printNumber("SizeOfStackReserve", PEHeader->SizeOfStackReserve);
    630     W.printNumber("SizeOfStackCommit", PEHeader->SizeOfStackCommit);
    631     W.printNumber("SizeOfHeapReserve", PEHeader->SizeOfHeapReserve);
    632     W.printNumber("SizeOfHeapCommit", PEHeader->SizeOfHeapCommit);
    633     W.printNumber("NumberOfRvaAndSize", PEHeader->NumberOfRvaAndSize);
    634 
    635     if (PEHeader->NumberOfRvaAndSize > 0) {
    636       DictScope D(W, "DataDirectory");
    637       static const char * const directory[] = {
    638         "ExportTable", "ImportTable", "ResourceTable", "ExceptionTable",
    639         "CertificateTable", "BaseRelocationTable", "Debug", "Architecture",
    640         "GlobalPtr", "TLSTable", "LoadConfigTable", "BoundImport", "IAT",
    641         "DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"
    642       };
    643 
    644       for (uint32_t i = 0; i < PEHeader->NumberOfRvaAndSize; ++i) {
    645         printDataDirectory(i, directory[i]);
    646       }
    647     }
    648   }
    649 }
    650 
    651 void COFFDumper::printSections() {
    652   error_code EC;
    653 
    654   ListScope SectionsD(W, "Sections");
    655   int SectionNumber = 0;
    656   for (section_iterator SecI = Obj->begin_sections(),
    657                         SecE = Obj->end_sections();
    658                         SecI != SecE; SecI.increment(EC)) {
    659     if (error(EC))
    660       break;
    661 
    662     ++SectionNumber;
    663     const coff_section *Section = Obj->getCOFFSection(SecI);
    664 
    665     StringRef Name;
    666     if (error(SecI->getName(Name)))
    667         Name = "";
    668 
    669     DictScope D(W, "Section");
    670     W.printNumber("Number", SectionNumber);
    671     W.printBinary("Name", Name, Section->Name);
    672     W.printHex   ("VirtualSize", Section->VirtualSize);
    673     W.printHex   ("VirtualAddress", Section->VirtualAddress);
    674     W.printNumber("RawDataSize", Section->SizeOfRawData);
    675     W.printHex   ("PointerToRawData", Section->PointerToRawData);
    676     W.printHex   ("PointerToRelocations", Section->PointerToRelocations);
    677     W.printHex   ("PointerToLineNumbers", Section->PointerToLinenumbers);
    678     W.printNumber("RelocationCount", Section->NumberOfRelocations);
    679     W.printNumber("LineNumberCount", Section->NumberOfLinenumbers);
    680     W.printFlags ("Characteristics", Section->Characteristics,
    681                     makeArrayRef(ImageSectionCharacteristics),
    682                     COFF::SectionCharacteristics(0x00F00000));
    683 
    684     if (opts::SectionRelocations) {
    685       ListScope D(W, "Relocations");
    686       for (relocation_iterator RelI = SecI->begin_relocations(),
    687                                RelE = SecI->end_relocations();
    688                                RelI != RelE; RelI.increment(EC)) {
    689         if (error(EC)) break;
    690 
    691         printRelocation(SecI, RelI);
    692       }
    693     }
    694 
    695     if (opts::SectionSymbols) {
    696       ListScope D(W, "Symbols");
    697       for (symbol_iterator SymI = Obj->begin_symbols(),
    698                            SymE = Obj->end_symbols();
    699                            SymI != SymE; SymI.increment(EC)) {
    700         if (error(EC)) break;
    701 
    702         bool Contained = false;
    703         if (SecI->containsSymbol(*SymI, Contained) || !Contained)
    704           continue;
    705 
    706         printSymbol(SymI);
    707       }
    708     }
    709 
    710     if (opts::SectionData) {
    711       StringRef Data;
    712       if (error(SecI->getContents(Data))) break;
    713 
    714       W.printBinaryBlock("SectionData", Data);
    715     }
    716   }
    717 }
    718 
    719 void COFFDumper::printRelocations() {
    720   ListScope D(W, "Relocations");
    721 
    722   error_code EC;
    723   int SectionNumber = 0;
    724   for (section_iterator SecI = Obj->begin_sections(),
    725                         SecE = Obj->end_sections();
    726                         SecI != SecE; SecI.increment(EC)) {
    727     ++SectionNumber;
    728     if (error(EC))
    729       break;
    730 
    731     StringRef Name;
    732     if (error(SecI->getName(Name)))
    733       continue;
    734 
    735     bool PrintedGroup = false;
    736     for (relocation_iterator RelI = SecI->begin_relocations(),
    737                              RelE = SecI->end_relocations();
    738                              RelI != RelE; RelI.increment(EC)) {
    739       if (error(EC)) break;
    740 
    741       if (!PrintedGroup) {
    742         W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";
    743         W.indent();
    744         PrintedGroup = true;
    745       }
    746 
    747       printRelocation(SecI, RelI);
    748     }
    749 
    750     if (PrintedGroup) {
    751       W.unindent();
    752       W.startLine() << "}\n";
    753     }
    754   }
    755 }
    756 
    757 void COFFDumper::printRelocation(section_iterator SecI,
    758                                  relocation_iterator RelI) {
    759   uint64_t Offset;
    760   uint64_t RelocType;
    761   SmallString<32> RelocName;
    762   StringRef SymbolName;
    763   StringRef Contents;
    764   if (error(RelI->getOffset(Offset))) return;
    765   if (error(RelI->getType(RelocType))) return;
    766   if (error(RelI->getTypeName(RelocName))) return;
    767   symbol_iterator Symbol = RelI->getSymbol();
    768   if (error(Symbol->getName(SymbolName))) return;
    769   if (error(SecI->getContents(Contents))) return;
    770 
    771   if (opts::ExpandRelocs) {
    772     DictScope Group(W, "Relocation");
    773     W.printHex("Offset", Offset);
    774     W.printNumber("Type", RelocName, RelocType);
    775     W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-");
    776   } else {
    777     raw_ostream& OS = W.startLine();
    778     OS << W.hex(Offset)
    779        << " " << RelocName
    780        << " " << (SymbolName.size() > 0 ? SymbolName : "-")
    781        << "\n";
    782   }
    783 }
    784 
    785 void COFFDumper::printSymbols() {
    786   ListScope Group(W, "Symbols");
    787 
    788   error_code EC;
    789   for (symbol_iterator SymI = Obj->begin_symbols(),
    790                        SymE = Obj->end_symbols();
    791                        SymI != SymE; SymI.increment(EC)) {
    792     if (error(EC)) break;
    793 
    794     printSymbol(SymI);
    795   }
    796 }
    797 
    798 void COFFDumper::printDynamicSymbols() {
    799   ListScope Group(W, "DynamicSymbols");
    800 }
    801 
    802 void COFFDumper::printSymbol(symbol_iterator SymI) {
    803   DictScope D(W, "Symbol");
    804 
    805   const coff_symbol *Symbol = Obj->getCOFFSymbol(SymI);
    806   const coff_section *Section;
    807   if (error_code EC = Obj->getSection(Symbol->SectionNumber, Section)) {
    808     W.startLine() << "Invalid section number: " << EC.message() << "\n";
    809     W.flush();
    810     return;
    811   }
    812 
    813   StringRef SymbolName;
    814   if (Obj->getSymbolName(Symbol, SymbolName))
    815     SymbolName = "";
    816 
    817   StringRef SectionName = "";
    818   if (Section)
    819     Obj->getSectionName(Section, SectionName);
    820 
    821   W.printString("Name", SymbolName);
    822   W.printNumber("Value", Symbol->Value);
    823   W.printNumber("Section", SectionName, Symbol->SectionNumber);
    824   W.printEnum  ("BaseType", Symbol->getBaseType(), makeArrayRef(ImageSymType));
    825   W.printEnum  ("ComplexType", Symbol->getComplexType(),
    826                                                    makeArrayRef(ImageSymDType));
    827   W.printEnum  ("StorageClass", Symbol->StorageClass,
    828                                                    makeArrayRef(ImageSymClass));
    829   W.printNumber("AuxSymbolCount", Symbol->NumberOfAuxSymbols);
    830 
    831   for (unsigned I = 0; I < Symbol->NumberOfAuxSymbols; ++I) {
    832     if (Symbol->StorageClass     == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
    833         Symbol->getBaseType()    == COFF::IMAGE_SYM_TYPE_NULL &&
    834         Symbol->getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION &&
    835         Symbol->SectionNumber > 0) {
    836       const coff_aux_function_definition *Aux;
    837       if (error(getSymbolAuxData(Obj, Symbol + I, Aux)))
    838         break;
    839 
    840       DictScope AS(W, "AuxFunctionDef");
    841       W.printNumber("TagIndex", Aux->TagIndex);
    842       W.printNumber("TotalSize", Aux->TotalSize);
    843       W.printHex("PointerToLineNumber", Aux->PointerToLineNumber);
    844       W.printHex("PointerToNextFunction", Aux->PointerToNextFunction);
    845       W.printBinary("Unused", makeArrayRef(Aux->Unused));
    846 
    847     } else if (
    848         Symbol->StorageClass   == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL ||
    849         (Symbol->StorageClass  == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
    850          Symbol->SectionNumber == 0 &&
    851          Symbol->Value         == 0)) {
    852       const coff_aux_weak_external_definition *Aux;
    853       if (error(getSymbolAuxData(Obj, Symbol + I, Aux)))
    854         break;
    855 
    856       const coff_symbol *Linked;
    857       StringRef LinkedName;
    858       error_code EC;
    859       if ((EC = Obj->getSymbol(Aux->TagIndex, Linked)) ||
    860           (EC = Obj->getSymbolName(Linked, LinkedName))) {
    861         LinkedName = "";
    862         error(EC);
    863       }
    864 
    865       DictScope AS(W, "AuxWeakExternal");
    866       W.printNumber("Linked", LinkedName, Aux->TagIndex);
    867       W.printEnum  ("Search", Aux->Characteristics,
    868                     makeArrayRef(WeakExternalCharacteristics));
    869       W.printBinary("Unused", Aux->Unused);
    870 
    871     } else if (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_FILE) {
    872       const coff_aux_file_record *Aux;
    873       if (error(getSymbolAuxData(Obj, Symbol + I, Aux)))
    874         break;
    875 
    876       DictScope AS(W, "AuxFileRecord");
    877       W.printString("FileName", StringRef(Aux->FileName));
    878 
    879     } else if (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_STATIC ||
    880                (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL &&
    881                 Symbol->SectionNumber != COFF::IMAGE_SYM_UNDEFINED)) {
    882       const coff_aux_section_definition *Aux;
    883       if (error(getSymbolAuxData(Obj, Symbol + I, Aux)))
    884         break;
    885 
    886       DictScope AS(W, "AuxSectionDef");
    887       W.printNumber("Length", Aux->Length);
    888       W.printNumber("RelocationCount", Aux->NumberOfRelocations);
    889       W.printNumber("LineNumberCount", Aux->NumberOfLinenumbers);
    890       W.printHex("Checksum", Aux->CheckSum);
    891       W.printNumber("Number", Aux->Number);
    892       W.printEnum("Selection", Aux->Selection, makeArrayRef(ImageCOMDATSelect));
    893       W.printBinary("Unused", makeArrayRef(Aux->Unused));
    894 
    895       if (Section && Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT
    896           && Aux->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
    897         const coff_section *Assoc;
    898         StringRef AssocName;
    899         error_code EC;
    900         if ((EC = Obj->getSection(Aux->Number, Assoc)) ||
    901             (EC = Obj->getSectionName(Assoc, AssocName))) {
    902           AssocName = "";
    903           error(EC);
    904         }
    905 
    906         W.printNumber("AssocSection", AssocName, Aux->Number);
    907       }
    908     } else if (Symbol->StorageClass == COFF::IMAGE_SYM_CLASS_CLR_TOKEN) {
    909       const coff_aux_clr_token *Aux;
    910       if (error(getSymbolAuxData(Obj, Symbol + I, Aux)))
    911         break;
    912 
    913       DictScope AS(W, "AuxCLRToken");
    914       W.printNumber("AuxType", Aux->AuxType);
    915       W.printNumber("Reserved", Aux->Reserved);
    916       W.printNumber("SymbolTableIndex", Aux->SymbolTableIndex);
    917       W.printBinary("Unused", Aux->Unused);
    918 
    919     } else {
    920       W.startLine() << "<unhandled auxiliary record>\n";
    921     }
    922   }
    923 }
    924 
    925 void COFFDumper::printUnwindInfo() {
    926   const coff_file_header *Header;
    927   if (error(Obj->getCOFFHeader(Header)))
    928     return;
    929 
    930   ListScope D(W, "UnwindInformation");
    931   if (Header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) {
    932     W.startLine() << "Unsupported image machine type "
    933               "(currently only AMD64 is supported).\n";
    934     return;
    935   }
    936 
    937   printX64UnwindInfo();
    938 }
    939 
    940 void COFFDumper::printX64UnwindInfo() {
    941   error_code EC;
    942   for (section_iterator SecI = Obj->begin_sections(),
    943                         SecE = Obj->end_sections();
    944                         SecI != SecE; SecI.increment(EC)) {
    945     if (error(EC)) break;
    946 
    947     StringRef Name;
    948     if (error(SecI->getName(Name)))
    949       continue;
    950     if (Name != ".pdata" && !Name.startswith(".pdata$"))
    951       continue;
    952 
    953     const coff_section *PData = Obj->getCOFFSection(SecI);
    954 
    955     ArrayRef<uint8_t> Contents;
    956     if (error(Obj->getSectionContents(PData, Contents)) ||
    957         Contents.empty())
    958       continue;
    959 
    960     ArrayRef<RuntimeFunction> RFs(
    961       reinterpret_cast<const RuntimeFunction *>(Contents.data()),
    962       Contents.size() / sizeof(RuntimeFunction));
    963 
    964     for (const RuntimeFunction *I = RFs.begin(), *E = RFs.end(); I < E; ++I) {
    965       const uint64_t OffsetInSection = std::distance(RFs.begin(), I)
    966                                      * sizeof(RuntimeFunction);
    967 
    968       printRuntimeFunction(*I, OffsetInSection, RelocMap[PData]);
    969     }
    970   }
    971 }
    972 
    973 void COFFDumper::printRuntimeFunction(
    974     const RuntimeFunction& RTF,
    975     uint64_t OffsetInSection,
    976     const std::vector<RelocationRef> &Rels) {
    977 
    978   DictScope D(W, "RuntimeFunction");
    979   W.printString("StartAddress",
    980                 formatSymbol(Rels, OffsetInSection + 0, RTF.StartAddress));
    981   W.printString("EndAddress",
    982                 formatSymbol(Rels, OffsetInSection + 4, RTF.EndAddress));
    983   W.printString("UnwindInfoAddress",
    984                 formatSymbol(Rels, OffsetInSection + 8, RTF.UnwindInfoOffset));
    985 
    986   const coff_section* XData = 0;
    987   uint64_t UnwindInfoOffset = 0;
    988   if (error(getSection(Rels, OffsetInSection + 8, &XData, &UnwindInfoOffset)))
    989     return;
    990 
    991   ArrayRef<uint8_t> XContents;
    992   if (error(Obj->getSectionContents(XData, XContents)) || XContents.empty())
    993     return;
    994 
    995   UnwindInfoOffset += RTF.UnwindInfoOffset;
    996   if (UnwindInfoOffset > XContents.size())
    997     return;
    998 
    999   const Win64EH::UnwindInfo *UI =
   1000     reinterpret_cast<const Win64EH::UnwindInfo *>(
   1001       XContents.data() + UnwindInfoOffset);
   1002 
   1003   printUnwindInfo(*UI, UnwindInfoOffset, RelocMap[XData]);
   1004 }
   1005 
   1006 void COFFDumper::printUnwindInfo(
   1007     const Win64EH::UnwindInfo& UI,
   1008     uint64_t OffsetInSection,
   1009     const std::vector<RelocationRef> &Rels) {
   1010   DictScope D(W, "UnwindInfo");
   1011   W.printNumber("Version", UI.getVersion());
   1012   W.printFlags("Flags", UI.getFlags(), makeArrayRef(UnwindFlags));
   1013   W.printNumber("PrologSize", UI.PrologSize);
   1014   if (UI.getFrameRegister() != 0) {
   1015     W.printEnum("FrameRegister", UI.getFrameRegister(),
   1016                 makeArrayRef(UnwindOpInfo));
   1017     W.printHex("FrameOffset", UI.getFrameOffset());
   1018   } else {
   1019     W.printString("FrameRegister", StringRef("-"));
   1020     W.printString("FrameOffset", StringRef("-"));
   1021   }
   1022 
   1023   W.printNumber("UnwindCodeCount", UI.NumCodes);
   1024   {
   1025     ListScope CodesD(W, "UnwindCodes");
   1026     ArrayRef<UnwindCode> UCs(&UI.UnwindCodes[0], UI.NumCodes);
   1027     for (const UnwindCode *I = UCs.begin(), *E = UCs.end(); I < E; ++I) {
   1028       unsigned UsedSlots = getNumUsedSlots(*I);
   1029       if (UsedSlots > UCs.size()) {
   1030         errs() << "Corrupt unwind data";
   1031         return;
   1032       }
   1033       printUnwindCode(UI, ArrayRef<UnwindCode>(I, E));
   1034       I += UsedSlots - 1;
   1035     }
   1036   }
   1037 
   1038   uint64_t LSDAOffset = OffsetInSection + getOffsetOfLSDA(UI);
   1039   if (UI.getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) {
   1040     W.printString("Handler", formatSymbol(Rels, LSDAOffset,
   1041                                         UI.getLanguageSpecificHandlerOffset()));
   1042   } else if (UI.getFlags() & UNW_ChainInfo) {
   1043     const RuntimeFunction *Chained = UI.getChainedFunctionEntry();
   1044     if (Chained) {
   1045       DictScope D(W, "Chained");
   1046       W.printString("StartAddress", formatSymbol(Rels, LSDAOffset + 0,
   1047                                                         Chained->StartAddress));
   1048       W.printString("EndAddress", formatSymbol(Rels, LSDAOffset + 4,
   1049                                                           Chained->EndAddress));
   1050       W.printString("UnwindInfoAddress", formatSymbol(Rels, LSDAOffset + 8,
   1051                                                     Chained->UnwindInfoOffset));
   1052     }
   1053   }
   1054 }
   1055 
   1056 // Prints one unwind code. Because an unwind code can occupy up to 3 slots in
   1057 // the unwind codes array, this function requires that the correct number of
   1058 // slots is provided.
   1059 void COFFDumper::printUnwindCode(const Win64EH::UnwindInfo& UI,
   1060                                  ArrayRef<UnwindCode> UCs) {
   1061   assert(UCs.size() >= getNumUsedSlots(UCs[0]));
   1062 
   1063   W.startLine() << format("0x%02X: ", unsigned(UCs[0].u.CodeOffset))
   1064                 << getUnwindCodeTypeName(UCs[0].getUnwindOp());
   1065 
   1066   uint32_t AllocSize = 0;
   1067 
   1068   switch (UCs[0].getUnwindOp()) {
   1069   case UOP_PushNonVol:
   1070     outs() << " reg=" << getUnwindRegisterName(UCs[0].getOpInfo());
   1071     break;
   1072 
   1073   case UOP_AllocLarge:
   1074     if (UCs[0].getOpInfo() == 0) {
   1075       AllocSize = UCs[1].FrameOffset * 8;
   1076     } else {
   1077       AllocSize = getLargeSlotValue(UCs);
   1078     }
   1079     outs() << " size=" << AllocSize;
   1080     break;
   1081   case UOP_AllocSmall:
   1082     outs() << " size=" << ((UCs[0].getOpInfo() + 1) * 8);
   1083     break;
   1084   case UOP_SetFPReg:
   1085     if (UI.getFrameRegister() == 0) {
   1086       outs() << " reg=<invalid>";
   1087     } else {
   1088       outs() << " reg=" << getUnwindRegisterName(UI.getFrameRegister())
   1089              << format(", offset=0x%X", UI.getFrameOffset() * 16);
   1090     }
   1091     break;
   1092   case UOP_SaveNonVol:
   1093     outs() << " reg=" << getUnwindRegisterName(UCs[0].getOpInfo())
   1094            << format(", offset=0x%X", UCs[1].FrameOffset * 8);
   1095     break;
   1096   case UOP_SaveNonVolBig:
   1097     outs() << " reg=" << getUnwindRegisterName(UCs[0].getOpInfo())
   1098            << format(", offset=0x%X", getLargeSlotValue(UCs));
   1099     break;
   1100   case UOP_SaveXMM128:
   1101     outs() << " reg=XMM" << static_cast<uint32_t>(UCs[0].getOpInfo())
   1102            << format(", offset=0x%X", UCs[1].FrameOffset * 16);
   1103     break;
   1104   case UOP_SaveXMM128Big:
   1105     outs() << " reg=XMM" << static_cast<uint32_t>(UCs[0].getOpInfo())
   1106            << format(", offset=0x%X", getLargeSlotValue(UCs));
   1107     break;
   1108   case UOP_PushMachFrame:
   1109     outs() << " errcode=" << (UCs[0].getOpInfo() == 0 ? "no" : "yes");
   1110     break;
   1111   }
   1112 
   1113   outs() << "\n";
   1114 }
   1115