PR21189: Teach llvm-readobj to dump bits of COFF symbol subsections required to debug...
[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 "ARMWinEHPrinter.h"
17 #include "Error.h"
18 #include "ObjDumper.h"
19 #include "StreamWriter.h"
20 #include "Win64EHDumper.h"
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/COFF.h"
26 #include "llvm/Support/Casting.h"
27 #include "llvm/Support/Compiler.h"
28 #include "llvm/Support/DataExtractor.h"
29 #include "llvm/Support/Format.h"
30 #include "llvm/Support/SourceMgr.h"
31 #include "llvm/Support/Win64EH.h"
32 #include "llvm/Support/raw_ostream.h"
33 #include <algorithm>
34 #include <cstring>
35 #include <system_error>
36 #include <time.h>
37
38 using namespace llvm;
39 using namespace llvm::object;
40 using namespace llvm::Win64EH;
41
42 namespace {
43
44 class COFFDumper : public ObjDumper {
45 public:
46   COFFDumper(const llvm::object::COFFObjectFile *Obj, StreamWriter& Writer)
47     : ObjDumper(Writer)
48     , Obj(Obj) {
49     cacheRelocations();
50   }
51
52   void printFileHeaders() override;
53   void printSections() override;
54   void printRelocations() override;
55   void printSymbols() override;
56   void printDynamicSymbols() override;
57   void printUnwindInfo() override;
58   void printCOFFImports() override;
59   void printCOFFDirectives() override;
60
61 private:
62   void printSymbol(const SymbolRef &Sym);
63   void printRelocation(const SectionRef &Section, const RelocationRef &Reloc);
64   void printDataDirectory(uint32_t Index, const std::string &FieldName);
65
66   template <class PEHeader> void printPEHeader(const PEHeader *Hdr);
67   void printBaseOfDataField(const pe32_header *Hdr);
68   void printBaseOfDataField(const pe32plus_header *Hdr);
69
70   void printCodeViewLineTables(const SectionRef &Section);
71
72   void printCodeViewSymbolsSubsection(StringRef Subsection,
73                                       const SectionRef &Section,
74                                       uint32_t Offset);
75
76   void cacheRelocations();
77
78   std::error_code resolveSymbol(const coff_section *Section, uint64_t Offset,
79                                 SymbolRef &Sym);
80   std::error_code resolveSymbolName(const coff_section *Section,
81                                     uint64_t Offset, StringRef &Name);
82   void printImportedSymbols(iterator_range<imported_symbol_iterator> Range);
83
84   typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy;
85
86   const llvm::object::COFFObjectFile *Obj;
87   RelocMapTy RelocMap;
88   StringRef CVFileIndexToStringOffsetTable;
89   StringRef CVStringTable;
90 };
91
92 } // namespace
93
94
95 namespace llvm {
96
97 std::error_code createCOFFDumper(const object::ObjectFile *Obj,
98                                  StreamWriter &Writer,
99                                  std::unique_ptr<ObjDumper> &Result) {
100   const COFFObjectFile *COFFObj = dyn_cast<COFFObjectFile>(Obj);
101   if (!COFFObj)
102     return readobj_error::unsupported_obj_file_format;
103
104   Result.reset(new COFFDumper(COFFObj, Writer));
105   return readobj_error::success;
106 }
107
108 } // namespace llvm
109
110 // Given a a section and an offset into this section the function returns the
111 // symbol used for the relocation at the offset.
112 std::error_code COFFDumper::resolveSymbol(const coff_section *Section,
113                                           uint64_t Offset, SymbolRef &Sym) {
114   const auto &Relocations = RelocMap[Section];
115   for (const auto &Relocation : Relocations) {
116     uint64_t RelocationOffset;
117     if (std::error_code EC = Relocation.getOffset(RelocationOffset))
118       return EC;
119
120     if (RelocationOffset == Offset) {
121       Sym = *Relocation.getSymbol();
122       return readobj_error::success;
123     }
124   }
125   return readobj_error::unknown_symbol;
126 }
127
128 // Given a section and an offset into this section the function returns the name
129 // of the symbol used for the relocation at the offset.
130 std::error_code COFFDumper::resolveSymbolName(const coff_section *Section,
131                                               uint64_t Offset,
132                                               StringRef &Name) {
133   SymbolRef Symbol;
134   if (std::error_code EC = resolveSymbol(Section, Offset, Symbol))
135     return EC;
136   if (std::error_code EC = Symbol.getName(Name))
137     return EC;
138   return object_error::success;
139 }
140
141 static const EnumEntry<COFF::MachineTypes> ImageFileMachineType[] = {
142   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_UNKNOWN  ),
143   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AM33     ),
144   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AMD64    ),
145   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM      ),
146   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARMNT    ),
147   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_EBC      ),
148   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_I386     ),
149   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_IA64     ),
150   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_M32R     ),
151   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPS16   ),
152   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU  ),
153   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU16),
154   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPC  ),
155   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPCFP),
156   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_R4000    ),
157   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3      ),
158   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3DSP   ),
159   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH4      ),
160   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH5      ),
161   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_THUMB    ),
162   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_WCEMIPSV2)
163 };
164
165 static const EnumEntry<COFF::Characteristics> ImageFileCharacteristics[] = {
166   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_RELOCS_STRIPPED        ),
167   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_EXECUTABLE_IMAGE       ),
168   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LINE_NUMS_STRIPPED     ),
169   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LOCAL_SYMS_STRIPPED    ),
170   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_AGGRESSIVE_WS_TRIM     ),
171   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LARGE_ADDRESS_AWARE    ),
172   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_BYTES_REVERSED_LO      ),
173   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_32BIT_MACHINE          ),
174   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_DEBUG_STRIPPED         ),
175   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP),
176   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_NET_RUN_FROM_SWAP      ),
177   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_SYSTEM                 ),
178   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_DLL                    ),
179   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_UP_SYSTEM_ONLY         ),
180   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_BYTES_REVERSED_HI      )
181 };
182
183 static const EnumEntry<COFF::WindowsSubsystem> PEWindowsSubsystem[] = {
184   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_UNKNOWN                ),
185   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_NATIVE                 ),
186   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_GUI            ),
187   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CUI            ),
188   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_POSIX_CUI              ),
189   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI         ),
190   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_APPLICATION        ),
191   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER),
192   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER     ),
193   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_ROM                ),
194   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_XBOX                   ),
195 };
196
197 static const EnumEntry<COFF::DLLCharacteristics> PEDLLCharacteristics[] = {
198   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA      ),
199   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE         ),
200   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY      ),
201   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT            ),
202   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION         ),
203   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_SEH               ),
204   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_BIND              ),
205   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_APPCONTAINER         ),
206   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER           ),
207   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_GUARD_CF             ),
208   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE),
209 };
210
211 static const EnumEntry<COFF::SectionCharacteristics>
212 ImageSectionCharacteristics[] = {
213   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NO_PAD           ),
214   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_CODE              ),
215   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_INITIALIZED_DATA  ),
216   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_UNINITIALIZED_DATA),
217   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_OTHER             ),
218   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_INFO              ),
219   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_REMOVE            ),
220   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_COMDAT            ),
221   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_GPREL                 ),
222   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_PURGEABLE         ),
223   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_16BIT             ),
224   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_LOCKED            ),
225   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_PRELOAD           ),
226   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1BYTES          ),
227   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2BYTES          ),
228   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4BYTES          ),
229   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8BYTES          ),
230   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_16BYTES         ),
231   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_32BYTES         ),
232   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_64BYTES         ),
233   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_128BYTES        ),
234   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_256BYTES        ),
235   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_512BYTES        ),
236   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1024BYTES       ),
237   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2048BYTES       ),
238   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4096BYTES       ),
239   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8192BYTES       ),
240   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_NRELOC_OVFL       ),
241   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_DISCARDABLE       ),
242   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_CACHED        ),
243   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_PAGED         ),
244   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_SHARED            ),
245   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_EXECUTE           ),
246   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_READ              ),
247   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_WRITE             )
248 };
249
250 static const EnumEntry<COFF::SymbolBaseType> ImageSymType[] = {
251   { "Null"  , COFF::IMAGE_SYM_TYPE_NULL   },
252   { "Void"  , COFF::IMAGE_SYM_TYPE_VOID   },
253   { "Char"  , COFF::IMAGE_SYM_TYPE_CHAR   },
254   { "Short" , COFF::IMAGE_SYM_TYPE_SHORT  },
255   { "Int"   , COFF::IMAGE_SYM_TYPE_INT    },
256   { "Long"  , COFF::IMAGE_SYM_TYPE_LONG   },
257   { "Float" , COFF::IMAGE_SYM_TYPE_FLOAT  },
258   { "Double", COFF::IMAGE_SYM_TYPE_DOUBLE },
259   { "Struct", COFF::IMAGE_SYM_TYPE_STRUCT },
260   { "Union" , COFF::IMAGE_SYM_TYPE_UNION  },
261   { "Enum"  , COFF::IMAGE_SYM_TYPE_ENUM   },
262   { "MOE"   , COFF::IMAGE_SYM_TYPE_MOE    },
263   { "Byte"  , COFF::IMAGE_SYM_TYPE_BYTE   },
264   { "Word"  , COFF::IMAGE_SYM_TYPE_WORD   },
265   { "UInt"  , COFF::IMAGE_SYM_TYPE_UINT   },
266   { "DWord" , COFF::IMAGE_SYM_TYPE_DWORD  }
267 };
268
269 static const EnumEntry<COFF::SymbolComplexType> ImageSymDType[] = {
270   { "Null"    , COFF::IMAGE_SYM_DTYPE_NULL     },
271   { "Pointer" , COFF::IMAGE_SYM_DTYPE_POINTER  },
272   { "Function", COFF::IMAGE_SYM_DTYPE_FUNCTION },
273   { "Array"   , COFF::IMAGE_SYM_DTYPE_ARRAY    }
274 };
275
276 static const EnumEntry<COFF::SymbolStorageClass> ImageSymClass[] = {
277   { "EndOfFunction"  , COFF::IMAGE_SYM_CLASS_END_OF_FUNCTION  },
278   { "Null"           , COFF::IMAGE_SYM_CLASS_NULL             },
279   { "Automatic"      , COFF::IMAGE_SYM_CLASS_AUTOMATIC        },
280   { "External"       , COFF::IMAGE_SYM_CLASS_EXTERNAL         },
281   { "Static"         , COFF::IMAGE_SYM_CLASS_STATIC           },
282   { "Register"       , COFF::IMAGE_SYM_CLASS_REGISTER         },
283   { "ExternalDef"    , COFF::IMAGE_SYM_CLASS_EXTERNAL_DEF     },
284   { "Label"          , COFF::IMAGE_SYM_CLASS_LABEL            },
285   { "UndefinedLabel" , COFF::IMAGE_SYM_CLASS_UNDEFINED_LABEL  },
286   { "MemberOfStruct" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_STRUCT },
287   { "Argument"       , COFF::IMAGE_SYM_CLASS_ARGUMENT         },
288   { "StructTag"      , COFF::IMAGE_SYM_CLASS_STRUCT_TAG       },
289   { "MemberOfUnion"  , COFF::IMAGE_SYM_CLASS_MEMBER_OF_UNION  },
290   { "UnionTag"       , COFF::IMAGE_SYM_CLASS_UNION_TAG        },
291   { "TypeDefinition" , COFF::IMAGE_SYM_CLASS_TYPE_DEFINITION  },
292   { "UndefinedStatic", COFF::IMAGE_SYM_CLASS_UNDEFINED_STATIC },
293   { "EnumTag"        , COFF::IMAGE_SYM_CLASS_ENUM_TAG         },
294   { "MemberOfEnum"   , COFF::IMAGE_SYM_CLASS_MEMBER_OF_ENUM   },
295   { "RegisterParam"  , COFF::IMAGE_SYM_CLASS_REGISTER_PARAM   },
296   { "BitField"       , COFF::IMAGE_SYM_CLASS_BIT_FIELD        },
297   { "Block"          , COFF::IMAGE_SYM_CLASS_BLOCK            },
298   { "Function"       , COFF::IMAGE_SYM_CLASS_FUNCTION         },
299   { "EndOfStruct"    , COFF::IMAGE_SYM_CLASS_END_OF_STRUCT    },
300   { "File"           , COFF::IMAGE_SYM_CLASS_FILE             },
301   { "Section"        , COFF::IMAGE_SYM_CLASS_SECTION          },
302   { "WeakExternal"   , COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL    },
303   { "CLRToken"       , COFF::IMAGE_SYM_CLASS_CLR_TOKEN        }
304 };
305
306 static const EnumEntry<COFF::COMDATType> ImageCOMDATSelect[] = {
307   { "NoDuplicates", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES },
308   { "Any"         , COFF::IMAGE_COMDAT_SELECT_ANY          },
309   { "SameSize"    , COFF::IMAGE_COMDAT_SELECT_SAME_SIZE    },
310   { "ExactMatch"  , COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH  },
311   { "Associative" , COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE  },
312   { "Largest"     , COFF::IMAGE_COMDAT_SELECT_LARGEST      },
313   { "Newest"      , COFF::IMAGE_COMDAT_SELECT_NEWEST       }
314 };
315
316 static const EnumEntry<COFF::WeakExternalCharacteristics>
317 WeakExternalCharacteristics[] = {
318   { "NoLibrary", COFF::IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY },
319   { "Library"  , COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY   },
320   { "Alias"    , COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS     }
321 };
322
323 template <typename T>
324 static std::error_code getSymbolAuxData(const COFFObjectFile *Obj,
325                                         COFFSymbolRef Symbol,
326                                         uint8_t AuxSymbolIdx, const T *&Aux) {
327   ArrayRef<uint8_t> AuxData = Obj->getSymbolAuxData(Symbol);
328   AuxData = AuxData.slice(AuxSymbolIdx * Obj->getSymbolTableEntrySize());
329   Aux = reinterpret_cast<const T*>(AuxData.data());
330   return readobj_error::success;
331 }
332
333 void COFFDumper::cacheRelocations() {
334   for (const SectionRef &S : Obj->sections()) {
335     const coff_section *Section = Obj->getCOFFSection(S);
336
337     for (const RelocationRef &Reloc : S.relocations())
338       RelocMap[Section].push_back(Reloc);
339
340     // Sort relocations by address.
341     std::sort(RelocMap[Section].begin(), RelocMap[Section].end(),
342               relocAddressLess);
343   }
344 }
345
346 void COFFDumper::printDataDirectory(uint32_t Index, const std::string &FieldName) {
347   const data_directory *Data;
348   if (Obj->getDataDirectory(Index, Data))
349     return;
350   W.printHex(FieldName + "RVA", Data->RelativeVirtualAddress);
351   W.printHex(FieldName + "Size", Data->Size);
352 }
353
354 void COFFDumper::printFileHeaders() {
355   time_t TDS = Obj->getTimeDateStamp();
356   char FormattedTime[20] = { };
357   strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS));
358
359   {
360     DictScope D(W, "ImageFileHeader");
361     W.printEnum  ("Machine", Obj->getMachine(),
362                     makeArrayRef(ImageFileMachineType));
363     W.printNumber("SectionCount", Obj->getNumberOfSections());
364     W.printHex   ("TimeDateStamp", FormattedTime, Obj->getTimeDateStamp());
365     W.printHex   ("PointerToSymbolTable", Obj->getPointerToSymbolTable());
366     W.printNumber("SymbolCount", Obj->getNumberOfSymbols());
367     W.printNumber("OptionalHeaderSize", Obj->getSizeOfOptionalHeader());
368     W.printFlags ("Characteristics", Obj->getCharacteristics(),
369                     makeArrayRef(ImageFileCharacteristics));
370   }
371
372   // Print PE header. This header does not exist if this is an object file and
373   // not an executable.
374   const pe32_header *PEHeader = nullptr;
375   if (error(Obj->getPE32Header(PEHeader)))
376     return;
377   if (PEHeader)
378     printPEHeader<pe32_header>(PEHeader);
379
380   const pe32plus_header *PEPlusHeader = nullptr;
381   if (error(Obj->getPE32PlusHeader(PEPlusHeader)))
382     return;
383   if (PEPlusHeader)
384     printPEHeader<pe32plus_header>(PEPlusHeader);
385 }
386
387 template <class PEHeader>
388 void COFFDumper::printPEHeader(const PEHeader *Hdr) {
389   DictScope D(W, "ImageOptionalHeader");
390   W.printNumber("MajorLinkerVersion", Hdr->MajorLinkerVersion);
391   W.printNumber("MinorLinkerVersion", Hdr->MinorLinkerVersion);
392   W.printNumber("SizeOfCode", Hdr->SizeOfCode);
393   W.printNumber("SizeOfInitializedData", Hdr->SizeOfInitializedData);
394   W.printNumber("SizeOfUninitializedData", Hdr->SizeOfUninitializedData);
395   W.printHex   ("AddressOfEntryPoint", Hdr->AddressOfEntryPoint);
396   W.printHex   ("BaseOfCode", Hdr->BaseOfCode);
397   printBaseOfDataField(Hdr);
398   W.printHex   ("ImageBase", Hdr->ImageBase);
399   W.printNumber("SectionAlignment", Hdr->SectionAlignment);
400   W.printNumber("FileAlignment", Hdr->FileAlignment);
401   W.printNumber("MajorOperatingSystemVersion",
402                 Hdr->MajorOperatingSystemVersion);
403   W.printNumber("MinorOperatingSystemVersion",
404                 Hdr->MinorOperatingSystemVersion);
405   W.printNumber("MajorImageVersion", Hdr->MajorImageVersion);
406   W.printNumber("MinorImageVersion", Hdr->MinorImageVersion);
407   W.printNumber("MajorSubsystemVersion", Hdr->MajorSubsystemVersion);
408   W.printNumber("MinorSubsystemVersion", Hdr->MinorSubsystemVersion);
409   W.printNumber("SizeOfImage", Hdr->SizeOfImage);
410   W.printNumber("SizeOfHeaders", Hdr->SizeOfHeaders);
411   W.printEnum  ("Subsystem", Hdr->Subsystem, makeArrayRef(PEWindowsSubsystem));
412   W.printFlags ("Subsystem", Hdr->DLLCharacteristics,
413                 makeArrayRef(PEDLLCharacteristics));
414   W.printNumber("SizeOfStackReserve", Hdr->SizeOfStackReserve);
415   W.printNumber("SizeOfStackCommit", Hdr->SizeOfStackCommit);
416   W.printNumber("SizeOfHeapReserve", Hdr->SizeOfHeapReserve);
417   W.printNumber("SizeOfHeapCommit", Hdr->SizeOfHeapCommit);
418   W.printNumber("NumberOfRvaAndSize", Hdr->NumberOfRvaAndSize);
419
420   if (Hdr->NumberOfRvaAndSize > 0) {
421     DictScope D(W, "DataDirectory");
422     static const char * const directory[] = {
423       "ExportTable", "ImportTable", "ResourceTable", "ExceptionTable",
424       "CertificateTable", "BaseRelocationTable", "Debug", "Architecture",
425       "GlobalPtr", "TLSTable", "LoadConfigTable", "BoundImport", "IAT",
426       "DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"
427     };
428
429     for (uint32_t i = 0; i < Hdr->NumberOfRvaAndSize; ++i) {
430       printDataDirectory(i, directory[i]);
431     }
432   }
433 }
434
435 void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) {
436   W.printHex("BaseOfData", Hdr->BaseOfData);
437 }
438
439 void COFFDumper::printBaseOfDataField(const pe32plus_header *) {}
440
441 void COFFDumper::printCodeViewLineTables(const SectionRef &Section) {
442   StringRef Data;
443   if (error(Section.getContents(Data)))
444     return;
445
446   SmallVector<StringRef, 10> FunctionNames;
447   StringMap<StringRef> FunctionLineTables;
448
449   ListScope D(W, "CodeViewLineTables");
450   {
451     // FIXME: Add more offset correctness checks.
452     DataExtractor DE(Data, true, 4);
453     uint32_t Offset = 0,
454              Magic = DE.getU32(&Offset);
455     W.printHex("Magic", Magic);
456     if (Magic != COFF::DEBUG_SECTION_MAGIC) {
457       error(object_error::parse_failed);
458       return;
459     }
460
461     bool Finished = false;
462     while (DE.isValidOffset(Offset) && !Finished) {
463       // The section consists of a number of subsection in the following format:
464       // |Type|PayloadSize|Payload...|
465       uint32_t SubSectionType = DE.getU32(&Offset),
466                PayloadSize = DE.getU32(&Offset);
467       ListScope S(W, "Subsection");
468       W.printHex("Type", SubSectionType);
469       W.printHex("PayloadSize", PayloadSize);
470       if (PayloadSize > Data.size() - Offset) {
471         error(object_error::parse_failed);
472         return;
473       }
474
475       // Print the raw contents to simplify debugging if anything goes wrong
476       // afterwards.
477       StringRef Contents = Data.substr(Offset, PayloadSize);
478       W.printBinaryBlock("Contents", Contents);
479
480       switch (SubSectionType) {
481       case COFF::DEBUG_SYMBOL_SUBSECTION:
482         printCodeViewSymbolsSubsection(Contents, Section, Offset);
483         break;
484       case COFF::DEBUG_LINE_TABLE_SUBSECTION: {
485         // Holds a PC to file:line table.  Some data to parse this subsection is
486         // stored in the other subsections, so just check sanity and store the
487         // pointers for deferred processing.
488
489         if (PayloadSize < 12) {
490           // There should be at least three words to store two function
491           // relocations and size of the code.
492           error(object_error::parse_failed);
493           return;
494         }
495
496         StringRef FunctionName;
497         if (error(resolveSymbolName(Obj->getCOFFSection(Section), Offset,
498                                     FunctionName)))
499           return;
500         W.printString("FunctionName", FunctionName);
501         if (FunctionLineTables.count(FunctionName) != 0) {
502           // Saw debug info for this function already?
503           error(object_error::parse_failed);
504           return;
505         }
506
507         FunctionLineTables[FunctionName] = Contents;
508         FunctionNames.push_back(FunctionName);
509         break;
510       }
511       case COFF::DEBUG_STRING_TABLE_SUBSECTION:
512         if (PayloadSize == 0 || CVStringTable.data() != nullptr ||
513             Contents.back() != '\0') {
514           // Empty or duplicate or non-null-terminated subsection.
515           error(object_error::parse_failed);
516           return;
517         }
518         CVStringTable = Contents;
519         break;
520       case COFF::DEBUG_INDEX_SUBSECTION:
521         // Holds the translation table from file indices
522         // to offsets in the string table.
523
524         if (PayloadSize == 0 ||
525             CVFileIndexToStringOffsetTable.data() != nullptr) {
526           // Empty or duplicate subsection.
527           error(object_error::parse_failed);
528           return;
529         }
530         CVFileIndexToStringOffsetTable = Contents;
531         break;
532       }
533       Offset += PayloadSize;
534
535       // Align the reading pointer by 4.
536       Offset += (-Offset) % 4;
537     }
538   }
539
540   // Dump the line tables now that we've read all the subsections and know all
541   // the required information.
542   for (unsigned I = 0, E = FunctionNames.size(); I != E; ++I) {
543     StringRef Name = FunctionNames[I];
544     ListScope S(W, "FunctionLineTable");
545     W.printString("FunctionName", Name);
546
547     DataExtractor DE(FunctionLineTables[Name], true, 4);
548     uint32_t Offset = 8;  // Skip relocations.
549     uint32_t FunctionSize = DE.getU32(&Offset);
550     W.printHex("CodeSize", FunctionSize);
551     while (DE.isValidOffset(Offset)) {
552       // For each range of lines with the same filename, we have a segment
553       // in the line table.  The filename string is accessed using double
554       // indirection to the string table subsection using the index subsection.
555       uint32_t OffsetInIndex = DE.getU32(&Offset),
556                SegmentLength   = DE.getU32(&Offset),
557                FullSegmentSize = DE.getU32(&Offset);
558       if (FullSegmentSize != 12 + 8 * SegmentLength) {
559         error(object_error::parse_failed);
560         return;
561       }
562
563       uint32_t FilenameOffset;
564       {
565         DataExtractor SDE(CVFileIndexToStringOffsetTable, true, 4);
566         uint32_t OffsetInSDE = OffsetInIndex;
567         if (!SDE.isValidOffset(OffsetInSDE)) {
568           error(object_error::parse_failed);
569           return;
570         }
571         FilenameOffset = SDE.getU32(&OffsetInSDE);
572       }
573
574       if (FilenameOffset == 0 || FilenameOffset + 1 >= CVStringTable.size() ||
575           CVStringTable.data()[FilenameOffset - 1] != '\0') {
576         // Each string in an F3 subsection should be preceded by a null
577         // character.
578         error(object_error::parse_failed);
579         return;
580       }
581
582       StringRef Filename(CVStringTable.data() + FilenameOffset);
583       ListScope S(W, "FilenameSegment");
584       W.printString("Filename", Filename);
585       for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset);
586            ++J) {
587         // Then go the (PC, LineNumber) pairs.  The line number is stored in the
588         // least significant 31 bits of the respective word in the table.
589         uint32_t PC = DE.getU32(&Offset),
590                  LineNumber = DE.getU32(&Offset) & 0x7fffffff;
591         if (PC >= FunctionSize) {
592           error(object_error::parse_failed);
593           return;
594         }
595         char Buffer[32];
596         format("+0x%X", PC).snprint(Buffer, 32);
597         W.printNumber(Buffer, LineNumber);
598       }
599     }
600   }
601 }
602
603 void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
604                                                 const SectionRef &Section,
605                                                 uint32_t OffsetInSection) {
606   if (Subsection.size() == 0) {
607     error(object_error::parse_failed);
608     return;
609   }
610   DataExtractor DE(Subsection, true, 4);
611   uint32_t Offset = 0;
612
613   // Function-level subsections have "procedure start" and "procedure end"
614   // commands that should come in pairs and surround relevant info.
615   bool InFunctionScope = false;
616   while (DE.isValidOffset(Offset)) {
617     // Read subsection segments one by one.
618     uint16_t Size = DE.getU16(&Offset);
619     // The section size includes the size of the type identifier.
620     if (Size < 2 || !DE.isValidOffsetForDataOfSize(Offset, Size)) {
621       error(object_error::parse_failed);
622       return;
623     }
624     Size -= 2;
625     uint16_t Type = DE.getU16(&Offset);
626     switch (Type) {
627     case COFF::DEBUG_SYMBOL_TYPE_PROC_START: {
628       DictScope S(W, "ProcStart");
629       if (InFunctionScope || Size < 36) {
630         error(object_error::parse_failed);
631         return;
632       }
633       InFunctionScope = true;
634
635       // We're currently interested in a limited subset of fields in this
636       // segment, just ignore the rest of the fields for now.
637       uint8_t Unused[12];
638       DE.getU8(&Offset, Unused, 12);
639       uint32_t CodeSize = DE.getU32(&Offset);
640       DE.getU8(&Offset, Unused, 12);
641       StringRef SectionName;
642       if (error(resolveSymbolName(Obj->getCOFFSection(Section),
643                                   OffsetInSection + Offset, SectionName)))
644         return;
645       Offset += 4;
646       DE.getU8(&Offset, Unused, 3);
647       StringRef FunctionName = DE.getCStr(&Offset);
648       if (!DE.isValidOffset(Offset)) {
649         error(object_error::parse_failed);
650         return;
651       }
652       W.printString("FunctionName", FunctionName);
653       W.printString("Section", SectionName);
654       W.printHex("CodeSize", CodeSize);
655
656       break;
657     }
658     case COFF::DEBUG_SYMBOL_TYPE_PROC_END: {
659       W.startLine() << "ProcEnd\n";
660       if (!InFunctionScope || Size > 0) {
661         error(object_error::parse_failed);
662         return;
663       }
664       InFunctionScope = false;
665       break;
666     }
667     default:
668       Offset += Size;
669       break;
670     }
671   }
672
673   if (InFunctionScope)
674     error(object_error::parse_failed);
675 }
676
677 void COFFDumper::printSections() {
678   ListScope SectionsD(W, "Sections");
679   int SectionNumber = 0;
680   for (const SectionRef &Sec : Obj->sections()) {
681     ++SectionNumber;
682     const coff_section *Section = Obj->getCOFFSection(Sec);
683
684     StringRef Name;
685     if (error(Sec.getName(Name)))
686       Name = "";
687
688     DictScope D(W, "Section");
689     W.printNumber("Number", SectionNumber);
690     W.printBinary("Name", Name, Section->Name);
691     W.printHex   ("VirtualSize", Section->VirtualSize);
692     W.printHex   ("VirtualAddress", Section->VirtualAddress);
693     W.printNumber("RawDataSize", Section->SizeOfRawData);
694     W.printHex   ("PointerToRawData", Section->PointerToRawData);
695     W.printHex   ("PointerToRelocations", Section->PointerToRelocations);
696     W.printHex   ("PointerToLineNumbers", Section->PointerToLinenumbers);
697     W.printNumber("RelocationCount", Section->NumberOfRelocations);
698     W.printNumber("LineNumberCount", Section->NumberOfLinenumbers);
699     W.printFlags ("Characteristics", Section->Characteristics,
700                     makeArrayRef(ImageSectionCharacteristics),
701                     COFF::SectionCharacteristics(0x00F00000));
702
703     if (opts::SectionRelocations) {
704       ListScope D(W, "Relocations");
705       for (const RelocationRef &Reloc : Sec.relocations())
706         printRelocation(Sec, Reloc);
707     }
708
709     if (opts::SectionSymbols) {
710       ListScope D(W, "Symbols");
711       for (const SymbolRef &Symbol : Obj->symbols()) {
712         if (!Sec.containsSymbol(Symbol))
713           continue;
714
715         printSymbol(Symbol);
716       }
717     }
718
719     if (Name == ".debug$S" && opts::CodeViewLineTables)
720       printCodeViewLineTables(Sec);
721
722     if (opts::SectionData &&
723         !(Section->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) {
724       StringRef Data;
725       if (error(Sec.getContents(Data)))
726         break;
727
728       W.printBinaryBlock("SectionData", Data);
729     }
730   }
731 }
732
733 void COFFDumper::printRelocations() {
734   ListScope D(W, "Relocations");
735
736   int SectionNumber = 0;
737   for (const SectionRef &Section : Obj->sections()) {
738     ++SectionNumber;
739     StringRef Name;
740     if (error(Section.getName(Name)))
741       continue;
742
743     bool PrintedGroup = false;
744     for (const RelocationRef &Reloc : Section.relocations()) {
745       if (!PrintedGroup) {
746         W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";
747         W.indent();
748         PrintedGroup = true;
749       }
750
751       printRelocation(Section, Reloc);
752     }
753
754     if (PrintedGroup) {
755       W.unindent();
756       W.startLine() << "}\n";
757     }
758   }
759 }
760
761 void COFFDumper::printRelocation(const SectionRef &Section,
762                                  const RelocationRef &Reloc) {
763   uint64_t Offset;
764   uint64_t RelocType;
765   SmallString<32> RelocName;
766   StringRef SymbolName;
767   StringRef Contents;
768   if (error(Reloc.getOffset(Offset)))
769     return;
770   if (error(Reloc.getType(RelocType)))
771     return;
772   if (error(Reloc.getTypeName(RelocName)))
773     return;
774   symbol_iterator Symbol = Reloc.getSymbol();
775   if (error(Symbol->getName(SymbolName)))
776     return;
777   if (error(Section.getContents(Contents)))
778     return;
779
780   if (opts::ExpandRelocs) {
781     DictScope Group(W, "Relocation");
782     W.printHex("Offset", Offset);
783     W.printNumber("Type", RelocName, RelocType);
784     W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-");
785   } else {
786     raw_ostream& OS = W.startLine();
787     OS << W.hex(Offset)
788        << " " << RelocName
789        << " " << (SymbolName.size() > 0 ? SymbolName : "-")
790        << "\n";
791   }
792 }
793
794 void COFFDumper::printSymbols() {
795   ListScope Group(W, "Symbols");
796
797   for (const SymbolRef &Symbol : Obj->symbols())
798     printSymbol(Symbol);
799 }
800
801 void COFFDumper::printDynamicSymbols() { ListScope Group(W, "DynamicSymbols"); }
802
803 static StringRef getSectionName(const llvm::object::COFFObjectFile *Obj,
804                                 COFFSymbolRef Symbol,
805                                 const coff_section *Section) {
806   if (Section) {
807     StringRef SectionName;
808     Obj->getSectionName(Section, SectionName);
809     return SectionName;
810   }
811   int32_t SectionNumber = Symbol.getSectionNumber();
812   if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG)
813     return "IMAGE_SYM_DEBUG";
814   if (SectionNumber == llvm::COFF::IMAGE_SYM_ABSOLUTE)
815     return "IMAGE_SYM_ABSOLUTE";
816   if (SectionNumber == llvm::COFF::IMAGE_SYM_UNDEFINED)
817     return "IMAGE_SYM_UNDEFINED";
818   return "";
819 }
820
821 void COFFDumper::printSymbol(const SymbolRef &Sym) {
822   DictScope D(W, "Symbol");
823
824   COFFSymbolRef Symbol = Obj->getCOFFSymbol(Sym);
825   const coff_section *Section;
826   if (std::error_code EC = Obj->getSection(Symbol.getSectionNumber(), Section)) {
827     W.startLine() << "Invalid section number: " << EC.message() << "\n";
828     W.flush();
829     return;
830   }
831
832   StringRef SymbolName;
833   if (Obj->getSymbolName(Symbol, SymbolName))
834     SymbolName = "";
835
836   StringRef SectionName = getSectionName(Obj, Symbol, Section);
837
838   W.printString("Name", SymbolName);
839   W.printNumber("Value", Symbol.getValue());
840   W.printNumber("Section", SectionName, Symbol.getSectionNumber());
841   W.printEnum  ("BaseType", Symbol.getBaseType(), makeArrayRef(ImageSymType));
842   W.printEnum  ("ComplexType", Symbol.getComplexType(),
843                                                    makeArrayRef(ImageSymDType));
844   W.printEnum  ("StorageClass", Symbol.getStorageClass(),
845                                                    makeArrayRef(ImageSymClass));
846   W.printNumber("AuxSymbolCount", Symbol.getNumberOfAuxSymbols());
847
848   for (uint8_t I = 0; I < Symbol.getNumberOfAuxSymbols(); ++I) {
849     if (Symbol.isFunctionDefinition()) {
850       const coff_aux_function_definition *Aux;
851       if (error(getSymbolAuxData(Obj, Symbol, I, Aux)))
852         break;
853
854       DictScope AS(W, "AuxFunctionDef");
855       W.printNumber("TagIndex", Aux->TagIndex);
856       W.printNumber("TotalSize", Aux->TotalSize);
857       W.printHex("PointerToLineNumber", Aux->PointerToLinenumber);
858       W.printHex("PointerToNextFunction", Aux->PointerToNextFunction);
859
860     } else if (Symbol.isWeakExternal()) {
861       const coff_aux_weak_external *Aux;
862       if (error(getSymbolAuxData(Obj, Symbol, I, Aux)))
863         break;
864
865       ErrorOr<COFFSymbolRef> Linked = Obj->getSymbol(Aux->TagIndex);
866       StringRef LinkedName;
867       std::error_code EC = Linked.getError();
868       if (EC || (EC = Obj->getSymbolName(*Linked, LinkedName))) {
869         LinkedName = "";
870         error(EC);
871       }
872
873       DictScope AS(W, "AuxWeakExternal");
874       W.printNumber("Linked", LinkedName, Aux->TagIndex);
875       W.printEnum  ("Search", Aux->Characteristics,
876                     makeArrayRef(WeakExternalCharacteristics));
877
878     } else if (Symbol.isFileRecord()) {
879       const char *FileName;
880       if (error(getSymbolAuxData(Obj, Symbol, I, FileName)))
881         break;
882
883       DictScope AS(W, "AuxFileRecord");
884
885       StringRef Name(FileName, Symbol.getNumberOfAuxSymbols() *
886                                    Obj->getSymbolTableEntrySize());
887       W.printString("FileName", Name.rtrim(StringRef("\0", 1)));
888       break;
889     } else if (Symbol.isSectionDefinition()) {
890       const coff_aux_section_definition *Aux;
891       if (error(getSymbolAuxData(Obj, Symbol, I, Aux)))
892         break;
893
894       int32_t AuxNumber = Aux->getNumber(Symbol.isBigObj());
895
896       DictScope AS(W, "AuxSectionDef");
897       W.printNumber("Length", Aux->Length);
898       W.printNumber("RelocationCount", Aux->NumberOfRelocations);
899       W.printNumber("LineNumberCount", Aux->NumberOfLinenumbers);
900       W.printHex("Checksum", Aux->CheckSum);
901       W.printNumber("Number", AuxNumber);
902       W.printEnum("Selection", Aux->Selection, makeArrayRef(ImageCOMDATSelect));
903
904       if (Section && Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT
905           && Aux->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
906         const coff_section *Assoc;
907         StringRef AssocName;
908         std::error_code EC;
909         if ((EC = Obj->getSection(AuxNumber, Assoc)) ||
910             (EC = Obj->getSectionName(Assoc, AssocName))) {
911           AssocName = "";
912           error(EC);
913         }
914
915         W.printNumber("AssocSection", AssocName, AuxNumber);
916       }
917     } else if (Symbol.isCLRToken()) {
918       const coff_aux_clr_token *Aux;
919       if (error(getSymbolAuxData(Obj, Symbol, I, Aux)))
920         break;
921
922       ErrorOr<COFFSymbolRef> ReferredSym =
923           Obj->getSymbol(Aux->SymbolTableIndex);
924       StringRef ReferredName;
925       std::error_code EC = ReferredSym.getError();
926       if (EC || (EC = Obj->getSymbolName(*ReferredSym, ReferredName))) {
927         ReferredName = "";
928         error(EC);
929       }
930
931       DictScope AS(W, "AuxCLRToken");
932       W.printNumber("AuxType", Aux->AuxType);
933       W.printNumber("Reserved", Aux->Reserved);
934       W.printNumber("SymbolTableIndex", ReferredName, Aux->SymbolTableIndex);
935
936     } else {
937       W.startLine() << "<unhandled auxiliary record>\n";
938     }
939   }
940 }
941
942 void COFFDumper::printUnwindInfo() {
943   ListScope D(W, "UnwindInformation");
944   switch (Obj->getMachine()) {
945   case COFF::IMAGE_FILE_MACHINE_AMD64: {
946     Win64EH::Dumper Dumper(W);
947     Win64EH::Dumper::SymbolResolver
948     Resolver = [](const object::coff_section *Section, uint64_t Offset,
949                   SymbolRef &Symbol, void *user_data) -> std::error_code {
950       COFFDumper *Dumper = reinterpret_cast<COFFDumper *>(user_data);
951       return Dumper->resolveSymbol(Section, Offset, Symbol);
952     };
953     Win64EH::Dumper::Context Ctx(*Obj, Resolver, this);
954     Dumper.printData(Ctx);
955     break;
956   }
957   case COFF::IMAGE_FILE_MACHINE_ARMNT: {
958     ARM::WinEH::Decoder Decoder(W);
959     Decoder.dumpProcedureData(*Obj);
960     break;
961   }
962   default:
963     W.printEnum("unsupported Image Machine", Obj->getMachine(),
964                 makeArrayRef(ImageFileMachineType));
965     break;
966   }
967 }
968
969 void COFFDumper::printImportedSymbols(
970     iterator_range<imported_symbol_iterator> Range) {
971   for (const ImportedSymbolRef &I : Range) {
972     StringRef Sym;
973     if (error(I.getSymbolName(Sym))) return;
974     uint16_t Ordinal;
975     if (error(I.getOrdinal(Ordinal))) return;
976     W.printNumber("Symbol", Sym, Ordinal);
977   }
978 }
979
980 void COFFDumper::printCOFFImports() {
981   // Regular imports
982   for (const ImportDirectoryEntryRef &I : Obj->import_directories()) {
983     DictScope Import(W, "Import");
984     StringRef Name;
985     if (error(I.getName(Name))) return;
986     W.printString("Name", Name);
987     uint32_t Addr;
988     if (error(I.getImportLookupTableRVA(Addr))) return;
989     W.printHex("ImportLookupTableRVA", Addr);
990     if (error(I.getImportAddressTableRVA(Addr))) return;
991     W.printHex("ImportAddressTableRVA", Addr);
992     printImportedSymbols(I.imported_symbols());
993   }
994
995   // Delay imports
996   for (const DelayImportDirectoryEntryRef &I : Obj->delay_import_directories()) {
997     DictScope Import(W, "DelayImport");
998     StringRef Name;
999     if (error(I.getName(Name))) return;
1000     W.printString("Name", Name);
1001     const delay_import_directory_table_entry *Table;
1002     if (error(I.getDelayImportTable(Table))) return;
1003     W.printHex("Attributes", Table->Attributes);
1004     W.printHex("ModuleHandle", Table->ModuleHandle);
1005     W.printHex("ImportAddressTable", Table->DelayImportAddressTable);
1006     W.printHex("ImportNameTable", Table->DelayImportNameTable);
1007     W.printHex("BoundDelayImportTable", Table->BoundDelayImportTable);
1008     W.printHex("UnloadDelayImportTable", Table->UnloadDelayImportTable);
1009     printImportedSymbols(I.imported_symbols());
1010   }
1011 }
1012
1013 void COFFDumper::printCOFFDirectives() {
1014   for (const SectionRef &Section : Obj->sections()) {
1015     StringRef Contents;
1016     StringRef Name;
1017
1018     if (error(Section.getName(Name)))
1019       continue;
1020     if (Name != ".drectve")
1021       continue;
1022
1023     if (error(Section.getContents(Contents)))
1024       return;
1025
1026     W.printString("Directive(s)", Contents);
1027   }
1028 }