]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/llvm-readobj/COFFDumper.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / 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 "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 }