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