blob: ba7ac9140b9221b0519671b85b241318bcadfdbd [file] [log] [blame]
Eric Christopher9cad53c2013-04-03 18:31:38 +00001//===-- 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"
Rafael Espindolaa6e9c3e2014-06-12 17:38:55 +000016#include "ARMWinEHPrinter.h"
Reid Kleckner72e2ba72016-01-13 19:32:35 +000017#include "CodeView.h"
Eric Christopher9cad53c2013-04-03 18:31:38 +000018#include "Error.h"
Chandler Carruth07baed52014-01-13 08:04:33 +000019#include "ObjDumper.h"
Lang Hames0000afd2015-06-26 23:56:53 +000020#include "StackMapPrinter.h"
Eric Christopher9cad53c2013-04-03 18:31:38 +000021#include "StreamWriter.h"
Saleem Abdulrasoole8839a72014-05-25 20:26:45 +000022#include "Win64EHDumper.h"
Eric Christopher9cad53c2013-04-03 18:31:38 +000023#include "llvm/ADT/DenseMap.h"
24#include "llvm/ADT/SmallString.h"
Colin LeMahieu9fbffee2014-11-19 17:10:39 +000025#include "llvm/ADT/StringExtras.h"
Reid Kleckner72e2ba72016-01-13 19:32:35 +000026#include "llvm/ADT/StringSet.h"
Reid Kleckner6b3faef2016-01-13 23:44:57 +000027#include "llvm/DebugInfo/CodeView/CodeView.h"
Reid Klecknere9ab3492016-01-14 19:20:17 +000028#include "llvm/DebugInfo/CodeView/Line.h"
Reid Kleckner6b3faef2016-01-13 23:44:57 +000029#include "llvm/DebugInfo/CodeView/TypeIndex.h"
30#include "llvm/DebugInfo/CodeView/TypeRecord.h"
31#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
Eric Christopher9cad53c2013-04-03 18:31:38 +000032#include "llvm/Object/COFF.h"
33#include "llvm/Object/ObjectFile.h"
Chandler Carruth07baed52014-01-13 08:04:33 +000034#include "llvm/Support/COFF.h"
Eric Christopher9cad53c2013-04-03 18:31:38 +000035#include "llvm/Support/Casting.h"
36#include "llvm/Support/Compiler.h"
Timur Iskhodzhanov48703be2013-12-19 11:37:14 +000037#include "llvm/Support/DataExtractor.h"
Eric Christopher9cad53c2013-04-03 18:31:38 +000038#include "llvm/Support/Format.h"
39#include "llvm/Support/SourceMgr.h"
40#include "llvm/Support/Win64EH.h"
41#include "llvm/Support/raw_ostream.h"
Eric Christopher9cad53c2013-04-03 18:31:38 +000042#include <algorithm>
43#include <cstring>
Rafael Espindolaa6e9c3e2014-06-12 17:38:55 +000044#include <system_error>
Eric Christopher9cad53c2013-04-03 18:31:38 +000045#include <time.h>
46
47using namespace llvm;
48using namespace llvm::object;
Reid Kleckner72e2ba72016-01-13 19:32:35 +000049using namespace llvm::codeview;
Reid Kleckner6b3faef2016-01-13 23:44:57 +000050using namespace llvm::support;
Eric Christopher9cad53c2013-04-03 18:31:38 +000051using namespace llvm::Win64EH;
52
53namespace {
54
55class COFFDumper : public ObjDumper {
56public:
57 COFFDumper(const llvm::object::COFFObjectFile *Obj, StreamWriter& Writer)
58 : ObjDumper(Writer)
59 , Obj(Obj) {
Eric Christopher9cad53c2013-04-03 18:31:38 +000060 }
61
Craig Topperfd38cbe2014-08-30 16:48:34 +000062 void printFileHeaders() override;
63 void printSections() override;
64 void printRelocations() override;
65 void printSymbols() override;
66 void printDynamicSymbols() override;
67 void printUnwindInfo() override;
Rui Ueyama1e152d52014-10-02 17:02:18 +000068 void printCOFFImports() override;
Saleem Abdulrasoolddd92642015-01-03 21:35:09 +000069 void printCOFFExports() override;
Saleem Abdulrasoolf9578632014-10-07 19:37:52 +000070 void printCOFFDirectives() override;
Rui Ueyama74e85132014-11-19 00:18:07 +000071 void printCOFFBaseReloc() override;
Reid Kleckner83ebad32015-12-16 18:28:12 +000072 void printCodeViewDebugInfo() override;
Lang Hames0000afd2015-06-26 23:56:53 +000073 void printStackMap() const override;
Eric Christopher9cad53c2013-04-03 18:31:38 +000074private:
Alexey Samsonov27dc8392014-03-18 06:53:02 +000075 void printSymbol(const SymbolRef &Sym);
Reid Kleckner1c7a9cd2016-01-14 17:51:57 +000076 void printRelocation(const SectionRef &Section, const RelocationRef &Reloc,
77 uint64_t Bias = 0);
Rui Ueyamaed64342b2013-07-19 23:23:29 +000078 void printDataDirectory(uint32_t Index, const std::string &FieldName);
Eric Christopher9cad53c2013-04-03 18:31:38 +000079
David Majnemer50267222014-11-05 06:24:35 +000080 void printDOSHeader(const dos_header *DH);
Rui Ueyama10ed9dd2014-01-26 04:15:52 +000081 template <class PEHeader> void printPEHeader(const PEHeader *Hdr);
82 void printBaseOfDataField(const pe32_header *Hdr);
83 void printBaseOfDataField(const pe32plus_header *Hdr);
84
Reid Kleckner72e2ba72016-01-13 19:32:35 +000085 void printCodeViewSymbolSection(StringRef SectionName, const SectionRef &Section);
86 void printCodeViewTypeSection(StringRef SectionName, const SectionRef &Section);
87 void printCodeViewFieldList(StringRef FieldData);
88 StringRef getTypeName(TypeIndex Ty);
Reid Kleckner8e7275c2016-01-15 00:11:21 +000089 StringRef getFileNameForFileOffset(uint32_t FileOffset);
90 void printFileNameForOffset(StringRef Label, uint32_t FileOffset);
Reid Kleckner72e2ba72016-01-13 19:32:35 +000091 void printTypeIndex(StringRef FieldName, TypeIndex TI);
Timur Iskhodzhanov48703be2013-12-19 11:37:14 +000092
Timur Iskhodzhanov56af52f2014-10-23 22:25:31 +000093 void printCodeViewSymbolsSubsection(StringRef Subsection,
94 const SectionRef &Section,
Reid Kleckner2893fd12016-01-14 17:51:54 +000095 StringRef SectionContents);
Timur Iskhodzhanov56af52f2014-10-23 22:25:31 +000096
Reid Klecknere9ab3492016-01-14 19:20:17 +000097 void printCodeViewInlineeLines(StringRef Subsection);
98
Reid Kleckner72e2ba72016-01-13 19:32:35 +000099 void printMemberAttributes(MemberAttributes Attrs);
100
Reid Kleckner2893fd12016-01-14 17:51:54 +0000101 void printRelocatedField(StringRef Label, const coff_section *Sec,
102 StringRef SectionContents, const ulittle32_t *Field,
103 StringRef *RelocSym = nullptr);
104
Reid Kleckner1c7a9cd2016-01-14 17:51:57 +0000105 void printBinaryBlockWithRelocs(StringRef Label, const SectionRef &Sec,
106 StringRef SectionContents, StringRef Block);
107
Reid Kleckner8e7275c2016-01-15 00:11:21 +0000108 /// Given a .debug$S section, find the string table and file checksum table.
109 void initializeFileAndStringTables(StringRef Data);
110
Eric Christopher9cad53c2013-04-03 18:31:38 +0000111 void cacheRelocations();
112
Rafael Espindola4453e42942014-06-13 03:07:50 +0000113 std::error_code resolveSymbol(const coff_section *Section, uint64_t Offset,
114 SymbolRef &Sym);
115 std::error_code resolveSymbolName(const coff_section *Section,
116 uint64_t Offset, StringRef &Name);
Reid Kleckner2893fd12016-01-14 17:51:54 +0000117 std::error_code resolveSymbolName(const coff_section *Section,
118 StringRef SectionContents,
119 const void *RelocPtr, StringRef &Name);
Rui Ueyama979fb402014-10-09 02:16:38 +0000120 void printImportedSymbols(iterator_range<imported_symbol_iterator> Range);
Rui Ueyamaffa4ceb2014-11-13 03:22:54 +0000121 void printDelayImportedSymbols(
122 const DelayImportDirectoryEntryRef &I,
123 iterator_range<imported_symbol_iterator> Range);
Rui Ueyama15d99352014-10-03 00:41:58 +0000124
Eric Christopher9cad53c2013-04-03 18:31:38 +0000125 typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy;
126
127 const llvm::object::COFFObjectFile *Obj;
Rafael Espindola76d650e2015-07-06 14:26:07 +0000128 bool RelocCached = false;
Eric Christopher9cad53c2013-04-03 18:31:38 +0000129 RelocMapTy RelocMap;
Reid Kleckner8e7275c2016-01-15 00:11:21 +0000130 StringRef CVFileChecksumTable;
Timur Iskhodzhanov11603332014-10-06 16:59:44 +0000131 StringRef CVStringTable;
Reid Kleckner72e2ba72016-01-13 19:32:35 +0000132
133 /// All user defined type records in .debug$T live in here. Type indices
134 /// greater than 0x1000 are user defined. Subtract 0x1000 from the index to
135 /// index into this vector.
136 SmallVector<StringRef, 10> CVUDTNames;
137
138 StringSet<> TypeNames;
Eric Christopher9cad53c2013-04-03 18:31:38 +0000139};
140
141} // namespace
142
143
144namespace llvm {
145
Rafael Espindola4453e42942014-06-13 03:07:50 +0000146std::error_code createCOFFDumper(const object::ObjectFile *Obj,
147 StreamWriter &Writer,
148 std::unique_ptr<ObjDumper> &Result) {
Eric Christopher9cad53c2013-04-03 18:31:38 +0000149 const COFFObjectFile *COFFObj = dyn_cast<COFFObjectFile>(Obj);
150 if (!COFFObj)
151 return readobj_error::unsupported_obj_file_format;
152
153 Result.reset(new COFFDumper(COFFObj, Writer));
154 return readobj_error::success;
155}
156
157} // namespace llvm
158
Saleem Abdulrasool5dd27f42014-05-25 20:26:37 +0000159// Given a a section and an offset into this section the function returns the
160// symbol used for the relocation at the offset.
Rafael Espindola4453e42942014-06-13 03:07:50 +0000161std::error_code COFFDumper::resolveSymbol(const coff_section *Section,
162 uint64_t Offset, SymbolRef &Sym) {
Rafael Espindola76d650e2015-07-06 14:26:07 +0000163 cacheRelocations();
Saleem Abdulrasool5dd27f42014-05-25 20:26:37 +0000164 const auto &Relocations = RelocMap[Section];
165 for (const auto &Relocation : Relocations) {
Rafael Espindola96d071c2015-06-29 23:29:12 +0000166 uint64_t RelocationOffset = Relocation.getOffset();
Eric Christopher9cad53c2013-04-03 18:31:38 +0000167
Saleem Abdulrasool5dd27f42014-05-25 20:26:37 +0000168 if (RelocationOffset == Offset) {
Saleem Abdulrasool4a6f5832014-05-20 05:18:06 +0000169 Sym = *Relocation.getSymbol();
Eric Christopher9cad53c2013-04-03 18:31:38 +0000170 return readobj_error::success;
171 }
172 }
Eric Christopher9cad53c2013-04-03 18:31:38 +0000173 return readobj_error::unknown_symbol;
174}
175
Saleem Abdulrasool5dd27f42014-05-25 20:26:37 +0000176// Given a section and an offset into this section the function returns the name
177// of the symbol used for the relocation at the offset.
Rafael Espindola4453e42942014-06-13 03:07:50 +0000178std::error_code COFFDumper::resolveSymbolName(const coff_section *Section,
179 uint64_t Offset,
180 StringRef &Name) {
Saleem Abdulrasool5dd27f42014-05-25 20:26:37 +0000181 SymbolRef Symbol;
Rafael Espindola4453e42942014-06-13 03:07:50 +0000182 if (std::error_code EC = resolveSymbol(Section, Offset, Symbol))
Saleem Abdulrasool5dd27f42014-05-25 20:26:37 +0000183 return EC;
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +0000184 ErrorOr<StringRef> NameOrErr = Symbol.getName();
185 if (std::error_code EC = NameOrErr.getError())
Saleem Abdulrasool5dd27f42014-05-25 20:26:37 +0000186 return EC;
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +0000187 Name = *NameOrErr;
Rui Ueyama7d099192015-06-09 15:20:42 +0000188 return std::error_code();
Eric Christopher9cad53c2013-04-03 18:31:38 +0000189}
190
Reid Kleckner2893fd12016-01-14 17:51:54 +0000191// Helper for when you have a pointer to real data and you want to know about
192// relocations against it.
193std::error_code COFFDumper::resolveSymbolName(const coff_section *Section,
194 StringRef SectionContents,
195 const void *RelocPtr,
196 StringRef &Name) {
197 assert(SectionContents.data() < RelocPtr &&
198 RelocPtr < SectionContents.data() + SectionContents.size() &&
199 "pointer to relocated object is not in section");
200 uint64_t Offset = ptrdiff_t(reinterpret_cast<const char *>(RelocPtr) -
201 SectionContents.data());
202 return resolveSymbolName(Section, Offset, Name);
203}
204
205void COFFDumper::printRelocatedField(StringRef Label, const coff_section *Sec,
206 StringRef SectionContents,
207 const ulittle32_t *Field,
208 StringRef *RelocSym) {
209 StringRef SymStorage;
210 StringRef &Symbol = RelocSym ? *RelocSym : SymStorage;
211 if (!resolveSymbolName(Sec, SectionContents, Field, Symbol))
212 W.printSymbolOffset(Label, Symbol, *Field);
213 else
214 W.printHex(Label, *Field);
215}
216
Reid Kleckner1c7a9cd2016-01-14 17:51:57 +0000217void COFFDumper::printBinaryBlockWithRelocs(StringRef Label,
218 const SectionRef &Sec,
219 StringRef SectionContents,
220 StringRef Block) {
221 W.printBinaryBlock(Label, Block);
222
223 assert(SectionContents.begin() < Block.begin() &&
224 SectionContents.end() >= Block.end() &&
225 "Block is not contained in SectionContents");
226 uint64_t OffsetStart = Block.data() - SectionContents.data();
227 uint64_t OffsetEnd = OffsetStart + Block.size();
228
229 cacheRelocations();
230 ListScope D(W, "BlockRelocations");
231 const coff_section *Section = Obj->getCOFFSection(Sec);
232 const auto &Relocations = RelocMap[Section];
233 for (const auto &Relocation : Relocations) {
234 uint64_t RelocationOffset = Relocation.getOffset();
235 if (OffsetStart <= RelocationOffset && RelocationOffset < OffsetEnd)
236 printRelocation(Sec, Relocation, OffsetStart);
237 }
238}
239
Eric Christopher9cad53c2013-04-03 18:31:38 +0000240static const EnumEntry<COFF::MachineTypes> ImageFileMachineType[] = {
241 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_UNKNOWN ),
242 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AM33 ),
243 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AMD64 ),
244 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM ),
Saleem Abdulrasool5e1780e2014-03-11 03:08:37 +0000245 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARMNT ),
Eric Christopher9cad53c2013-04-03 18:31:38 +0000246 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_EBC ),
247 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_I386 ),
248 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_IA64 ),
249 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_M32R ),
250 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPS16 ),
251 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU ),
252 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU16),
253 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPC ),
254 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPCFP),
255 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_R4000 ),
256 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3 ),
257 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3DSP ),
258 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH4 ),
259 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH5 ),
260 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_THUMB ),
261 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_WCEMIPSV2)
262};
263
264static const EnumEntry<COFF::Characteristics> ImageFileCharacteristics[] = {
265 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_RELOCS_STRIPPED ),
266 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_EXECUTABLE_IMAGE ),
267 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LINE_NUMS_STRIPPED ),
268 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LOCAL_SYMS_STRIPPED ),
269 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_AGGRESSIVE_WS_TRIM ),
270 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LARGE_ADDRESS_AWARE ),
271 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_BYTES_REVERSED_LO ),
272 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_32BIT_MACHINE ),
273 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_DEBUG_STRIPPED ),
274 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP),
275 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_NET_RUN_FROM_SWAP ),
276 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_SYSTEM ),
277 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_DLL ),
278 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_UP_SYSTEM_ONLY ),
279 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_BYTES_REVERSED_HI )
280};
281
Rui Ueyama82ebd8e2013-06-12 19:10:33 +0000282static const EnumEntry<COFF::WindowsSubsystem> PEWindowsSubsystem[] = {
283 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_UNKNOWN ),
284 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_NATIVE ),
285 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_GUI ),
286 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CUI ),
287 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_POSIX_CUI ),
288 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI ),
289 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_APPLICATION ),
290 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER),
291 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER ),
292 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_ROM ),
293 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_XBOX ),
294};
295
296static const EnumEntry<COFF::DLLCharacteristics> PEDLLCharacteristics[] = {
Rui Ueyama06dc5e72014-01-27 04:22:24 +0000297 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA ),
Rui Ueyama82ebd8e2013-06-12 19:10:33 +0000298 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE ),
299 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY ),
300 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT ),
301 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION ),
302 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_SEH ),
303 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_BIND ),
Saleem Abdulrasoold90f86d2014-06-27 03:11:18 +0000304 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_APPCONTAINER ),
Rui Ueyama82ebd8e2013-06-12 19:10:33 +0000305 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER ),
Saleem Abdulrasoold90f86d2014-06-27 03:11:18 +0000306 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_GUARD_CF ),
Rui Ueyama82ebd8e2013-06-12 19:10:33 +0000307 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE),
308};
309
Eric Christopher9cad53c2013-04-03 18:31:38 +0000310static const EnumEntry<COFF::SectionCharacteristics>
311ImageSectionCharacteristics[] = {
David Majnemerd3238882015-07-30 16:47:56 +0000312 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NOLOAD ),
Eric Christopher9cad53c2013-04-03 18:31:38 +0000313 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NO_PAD ),
314 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_CODE ),
315 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_INITIALIZED_DATA ),
316 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_UNINITIALIZED_DATA),
317 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_OTHER ),
318 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_INFO ),
319 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_REMOVE ),
320 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_COMDAT ),
321 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_GPREL ),
322 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_PURGEABLE ),
323 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_16BIT ),
324 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_LOCKED ),
325 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_PRELOAD ),
326 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1BYTES ),
327 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2BYTES ),
328 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4BYTES ),
329 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8BYTES ),
330 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_16BYTES ),
331 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_32BYTES ),
332 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_64BYTES ),
333 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_128BYTES ),
334 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_256BYTES ),
335 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_512BYTES ),
336 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1024BYTES ),
337 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2048BYTES ),
338 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4096BYTES ),
339 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8192BYTES ),
340 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_NRELOC_OVFL ),
341 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_DISCARDABLE ),
342 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_CACHED ),
343 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_PAGED ),
344 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_SHARED ),
345 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_EXECUTE ),
346 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_READ ),
347 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_WRITE )
348};
349
350static const EnumEntry<COFF::SymbolBaseType> ImageSymType[] = {
351 { "Null" , COFF::IMAGE_SYM_TYPE_NULL },
352 { "Void" , COFF::IMAGE_SYM_TYPE_VOID },
353 { "Char" , COFF::IMAGE_SYM_TYPE_CHAR },
354 { "Short" , COFF::IMAGE_SYM_TYPE_SHORT },
355 { "Int" , COFF::IMAGE_SYM_TYPE_INT },
356 { "Long" , COFF::IMAGE_SYM_TYPE_LONG },
357 { "Float" , COFF::IMAGE_SYM_TYPE_FLOAT },
358 { "Double", COFF::IMAGE_SYM_TYPE_DOUBLE },
359 { "Struct", COFF::IMAGE_SYM_TYPE_STRUCT },
360 { "Union" , COFF::IMAGE_SYM_TYPE_UNION },
361 { "Enum" , COFF::IMAGE_SYM_TYPE_ENUM },
362 { "MOE" , COFF::IMAGE_SYM_TYPE_MOE },
363 { "Byte" , COFF::IMAGE_SYM_TYPE_BYTE },
364 { "Word" , COFF::IMAGE_SYM_TYPE_WORD },
365 { "UInt" , COFF::IMAGE_SYM_TYPE_UINT },
366 { "DWord" , COFF::IMAGE_SYM_TYPE_DWORD }
367};
368
369static const EnumEntry<COFF::SymbolComplexType> ImageSymDType[] = {
370 { "Null" , COFF::IMAGE_SYM_DTYPE_NULL },
371 { "Pointer" , COFF::IMAGE_SYM_DTYPE_POINTER },
372 { "Function", COFF::IMAGE_SYM_DTYPE_FUNCTION },
373 { "Array" , COFF::IMAGE_SYM_DTYPE_ARRAY }
374};
375
376static const EnumEntry<COFF::SymbolStorageClass> ImageSymClass[] = {
377 { "EndOfFunction" , COFF::IMAGE_SYM_CLASS_END_OF_FUNCTION },
378 { "Null" , COFF::IMAGE_SYM_CLASS_NULL },
379 { "Automatic" , COFF::IMAGE_SYM_CLASS_AUTOMATIC },
380 { "External" , COFF::IMAGE_SYM_CLASS_EXTERNAL },
381 { "Static" , COFF::IMAGE_SYM_CLASS_STATIC },
382 { "Register" , COFF::IMAGE_SYM_CLASS_REGISTER },
383 { "ExternalDef" , COFF::IMAGE_SYM_CLASS_EXTERNAL_DEF },
384 { "Label" , COFF::IMAGE_SYM_CLASS_LABEL },
385 { "UndefinedLabel" , COFF::IMAGE_SYM_CLASS_UNDEFINED_LABEL },
386 { "MemberOfStruct" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_STRUCT },
387 { "Argument" , COFF::IMAGE_SYM_CLASS_ARGUMENT },
388 { "StructTag" , COFF::IMAGE_SYM_CLASS_STRUCT_TAG },
389 { "MemberOfUnion" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_UNION },
390 { "UnionTag" , COFF::IMAGE_SYM_CLASS_UNION_TAG },
391 { "TypeDefinition" , COFF::IMAGE_SYM_CLASS_TYPE_DEFINITION },
392 { "UndefinedStatic", COFF::IMAGE_SYM_CLASS_UNDEFINED_STATIC },
393 { "EnumTag" , COFF::IMAGE_SYM_CLASS_ENUM_TAG },
394 { "MemberOfEnum" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_ENUM },
395 { "RegisterParam" , COFF::IMAGE_SYM_CLASS_REGISTER_PARAM },
396 { "BitField" , COFF::IMAGE_SYM_CLASS_BIT_FIELD },
397 { "Block" , COFF::IMAGE_SYM_CLASS_BLOCK },
398 { "Function" , COFF::IMAGE_SYM_CLASS_FUNCTION },
399 { "EndOfStruct" , COFF::IMAGE_SYM_CLASS_END_OF_STRUCT },
400 { "File" , COFF::IMAGE_SYM_CLASS_FILE },
401 { "Section" , COFF::IMAGE_SYM_CLASS_SECTION },
402 { "WeakExternal" , COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL },
403 { "CLRToken" , COFF::IMAGE_SYM_CLASS_CLR_TOKEN }
404};
405
406static const EnumEntry<COFF::COMDATType> ImageCOMDATSelect[] = {
407 { "NoDuplicates", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES },
408 { "Any" , COFF::IMAGE_COMDAT_SELECT_ANY },
409 { "SameSize" , COFF::IMAGE_COMDAT_SELECT_SAME_SIZE },
410 { "ExactMatch" , COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH },
411 { "Associative" , COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE },
412 { "Largest" , COFF::IMAGE_COMDAT_SELECT_LARGEST },
413 { "Newest" , COFF::IMAGE_COMDAT_SELECT_NEWEST }
414};
415
416static const EnumEntry<COFF::WeakExternalCharacteristics>
417WeakExternalCharacteristics[] = {
418 { "NoLibrary", COFF::IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY },
419 { "Library" , COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY },
420 { "Alias" , COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS }
421};
422
Reid Kleckner72e2ba72016-01-13 19:32:35 +0000423static const EnumEntry<CompileSym3::Flags> CompileSym3Flags[] = {
424 LLVM_READOBJ_ENUM_ENT(CompileSym3, EC),
425 LLVM_READOBJ_ENUM_ENT(CompileSym3, NoDbgInfo),
426 LLVM_READOBJ_ENUM_ENT(CompileSym3, LTCG),
427 LLVM_READOBJ_ENUM_ENT(CompileSym3, NoDataAlign),
428 LLVM_READOBJ_ENUM_ENT(CompileSym3, ManagedPresent),
429 LLVM_READOBJ_ENUM_ENT(CompileSym3, SecurityChecks),
430 LLVM_READOBJ_ENUM_ENT(CompileSym3, HotPatch),
431 LLVM_READOBJ_ENUM_ENT(CompileSym3, CVTCIL),
432 LLVM_READOBJ_ENUM_ENT(CompileSym3, MSILModule),
433 LLVM_READOBJ_ENUM_ENT(CompileSym3, Sdl),
434 LLVM_READOBJ_ENUM_ENT(CompileSym3, PGO),
435 LLVM_READOBJ_ENUM_ENT(CompileSym3, Exp),
436};
437
438static const EnumEntry<codeview::SourceLanguage> SourceLanguages[] = {
439 LLVM_READOBJ_ENUM_ENT(SourceLanguage, C),
440 LLVM_READOBJ_ENUM_ENT(SourceLanguage, Cpp),
441 LLVM_READOBJ_ENUM_ENT(SourceLanguage, Fortran),
442 LLVM_READOBJ_ENUM_ENT(SourceLanguage, Masm),
443 LLVM_READOBJ_ENUM_ENT(SourceLanguage, Pascal),
444 LLVM_READOBJ_ENUM_ENT(SourceLanguage, Basic),
445 LLVM_READOBJ_ENUM_ENT(SourceLanguage, Cobol),
446 LLVM_READOBJ_ENUM_ENT(SourceLanguage, Link),
447 LLVM_READOBJ_ENUM_ENT(SourceLanguage, Cvtres),
448 LLVM_READOBJ_ENUM_ENT(SourceLanguage, Cvtpgd),
449 LLVM_READOBJ_ENUM_ENT(SourceLanguage, CSharp),
450 LLVM_READOBJ_ENUM_ENT(SourceLanguage, VB),
451 LLVM_READOBJ_ENUM_ENT(SourceLanguage, ILAsm),
452 LLVM_READOBJ_ENUM_ENT(SourceLanguage, Java),
453 LLVM_READOBJ_ENUM_ENT(SourceLanguage, JScript),
454 LLVM_READOBJ_ENUM_ENT(SourceLanguage, MSIL),
455 LLVM_READOBJ_ENUM_ENT(SourceLanguage, HLSL),
456};
457
458static const EnumEntry<uint32_t> SubSectionTypes[] = {
459 LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, Symbols),
460 LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, Lines),
461 LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, StringTable),
462 LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, FileChecksums),
463 LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, FrameData),
464 LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, InlineeLines),
465 LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, CrossScopeImports),
466 LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, CrossScopeExports),
467 LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, ILLines),
468 LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, FuncMDTokenMap),
469 LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, TypeMDTokenMap),
470 LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, MergedAssemblyInput),
471 LLVM_READOBJ_ENUM_CLASS_ENT(ModuleSubstreamKind, CoffSymbolRVA),
472};
473
474static const EnumEntry<unsigned> CPUTypeNames[] = {
475 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Intel8080),
476 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Intel8086),
477 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Intel80286),
478 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Intel80386),
479 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Intel80486),
480 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Pentium),
481 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PentiumPro),
482 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Pentium3),
483 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPS),
484 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPS16),
485 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPS32),
486 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPS64),
487 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPSI),
488 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPSII),
489 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPSIII),
490 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPSIV),
491 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, MIPSV),
492 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M68000),
493 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M68010),
494 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M68020),
495 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M68030),
496 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M68040),
497 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Alpha),
498 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Alpha21164),
499 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Alpha21164A),
500 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Alpha21264),
501 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Alpha21364),
502 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPC601),
503 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPC603),
504 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPC604),
505 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPC620),
506 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPCFP),
507 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, PPCBE),
508 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, SH3),
509 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, SH3E),
510 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, SH3DSP),
511 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, SH4),
512 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, SHMedia),
513 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM3),
514 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM4),
515 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM4T),
516 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM5),
517 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM5T),
518 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM6),
519 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM_XMAC),
520 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM_WMMX),
521 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARM7),
522 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Omni),
523 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Ia64),
524 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Ia64_2),
525 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, CEE),
526 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, AM33),
527 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, M32R),
528 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, TriCore),
529 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, X64),
530 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, EBC),
531 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, Thumb),
532 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, ARMNT),
533 LLVM_READOBJ_ENUM_CLASS_ENT(CPUType, D3D11_Shader),
534};
535
536static const EnumEntry<uint8_t> ProcSymFlags[] = {
537 LLVM_READOBJ_ENUM_ENT(ProcFlags, HasFP),
538 LLVM_READOBJ_ENUM_ENT(ProcFlags, HasIRET),
539 LLVM_READOBJ_ENUM_ENT(ProcFlags, HasFRET),
540 LLVM_READOBJ_ENUM_ENT(ProcFlags, IsNoReturn),
541 LLVM_READOBJ_ENUM_ENT(ProcFlags, IsUnreachable),
542 LLVM_READOBJ_ENUM_ENT(ProcFlags, HasCustomCallingConv),
543 LLVM_READOBJ_ENUM_ENT(ProcFlags, IsNoInline),
544 LLVM_READOBJ_ENUM_ENT(ProcFlags, HasOptimizedDebugInfo),
545};
546
547static const EnumEntry<uint32_t> FrameProcSymFlags[] = {
548 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, HasAlloca),
549 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, HasSetJmp),
550 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, HasLongJmp),
551 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, HasInlineAssembly),
552 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, HasExceptionHandling),
553 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, MarkedInline),
554 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions,
555 HasStructuredExceptionHandling),
556 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, Naked),
557 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, SecurityChecks),
558 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions,
559 AsynchronousExceptionHandling),
560 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions,
561 NoStackOrderingForSecurityChecks),
562 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, Inlined),
563 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, StrictSecurityChecks),
564 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, SafeBuffers),
565 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions,
566 ProfileGuidedOptimization),
567 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, ValidProfileCounts),
568 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, OptimizedForSpeed),
569 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfg),
570 LLVM_READOBJ_ENUM_CLASS_ENT(FrameProcedureOptions, GuardCfw),
571};
572
573static const EnumEntry<uint32_t> FrameDataFlags[] = {
574 LLVM_READOBJ_ENUM_ENT(FrameData, HasSEH),
575 LLVM_READOBJ_ENUM_ENT(FrameData, HasEH),
576 LLVM_READOBJ_ENUM_ENT(FrameData, IsFunctionStart),
577};
578
579static const EnumEntry<uint16_t> LocalFlags[] = {
580 LLVM_READOBJ_ENUM_ENT(LocalSym, IsParameter),
581 LLVM_READOBJ_ENUM_ENT(LocalSym, IsAddressTaken),
582 LLVM_READOBJ_ENUM_ENT(LocalSym, IsCompilerGenerated),
583 LLVM_READOBJ_ENUM_ENT(LocalSym, IsAggregate),
584 LLVM_READOBJ_ENUM_ENT(LocalSym, IsAggregated),
585 LLVM_READOBJ_ENUM_ENT(LocalSym, IsAliased),
586 LLVM_READOBJ_ENUM_ENT(LocalSym, IsAlias),
587 LLVM_READOBJ_ENUM_ENT(LocalSym, IsReturnValue),
588 LLVM_READOBJ_ENUM_ENT(LocalSym, IsOptimizedOut),
589 LLVM_READOBJ_ENUM_ENT(LocalSym, IsEnregisteredGlobal),
590 LLVM_READOBJ_ENUM_ENT(LocalSym, IsEnregisteredStatic),
591};
592
593static const EnumEntry<uint16_t> FrameCookieKinds[] = {
594 LLVM_READOBJ_ENUM_ENT(FrameCookieSym, Copy),
595 LLVM_READOBJ_ENUM_ENT(FrameCookieSym, XorStackPointer),
596 LLVM_READOBJ_ENUM_ENT(FrameCookieSym, XorFramePointer),
597 LLVM_READOBJ_ENUM_ENT(FrameCookieSym, XorR13),
598};
599
600static const EnumEntry<uint16_t> ClassOptionNames[] = {
601 LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, Packed),
602 LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, HasConstructorOrDestructor),
603 LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, HasOverloadedOperator),
604 LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, Nested),
605 LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, ContainsNestedClass),
606 LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, HasOverloadedAssignmentOperator),
607 LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, HasConversionOperator),
608 LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, ForwardReference),
609 LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, Scoped),
610 LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, HasUniqueName),
611 LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, Sealed),
612 LLVM_READOBJ_ENUM_CLASS_ENT(ClassOptions, Intrinsic),
613};
614
615static const EnumEntry<uint8_t> MemberAccessNames[] = {
616 LLVM_READOBJ_ENUM_CLASS_ENT(MemberAccess, None),
617 LLVM_READOBJ_ENUM_CLASS_ENT(MemberAccess, Private),
618 LLVM_READOBJ_ENUM_CLASS_ENT(MemberAccess, Protected),
619 LLVM_READOBJ_ENUM_CLASS_ENT(MemberAccess, Public),
620};
621
622static const EnumEntry<uint16_t> MethodOptionNames[] = {
623 LLVM_READOBJ_ENUM_CLASS_ENT(MethodOptions, Pseudo),
624 LLVM_READOBJ_ENUM_CLASS_ENT(MethodOptions, NoInherit),
625 LLVM_READOBJ_ENUM_CLASS_ENT(MethodOptions, NoConstruct),
626 LLVM_READOBJ_ENUM_CLASS_ENT(MethodOptions, CompilerGenerated),
627 LLVM_READOBJ_ENUM_CLASS_ENT(MethodOptions, Sealed),
628};
629
630static const EnumEntry<uint16_t> MemberKindNames[] = {
631 LLVM_READOBJ_ENUM_CLASS_ENT(MethodKind, Vanilla),
632 LLVM_READOBJ_ENUM_CLASS_ENT(MethodKind, Virtual),
633 LLVM_READOBJ_ENUM_CLASS_ENT(MethodKind, Static),
634 LLVM_READOBJ_ENUM_CLASS_ENT(MethodKind, Friend),
635 LLVM_READOBJ_ENUM_CLASS_ENT(MethodKind, IntroducingVirtual),
636 LLVM_READOBJ_ENUM_CLASS_ENT(MethodKind, PureVirtual),
637 LLVM_READOBJ_ENUM_CLASS_ENT(MethodKind, PureIntroducingVirtual),
638};
639
640/// The names here all end in "*". If the simple type is a pointer type, we
641/// return the whole name. Otherwise we lop off the last character in our
642/// StringRef.
643static const EnumEntry<SimpleTypeKind> SimpleTypeNames[] = {
644 {"void*", SimpleTypeKind::Void},
645 {"<not translated>*", SimpleTypeKind::NotTranslated},
646 {"HRESULT*", SimpleTypeKind::HResult},
647 {"signed char*", SimpleTypeKind::SignedCharacter},
648 {"unsigned char*", SimpleTypeKind::UnsignedCharacter},
649 {"char*", SimpleTypeKind::NarrowCharacter},
650 {"wchar_t*", SimpleTypeKind::WideCharacter},
651 {"__int8*", SimpleTypeKind::SByte},
652 {"unsigned __int8*", SimpleTypeKind::Byte},
653 {"short*", SimpleTypeKind::Int16Short},
654 {"unsigned short*", SimpleTypeKind::UInt16Short},
655 {"__int16*", SimpleTypeKind::Int16},
656 {"unsigned __int16*", SimpleTypeKind::UInt16},
657 {"long*", SimpleTypeKind::Int32Long},
658 {"unsigned long*", SimpleTypeKind::UInt32Long},
659 {"int*", SimpleTypeKind::Int32},
660 {"unsigned*", SimpleTypeKind::UInt32},
661 {"__int64*", SimpleTypeKind::Int64Quad},
662 {"unsigned __int64*", SimpleTypeKind::UInt64Quad},
663 {"__int64*", SimpleTypeKind::Int64},
664 {"unsigned __int64*", SimpleTypeKind::UInt64},
665 {"__int128*", SimpleTypeKind::Int128},
666 {"unsigned __int128*", SimpleTypeKind::UInt128},
667 {"__half*", SimpleTypeKind::Float16},
668 {"float*", SimpleTypeKind::Float32},
669 {"float*", SimpleTypeKind::Float32PartialPrecision},
670 {"__float48*", SimpleTypeKind::Float48},
671 {"double*", SimpleTypeKind::Float64},
672 {"long double*", SimpleTypeKind::Float80},
673 {"__float128*", SimpleTypeKind::Float128},
674 {"_Complex float*", SimpleTypeKind::Complex32},
675 {"_Complex double*", SimpleTypeKind::Complex64},
676 {"_Complex long double*", SimpleTypeKind::Complex80},
677 {"_Complex __float128*", SimpleTypeKind::Complex128},
678 {"bool*", SimpleTypeKind::Boolean8},
679 {"__bool16*", SimpleTypeKind::Boolean16},
680 {"__bool32*", SimpleTypeKind::Boolean32},
681 {"__bool64*", SimpleTypeKind::Boolean64},
682};
683
Reid Kleckner6b3faef2016-01-13 23:44:57 +0000684static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
685#define LEAF_TYPE(name, val) LLVM_READOBJ_ENUM_ENT(TypeLeafKind, name),
686#include "llvm/DebugInfo/CodeView/CVLeafTypes.def"
Reid Kleckner72e2ba72016-01-13 19:32:35 +0000687};
688
689static const EnumEntry<uint8_t> PtrKindNames[] = {
690 LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, Near16),
691 LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, Far16),
692 LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, Huge16),
693 LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, BasedOnSegment),
694 LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, BasedOnValue),
695 LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, BasedOnSegmentValue),
696 LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, BasedOnAddress),
697 LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, BasedOnSegmentAddress),
698 LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, BasedOnType),
699 LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, BasedOnSelf),
700 LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, Near32),
701 LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, Far32),
702 LLVM_READOBJ_ENUM_CLASS_ENT(PointerKind, Near64),
703};
704
705static const EnumEntry<uint8_t> PtrModeNames[] = {
706 LLVM_READOBJ_ENUM_CLASS_ENT(PointerMode, Pointer),
707 LLVM_READOBJ_ENUM_CLASS_ENT(PointerMode, LValueReference),
708 LLVM_READOBJ_ENUM_CLASS_ENT(PointerMode, PointerToDataMember),
709 LLVM_READOBJ_ENUM_CLASS_ENT(PointerMode, PointerToMemberFunction),
710 LLVM_READOBJ_ENUM_CLASS_ENT(PointerMode, RValueReference),
711};
712
713static const EnumEntry<uint16_t> PtrMemberRepNames[] = {
714 LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation, Unknown),
715 LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation,
716 SingleInheritanceData),
717 LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation,
718 MultipleInheritanceData),
719 LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation,
720 VirtualInheritanceData),
721 LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation, GeneralData),
722 LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation,
723 SingleInheritanceFunction),
724 LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation,
725 MultipleInheritanceFunction),
726 LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation,
727 VirtualInheritanceFunction),
728 LLVM_READOBJ_ENUM_CLASS_ENT(PointerToMemberRepresentation, GeneralFunction),
729};
730
731static const EnumEntry<uint16_t> TypeModifierNames[] = {
732 LLVM_READOBJ_ENUM_CLASS_ENT(ModifierOptions, Const),
733 LLVM_READOBJ_ENUM_CLASS_ENT(ModifierOptions, Volatile),
734 LLVM_READOBJ_ENUM_CLASS_ENT(ModifierOptions, Unaligned),
735};
736
737static const EnumEntry<uint8_t> CallingConventions[] = {
738 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, NearC),
739 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, FarC),
740 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, NearPascal),
741 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, FarPascal),
742 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, NearFast),
743 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, FarFast),
744 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, NearStdCall),
745 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, FarStdCall),
746 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, NearSysCall),
747 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, FarSysCall),
748 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, ThisCall),
749 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, MipsCall),
750 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, Generic),
751 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, AlphaCall),
752 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, PpcCall),
753 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, SHCall),
754 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, ArmCall),
755 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, AM33Call),
756 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, TriCall),
757 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, SH5Call),
758 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, M32RCall),
759 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, ClrCall),
760 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, Inline),
761 LLVM_READOBJ_ENUM_CLASS_ENT(CallingConvention, NearVector),
762};
763
764static const EnumEntry<uint8_t> FunctionOptionEnum[] = {
765 LLVM_READOBJ_ENUM_CLASS_ENT(FunctionOptions, CxxReturnUdt),
766 LLVM_READOBJ_ENUM_CLASS_ENT(FunctionOptions, Constructor),
767 LLVM_READOBJ_ENUM_CLASS_ENT(FunctionOptions, ConstructorWithVirtualBases),
768};
769
Rafael Espindola4453e42942014-06-13 03:07:50 +0000770template <typename T>
771static std::error_code getSymbolAuxData(const COFFObjectFile *Obj,
David Majnemer44f51e52014-09-10 12:51:52 +0000772 COFFSymbolRef Symbol,
773 uint8_t AuxSymbolIdx, const T *&Aux) {
Eric Christopher9cad53c2013-04-03 18:31:38 +0000774 ArrayRef<uint8_t> AuxData = Obj->getSymbolAuxData(Symbol);
David Majnemer44f51e52014-09-10 12:51:52 +0000775 AuxData = AuxData.slice(AuxSymbolIdx * Obj->getSymbolTableEntrySize());
Eric Christopher9cad53c2013-04-03 18:31:38 +0000776 Aux = reinterpret_cast<const T*>(AuxData.data());
777 return readobj_error::success;
778}
779
Eric Christopher9cad53c2013-04-03 18:31:38 +0000780void COFFDumper::cacheRelocations() {
Rafael Espindola76d650e2015-07-06 14:26:07 +0000781 if (RelocCached)
782 return;
783 RelocCached = true;
784
Alexey Samsonov27dc8392014-03-18 06:53:02 +0000785 for (const SectionRef &S : Obj->sections()) {
786 const coff_section *Section = Obj->getCOFFSection(S);
Eric Christopher9cad53c2013-04-03 18:31:38 +0000787
Alexey Samsonov27dc8392014-03-18 06:53:02 +0000788 for (const RelocationRef &Reloc : S.relocations())
Alexey Samsonovaa4d2952014-03-14 14:22:49 +0000789 RelocMap[Section].push_back(Reloc);
Eric Christopher9cad53c2013-04-03 18:31:38 +0000790
791 // Sort relocations by address.
792 std::sort(RelocMap[Section].begin(), RelocMap[Section].end(),
793 relocAddressLess);
794 }
795}
796
Rui Ueyamaed64342b2013-07-19 23:23:29 +0000797void COFFDumper::printDataDirectory(uint32_t Index, const std::string &FieldName) {
798 const data_directory *Data;
799 if (Obj->getDataDirectory(Index, Data))
800 return;
801 W.printHex(FieldName + "RVA", Data->RelativeVirtualAddress);
802 W.printHex(FieldName + "Size", Data->Size);
803}
804
Eric Christopher9cad53c2013-04-03 18:31:38 +0000805void COFFDumper::printFileHeaders() {
David Majnemer44f51e52014-09-10 12:51:52 +0000806 time_t TDS = Obj->getTimeDateStamp();
Eric Christopher9cad53c2013-04-03 18:31:38 +0000807 char FormattedTime[20] = { };
808 strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS));
809
810 {
811 DictScope D(W, "ImageFileHeader");
David Majnemer44f51e52014-09-10 12:51:52 +0000812 W.printEnum ("Machine", Obj->getMachine(),
Eric Christopher9cad53c2013-04-03 18:31:38 +0000813 makeArrayRef(ImageFileMachineType));
David Majnemer44f51e52014-09-10 12:51:52 +0000814 W.printNumber("SectionCount", Obj->getNumberOfSections());
815 W.printHex ("TimeDateStamp", FormattedTime, Obj->getTimeDateStamp());
816 W.printHex ("PointerToSymbolTable", Obj->getPointerToSymbolTable());
817 W.printNumber("SymbolCount", Obj->getNumberOfSymbols());
818 W.printNumber("OptionalHeaderSize", Obj->getSizeOfOptionalHeader());
819 W.printFlags ("Characteristics", Obj->getCharacteristics(),
Eric Christopher9cad53c2013-04-03 18:31:38 +0000820 makeArrayRef(ImageFileCharacteristics));
821 }
Rui Ueyama82ebd8e2013-06-12 19:10:33 +0000822
823 // Print PE header. This header does not exist if this is an object file and
824 // not an executable.
Craig Toppere6cb63e2014-04-25 04:24:47 +0000825 const pe32_header *PEHeader = nullptr;
Rafael Espindolafb3acd62015-07-20 03:23:55 +0000826 error(Obj->getPE32Header(PEHeader));
Rui Ueyama10ed9dd2014-01-26 04:15:52 +0000827 if (PEHeader)
828 printPEHeader<pe32_header>(PEHeader);
Rui Ueyama82ebd8e2013-06-12 19:10:33 +0000829
Craig Toppere6cb63e2014-04-25 04:24:47 +0000830 const pe32plus_header *PEPlusHeader = nullptr;
Rafael Espindolafb3acd62015-07-20 03:23:55 +0000831 error(Obj->getPE32PlusHeader(PEPlusHeader));
Rui Ueyama10ed9dd2014-01-26 04:15:52 +0000832 if (PEPlusHeader)
833 printPEHeader<pe32plus_header>(PEPlusHeader);
David Majnemer50267222014-11-05 06:24:35 +0000834
835 if (const dos_header *DH = Obj->getDOSHeader())
836 printDOSHeader(DH);
837}
838
839void COFFDumper::printDOSHeader(const dos_header *DH) {
840 DictScope D(W, "DOSHeader");
841 W.printString("Magic", StringRef(DH->Magic, sizeof(DH->Magic)));
842 W.printNumber("UsedBytesInTheLastPage", DH->UsedBytesInTheLastPage);
843 W.printNumber("FileSizeInPages", DH->FileSizeInPages);
844 W.printNumber("NumberOfRelocationItems", DH->NumberOfRelocationItems);
845 W.printNumber("HeaderSizeInParagraphs", DH->HeaderSizeInParagraphs);
846 W.printNumber("MinimumExtraParagraphs", DH->MinimumExtraParagraphs);
847 W.printNumber("MaximumExtraParagraphs", DH->MaximumExtraParagraphs);
848 W.printNumber("InitialRelativeSS", DH->InitialRelativeSS);
849 W.printNumber("InitialSP", DH->InitialSP);
850 W.printNumber("Checksum", DH->Checksum);
851 W.printNumber("InitialIP", DH->InitialIP);
852 W.printNumber("InitialRelativeCS", DH->InitialRelativeCS);
853 W.printNumber("AddressOfRelocationTable", DH->AddressOfRelocationTable);
854 W.printNumber("OverlayNumber", DH->OverlayNumber);
855 W.printNumber("OEMid", DH->OEMid);
856 W.printNumber("OEMinfo", DH->OEMinfo);
857 W.printNumber("AddressOfNewExeHeader", DH->AddressOfNewExeHeader);
Rui Ueyama10ed9dd2014-01-26 04:15:52 +0000858}
Rui Ueyamaed64342b2013-07-19 23:23:29 +0000859
Rui Ueyama10ed9dd2014-01-26 04:15:52 +0000860template <class PEHeader>
861void COFFDumper::printPEHeader(const PEHeader *Hdr) {
862 DictScope D(W, "ImageOptionalHeader");
863 W.printNumber("MajorLinkerVersion", Hdr->MajorLinkerVersion);
864 W.printNumber("MinorLinkerVersion", Hdr->MinorLinkerVersion);
865 W.printNumber("SizeOfCode", Hdr->SizeOfCode);
866 W.printNumber("SizeOfInitializedData", Hdr->SizeOfInitializedData);
867 W.printNumber("SizeOfUninitializedData", Hdr->SizeOfUninitializedData);
868 W.printHex ("AddressOfEntryPoint", Hdr->AddressOfEntryPoint);
869 W.printHex ("BaseOfCode", Hdr->BaseOfCode);
870 printBaseOfDataField(Hdr);
871 W.printHex ("ImageBase", Hdr->ImageBase);
872 W.printNumber("SectionAlignment", Hdr->SectionAlignment);
873 W.printNumber("FileAlignment", Hdr->FileAlignment);
874 W.printNumber("MajorOperatingSystemVersion",
875 Hdr->MajorOperatingSystemVersion);
876 W.printNumber("MinorOperatingSystemVersion",
877 Hdr->MinorOperatingSystemVersion);
878 W.printNumber("MajorImageVersion", Hdr->MajorImageVersion);
879 W.printNumber("MinorImageVersion", Hdr->MinorImageVersion);
880 W.printNumber("MajorSubsystemVersion", Hdr->MajorSubsystemVersion);
881 W.printNumber("MinorSubsystemVersion", Hdr->MinorSubsystemVersion);
882 W.printNumber("SizeOfImage", Hdr->SizeOfImage);
883 W.printNumber("SizeOfHeaders", Hdr->SizeOfHeaders);
884 W.printEnum ("Subsystem", Hdr->Subsystem, makeArrayRef(PEWindowsSubsystem));
David Majnemer774aadf2014-11-18 02:45:28 +0000885 W.printFlags ("Characteristics", Hdr->DLLCharacteristics,
Rui Ueyama10ed9dd2014-01-26 04:15:52 +0000886 makeArrayRef(PEDLLCharacteristics));
887 W.printNumber("SizeOfStackReserve", Hdr->SizeOfStackReserve);
888 W.printNumber("SizeOfStackCommit", Hdr->SizeOfStackCommit);
889 W.printNumber("SizeOfHeapReserve", Hdr->SizeOfHeapReserve);
890 W.printNumber("SizeOfHeapCommit", Hdr->SizeOfHeapCommit);
891 W.printNumber("NumberOfRvaAndSize", Hdr->NumberOfRvaAndSize);
Rui Ueyamaed64342b2013-07-19 23:23:29 +0000892
Rui Ueyama10ed9dd2014-01-26 04:15:52 +0000893 if (Hdr->NumberOfRvaAndSize > 0) {
894 DictScope D(W, "DataDirectory");
895 static const char * const directory[] = {
896 "ExportTable", "ImportTable", "ResourceTable", "ExceptionTable",
897 "CertificateTable", "BaseRelocationTable", "Debug", "Architecture",
898 "GlobalPtr", "TLSTable", "LoadConfigTable", "BoundImport", "IAT",
899 "DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"
900 };
901
902 for (uint32_t i = 0; i < Hdr->NumberOfRvaAndSize; ++i) {
903 printDataDirectory(i, directory[i]);
Rui Ueyamaed64342b2013-07-19 23:23:29 +0000904 }
Rui Ueyama82ebd8e2013-06-12 19:10:33 +0000905 }
Eric Christopher9cad53c2013-04-03 18:31:38 +0000906}
907
Rui Ueyama10ed9dd2014-01-26 04:15:52 +0000908void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) {
909 W.printHex("BaseOfData", Hdr->BaseOfData);
910}
911
912void COFFDumper::printBaseOfDataField(const pe32plus_header *) {}
913
Reid Kleckner83ebad32015-12-16 18:28:12 +0000914void COFFDumper::printCodeViewDebugInfo() {
Reid Kleckner72e2ba72016-01-13 19:32:35 +0000915 // Print types first to build CVUDTNames, then print symbols.
Reid Kleckner83ebad32015-12-16 18:28:12 +0000916 for (const SectionRef &S : Obj->sections()) {
Reid Kleckner72e2ba72016-01-13 19:32:35 +0000917 StringRef SectionName;
918 error(S.getName(SectionName));
919 if (SectionName == ".debug$T")
920 printCodeViewTypeSection(SectionName, S);
921 }
922 for (const SectionRef &S : Obj->sections()) {
923 StringRef SectionName;
924 error(S.getName(SectionName));
925 if (SectionName == ".debug$S")
926 printCodeViewSymbolSection(SectionName, S);
Reid Kleckner83ebad32015-12-16 18:28:12 +0000927 }
928}
929
Reid Kleckner72e2ba72016-01-13 19:32:35 +0000930/// Consumes sizeof(T) bytes from the given byte sequence. Returns an error if
931/// there are not enough bytes remaining. Reinterprets the consumed bytes as a
932/// T object and points 'Res' at them.
933template <typename T>
934static std::error_code consumeObject(StringRef &Data, const T *&Res) {
935 if (Data.size() < sizeof(*Res))
936 return object_error::parse_failed;
937 Res = reinterpret_cast<const T *>(Data.data());
938 Data = Data.drop_front(sizeof(*Res));
939 return std::error_code();
940}
941
942static std::error_code consumeUInt32(StringRef &Data, uint32_t &Res) {
943 const ulittle32_t *IntPtr;
944 if (auto EC = consumeObject(Data, IntPtr))
945 return EC;
946 Res = *IntPtr;
947 return std::error_code();
948}
949
Reid Kleckner8e7275c2016-01-15 00:11:21 +0000950void COFFDumper::initializeFileAndStringTables(StringRef Data) {
951 while (!Data.empty() && (CVFileChecksumTable.data() == nullptr ||
952 CVStringTable.data() == nullptr)) {
953 // The section consists of a number of subsection in the following format:
954 // |SubSectionType|SubSectionSize|Contents...|
955 uint32_t SubType, SubSectionSize;
956 error(consumeUInt32(Data, SubType));
957 error(consumeUInt32(Data, SubSectionSize));
958 if (SubSectionSize > Data.size())
959 return error(object_error::parse_failed);
960 switch (ModuleSubstreamKind(SubType)) {
961 case ModuleSubstreamKind::FileChecksums:
962 CVFileChecksumTable = Data.substr(0, SubSectionSize);
963 break;
964 case ModuleSubstreamKind::StringTable:
965 CVStringTable = Data.substr(0, SubSectionSize);
966 break;
967 default:
968 break;
969 }
970 Data = Data.drop_front(alignTo(SubSectionSize, 4));
971 }
972}
973
Reid Kleckner72e2ba72016-01-13 19:32:35 +0000974void COFFDumper::printCodeViewSymbolSection(StringRef SectionName,
975 const SectionRef &Section) {
976 StringRef SectionContents;
977 error(Section.getContents(SectionContents));
978 StringRef Data = SectionContents;
Timur Iskhodzhanov48703be2013-12-19 11:37:14 +0000979
980 SmallVector<StringRef, 10> FunctionNames;
981 StringMap<StringRef> FunctionLineTables;
Reid Kleckner72e2ba72016-01-13 19:32:35 +0000982 std::map<StringRef, const FrameData *> FunctionFrameData;
Timur Iskhodzhanov48703be2013-12-19 11:37:14 +0000983
Zachary Turner99f02152015-02-18 19:32:05 +0000984 ListScope D(W, "CodeViewDebugInfo");
Reid Kleckner72e2ba72016-01-13 19:32:35 +0000985 // Print the section to allow correlation with printSections.
986 W.printNumber("Section", SectionName, Obj->getSectionID(Section));
Timur Iskhodzhanov48703be2013-12-19 11:37:14 +0000987
Reid Kleckner72e2ba72016-01-13 19:32:35 +0000988 uint32_t Magic;
989 error(consumeUInt32(Data, Magic));
990 W.printHex("Magic", Magic);
991 if (Magic != COFF::DEBUG_SECTION_MAGIC)
992 return error(object_error::parse_failed);
993
Reid Kleckner8e7275c2016-01-15 00:11:21 +0000994 initializeFileAndStringTables(Data);
995
Reid Kleckner72e2ba72016-01-13 19:32:35 +0000996 while (!Data.empty()) {
997 // The section consists of a number of subsection in the following format:
998 // |SubSectionType|SubSectionSize|Contents...|
999 uint32_t SubType, SubSectionSize;
1000 error(consumeUInt32(Data, SubType));
1001 error(consumeUInt32(Data, SubSectionSize));
1002
1003 ListScope S(W, "Subsection");
1004 W.printEnum("SubSectionType", SubType, makeArrayRef(SubSectionTypes));
1005 W.printHex("SubSectionSize", SubSectionSize);
1006
1007 // Get the contents of the subsection.
1008 if (SubSectionSize > Data.size())
1009 return error(object_error::parse_failed);
1010 StringRef Contents = Data.substr(0, SubSectionSize);
1011
1012 // Add SubSectionSize to the current offset and align that offset to find
1013 // the next subsection.
1014 size_t SectionOffset = Data.data() - SectionContents.data();
1015 size_t NextOffset = SectionOffset + SubSectionSize;
Rui Ueyamada00f2f2016-01-14 21:06:47 +00001016 NextOffset = alignTo(NextOffset, 4);
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001017 Data = SectionContents.drop_front(NextOffset);
1018
1019 // Optionally print the subsection bytes in case our parsing gets confused
1020 // later.
1021 if (opts::CodeViewSubsectionBytes)
1022 W.printBinaryBlock("SubSectionContents", Contents);
1023
1024 switch (ModuleSubstreamKind(SubType)) {
1025 case ModuleSubstreamKind::Symbols:
Reid Kleckner2893fd12016-01-14 17:51:54 +00001026 printCodeViewSymbolsSubsection(Contents, Section, SectionContents);
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001027 break;
Reid Klecknere9ab3492016-01-14 19:20:17 +00001028
1029 case ModuleSubstreamKind::InlineeLines:
1030 printCodeViewInlineeLines(Contents);
1031 break;
1032
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001033 case ModuleSubstreamKind::Lines: {
1034 // Holds a PC to file:line table. Some data to parse this subsection is
1035 // stored in the other subsections, so just check sanity and store the
1036 // pointers for deferred processing.
1037
1038 if (SubSectionSize < 12) {
1039 // There should be at least three words to store two function
1040 // relocations and size of the code.
Timur Iskhodzhanov48703be2013-12-19 11:37:14 +00001041 error(object_error::parse_failed);
1042 return;
1043 }
1044
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001045 StringRef LinkageName;
1046 error(resolveSymbolName(Obj->getCOFFSection(Section), SectionOffset,
1047 LinkageName));
1048 W.printString("LinkageName", LinkageName);
1049 if (FunctionLineTables.count(LinkageName) != 0) {
1050 // Saw debug info for this function already?
1051 error(object_error::parse_failed);
1052 return;
Zachary Turner99f02152015-02-18 19:32:05 +00001053 }
Timur Iskhodzhanov48703be2013-12-19 11:37:14 +00001054
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001055 FunctionLineTables[LinkageName] = Contents;
1056 FunctionNames.push_back(LinkageName);
1057 break;
1058 }
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001059 case ModuleSubstreamKind::FrameData: {
1060 const size_t RelocationSize = 4;
1061 if (SubSectionSize != sizeof(FrameData) + RelocationSize) {
1062 // There should be exactly one relocation followed by the FrameData
1063 // contents.
1064 error(object_error::parse_failed);
1065 return;
1066 }
Timur Iskhodzhanov48703be2013-12-19 11:37:14 +00001067
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001068 const auto *FD = reinterpret_cast<const FrameData *>(
1069 Contents.drop_front(RelocationSize).data());
1070
1071 StringRef LinkageName;
1072 error(resolveSymbolName(Obj->getCOFFSection(Section), SectionOffset,
1073 LinkageName));
Reid Kleckner1d9970a2016-01-14 18:03:29 +00001074 if (!FunctionFrameData.insert(std::make_pair(LinkageName, FD)).second) {
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001075 error(object_error::parse_failed);
1076 return;
1077 }
1078 break;
1079 }
1080
1081 // Do nothing for unrecognized subsections.
1082 default:
1083 break;
Timur Iskhodzhanov48703be2013-12-19 11:37:14 +00001084 }
1085 }
1086
1087 // Dump the line tables now that we've read all the subsections and know all
1088 // the required information.
1089 for (unsigned I = 0, E = FunctionNames.size(); I != E; ++I) {
1090 StringRef Name = FunctionNames[I];
1091 ListScope S(W, "FunctionLineTable");
Reid Kleckner7c0c0c02015-12-15 01:23:55 +00001092 W.printString("LinkageName", Name);
Timur Iskhodzhanov48703be2013-12-19 11:37:14 +00001093
1094 DataExtractor DE(FunctionLineTables[Name], true, 4);
David Majnemer3f49e662015-07-09 00:19:51 +00001095 uint32_t Offset = 6; // Skip relocations.
1096 uint16_t Flags = DE.getU16(&Offset);
1097 W.printHex("Flags", Flags);
1098 bool HasColumnInformation =
1099 Flags & COFF::DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS;
Timur Iskhodzhanov48703be2013-12-19 11:37:14 +00001100 uint32_t FunctionSize = DE.getU32(&Offset);
1101 W.printHex("CodeSize", FunctionSize);
1102 while (DE.isValidOffset(Offset)) {
1103 // For each range of lines with the same filename, we have a segment
1104 // in the line table. The filename string is accessed using double
1105 // indirection to the string table subsection using the index subsection.
1106 uint32_t OffsetInIndex = DE.getU32(&Offset),
David Majnemer04948362016-01-13 01:05:16 +00001107 NumLines = DE.getU32(&Offset),
David Majnemer0373d532015-07-09 18:14:31 +00001108 FullSegmentSize = DE.getU32(&Offset);
1109
David Majnemer04948362016-01-13 01:05:16 +00001110 uint32_t ColumnOffset = Offset + 8 * NumLines;
1111 DataExtractor ColumnDE(DE.getData(), true, 4);
1112
David Majnemer0373d532015-07-09 18:14:31 +00001113 if (FullSegmentSize !=
David Majnemer04948362016-01-13 01:05:16 +00001114 12 + 8 * NumLines + (HasColumnInformation ? 4 * NumLines : 0)) {
David Majnemer0373d532015-07-09 18:14:31 +00001115 error(object_error::parse_failed);
1116 return;
1117 }
Justin Bognera1413db2015-07-09 04:27:36 +00001118
Timur Iskhodzhanov48703be2013-12-19 11:37:14 +00001119 ListScope S(W, "FilenameSegment");
Reid Kleckner8e7275c2016-01-15 00:11:21 +00001120 printFileNameForOffset("Filename", OffsetInIndex);
David Majnemer04948362016-01-13 01:05:16 +00001121 for (unsigned LineIdx = 0;
1122 LineIdx != NumLines && DE.isValidOffset(Offset); ++LineIdx) {
Timur Iskhodzhanov48703be2013-12-19 11:37:14 +00001123 // Then go the (PC, LineNumber) pairs. The line number is stored in the
1124 // least significant 31 bits of the respective word in the table.
David Majnemer04948362016-01-13 01:05:16 +00001125 uint32_t PC = DE.getU32(&Offset), LineData = DE.getU32(&Offset);
Timur Iskhodzhanov48703be2013-12-19 11:37:14 +00001126 if (PC >= FunctionSize) {
1127 error(object_error::parse_failed);
1128 return;
1129 }
1130 char Buffer[32];
1131 format("+0x%X", PC).snprint(Buffer, 32);
David Majnemer04948362016-01-13 01:05:16 +00001132 ListScope PCScope(W, Buffer);
1133 uint32_t LineNumberStart = LineData & COFF::CVL_MaxLineNumber;
1134 uint32_t LineNumberEndDelta =
1135 (LineData >> COFF::CVL_LineNumberStartBits) &
1136 COFF::CVL_LineNumberEndDeltaMask;
1137 bool IsStatement = LineData & COFF::CVL_IsStatement;
1138 W.printNumber("LineNumberStart", LineNumberStart);
1139 W.printNumber("LineNumberEndDelta", LineNumberEndDelta);
1140 W.printBoolean("IsStatement", IsStatement);
1141 if (HasColumnInformation &&
1142 ColumnDE.isValidOffsetForDataOfSize(ColumnOffset, 4)) {
1143 uint16_t ColStart = ColumnDE.getU16(&ColumnOffset);
David Majnemer3f49e662015-07-09 00:19:51 +00001144 W.printNumber("ColStart", ColStart);
David Majnemer04948362016-01-13 01:05:16 +00001145 uint16_t ColEnd = ColumnDE.getU16(&ColumnOffset);
David Majnemer3f49e662015-07-09 00:19:51 +00001146 W.printNumber("ColEnd", ColEnd);
1147 }
1148 }
David Majnemer04948362016-01-13 01:05:16 +00001149 // Skip over the column data.
1150 if (HasColumnInformation) {
1151 for (unsigned LineIdx = 0;
1152 LineIdx != NumLines && DE.isValidOffset(Offset); ++LineIdx) {
1153 DE.getU32(&Offset);
1154 }
1155 }
Timur Iskhodzhanov48703be2013-12-19 11:37:14 +00001156 }
1157 }
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001158
1159 for (auto FrameDataPair : FunctionFrameData) {
1160 StringRef LinkageName = FrameDataPair.first;
1161 const FrameData *FD = FrameDataPair.second;
1162 ListScope S(W, "FunctionFrameData");
1163 W.printString("LinkageName", LinkageName);
1164 W.printHex("RvaStart", FD->RvaStart);
1165 W.printHex("CodeSize", FD->CodeSize);
1166 W.printHex("LocalSize", FD->LocalSize);
1167 W.printHex("ParamsSize", FD->ParamsSize);
1168 W.printHex("MaxStackSize", FD->MaxStackSize);
1169 W.printString("FrameFunc", StringRef(CVStringTable.data() + FD->FrameFunc));
1170 W.printHex("PrologSize", FD->PrologSize);
1171 W.printHex("SavedRegsSize", FD->SavedRegsSize);
1172 W.printFlags("Flags", FD->Flags, makeArrayRef(FrameDataFlags));
1173 }
1174}
1175
1176static std::error_code decodeNumerictLeaf(StringRef &Data, APSInt &Num) {
1177 // Used to avoid overload ambiguity on APInt construtor.
1178 bool FalseVal = false;
1179 if (Data.size() < 2)
1180 return object_error::parse_failed;
1181 uint16_t Short = *reinterpret_cast<const ulittle16_t *>(Data.data());
1182 Data = Data.drop_front(2);
1183 if (Short < LF_NUMERIC) {
1184 Num = APSInt(APInt(/*numBits=*/16, Short, /*isSigned=*/false),
1185 /*isUnsigned=*/true);
1186 return std::error_code();
1187 }
1188 switch (Short) {
1189 case LF_CHAR:
1190 Num = APSInt(APInt(/*numBits=*/8,
1191 *reinterpret_cast<const int8_t *>(Data.data()),
1192 /*isSigned=*/true),
1193 /*isUnsigned=*/false);
1194 Data = Data.drop_front(1);
1195 return std::error_code();
1196 case LF_SHORT:
1197 Num = APSInt(APInt(/*numBits=*/16,
1198 *reinterpret_cast<const little16_t *>(Data.data()),
1199 /*isSigned=*/true),
1200 /*isUnsigned=*/false);
1201 Data = Data.drop_front(2);
1202 return std::error_code();
1203 case LF_USHORT:
1204 Num = APSInt(APInt(/*numBits=*/16,
1205 *reinterpret_cast<const ulittle16_t *>(Data.data()),
1206 /*isSigned=*/false),
1207 /*isUnsigned=*/true);
1208 Data = Data.drop_front(2);
1209 return std::error_code();
1210 case LF_LONG:
1211 Num = APSInt(APInt(/*numBits=*/32,
1212 *reinterpret_cast<const little32_t *>(Data.data()),
1213 /*isSigned=*/true),
1214 /*isUnsigned=*/false);
1215 Data = Data.drop_front(4);
1216 return std::error_code();
1217 case LF_ULONG:
1218 Num = APSInt(APInt(/*numBits=*/32,
1219 *reinterpret_cast<const ulittle32_t *>(Data.data()),
1220 /*isSigned=*/FalseVal),
1221 /*isUnsigned=*/true);
1222 Data = Data.drop_front(4);
1223 return std::error_code();
1224 case LF_QUADWORD:
1225 Num = APSInt(APInt(/*numBits=*/64,
1226 *reinterpret_cast<const little64_t *>(Data.data()),
1227 /*isSigned=*/true),
1228 /*isUnsigned=*/false);
1229 Data = Data.drop_front(8);
1230 return std::error_code();
1231 case LF_UQUADWORD:
1232 Num = APSInt(APInt(/*numBits=*/64,
1233 *reinterpret_cast<const ulittle64_t *>(Data.data()),
1234 /*isSigned=*/false),
1235 /*isUnsigned=*/true);
1236 Data = Data.drop_front(8);
1237 return std::error_code();
1238 }
1239 return object_error::parse_failed;
1240}
1241
1242/// Decode an unsigned integer numeric leaf value.
1243std::error_code decodeUIntLeaf(StringRef &Data, uint64_t &Num) {
1244 APSInt N;
1245 if (std::error_code err = decodeNumerictLeaf(Data, N))
1246 return err;
1247 if (N.isSigned() || !N.isIntN(64))
1248 return object_error::parse_failed;
1249 Num = N.getLimitedValue();
1250 return std::error_code();
Timur Iskhodzhanov48703be2013-12-19 11:37:14 +00001251}
1252
Timur Iskhodzhanov56af52f2014-10-23 22:25:31 +00001253void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
1254 const SectionRef &Section,
Reid Kleckner2893fd12016-01-14 17:51:54 +00001255 StringRef SectionContents) {
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001256 if (Subsection.size() < sizeof(SymRecord))
1257 return error(object_error::parse_failed);
Timur Iskhodzhanov56af52f2014-10-23 22:25:31 +00001258
Reid Kleckner2893fd12016-01-14 17:51:54 +00001259 const coff_section *Sec = Obj->getCOFFSection(Section);
1260
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001261 // This holds the remaining data to parse.
1262 StringRef Data = Subsection;
1263
Timur Iskhodzhanov56af52f2014-10-23 22:25:31 +00001264 bool InFunctionScope = false;
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001265 while (!Data.empty()) {
1266 const SymRecord *Rec;
1267 error(consumeObject(Data, Rec));
1268
1269 StringRef SymData = Data.substr(0, Rec->RecordLength - 2);
Reid Kleckner1c7a9cd2016-01-14 17:51:57 +00001270 StringRef OrigSymData = SymData;
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001271
1272 Data = Data.drop_front(Rec->RecordLength - 2);
1273
Reid Kleckner6b3faef2016-01-13 23:44:57 +00001274 SymbolRecordKind Kind = Rec->getKind();
1275 switch (Kind) {
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001276 case S_LPROC32:
1277 case S_GPROC32:
1278 case S_GPROC32_ID:
1279 case S_LPROC32_ID:
1280 case S_LPROC32_DPC:
1281 case S_LPROC32_DPC_ID: {
Timur Iskhodzhanov56af52f2014-10-23 22:25:31 +00001282 DictScope S(W, "ProcStart");
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001283 const ProcSym *Proc;
1284 error(consumeObject(SymData, Proc));
1285 if (InFunctionScope)
1286 return error(object_error::parse_failed);
Timur Iskhodzhanov56af52f2014-10-23 22:25:31 +00001287 InFunctionScope = true;
1288
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001289 StringRef LinkageName;
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001290 StringRef DisplayName = SymData.split('\0').first;
1291 W.printHex("PtrParent", Proc->PtrParent);
1292 W.printHex("PtrEnd", Proc->PtrEnd);
1293 W.printHex("PtrNext", Proc->PtrNext);
1294 W.printHex("CodeSize", Proc->CodeSize);
1295 W.printHex("DbgStart", Proc->DbgStart);
1296 W.printHex("DbgEnd", Proc->DbgEnd);
1297 printTypeIndex("FunctionType", Proc->FunctionType);
Reid Kleckner2893fd12016-01-14 17:51:54 +00001298 printRelocatedField("CodeOffset", Sec, SectionContents, &Proc->CodeOffset,
1299 &LinkageName);
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001300 W.printHex("Segment", Proc->Segment);
1301 W.printFlags("Flags", Proc->Flags, makeArrayRef(ProcSymFlags));
1302 W.printString("DisplayName", DisplayName);
1303 W.printString("LinkageName", LinkageName);
Timur Iskhodzhanov56af52f2014-10-23 22:25:31 +00001304 break;
1305 }
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001306
1307 case S_PROC_ID_END: {
Timur Iskhodzhanov56af52f2014-10-23 22:25:31 +00001308 W.startLine() << "ProcEnd\n";
Timur Iskhodzhanov56af52f2014-10-23 22:25:31 +00001309 InFunctionScope = false;
1310 break;
1311 }
Zachary Turner99f02152015-02-18 19:32:05 +00001312
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001313 case S_BLOCK32: {
1314 DictScope S(W, "BlockStart");
1315 const BlockSym *Block;
1316 error(consumeObject(SymData, Block));
1317
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001318 StringRef BlockName = SymData.split('\0').first;
Reid Kleckner2893fd12016-01-14 17:51:54 +00001319 StringRef LinkageName;
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001320 W.printHex("PtrParent", Block->PtrParent);
1321 W.printHex("PtrEnd", Block->PtrEnd);
1322 W.printHex("CodeSize", Block->CodeSize);
Reid Kleckner2893fd12016-01-14 17:51:54 +00001323 printRelocatedField("CodeOffset", Sec, SectionContents,
1324 &Block->CodeOffset, &LinkageName);
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001325 W.printHex("Segment", Block->Segment);
1326 W.printString("BlockName", BlockName);
1327 W.printString("LinkageName", LinkageName);
1328 break;
1329 }
1330
1331 case S_END: {
1332 W.startLine() << "BlockEnd\n";
1333 InFunctionScope = false;
1334 break;
1335 }
1336
1337 case S_LABEL32: {
1338 DictScope S(W, "Label");
1339 const LabelSym *Label;
1340 error(consumeObject(SymData, Label));
1341
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001342 StringRef DisplayName = SymData.split('\0').first;
Reid Kleckner2893fd12016-01-14 17:51:54 +00001343 StringRef LinkageName;
1344 printRelocatedField("CodeOffset", Sec, SectionContents,
1345 &Label->CodeOffset, &LinkageName);
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001346 W.printHex("Segment", Label->Segment);
1347 W.printHex("Flags", Label->Flags);
1348 W.printFlags("Flags", Label->Flags, makeArrayRef(ProcSymFlags));
1349 W.printString("DisplayName", DisplayName);
1350 W.printString("LinkageName", LinkageName);
1351 break;
1352 }
1353
1354 case S_INLINESITE: {
1355 DictScope S(W, "InlineSite");
1356 const InlineSiteSym *InlineSite;
1357 error(consumeObject(SymData, InlineSite));
1358 W.printHex("PtrParent", InlineSite->PtrParent);
1359 W.printHex("PtrEnd", InlineSite->PtrEnd);
1360 printTypeIndex("Inlinee", InlineSite->Inlinee);
David Majnemere21e9092016-01-14 06:12:30 +00001361
1362 auto GetCompressedAnnotation = [&]() -> uint32_t {
1363 if (SymData.empty())
1364 return -1;
1365
1366 uint8_t FirstByte = SymData.front();
1367 SymData = SymData.drop_front();
1368
1369 if ((FirstByte & 0x80) == 0x00)
1370 return FirstByte;
1371
1372 if (SymData.empty())
1373 return -1;
1374
1375 uint8_t SecondByte = SymData.front();
1376 SymData = SymData.drop_front();
1377
1378 if ((FirstByte & 0xC0) == 0x80)
1379 return ((FirstByte & 0x3F) << 8) | SecondByte;
1380
1381 if (SymData.empty())
1382 return -1;
1383
1384 uint8_t ThirdByte = SymData.front();
1385 SymData = SymData.drop_front();
1386
1387 if (SymData.empty())
1388 return -1;
1389
1390 uint8_t FourthByte = SymData.front();
1391 SymData = SymData.drop_front();
1392
1393 if ((FirstByte & 0xE0) == 0xC0)
1394 return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
1395 (ThirdByte << 8) | FourthByte;
1396
1397 return -1;
1398 };
1399 auto DecodeSignedOperand = [](uint32_t Operand) -> int32_t {
1400 if (Operand & 1)
1401 return -(Operand >> 1);
1402 return Operand >> 1;
1403 };
1404
1405 ListScope BinaryAnnotations(W, "BinaryAnnotations");
1406 while (!SymData.empty()) {
1407 uint32_t OpCode = GetCompressedAnnotation();
1408 switch (OpCode) {
1409 default:
1410 case Invalid:
1411 return error(object_error::parse_failed);
1412 case CodeOffset:
Reid Kleckner43842b52016-01-14 21:50:05 +00001413 W.printHex("CodeOffset", GetCompressedAnnotation());
David Majnemere21e9092016-01-14 06:12:30 +00001414 break;
1415 case ChangeCodeOffsetBase:
1416 W.printNumber("ChangeCodeOffsetBase", GetCompressedAnnotation());
1417 break;
1418 case ChangeCodeOffset:
Reid Kleckner43842b52016-01-14 21:50:05 +00001419 W.printHex("ChangeCodeOffset", GetCompressedAnnotation());
David Majnemere21e9092016-01-14 06:12:30 +00001420 break;
1421 case ChangeCodeLength:
1422 W.printNumber("ChangeCodeLength", GetCompressedAnnotation());
1423 break;
1424 case ChangeFile:
Reid Kleckner43842b52016-01-14 21:50:05 +00001425 W.printHex("ChangeFile", GetCompressedAnnotation());
David Majnemere21e9092016-01-14 06:12:30 +00001426 break;
1427 case ChangeLineOffset:
1428 W.printNumber("ChangeLineOffset",
1429 DecodeSignedOperand(GetCompressedAnnotation()));
1430 break;
1431 case ChangeLineEndDelta:
1432 W.printNumber("ChangeLineEndDelta", GetCompressedAnnotation());
1433 break;
1434 case ChangeRangeKind:
1435 W.printNumber("ChangeRangeKind", GetCompressedAnnotation());
1436 break;
1437 case ChangeColumnStart:
1438 W.printNumber("ChangeColumnStart", GetCompressedAnnotation());
1439 break;
1440 case ChangeColumnEndDelta:
1441 W.printNumber("ChangeColumnEndDelta",
1442 DecodeSignedOperand(GetCompressedAnnotation()));
1443 break;
1444 case ChangeCodeOffsetAndLineOffset: {
1445 uint32_t Annotation = GetCompressedAnnotation();
Reid Kleckner8e7275c2016-01-15 00:11:21 +00001446 int32_t LineOffset = DecodeSignedOperand(Annotation >> 4);
Reid Kleckner43842b52016-01-14 21:50:05 +00001447 uint32_t CodeOffset = Annotation & 0xf;
Reid Kleckner8e7275c2016-01-15 00:11:21 +00001448 W.startLine() << "ChangeCodeOffsetAndLineOffset: {LineOffset: "
1449 << LineOffset << ", CodeOffset: " << W.hex(CodeOffset)
Reid Kleckner43842b52016-01-14 21:50:05 +00001450 << "}\n";
David Majnemere21e9092016-01-14 06:12:30 +00001451 break;
1452 }
1453 case ChangeCodeLengthAndCodeOffset: {
Reid Kleckner43842b52016-01-14 21:50:05 +00001454 uint32_t Length = GetCompressedAnnotation();
1455 uint32_t CodeOffset = GetCompressedAnnotation();
1456 W.startLine() << "ChangeCodeLengthAndCodeOffset: {Length: "
1457 << W.hex(Length)
1458 << ", CodeOffset: " << W.hex(CodeOffset) << "}\n";
David Majnemere21e9092016-01-14 06:12:30 +00001459 break;
1460 }
1461 case ChangeColumnEnd:
1462 W.printNumber("ChangeColumnEnd", GetCompressedAnnotation());
1463 break;
1464 }
1465 }
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001466 break;
1467 }
1468
1469 case S_INLINESITE_END: {
1470 DictScope S(W, "InlineSiteEnd");
1471 break;
1472 }
1473
Reid Kleckner43842b52016-01-14 21:50:05 +00001474 case S_CALLERS:
1475 case S_CALLEES: {
1476 ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers");
1477 uint32_t Count;
1478 error(consumeUInt32(SymData, Count));
1479 for (uint32_t I = 0; I < Count; ++I) {
1480 const TypeIndex *FuncID;
1481 error(consumeObject(SymData, FuncID));
1482 printTypeIndex("FuncID", *FuncID);
1483 }
1484 break;
1485 }
1486
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001487 case S_LOCAL: {
1488 DictScope S(W, "Local");
1489 const LocalSym *Local;
1490 error(consumeObject(SymData, Local));
1491 printTypeIndex("Type", Local->Type);
1492 W.printFlags("Flags", uint16_t(Local->Flags), makeArrayRef(LocalFlags));
1493 StringRef VarName = SymData.split('\0').first;
1494 W.printString("VarName", VarName);
1495 break;
1496 }
1497
1498 case S_CALLSITEINFO: {
1499 DictScope S(W, "CallSiteInfo");
1500 const CallSiteInfoSym *CallSiteInfo;
1501 error(consumeObject(SymData, CallSiteInfo));
1502
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001503 StringRef LinkageName;
Reid Kleckner2893fd12016-01-14 17:51:54 +00001504 printRelocatedField("CodeOffset", Sec, SectionContents,
1505 &CallSiteInfo->CodeOffset, &LinkageName);
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001506 W.printHex("Segment", CallSiteInfo->Segment);
1507 W.printHex("Reserved", CallSiteInfo->Reserved);
1508 printTypeIndex("Type", CallSiteInfo->Type);
1509 W.printString("LinkageName", LinkageName);
1510 break;
1511 }
1512
1513 case S_HEAPALLOCSITE: {
1514 DictScope S(W, "HeapAllocationSite");
1515 const HeapAllocationSiteSym *HeapAllocationSite;
1516 error(consumeObject(SymData, HeapAllocationSite));
1517
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001518 StringRef LinkageName;
Reid Kleckner2893fd12016-01-14 17:51:54 +00001519 printRelocatedField("CodeOffset", Sec, SectionContents,
1520 &HeapAllocationSite->CodeOffset, &LinkageName);
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001521 W.printHex("Segment", HeapAllocationSite->Segment);
1522 W.printHex("CallInstructionSize",
1523 HeapAllocationSite->CallInstructionSize);
1524 printTypeIndex("Type", HeapAllocationSite->Type);
1525 W.printString("LinkageName", LinkageName);
1526 break;
1527 }
1528
1529 case S_FRAMECOOKIE: {
1530 DictScope S(W, "FrameCookie");
1531 const FrameCookieSym *FrameCookie;
1532 error(consumeObject(SymData, FrameCookie));
Reid Kleckner2893fd12016-01-14 17:51:54 +00001533
1534 StringRef LinkageName;
1535 printRelocatedField("CodeOffset", Sec, SectionContents,
1536 &FrameCookie->CodeOffset, &LinkageName);
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001537 W.printHex("Register", FrameCookie->Register);
1538 W.printEnum("CookieKind", uint16_t(FrameCookie->CookieKind),
1539 makeArrayRef(FrameCookieKinds));
1540 break;
1541 }
1542
1543 case S_LDATA32:
1544 case S_GDATA32:
1545 case S_LMANDATA:
1546 case S_GMANDATA: {
1547 DictScope S(W, "DataSym");
1548 const DataSym *Data;
1549 error(consumeObject(SymData, Data));
1550
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001551 StringRef DisplayName = SymData.split('\0').first;
Reid Kleckner2893fd12016-01-14 17:51:54 +00001552 StringRef LinkageName;
1553 printRelocatedField("DataOffset", Sec, SectionContents, &Data->DataOffset,
1554 &LinkageName);
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001555 printTypeIndex("Type", Data->Type);
1556 W.printString("DisplayName", DisplayName);
1557 W.printString("LinkageName", LinkageName);
1558 break;
1559 }
Reid Kleckner2893fd12016-01-14 17:51:54 +00001560
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001561 case S_LTHREAD32:
1562 case S_GTHREAD32: {
1563 DictScope S(W, "ThreadLocalDataSym");
Reid Kleckner2893fd12016-01-14 17:51:54 +00001564 const ThreadLocalDataSym *Data;
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001565 error(consumeObject(SymData, Data));
1566
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001567 StringRef DisplayName = SymData.split('\0').first;
Reid Kleckner2893fd12016-01-14 17:51:54 +00001568 StringRef LinkageName;
1569 printRelocatedField("DataOffset", Sec, SectionContents, &Data->DataOffset,
1570 &LinkageName);
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001571 printTypeIndex("Type", Data->Type);
1572 W.printString("DisplayName", DisplayName);
1573 W.printString("LinkageName", LinkageName);
1574 break;
1575 }
1576
1577 case S_OBJNAME: {
1578 DictScope S(W, "ObjectName");
1579 const ObjNameSym *ObjName;
1580 error(consumeObject(SymData, ObjName));
1581 W.printHex("Signature", ObjName->Signature);
1582 StringRef ObjectName = SymData.split('\0').first;
1583 W.printString("ObjectName", ObjectName);
1584 break;
1585 }
1586
1587 case S_COMPILE3: {
1588 DictScope S(W, "CompilerFlags");
1589 const CompileSym3 *CompFlags;
1590 error(consumeObject(SymData, CompFlags));
1591 W.printEnum("Language", CompFlags->getLanguage(),
1592 makeArrayRef(SourceLanguages));
1593 W.printFlags("Flags", CompFlags->flags & ~0xff,
1594 makeArrayRef(CompileSym3Flags));
1595 W.printEnum("Machine", unsigned(CompFlags->Machine),
1596 makeArrayRef(CPUTypeNames));
1597 std::string FrontendVersion;
1598 {
1599 raw_string_ostream Out(FrontendVersion);
1600 Out << CompFlags->VersionFrontendMajor << '.'
1601 << CompFlags->VersionFrontendMinor << '.'
1602 << CompFlags->VersionFrontendBuild << '.'
1603 << CompFlags->VersionFrontendQFE;
Zachary Turner99f02152015-02-18 19:32:05 +00001604 }
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001605 std::string BackendVersion;
1606 {
1607 raw_string_ostream Out(BackendVersion);
1608 Out << CompFlags->VersionBackendMajor << '.'
1609 << CompFlags->VersionBackendMinor << '.'
1610 << CompFlags->VersionBackendBuild << '.'
1611 << CompFlags->VersionBackendQFE;
1612 }
1613 W.printString("FrontendVersion", FrontendVersion);
1614 W.printString("BackendVersion", BackendVersion);
1615 StringRef VersionName = SymData.split('\0').first;
1616 W.printString("VersionName", VersionName);
1617 break;
1618 }
Zachary Turner99f02152015-02-18 19:32:05 +00001619
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001620 case S_FRAMEPROC: {
1621 DictScope S(W, "FrameProc");
1622 const FrameProcSym *FrameProc;
1623 error(consumeObject(SymData, FrameProc));
1624 W.printHex("TotalFrameBytes", FrameProc->TotalFrameBytes);
1625 W.printHex("PaddingFrameBytes", FrameProc->PaddingFrameBytes);
1626 W.printHex("OffsetToPadding", FrameProc->OffsetToPadding);
1627 W.printHex("BytesOfCalleeSavedRegisters", FrameProc->BytesOfCalleeSavedRegisters);
1628 W.printHex("OffsetOfExceptionHandler", FrameProc->OffsetOfExceptionHandler);
1629 W.printHex("SectionIdOfExceptionHandler", FrameProc->SectionIdOfExceptionHandler);
1630 W.printFlags("Flags", FrameProc->Flags, makeArrayRef(FrameProcSymFlags));
1631 break;
1632 }
1633
1634 case S_UDT:
1635 case S_COBOLUDT: {
1636 DictScope S(W, "UDT");
1637 const UDTSym *UDT;
1638 error(consumeObject(SymData, UDT));
1639 printTypeIndex("Type", UDT->Type);
1640 StringRef UDTName = SymData.split('\0').first;
1641 W.printString("UDTName", UDTName);
1642 break;
1643 }
1644
1645 case S_BPREL32: {
1646 DictScope S(W, "BPRelativeSym");
1647 const BPRelativeSym *BPRel;
1648 error(consumeObject(SymData, BPRel));
1649 W.printHex("Offset", BPRel->Offset);
1650 printTypeIndex("Type", BPRel->Type);
1651 StringRef VarName = SymData.split('\0').first;
1652 W.printString("VarName", VarName);
1653 break;
1654 }
1655
1656 case S_REGREL32: {
1657 DictScope S(W, "RegRelativeSym");
1658 const RegRelativeSym *RegRel;
1659 error(consumeObject(SymData, RegRel));
1660 W.printHex("Offset", RegRel->Offset);
1661 printTypeIndex("Type", RegRel->Type);
1662 W.printHex("Register", RegRel->Register);
1663 StringRef VarName = SymData.split('\0').first;
1664 W.printString("VarName", VarName);
1665 break;
1666 }
1667
1668 case S_BUILDINFO: {
1669 DictScope S(W, "BuildInfo");
1670 const BuildInfoSym *BuildInfo;
1671 error(consumeObject(SymData, BuildInfo));
1672 W.printNumber("BuildId", BuildInfo->BuildId);
1673 break;
1674 }
1675
1676 case S_CONSTANT:
1677 case S_MANCONSTANT: {
1678 DictScope S(W, "Constant");
1679 const ConstantSym *Constant;
1680 error(consumeObject(SymData, Constant));
1681 printTypeIndex("Type", Constant->Type);
1682 APSInt Value;
1683 error(decodeNumerictLeaf(SymData, Value));
1684 W.printNumber("Value", Value);
1685 StringRef Name = SymData.split('\0').first;
1686 W.printString("Name", Name);
1687 break;
1688 }
1689
1690 default: {
1691 DictScope S(W, "UnknownSym");
Reid Kleckner6b3faef2016-01-13 23:44:57 +00001692 W.printHex("Kind", unsigned(Kind));
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001693 W.printHex("Size", Rec->RecordLength);
Timur Iskhodzhanov56af52f2014-10-23 22:25:31 +00001694 break;
1695 }
Zachary Turner99f02152015-02-18 19:32:05 +00001696 }
Reid Kleckner1c7a9cd2016-01-14 17:51:57 +00001697
1698 if (opts::CodeViewSubsectionBytes)
1699 printBinaryBlockWithRelocs("SymData", Section, SectionContents,
1700 OrigSymData);
Timur Iskhodzhanov56af52f2014-10-23 22:25:31 +00001701 }
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001702}
Timur Iskhodzhanov56af52f2014-10-23 22:25:31 +00001703
Reid Klecknere9ab3492016-01-14 19:20:17 +00001704void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
1705 StringRef Data = Subsection;
1706 uint32_t Signature;
1707 error(consumeUInt32(Data, Signature));
1708 bool HasExtraFiles = Signature == unsigned(InlineeLinesSignature::ExtraFiles);
1709
1710 while (!Data.empty()) {
1711 const InlineeSourceLine *ISL;
1712 error(consumeObject(Data, ISL));
1713 DictScope S(W, "InlineeSourceLine");
1714 printTypeIndex("Inlinee", ISL->Inlinee);
Reid Kleckner8e7275c2016-01-15 00:11:21 +00001715 printFileNameForOffset("FileID", ISL->FileID);
Reid Klecknere9ab3492016-01-14 19:20:17 +00001716 W.printNumber("SourceLineNum", ISL->SourceLineNum);
1717
1718 if (HasExtraFiles) {
1719 uint32_t ExtraFileCount;
1720 error(consumeUInt32(Data, ExtraFileCount));
1721 W.printNumber("ExtraFileCount", ExtraFileCount);
1722 ListScope ExtraFiles(W, "ExtraFiles");
1723 for (unsigned I = 0; I < ExtraFileCount; ++I) {
1724 uint32_t FileID;
1725 error(consumeUInt32(Data, FileID));
Reid Kleckner8e7275c2016-01-15 00:11:21 +00001726 printFileNameForOffset("FileID", FileID);
Reid Klecknere9ab3492016-01-14 19:20:17 +00001727 }
1728 }
1729 }
1730}
1731
Reid Kleckner6b3faef2016-01-13 23:44:57 +00001732StringRef getRemainingTypeBytes(const TypeRecordPrefix *Rec, const char *Start) {
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001733 ptrdiff_t StartOffset = Start - reinterpret_cast<const char *>(Rec);
1734 size_t RecSize = Rec->Len + 2;
1735 assert(StartOffset >= 0 && "negative start-offset!");
1736 assert(static_cast<size_t>(StartOffset) <= RecSize &&
1737 "Start beyond the end of Rec");
1738 return StringRef(Start, RecSize - StartOffset);
1739}
1740
Reid Kleckner6b3faef2016-01-13 23:44:57 +00001741StringRef getRemainingBytesAsString(const TypeRecordPrefix *Rec, const char *Start) {
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001742 StringRef Remaining = getRemainingTypeBytes(Rec, Start);
1743 StringRef Leading, Trailing;
1744 std::tie(Leading, Trailing) = Remaining.split('\0');
1745 return Leading;
1746}
1747
1748StringRef COFFDumper::getTypeName(TypeIndex TI) {
1749 if (TI.isNoType())
1750 return "<no type>";
1751
1752 if (TI.isSimple()) {
1753 // This is a simple type.
1754 for (const auto &SimpleTypeName : SimpleTypeNames) {
1755 if (SimpleTypeName.Value == TI.getSimpleKind()) {
1756 if (TI.getSimpleMode() == SimpleTypeMode::Direct)
1757 return SimpleTypeName.Name.drop_back(1);
1758 // Otherwise, this is a pointer type. We gloss over the distinction
1759 // between near, far, 64, 32, etc, and just give a pointer type.
1760 return SimpleTypeName.Name;
1761 }
1762 }
1763 return "<unknown simple type>";
1764 }
1765
1766 // User-defined type.
1767 StringRef UDTName;
1768 unsigned UDTIndex = TI.getIndex() - 0x1000;
1769 if (UDTIndex < CVUDTNames.size())
1770 return CVUDTNames[UDTIndex];
1771
1772 return "<unknown UDT>";
1773}
1774
1775void COFFDumper::printTypeIndex(StringRef FieldName, TypeIndex TI) {
1776 StringRef TypeName;
1777 if (!TI.isNoType())
1778 TypeName = getTypeName(TI);
1779 if (!TypeName.empty())
1780 W.printHex(FieldName, TypeName, TI.getIndex());
1781 else
1782 W.printHex(FieldName, TI.getIndex());
1783}
1784
Reid Kleckner8e7275c2016-01-15 00:11:21 +00001785StringRef COFFDumper::getFileNameForFileOffset(uint32_t FileOffset) {
1786 // The file checksum subsection should precede all references to it.
1787 if (!CVFileChecksumTable.data() || !CVStringTable.data())
1788 error(object_error::parse_failed);
1789 // Check if the file checksum table offset is valid.
1790 if (FileOffset >= CVFileChecksumTable.size())
1791 error(object_error::parse_failed);
1792
1793 // The string table offset comes first before the file checksum.
1794 StringRef Data = CVFileChecksumTable.drop_front(FileOffset);
1795 uint32_t StringOffset;
1796 error(consumeUInt32(Data, StringOffset));
1797
1798 // Check if the string table offset is valid.
1799 if (StringOffset >= CVStringTable.size())
1800 error(object_error::parse_failed);
1801
1802 // Return the null-terminated string.
1803 return CVStringTable.drop_front(StringOffset).split('\0').first;
1804}
1805
1806void COFFDumper::printFileNameForOffset(StringRef Label, uint32_t FileOffset) {
1807 W.printHex(Label, getFileNameForFileOffset(FileOffset), FileOffset);
1808}
1809
Reid Kleckner6b3faef2016-01-13 23:44:57 +00001810static StringRef getLeafTypeName(TypeLeafKind LT) {
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001811 switch (LT) {
1812 case LF_STRING_ID: return "StringId";
1813 case LF_FIELDLIST: return "FieldList";
1814 case LF_ARGLIST:
1815 case LF_SUBSTR_LIST: return "ArgList";
1816 case LF_CLASS:
1817 case LF_STRUCTURE:
1818 case LF_INTERFACE: return "ClassType";
1819 case LF_UNION: return "UnionType";
1820 case LF_ENUM: return "EnumType";
1821 case LF_ARRAY: return "ArrayType";
1822 case LF_VFTABLE: return "VFTableType";
1823 case LF_MFUNC_ID: return "MemberFuncId";
1824 case LF_PROCEDURE: return "ProcedureType";
1825 case LF_MFUNCTION: return "MemberFunctionType";
1826 case LF_METHODLIST: return "MethodListEntry";
1827 case LF_FUNC_ID: return "FuncId";
1828 case LF_TYPESERVER2: return "TypeServer2";
1829 case LF_POINTER: return "PointerType";
1830 case LF_MODIFIER: return "TypeModifier";
1831 case LF_VTSHAPE: return "VTableShape";
1832 case LF_UDT_SRC_LINE: return "UDTSrcLine";
1833 case LF_BUILDINFO: return "BuildInfo";
1834 default: break;
1835 }
1836 return "UnknownLeaf";
1837}
1838
1839void COFFDumper::printCodeViewTypeSection(StringRef SectionName,
1840 const SectionRef &Section) {
1841 ListScope D(W, "CodeViewTypes");
1842 W.printNumber("Section", SectionName, Obj->getSectionID(Section));
1843 StringRef Data;
1844 error(Section.getContents(Data));
1845 W.printBinaryBlock("Data", Data);
1846
1847 unsigned Magic = *reinterpret_cast<const ulittle32_t *>(Data.data());
1848 W.printHex("Magic", Magic);
1849
1850 Data = Data.drop_front(4);
1851
1852 while (!Data.empty()) {
Reid Kleckner6b3faef2016-01-13 23:44:57 +00001853 const TypeRecordPrefix *Rec;
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001854 error(consumeObject(Data, Rec));
Reid Kleckner6b3faef2016-01-13 23:44:57 +00001855 auto Leaf = static_cast<TypeLeafKind>(uint16_t(Rec->Leaf));
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001856
1857 // This record is 'Len - 2' bytes, and the next one starts immediately
1858 // afterwards.
1859 StringRef LeafData = Data.substr(0, Rec->Len - 2);
1860 StringRef RemainingData = Data.drop_front(LeafData.size());
1861
1862 // Find the name of this leaf type.
1863 StringRef LeafName = getLeafTypeName(Leaf);
1864 DictScope S(W, LeafName);
1865 unsigned NextTypeIndex = 0x1000 + CVUDTNames.size();
Reid Kleckner6b3faef2016-01-13 23:44:57 +00001866 W.printEnum("TypeLeafKind", unsigned(Leaf), makeArrayRef(LeafTypeNames));
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001867 W.printHex("TypeIndex", NextTypeIndex);
1868
1869 // Fill this in inside the switch to get something in CVUDTNames.
1870 StringRef Name;
1871
1872 switch (Leaf) {
1873 default: {
1874 W.printHex("Size", Rec->Len);
Reid Kleckner72e2ba72016-01-13 19:32:35 +00001875 break;
1876 }
1877
1878 case LF_STRING_ID: {
1879 const StringId *String;
1880 error(consumeObject(LeafData, String));
1881 W.printHex("Id", String->id.getIndex());
1882 StringRef StringData = getRemainingBytesAsString(Rec, LeafData.data());
1883 W.printString("StringData", StringData);
1884 // Put this in CVUDTNames so it gets printed with LF_UDT_SRC_LINE.
1885 Name = StringData;
1886 break;
1887 }
1888
1889 case LF_FIELDLIST: {
1890 W.printHex("Size", Rec->Len);
1891 // FieldList has no fixed prefix that can be described with a struct. All
1892 // the bytes must be interpreted as more records.
1893 printCodeViewFieldList(LeafData);
1894 break;
1895 }
1896
1897 case LF_ARGLIST:
1898 case LF_SUBSTR_LIST: {
1899 const ArgList *Args;
1900 error(consumeObject(LeafData, Args));
1901 W.printNumber("NumArgs", Args->NumArgs);
1902 ListScope Arguments(W, "Arguments");
1903 SmallString<256> TypeName("(");
1904 for (uint32_t ArgI = 0; ArgI != Args->NumArgs; ++ArgI) {
1905 const TypeIndex *Type;
1906 error(consumeObject(LeafData, Type));
1907 printTypeIndex("ArgType", *Type);
1908 StringRef ArgTypeName = getTypeName(*Type);
1909 TypeName.append(ArgTypeName);
1910 if (ArgI + 1 != Args->NumArgs)
1911 TypeName.append(", ");
1912 }
1913 TypeName.push_back(')');
1914 Name = TypeNames.insert(TypeName).first->getKey();
1915 break;
1916 }
1917
1918 case LF_CLASS:
1919 case LF_STRUCTURE:
1920 case LF_INTERFACE: {
1921 const ClassType *Class;
1922 error(consumeObject(LeafData, Class));
1923 W.printNumber("MemberCount", Class->MemberCount);
1924 uint16_t Props = Class->Properties;
1925 W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
1926 printTypeIndex("FieldList", Class->FieldList);
1927 printTypeIndex("DerivedFrom", Class->DerivedFrom);
1928 printTypeIndex("VShape", Class->VShape);
1929 uint64_t SizeOf;
1930 error(decodeUIntLeaf(LeafData, SizeOf));
1931 W.printNumber("SizeOf", SizeOf);
1932 StringRef LinkageName;
1933 std::tie(Name, LinkageName) = LeafData.split('\0');
1934 W.printString("Name", Name);
1935 if (Props & uint16_t(ClassOptions::HasUniqueName)) {
1936 LinkageName = getRemainingBytesAsString(Rec, LinkageName.data());
1937 if (LinkageName.empty())
1938 return error(object_error::parse_failed);
1939 W.printString("LinkageName", LinkageName);
1940 }
1941 break;
1942 }
1943
1944 case LF_UNION: {
1945 const UnionType *Union;
1946 error(consumeObject(LeafData, Union));
1947 W.printNumber("MemberCount", Union->MemberCount);
1948 uint16_t Props = Union->Properties;
1949 W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
1950 printTypeIndex("FieldList", Union->FieldList);
1951 uint64_t SizeOf;
1952 error(decodeUIntLeaf(LeafData, SizeOf));
1953 W.printNumber("SizeOf", SizeOf);
1954 StringRef LinkageName;
1955 std::tie(Name, LinkageName) = LeafData.split('\0');
1956 W.printString("Name", Name);
1957 if (Props & uint16_t(ClassOptions::HasUniqueName)) {
1958 LinkageName = getRemainingBytesAsString(Rec, LinkageName.data());
1959 if (LinkageName.empty())
1960 return error(object_error::parse_failed);
1961 W.printString("LinkageName", LinkageName);
1962 }
1963 break;
1964 }
1965
1966 case LF_ENUM: {
1967 const EnumType *Enum;
1968 error(consumeObject(LeafData, Enum));
1969 W.printNumber("NumEnumerators", Enum->NumEnumerators);
1970 W.printFlags("Properties", uint16_t(Enum->Properties),
1971 makeArrayRef(ClassOptionNames));
1972 printTypeIndex("UnderlyingType", Enum->UnderlyingType);
1973 printTypeIndex("FieldListType", Enum->FieldListType);
1974 Name = LeafData.split('\0').first;
1975 W.printString("Name", Name);
1976 break;
1977 }
1978
1979 case LF_ARRAY: {
1980 const ArrayType *AT;
1981 error(consumeObject(LeafData, AT));
1982 printTypeIndex("ElementType", AT->ElementType);
1983 printTypeIndex("IndexType", AT->IndexType);
1984 uint64_t SizeOf;
1985 error(decodeUIntLeaf(LeafData, SizeOf));
1986 W.printNumber("SizeOf", SizeOf);
1987 Name = LeafData.split('\0').first;
1988 W.printString("Name", Name);
1989 break;
1990 }
1991
1992 case LF_VFTABLE: {
1993 const VFTableType *VFT;
1994 error(consumeObject(LeafData, VFT));
1995 printTypeIndex("CompleteClass", VFT->CompleteClass);
1996 printTypeIndex("OverriddenVFTable", VFT->OverriddenVFTable);
1997 W.printHex("VFPtrOffset", VFT->VFPtrOffset);
1998 StringRef NamesData = LeafData.substr(0, VFT->NamesLen);
1999 std::tie(Name, NamesData) = NamesData.split('\0');
2000 W.printString("VFTableName", Name);
2001 while (!NamesData.empty()) {
2002 StringRef MethodName;
2003 std::tie(MethodName, NamesData) = NamesData.split('\0');
2004 W.printString("MethodName", MethodName);
2005 }
2006 break;
2007 }
2008
2009 case LF_MFUNC_ID: {
2010 const MemberFuncId *Id;
2011 error(consumeObject(LeafData, Id));
2012 printTypeIndex("ClassType", Id->ClassType);
2013 printTypeIndex("FunctionType", Id->FunctionType);
2014 Name = LeafData.split('\0').first;
2015 W.printString("Name", Name);
2016 break;
2017 }
2018
2019 case LF_PROCEDURE: {
2020 const ProcedureType *Proc;
2021 error(consumeObject(LeafData, Proc));
2022 printTypeIndex("ReturnType", Proc->ReturnType);
2023 W.printEnum("CallingConvention", uint8_t(Proc->CallConv),
2024 makeArrayRef(CallingConventions));
2025 W.printFlags("FunctionOptions", uint8_t(Proc->Options),
2026 makeArrayRef(FunctionOptionEnum));
2027 W.printNumber("NumParameters", Proc->NumParameters);
2028 printTypeIndex("ArgListType", Proc->ArgListType);
2029
2030 StringRef ReturnTypeName = getTypeName(Proc->ReturnType);
2031 StringRef ArgListTypeName = getTypeName(Proc->ArgListType);
2032 SmallString<256> TypeName(ReturnTypeName);
2033 TypeName.push_back(' ');
2034 TypeName.append(ArgListTypeName);
2035 Name = TypeNames.insert(TypeName).first->getKey();
2036 break;
2037 }
2038
2039 case LF_MFUNCTION: {
2040 const MemberFunctionType *MemberFunc;
2041 error(consumeObject(LeafData, MemberFunc));
2042 printTypeIndex("ReturnType", MemberFunc->ReturnType);
2043 printTypeIndex("ClassType", MemberFunc->ClassType);
2044 printTypeIndex("ThisType", MemberFunc->ThisType);
2045 W.printEnum("CallingConvention", uint8_t(MemberFunc->CallConv),
2046 makeArrayRef(CallingConventions));
2047 W.printFlags("FunctionOptions", uint8_t(MemberFunc->Options),
2048 makeArrayRef(FunctionOptionEnum));
2049 W.printNumber("NumParameters", MemberFunc->NumParameters);
2050 printTypeIndex("ArgListType", MemberFunc->ArgListType);
2051 W.printNumber("ThisAdjustment", MemberFunc->ThisAdjustment);
2052
2053 StringRef ReturnTypeName = getTypeName(MemberFunc->ReturnType);
2054 StringRef ClassTypeName = getTypeName(MemberFunc->ClassType);
2055 StringRef ArgListTypeName = getTypeName(MemberFunc->ArgListType);
2056 SmallString<256> TypeName(ReturnTypeName);
2057 TypeName.push_back(' ');
2058 TypeName.append(ClassTypeName);
2059 TypeName.append("::");
2060 TypeName.append(ArgListTypeName);
2061 Name = TypeNames.insert(TypeName).first->getKey();
2062 break;
2063 }
2064
2065 case LF_METHODLIST: {
2066 while (!LeafData.empty()) {
2067 const MethodListEntry *Method;
2068 error(consumeObject(LeafData, Method));
2069 ListScope S(W, "Method");
2070 printMemberAttributes(Method->Attrs);
2071 printTypeIndex("Type", Method->Type);
2072 if (Method->isIntroducedVirtual()) {
2073 const little32_t *VFTOffsetPtr;
2074 error(consumeObject(LeafData, VFTOffsetPtr));
2075 W.printHex("VFTableOffset", *VFTOffsetPtr);
2076 }
2077 }
2078 break;
2079 }
2080
2081 case LF_FUNC_ID: {
2082 const FuncId *Func;
2083 error(consumeObject(LeafData, Func));
2084 printTypeIndex("ParentScope", Func->ParentScope);
2085 printTypeIndex("FunctionType", Func->FunctionType);
Reid Kleckner089db212016-01-14 17:52:01 +00002086 StringRef Null;
Reid Kleckner72e2ba72016-01-13 19:32:35 +00002087 std::tie(Name, Null) = LeafData.split('\0');
2088 W.printString("Name", Name);
2089 break;
2090 }
2091
2092 case LF_TYPESERVER2: {
2093 const TypeServer2 *TypeServer;
2094 error(consumeObject(LeafData, TypeServer));
2095 W.printBinary("Signature", StringRef(TypeServer->Signature, 16));
2096 W.printNumber("Age", TypeServer->Age);
2097 Name = LeafData.split('\0').first;
2098 W.printString("Name", Name);
2099 break;
2100 }
2101
2102 case LF_POINTER: {
2103 const PointerType *Ptr;
2104 error(consumeObject(LeafData, Ptr));
2105 printTypeIndex("PointeeType", Ptr->PointeeType);
2106 W.printHex("PointerAttributes", Ptr->Attrs);
2107 W.printEnum("PtrType", unsigned(Ptr->getPtrKind()),
2108 makeArrayRef(PtrKindNames));
2109 W.printEnum("PtrMode", unsigned(Ptr->getPtrMode()),
2110 makeArrayRef(PtrModeNames));
2111 W.printNumber("IsFlat", Ptr->isFlat());
2112 W.printNumber("IsConst", Ptr->isConst());
2113 W.printNumber("IsVolatile", Ptr->isVolatile());
2114 W.printNumber("IsUnaligned", Ptr->isUnaligned());
2115
2116 if (Ptr->isPointerToMember()) {
2117 const PointerToMemberTail *PMT;
2118 error(consumeObject(LeafData, PMT));
2119 printTypeIndex("ClassType", PMT->ClassType);
2120 W.printEnum("Representation", PMT->Representation,
2121 makeArrayRef(PtrMemberRepNames));
2122
2123 StringRef PointeeName = getTypeName(Ptr->PointeeType);
2124 StringRef ClassName = getTypeName(PMT->ClassType);
2125 SmallString<256> TypeName(PointeeName);
2126 TypeName.push_back(' ');
2127 TypeName.append(ClassName);
2128 TypeName.append("::*");
2129 Name = TypeNames.insert(TypeName).first->getKey();
2130 } else {
2131 W.printBinaryBlock("TailData", LeafData);
2132
2133 SmallString<256> TypeName;
2134 if (Ptr->isConst())
2135 TypeName.append("const ");
2136 if (Ptr->isVolatile())
2137 TypeName.append("volatile ");
2138 if (Ptr->isUnaligned())
2139 TypeName.append("__unaligned ");
2140
2141 TypeName.append(getTypeName(Ptr->PointeeType));
2142
2143 if (Ptr->getPtrMode() == PointerMode::LValueReference)
2144 TypeName.append("&");
2145 else if (Ptr->getPtrMode() == PointerMode::RValueReference)
2146 TypeName.append("&&");
2147 else if (Ptr->getPtrMode() == PointerMode::Pointer)
2148 TypeName.append("*");
2149
2150 Name = TypeNames.insert(TypeName).first->getKey();
2151 }
2152 break;
2153 }
2154
2155 case LF_MODIFIER: {
2156 const TypeModifier *Mod;
2157 error(consumeObject(LeafData, Mod));
2158 printTypeIndex("ModifiedType", Mod->ModifiedType);
2159 W.printFlags("Modifiers", Mod->Modifiers,
2160 makeArrayRef(TypeModifierNames));
2161
2162 StringRef ModifiedName = getTypeName(Mod->ModifiedType);
2163 SmallString<256> TypeName;
2164 if (Mod->Modifiers & uint16_t(ModifierOptions::Const))
2165 TypeName.append("const ");
2166 if (Mod->Modifiers & uint16_t(ModifierOptions::Volatile))
2167 TypeName.append("volatile ");
2168 if (Mod->Modifiers & uint16_t(ModifierOptions::Unaligned))
2169 TypeName.append("__unaligned ");
2170 TypeName.append(ModifiedName);
2171 Name = TypeNames.insert(TypeName).first->getKey();
2172 break;
2173 }
2174
2175 case LF_VTSHAPE: {
2176 const VTableShape *Shape;
2177 error(consumeObject(LeafData, Shape));
2178 unsigned VFEntryCount = Shape->VFEntryCount;
2179 W.printNumber("VFEntryCount", VFEntryCount);
2180 // We could print out whether the methods are near or far, but in practice
2181 // today everything is CV_VTS_near32, so it's just noise.
2182 break;
2183 }
2184
2185 case LF_UDT_SRC_LINE: {
2186 const UDTSrcLine *Line;
2187 error(consumeObject(LeafData, Line));
2188 printTypeIndex("UDT", Line->UDT);
2189 printTypeIndex("SourceFile", Line->SourceFile);
2190 W.printNumber("LineNumber", Line->LineNumber);
2191 break;
2192 }
2193
2194 case LF_BUILDINFO: {
2195 const BuildInfo *Args;
2196 error(consumeObject(LeafData, Args));
2197 W.printNumber("NumArgs", Args->NumArgs);
2198
2199 ListScope Arguments(W, "Arguments");
2200 for (uint32_t ArgI = 0; ArgI != Args->NumArgs; ++ArgI) {
2201 const TypeIndex *Type;
2202 error(consumeObject(LeafData, Type));
2203 printTypeIndex("ArgType", *Type);
2204 }
2205 break;
2206 }
2207 }
2208
Reid Kleckner1c7a9cd2016-01-14 17:51:57 +00002209 if (opts::CodeViewSubsectionBytes)
2210 W.printBinaryBlock("LeafData", LeafData);
2211
Reid Kleckner72e2ba72016-01-13 19:32:35 +00002212 CVUDTNames.push_back(Name);
2213
2214 Data = RemainingData;
2215 // FIXME: The stream contains LF_PAD bytes that we need to ignore, but those
2216 // are typically included in LeafData. We may need to call skipPadding() if
2217 // we ever find a record that doesn't count those bytes.
2218 }
2219}
2220
2221static StringRef skipPadding(StringRef Data) {
2222 if (Data.empty())
2223 return Data;
2224 uint8_t Leaf = Data.front();
2225 if (Leaf < LF_PAD0)
2226 return Data;
2227 // Leaf is greater than 0xf0. We should advance by the number of bytes in the
2228 // low 4 bits.
2229 return Data.drop_front(Leaf & 0x0F);
2230}
2231
2232void COFFDumper::printMemberAttributes(MemberAttributes Attrs) {
2233 W.printEnum("AccessSpecifier", uint8_t(Attrs.getAccess()),
2234 makeArrayRef(MemberAccessNames));
2235 auto MK = Attrs.getMethodKind();
2236 // Data members will be vanilla. Don't try to print a method kind for them.
2237 if (MK != MethodKind::Vanilla)
2238 W.printEnum("MethodKind", unsigned(MK), makeArrayRef(MemberKindNames));
2239 if (Attrs.getFlags() != MethodOptions::None) {
2240 W.printFlags("MethodOptions", unsigned(Attrs.getFlags()),
2241 makeArrayRef(MethodOptionNames));
2242 }
2243}
2244
2245void COFFDumper::printCodeViewFieldList(StringRef FieldData) {
2246 while (!FieldData.empty()) {
2247 const ulittle16_t *LeafPtr;
2248 error(consumeObject(FieldData, LeafPtr));
2249 uint16_t Leaf = *LeafPtr;
2250 switch (Leaf) {
2251 default:
2252 W.printHex("UnknownMember", Leaf);
2253 // We can't advance once we hit an unknown field. The size is not encoded.
2254 return;
2255
2256 case LF_NESTTYPE: {
2257 const NestedType *Nested;
2258 error(consumeObject(FieldData, Nested));
2259 DictScope S(W, "NestedType");
2260 printTypeIndex("Type", Nested->Type);
2261 StringRef Name;
2262 std::tie(Name, FieldData) = FieldData.split('\0');
2263 W.printString("Name", Name);
2264 break;
2265 }
2266
2267 case LF_ONEMETHOD: {
2268 const OneMethod *Method;
2269 error(consumeObject(FieldData, Method));
2270 DictScope S(W, "OneMethod");
2271 printMemberAttributes(Method->Attrs);
2272 printTypeIndex("Type", Method->Type);
2273 // If virtual, then read the vftable offset.
2274 if (Method->isIntroducedVirtual()) {
2275 const little32_t *VFTOffsetPtr;
2276 error(consumeObject(FieldData, VFTOffsetPtr));
2277 W.printHex("VFTableOffset", *VFTOffsetPtr);
2278 }
2279 StringRef Name;
2280 std::tie(Name, FieldData) = FieldData.split('\0');
2281 W.printString("Name", Name);
2282 break;
2283 }
2284
2285 case LF_METHOD: {
2286 const OverloadedMethod *Method;
2287 error(consumeObject(FieldData, Method));
2288 DictScope S(W, "OverloadedMethod");
2289 W.printHex("MethodCount", Method->MethodCount);
2290 W.printHex("MethodListIndex", Method->MethList.getIndex());
2291 StringRef Name;
2292 std::tie(Name, FieldData) = FieldData.split('\0');
2293 W.printString("Name", Name);
2294 break;
2295 }
2296
2297 case LF_MEMBER: {
2298 const DataMember *Field;
2299 error(consumeObject(FieldData, Field));
2300 DictScope S(W, "DataMember");
2301 printMemberAttributes(Field->Attrs);
2302 printTypeIndex("Type", Field->Type);
2303 uint64_t FieldOffset;
2304 error(decodeUIntLeaf(FieldData, FieldOffset));
2305 W.printHex("FieldOffset", FieldOffset);
2306 StringRef Name;
2307 std::tie(Name, FieldData) = FieldData.split('\0');
2308 W.printString("Name", Name);
2309 break;
2310 }
2311
2312 case LF_STMEMBER: {
2313 const StaticDataMember *Field;
2314 error(consumeObject(FieldData, Field));
2315 DictScope S(W, "StaticDataMember");
2316 printMemberAttributes(Field->Attrs);
2317 printTypeIndex("Type", Field->Type);
2318 StringRef Name;
2319 std::tie(Name, FieldData) = FieldData.split('\0');
2320 W.printString("Name", Name);
2321 break;
2322 }
2323
2324 case LF_VFUNCTAB: {
2325 const VirtualFunctionPointer *VFTable;
2326 error(consumeObject(FieldData, VFTable));
2327 DictScope S(W, "VirtualFunctionPointer");
2328 printTypeIndex("Type", VFTable->Type);
2329 break;
2330 }
2331
2332 case LF_ENUMERATE: {
2333 const Enumerator *Enum;
2334 error(consumeObject(FieldData, Enum));
2335 DictScope S(W, "Enumerator");
2336 printMemberAttributes(Enum->Attrs);
2337 APSInt EnumValue;
2338 error(decodeNumerictLeaf(FieldData, EnumValue));
2339 W.printNumber("EnumValue", EnumValue);
2340 StringRef Name;
2341 std::tie(Name, FieldData) = FieldData.split('\0');
2342 W.printString("Name", Name);
2343 break;
2344 }
2345
2346 case LF_BCLASS:
2347 case LF_BINTERFACE: {
2348 const BaseClass *Base;
2349 error(consumeObject(FieldData, Base));
2350 DictScope S(W, "BaseClass");
2351 printMemberAttributes(Base->Attrs);
2352 printTypeIndex("BaseType", Base->BaseType);
2353 uint64_t BaseOffset;
2354 error(decodeUIntLeaf(FieldData, BaseOffset));
2355 W.printHex("BaseOffset", BaseOffset);
2356 break;
2357 }
2358
2359 case LF_VBCLASS:
2360 case LF_IVBCLASS: {
2361 const VirtualBaseClass *Base;
2362 error(consumeObject(FieldData, Base));
2363 DictScope S(W, "VirtualBaseClass");
2364 printMemberAttributes(Base->Attrs);
2365 printTypeIndex("BaseType", Base->BaseType);
2366 printTypeIndex("VBPtrType", Base->VBPtrType);
2367 uint64_t VBPtrOffset, VBTableIndex;
2368 error(decodeUIntLeaf(FieldData, VBPtrOffset));
2369 error(decodeUIntLeaf(FieldData, VBTableIndex));
2370 W.printHex("VBPtrOffset", VBPtrOffset);
2371 W.printHex("VBTableIndex", VBTableIndex);
2372 break;
2373 }
2374 }
2375
2376 // Handle padding.
2377 FieldData = skipPadding(FieldData);
2378 }
Timur Iskhodzhanov56af52f2014-10-23 22:25:31 +00002379}
2380
Eric Christopher9cad53c2013-04-03 18:31:38 +00002381void COFFDumper::printSections() {
Eric Christopher9cad53c2013-04-03 18:31:38 +00002382 ListScope SectionsD(W, "Sections");
2383 int SectionNumber = 0;
Alexey Samsonov27dc8392014-03-18 06:53:02 +00002384 for (const SectionRef &Sec : Obj->sections()) {
Eric Christopher9cad53c2013-04-03 18:31:38 +00002385 ++SectionNumber;
Alexey Samsonov27dc8392014-03-18 06:53:02 +00002386 const coff_section *Section = Obj->getCOFFSection(Sec);
Eric Christopher9cad53c2013-04-03 18:31:38 +00002387
2388 StringRef Name;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002389 error(Sec.getName(Name));
Eric Christopher9cad53c2013-04-03 18:31:38 +00002390
2391 DictScope D(W, "Section");
2392 W.printNumber("Number", SectionNumber);
2393 W.printBinary("Name", Name, Section->Name);
2394 W.printHex ("VirtualSize", Section->VirtualSize);
2395 W.printHex ("VirtualAddress", Section->VirtualAddress);
2396 W.printNumber("RawDataSize", Section->SizeOfRawData);
2397 W.printHex ("PointerToRawData", Section->PointerToRawData);
2398 W.printHex ("PointerToRelocations", Section->PointerToRelocations);
2399 W.printHex ("PointerToLineNumbers", Section->PointerToLinenumbers);
2400 W.printNumber("RelocationCount", Section->NumberOfRelocations);
2401 W.printNumber("LineNumberCount", Section->NumberOfLinenumbers);
2402 W.printFlags ("Characteristics", Section->Characteristics,
2403 makeArrayRef(ImageSectionCharacteristics),
2404 COFF::SectionCharacteristics(0x00F00000));
2405
2406 if (opts::SectionRelocations) {
2407 ListScope D(W, "Relocations");
Alexey Samsonov27dc8392014-03-18 06:53:02 +00002408 for (const RelocationRef &Reloc : Sec.relocations())
2409 printRelocation(Sec, Reloc);
Eric Christopher9cad53c2013-04-03 18:31:38 +00002410 }
2411
2412 if (opts::SectionSymbols) {
2413 ListScope D(W, "Symbols");
Alexey Samsonov27dc8392014-03-18 06:53:02 +00002414 for (const SymbolRef &Symbol : Obj->symbols()) {
Rafael Espindola80291272014-10-08 15:28:58 +00002415 if (!Sec.containsSymbol(Symbol))
Eric Christopher9cad53c2013-04-03 18:31:38 +00002416 continue;
2417
Alexey Samsonov27dc8392014-03-18 06:53:02 +00002418 printSymbol(Symbol);
Eric Christopher9cad53c2013-04-03 18:31:38 +00002419 }
2420 }
2421
David Majnemerdac39852014-09-26 22:32:16 +00002422 if (opts::SectionData &&
2423 !(Section->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) {
Eric Christopher9cad53c2013-04-03 18:31:38 +00002424 StringRef Data;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002425 error(Sec.getContents(Data));
Eric Christopher9cad53c2013-04-03 18:31:38 +00002426
2427 W.printBinaryBlock("SectionData", Data);
2428 }
2429 }
2430}
2431
2432void COFFDumper::printRelocations() {
2433 ListScope D(W, "Relocations");
2434
Eric Christopher9cad53c2013-04-03 18:31:38 +00002435 int SectionNumber = 0;
Alexey Samsonov27dc8392014-03-18 06:53:02 +00002436 for (const SectionRef &Section : Obj->sections()) {
Eric Christopher9cad53c2013-04-03 18:31:38 +00002437 ++SectionNumber;
Eric Christopher9cad53c2013-04-03 18:31:38 +00002438 StringRef Name;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002439 error(Section.getName(Name));
Eric Christopher9cad53c2013-04-03 18:31:38 +00002440
2441 bool PrintedGroup = false;
Alexey Samsonov27dc8392014-03-18 06:53:02 +00002442 for (const RelocationRef &Reloc : Section.relocations()) {
Eric Christopher9cad53c2013-04-03 18:31:38 +00002443 if (!PrintedGroup) {
2444 W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";
2445 W.indent();
2446 PrintedGroup = true;
2447 }
2448
Alexey Samsonov27dc8392014-03-18 06:53:02 +00002449 printRelocation(Section, Reloc);
Eric Christopher9cad53c2013-04-03 18:31:38 +00002450 }
2451
2452 if (PrintedGroup) {
2453 W.unindent();
2454 W.startLine() << "}\n";
2455 }
2456 }
2457}
2458
Alexey Samsonov27dc8392014-03-18 06:53:02 +00002459void COFFDumper::printRelocation(const SectionRef &Section,
Reid Kleckner1c7a9cd2016-01-14 17:51:57 +00002460 const RelocationRef &Reloc, uint64_t Bias) {
2461 uint64_t Offset = Reloc.getOffset() - Bias;
Rafael Espindola99c041b2015-06-30 01:53:01 +00002462 uint64_t RelocType = Reloc.getType();
Eric Christopher9cad53c2013-04-03 18:31:38 +00002463 SmallString<32> RelocName;
Eric Christopher9cad53c2013-04-03 18:31:38 +00002464 StringRef SymbolName;
Rafael Espindola41bb4322015-06-30 04:08:37 +00002465 Reloc.getTypeName(RelocName);
Alexey Samsonovaa4d2952014-03-14 14:22:49 +00002466 symbol_iterator Symbol = Reloc.getSymbol();
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +00002467 if (Symbol != Obj->symbol_end()) {
2468 ErrorOr<StringRef> SymbolNameOrErr = Symbol->getName();
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002469 error(SymbolNameOrErr.getError());
Rafael Espindola5d0c2ff2015-07-02 20:55:21 +00002470 SymbolName = *SymbolNameOrErr;
2471 }
Eric Christopher9cad53c2013-04-03 18:31:38 +00002472
Nico Rieckf3f0b792013-04-12 04:01:52 +00002473 if (opts::ExpandRelocs) {
2474 DictScope Group(W, "Relocation");
2475 W.printHex("Offset", Offset);
2476 W.printNumber("Type", RelocName, RelocType);
David Majnemer1f80b0a2014-11-13 07:42:11 +00002477 W.printString("Symbol", SymbolName.empty() ? "-" : SymbolName);
Nico Rieckf3f0b792013-04-12 04:01:52 +00002478 } else {
2479 raw_ostream& OS = W.startLine();
2480 OS << W.hex(Offset)
2481 << " " << RelocName
David Majnemer1f80b0a2014-11-13 07:42:11 +00002482 << " " << (SymbolName.empty() ? "-" : SymbolName)
Nico Rieckf3f0b792013-04-12 04:01:52 +00002483 << "\n";
2484 }
Eric Christopher9cad53c2013-04-03 18:31:38 +00002485}
2486
2487void COFFDumper::printSymbols() {
2488 ListScope Group(W, "Symbols");
2489
Alexey Samsonov27dc8392014-03-18 06:53:02 +00002490 for (const SymbolRef &Symbol : Obj->symbols())
2491 printSymbol(Symbol);
Eric Christopher9cad53c2013-04-03 18:31:38 +00002492}
2493
Alexey Samsonov27dc8392014-03-18 06:53:02 +00002494void COFFDumper::printDynamicSymbols() { ListScope Group(W, "DynamicSymbols"); }
Eric Christopher9cad53c2013-04-03 18:31:38 +00002495
David Majnemer236b0ca2014-11-17 11:17:17 +00002496static ErrorOr<StringRef>
2497getSectionName(const llvm::object::COFFObjectFile *Obj, int32_t SectionNumber,
2498 const coff_section *Section) {
David Majnemerf4dc4562014-09-20 00:25:06 +00002499 if (Section) {
2500 StringRef SectionName;
David Majnemer236b0ca2014-11-17 11:17:17 +00002501 if (std::error_code EC = Obj->getSectionName(Section, SectionName))
2502 return EC;
David Majnemerf4dc4562014-09-20 00:25:06 +00002503 return SectionName;
2504 }
David Majnemerf4dc4562014-09-20 00:25:06 +00002505 if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG)
David Majnemer236b0ca2014-11-17 11:17:17 +00002506 return StringRef("IMAGE_SYM_DEBUG");
David Majnemerf4dc4562014-09-20 00:25:06 +00002507 if (SectionNumber == llvm::COFF::IMAGE_SYM_ABSOLUTE)
David Majnemer236b0ca2014-11-17 11:17:17 +00002508 return StringRef("IMAGE_SYM_ABSOLUTE");
David Majnemerf4dc4562014-09-20 00:25:06 +00002509 if (SectionNumber == llvm::COFF::IMAGE_SYM_UNDEFINED)
David Majnemer236b0ca2014-11-17 11:17:17 +00002510 return StringRef("IMAGE_SYM_UNDEFINED");
2511 return StringRef("");
David Majnemerf4dc4562014-09-20 00:25:06 +00002512}
2513
Alexey Samsonov27dc8392014-03-18 06:53:02 +00002514void COFFDumper::printSymbol(const SymbolRef &Sym) {
Eric Christopher9cad53c2013-04-03 18:31:38 +00002515 DictScope D(W, "Symbol");
2516
David Majnemer44f51e52014-09-10 12:51:52 +00002517 COFFSymbolRef Symbol = Obj->getCOFFSymbol(Sym);
Eric Christopher9cad53c2013-04-03 18:31:38 +00002518 const coff_section *Section;
David Majnemer44f51e52014-09-10 12:51:52 +00002519 if (std::error_code EC = Obj->getSection(Symbol.getSectionNumber(), Section)) {
Eric Christopher9cad53c2013-04-03 18:31:38 +00002520 W.startLine() << "Invalid section number: " << EC.message() << "\n";
2521 W.flush();
2522 return;
2523 }
2524
2525 StringRef SymbolName;
2526 if (Obj->getSymbolName(Symbol, SymbolName))
2527 SymbolName = "";
2528
David Majnemer236b0ca2014-11-17 11:17:17 +00002529 StringRef SectionName = "";
2530 ErrorOr<StringRef> Res =
2531 getSectionName(Obj, Symbol.getSectionNumber(), Section);
2532 if (Res)
2533 SectionName = *Res;
Eric Christopher9cad53c2013-04-03 18:31:38 +00002534
2535 W.printString("Name", SymbolName);
David Majnemer44f51e52014-09-10 12:51:52 +00002536 W.printNumber("Value", Symbol.getValue());
2537 W.printNumber("Section", SectionName, Symbol.getSectionNumber());
2538 W.printEnum ("BaseType", Symbol.getBaseType(), makeArrayRef(ImageSymType));
2539 W.printEnum ("ComplexType", Symbol.getComplexType(),
Eric Christopher9cad53c2013-04-03 18:31:38 +00002540 makeArrayRef(ImageSymDType));
David Majnemer44f51e52014-09-10 12:51:52 +00002541 W.printEnum ("StorageClass", Symbol.getStorageClass(),
Eric Christopher9cad53c2013-04-03 18:31:38 +00002542 makeArrayRef(ImageSymClass));
David Majnemer44f51e52014-09-10 12:51:52 +00002543 W.printNumber("AuxSymbolCount", Symbol.getNumberOfAuxSymbols());
Eric Christopher9cad53c2013-04-03 18:31:38 +00002544
David Majnemer44f51e52014-09-10 12:51:52 +00002545 for (uint8_t I = 0; I < Symbol.getNumberOfAuxSymbols(); ++I) {
2546 if (Symbol.isFunctionDefinition()) {
Eric Christopher9cad53c2013-04-03 18:31:38 +00002547 const coff_aux_function_definition *Aux;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002548 error(getSymbolAuxData(Obj, Symbol, I, Aux));
Eric Christopher9cad53c2013-04-03 18:31:38 +00002549
2550 DictScope AS(W, "AuxFunctionDef");
2551 W.printNumber("TagIndex", Aux->TagIndex);
2552 W.printNumber("TotalSize", Aux->TotalSize);
David Majnemerf3a2af52014-03-19 04:33:27 +00002553 W.printHex("PointerToLineNumber", Aux->PointerToLinenumber);
Eric Christopher9cad53c2013-04-03 18:31:38 +00002554 W.printHex("PointerToNextFunction", Aux->PointerToNextFunction);
Eric Christopher9cad53c2013-04-03 18:31:38 +00002555
David Majnemerc7d7c6f2014-10-31 05:07:00 +00002556 } else if (Symbol.isAnyUndefined()) {
David Majnemerf3a2af52014-03-19 04:33:27 +00002557 const coff_aux_weak_external *Aux;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002558 error(getSymbolAuxData(Obj, Symbol, I, Aux));
Eric Christopher9cad53c2013-04-03 18:31:38 +00002559
David Majnemer44f51e52014-09-10 12:51:52 +00002560 ErrorOr<COFFSymbolRef> Linked = Obj->getSymbol(Aux->TagIndex);
Eric Christopher9cad53c2013-04-03 18:31:38 +00002561 StringRef LinkedName;
David Majnemer44f51e52014-09-10 12:51:52 +00002562 std::error_code EC = Linked.getError();
2563 if (EC || (EC = Obj->getSymbolName(*Linked, LinkedName))) {
Eric Christopher9cad53c2013-04-03 18:31:38 +00002564 LinkedName = "";
2565 error(EC);
2566 }
2567
2568 DictScope AS(W, "AuxWeakExternal");
2569 W.printNumber("Linked", LinkedName, Aux->TagIndex);
2570 W.printEnum ("Search", Aux->Characteristics,
2571 makeArrayRef(WeakExternalCharacteristics));
Eric Christopher9cad53c2013-04-03 18:31:38 +00002572
David Majnemer44f51e52014-09-10 12:51:52 +00002573 } else if (Symbol.isFileRecord()) {
2574 const char *FileName;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002575 error(getSymbolAuxData(Obj, Symbol, I, FileName));
Eric Christopher9cad53c2013-04-03 18:31:38 +00002576
Nico Rieck0ab8e602013-04-22 08:35:11 +00002577 DictScope AS(W, "AuxFileRecord");
Saleem Abdulrasoold38c6b12014-04-14 02:37:23 +00002578
David Majnemer44f51e52014-09-10 12:51:52 +00002579 StringRef Name(FileName, Symbol.getNumberOfAuxSymbols() *
2580 Obj->getSymbolTableEntrySize());
Saleem Abdulrasoold38c6b12014-04-14 02:37:23 +00002581 W.printString("FileName", Name.rtrim(StringRef("\0", 1)));
Saleem Abdulrasool3b5e0012014-04-16 04:15:29 +00002582 break;
David Majnemer44f51e52014-09-10 12:51:52 +00002583 } else if (Symbol.isSectionDefinition()) {
Eric Christopher9cad53c2013-04-03 18:31:38 +00002584 const coff_aux_section_definition *Aux;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002585 error(getSymbolAuxData(Obj, Symbol, I, Aux));
Eric Christopher9cad53c2013-04-03 18:31:38 +00002586
David Majnemer4d571592014-09-15 19:42:42 +00002587 int32_t AuxNumber = Aux->getNumber(Symbol.isBigObj());
2588
Eric Christopher9cad53c2013-04-03 18:31:38 +00002589 DictScope AS(W, "AuxSectionDef");
2590 W.printNumber("Length", Aux->Length);
2591 W.printNumber("RelocationCount", Aux->NumberOfRelocations);
2592 W.printNumber("LineNumberCount", Aux->NumberOfLinenumbers);
2593 W.printHex("Checksum", Aux->CheckSum);
David Majnemer4d571592014-09-15 19:42:42 +00002594 W.printNumber("Number", AuxNumber);
Eric Christopher9cad53c2013-04-03 18:31:38 +00002595 W.printEnum("Selection", Aux->Selection, makeArrayRef(ImageCOMDATSelect));
Eric Christopher9cad53c2013-04-03 18:31:38 +00002596
Nico Riecka711dee2013-04-22 08:34:59 +00002597 if (Section && Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT
Eric Christopher9cad53c2013-04-03 18:31:38 +00002598 && Aux->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
2599 const coff_section *Assoc;
David Majnemer236b0ca2014-11-17 11:17:17 +00002600 StringRef AssocName = "";
2601 std::error_code EC = Obj->getSection(AuxNumber, Assoc);
2602 ErrorOr<StringRef> Res = getSectionName(Obj, AuxNumber, Assoc);
2603 if (Res)
2604 AssocName = *Res;
2605 if (!EC)
2606 EC = Res.getError();
2607 if (EC) {
Eric Christopher9cad53c2013-04-03 18:31:38 +00002608 AssocName = "";
2609 error(EC);
2610 }
2611
David Majnemer4d571592014-09-15 19:42:42 +00002612 W.printNumber("AssocSection", AssocName, AuxNumber);
Eric Christopher9cad53c2013-04-03 18:31:38 +00002613 }
David Majnemer44f51e52014-09-10 12:51:52 +00002614 } else if (Symbol.isCLRToken()) {
Eric Christopher9cad53c2013-04-03 18:31:38 +00002615 const coff_aux_clr_token *Aux;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002616 error(getSymbolAuxData(Obj, Symbol, I, Aux));
Eric Christopher9cad53c2013-04-03 18:31:38 +00002617
David Majnemer44f51e52014-09-10 12:51:52 +00002618 ErrorOr<COFFSymbolRef> ReferredSym =
2619 Obj->getSymbol(Aux->SymbolTableIndex);
Nico Rieck8678acd2014-03-17 01:46:52 +00002620 StringRef ReferredName;
David Majnemer44f51e52014-09-10 12:51:52 +00002621 std::error_code EC = ReferredSym.getError();
2622 if (EC || (EC = Obj->getSymbolName(*ReferredSym, ReferredName))) {
Nico Rieck8678acd2014-03-17 01:46:52 +00002623 ReferredName = "";
2624 error(EC);
2625 }
2626
Eric Christopher9cad53c2013-04-03 18:31:38 +00002627 DictScope AS(W, "AuxCLRToken");
2628 W.printNumber("AuxType", Aux->AuxType);
2629 W.printNumber("Reserved", Aux->Reserved);
Nico Rieck8678acd2014-03-17 01:46:52 +00002630 W.printNumber("SymbolTableIndex", ReferredName, Aux->SymbolTableIndex);
Eric Christopher9cad53c2013-04-03 18:31:38 +00002631
2632 } else {
2633 W.startLine() << "<unhandled auxiliary record>\n";
2634 }
2635 }
2636}
2637
2638void COFFDumper::printUnwindInfo() {
Eric Christopher9cad53c2013-04-03 18:31:38 +00002639 ListScope D(W, "UnwindInformation");
David Majnemer44f51e52014-09-10 12:51:52 +00002640 switch (Obj->getMachine()) {
Saleem Abdulrasoole8839a72014-05-25 20:26:45 +00002641 case COFF::IMAGE_FILE_MACHINE_AMD64: {
2642 Win64EH::Dumper Dumper(W);
Rafael Espindola4453e42942014-06-13 03:07:50 +00002643 Win64EH::Dumper::SymbolResolver
2644 Resolver = [](const object::coff_section *Section, uint64_t Offset,
2645 SymbolRef &Symbol, void *user_data) -> std::error_code {
2646 COFFDumper *Dumper = reinterpret_cast<COFFDumper *>(user_data);
2647 return Dumper->resolveSymbol(Section, Offset, Symbol);
2648 };
Saleem Abdulrasool65dbbb52014-05-25 21:37:59 +00002649 Win64EH::Dumper::Context Ctx(*Obj, Resolver, this);
Saleem Abdulrasoole8839a72014-05-25 20:26:45 +00002650 Dumper.printData(Ctx);
2651 break;
Eric Christopher9cad53c2013-04-03 18:31:38 +00002652 }
Saleem Abdulrasoole6971ca2014-06-04 15:47:15 +00002653 case COFF::IMAGE_FILE_MACHINE_ARMNT: {
2654 ARM::WinEH::Decoder Decoder(W);
2655 Decoder.dumpProcedureData(*Obj);
2656 break;
2657 }
Saleem Abdulrasoole8839a72014-05-25 20:26:45 +00002658 default:
David Majnemer44f51e52014-09-10 12:51:52 +00002659 W.printEnum("unsupported Image Machine", Obj->getMachine(),
Saleem Abdulrasoole8839a72014-05-25 20:26:45 +00002660 makeArrayRef(ImageFileMachineType));
2661 break;
Eric Christopher9cad53c2013-04-03 18:31:38 +00002662 }
2663}
2664
Rui Ueyama979fb402014-10-09 02:16:38 +00002665void COFFDumper::printImportedSymbols(
2666 iterator_range<imported_symbol_iterator> Range) {
2667 for (const ImportedSymbolRef &I : Range) {
Rui Ueyama15d99352014-10-03 00:41:58 +00002668 StringRef Sym;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002669 error(I.getSymbolName(Sym));
Rui Ueyama15d99352014-10-03 00:41:58 +00002670 uint16_t Ordinal;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002671 error(I.getOrdinal(Ordinal));
Rui Ueyama15d99352014-10-03 00:41:58 +00002672 W.printNumber("Symbol", Sym, Ordinal);
2673 }
2674}
2675
Rui Ueyamaffa4ceb2014-11-13 03:22:54 +00002676void COFFDumper::printDelayImportedSymbols(
2677 const DelayImportDirectoryEntryRef &I,
2678 iterator_range<imported_symbol_iterator> Range) {
2679 int Index = 0;
2680 for (const ImportedSymbolRef &S : Range) {
2681 DictScope Import(W, "Import");
2682 StringRef Sym;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002683 error(S.getSymbolName(Sym));
Rui Ueyamaffa4ceb2014-11-13 03:22:54 +00002684 uint16_t Ordinal;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002685 error(S.getOrdinal(Ordinal));
Rui Ueyamaffa4ceb2014-11-13 03:22:54 +00002686 W.printNumber("Symbol", Sym, Ordinal);
2687 uint64_t Addr;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002688 error(I.getImportAddress(Index++, Addr));
Rui Ueyamaffa4ceb2014-11-13 03:22:54 +00002689 W.printHex("Address", Addr);
2690 }
2691}
2692
Rui Ueyama1e152d52014-10-02 17:02:18 +00002693void COFFDumper::printCOFFImports() {
Rui Ueyama15d99352014-10-03 00:41:58 +00002694 // Regular imports
Rui Ueyama979fb402014-10-09 02:16:38 +00002695 for (const ImportDirectoryEntryRef &I : Obj->import_directories()) {
Rui Ueyama1e152d52014-10-02 17:02:18 +00002696 DictScope Import(W, "Import");
2697 StringRef Name;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002698 error(I.getName(Name));
Rui Ueyama1e152d52014-10-02 17:02:18 +00002699 W.printString("Name", Name);
2700 uint32_t Addr;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002701 error(I.getImportLookupTableRVA(Addr));
Rui Ueyama1e152d52014-10-02 17:02:18 +00002702 W.printHex("ImportLookupTableRVA", Addr);
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002703 error(I.getImportAddressTableRVA(Addr));
Rui Ueyama1e152d52014-10-02 17:02:18 +00002704 W.printHex("ImportAddressTableRVA", Addr);
Rui Ueyama979fb402014-10-09 02:16:38 +00002705 printImportedSymbols(I.imported_symbols());
Rui Ueyama15d99352014-10-03 00:41:58 +00002706 }
2707
2708 // Delay imports
Rui Ueyama979fb402014-10-09 02:16:38 +00002709 for (const DelayImportDirectoryEntryRef &I : Obj->delay_import_directories()) {
Rui Ueyama15d99352014-10-03 00:41:58 +00002710 DictScope Import(W, "DelayImport");
2711 StringRef Name;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002712 error(I.getName(Name));
Rui Ueyama15d99352014-10-03 00:41:58 +00002713 W.printString("Name", Name);
Rui Ueyama1af08652014-10-03 18:07:18 +00002714 const delay_import_directory_table_entry *Table;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002715 error(I.getDelayImportTable(Table));
Rui Ueyama1af08652014-10-03 18:07:18 +00002716 W.printHex("Attributes", Table->Attributes);
2717 W.printHex("ModuleHandle", Table->ModuleHandle);
2718 W.printHex("ImportAddressTable", Table->DelayImportAddressTable);
2719 W.printHex("ImportNameTable", Table->DelayImportNameTable);
2720 W.printHex("BoundDelayImportTable", Table->BoundDelayImportTable);
2721 W.printHex("UnloadDelayImportTable", Table->UnloadDelayImportTable);
Rui Ueyamaffa4ceb2014-11-13 03:22:54 +00002722 printDelayImportedSymbols(I, I.imported_symbols());
Rui Ueyama1e152d52014-10-02 17:02:18 +00002723 }
2724}
Saleem Abdulrasoolf9578632014-10-07 19:37:52 +00002725
Saleem Abdulrasoolddd92642015-01-03 21:35:09 +00002726void COFFDumper::printCOFFExports() {
2727 for (const ExportDirectoryEntryRef &E : Obj->export_directories()) {
2728 DictScope Export(W, "Export");
2729
2730 StringRef Name;
2731 uint32_t Ordinal, RVA;
2732
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002733 error(E.getSymbolName(Name));
2734 error(E.getOrdinal(Ordinal));
2735 error(E.getExportRVA(RVA));
Saleem Abdulrasoolddd92642015-01-03 21:35:09 +00002736
2737 W.printNumber("Ordinal", Ordinal);
2738 W.printString("Name", Name);
2739 W.printHex("RVA", RVA);
2740 }
2741}
2742
Saleem Abdulrasoolf9578632014-10-07 19:37:52 +00002743void COFFDumper::printCOFFDirectives() {
2744 for (const SectionRef &Section : Obj->sections()) {
2745 StringRef Contents;
2746 StringRef Name;
2747
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002748 error(Section.getName(Name));
Saleem Abdulrasoolf9578632014-10-07 19:37:52 +00002749 if (Name != ".drectve")
2750 continue;
2751
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002752 error(Section.getContents(Contents));
Saleem Abdulrasoolf9578632014-10-07 19:37:52 +00002753
2754 W.printString("Directive(s)", Contents);
2755 }
2756}
Rui Ueyama74e85132014-11-19 00:18:07 +00002757
2758static StringRef getBaseRelocTypeName(uint8_t Type) {
2759 switch (Type) {
2760 case COFF::IMAGE_REL_BASED_ABSOLUTE: return "ABSOLUTE";
2761 case COFF::IMAGE_REL_BASED_HIGH: return "HIGH";
2762 case COFF::IMAGE_REL_BASED_LOW: return "LOW";
2763 case COFF::IMAGE_REL_BASED_HIGHLOW: return "HIGHLOW";
2764 case COFF::IMAGE_REL_BASED_HIGHADJ: return "HIGHADJ";
Saleem Abdulrasool5a41c372015-01-16 20:16:09 +00002765 case COFF::IMAGE_REL_BASED_ARM_MOV32T: return "ARM_MOV32(T)";
Rui Ueyama74e85132014-11-19 00:18:07 +00002766 case COFF::IMAGE_REL_BASED_DIR64: return "DIR64";
Colin LeMahieu9fbffee2014-11-19 17:10:39 +00002767 default: return "unknown (" + llvm::utostr(Type) + ")";
Rui Ueyama74e85132014-11-19 00:18:07 +00002768 }
2769}
2770
2771void COFFDumper::printCOFFBaseReloc() {
2772 ListScope D(W, "BaseReloc");
2773 for (const BaseRelocRef &I : Obj->base_relocs()) {
2774 uint8_t Type;
2775 uint32_t RVA;
Rafael Espindolafb3acd62015-07-20 03:23:55 +00002776 error(I.getRVA(RVA));
2777 error(I.getType(Type));
Rui Ueyama74e85132014-11-19 00:18:07 +00002778 DictScope Import(W, "Entry");
2779 W.printString("Type", getBaseRelocTypeName(Type));
2780 W.printHex("Address", RVA);
2781 }
2782}
Lang Hames0000afd2015-06-26 23:56:53 +00002783
2784void COFFDumper::printStackMap() const {
2785 object::SectionRef StackMapSection;
2786 for (auto Sec : Obj->sections()) {
2787 StringRef Name;
2788 Sec.getName(Name);
2789 if (Name == ".llvm_stackmaps") {
2790 StackMapSection = Sec;
2791 break;
2792 }
2793 }
2794
2795 if (StackMapSection == object::SectionRef())
2796 return;
2797
2798 StringRef StackMapContents;
2799 StackMapSection.getContents(StackMapContents);
2800 ArrayRef<uint8_t> StackMapContentsArray(
2801 reinterpret_cast<const uint8_t*>(StackMapContents.data()),
2802 StackMapContents.size());
2803
2804 if (Obj->isLittleEndian())
2805 prettyPrintStackMap(
2806 llvm::outs(),
2807 StackMapV1Parser<support::little>(StackMapContentsArray));
2808 else
2809 prettyPrintStackMap(llvm::outs(),
2810 StackMapV1Parser<support::big>(StackMapContentsArray));
2811}