1 //===-- COFFDumper.cpp - COFF-specific dumper -------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief This file implements the COFF-specific dumper for llvm-readobj.
13 //===----------------------------------------------------------------------===//
15 #include "llvm-readobj.h"
16 #include "ARMWinEHPrinter.h"
18 #include "ObjDumper.h"
19 #include "StreamWriter.h"
20 #include "Win64EHDumper.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/ADT/SmallString.h"
23 #include "llvm/ADT/StringExtras.h"
24 #include "llvm/Object/COFF.h"
25 #include "llvm/Object/ObjectFile.h"
26 #include "llvm/Support/COFF.h"
27 #include "llvm/Support/Casting.h"
28 #include "llvm/Support/Compiler.h"
29 #include "llvm/Support/DataExtractor.h"
30 #include "llvm/Support/Format.h"
31 #include "llvm/Support/SourceMgr.h"
32 #include "llvm/Support/Win64EH.h"
33 #include "llvm/Support/raw_ostream.h"
36 #include <system_error>
40 using namespace llvm::object
;
41 using namespace llvm::Win64EH
;
45 class COFFDumper
: public ObjDumper
{
47 COFFDumper(const llvm::object::COFFObjectFile
*Obj
, StreamWriter
& Writer
)
53 void printFileHeaders() override
;
54 void printSections() override
;
55 void printRelocations() override
;
56 void printSymbols() override
;
57 void printDynamicSymbols() override
;
58 void printUnwindInfo() override
;
59 void printCOFFImports() override
;
60 void printCOFFExports() override
;
61 void printCOFFDirectives() override
;
62 void printCOFFBaseReloc() override
;
65 void printSymbol(const SymbolRef
&Sym
);
66 void printRelocation(const SectionRef
&Section
, const RelocationRef
&Reloc
);
67 void printDataDirectory(uint32_t Index
, const std::string
&FieldName
);
69 void printDOSHeader(const dos_header
*DH
);
70 template <class PEHeader
> void printPEHeader(const PEHeader
*Hdr
);
71 void printBaseOfDataField(const pe32_header
*Hdr
);
72 void printBaseOfDataField(const pe32plus_header
*Hdr
);
74 void printCodeViewLineTables(const SectionRef
&Section
);
76 void printCodeViewSymbolsSubsection(StringRef Subsection
,
77 const SectionRef
&Section
,
80 void cacheRelocations();
82 std::error_code
resolveSymbol(const coff_section
*Section
, uint64_t Offset
,
84 std::error_code
resolveSymbolName(const coff_section
*Section
,
85 uint64_t Offset
, StringRef
&Name
);
86 void printImportedSymbols(iterator_range
<imported_symbol_iterator
> Range
);
87 void printDelayImportedSymbols(
88 const DelayImportDirectoryEntryRef
&I
,
89 iterator_range
<imported_symbol_iterator
> Range
);
91 typedef DenseMap
<const coff_section
*, std::vector
<RelocationRef
> > RelocMapTy
;
93 const llvm::object::COFFObjectFile
*Obj
;
95 StringRef CVFileIndexToStringOffsetTable
;
96 StringRef CVStringTable
;
104 std::error_code
createCOFFDumper(const object::ObjectFile
*Obj
,
105 StreamWriter
&Writer
,
106 std::unique_ptr
<ObjDumper
> &Result
) {
107 const COFFObjectFile
*COFFObj
= dyn_cast
<COFFObjectFile
>(Obj
);
109 return readobj_error::unsupported_obj_file_format
;
111 Result
.reset(new COFFDumper(COFFObj
, Writer
));
112 return readobj_error::success
;
117 // Given a a section and an offset into this section the function returns the
118 // symbol used for the relocation at the offset.
119 std::error_code
COFFDumper::resolveSymbol(const coff_section
*Section
,
120 uint64_t Offset
, SymbolRef
&Sym
) {
121 const auto &Relocations
= RelocMap
[Section
];
122 for (const auto &Relocation
: Relocations
) {
123 uint64_t RelocationOffset
;
124 if (std::error_code EC
= Relocation
.getOffset(RelocationOffset
))
127 if (RelocationOffset
== Offset
) {
128 Sym
= *Relocation
.getSymbol();
129 return readobj_error::success
;
132 return readobj_error::unknown_symbol
;
135 // Given a section and an offset into this section the function returns the name
136 // of the symbol used for the relocation at the offset.
137 std::error_code
COFFDumper::resolveSymbolName(const coff_section
*Section
,
141 if (std::error_code EC
= resolveSymbol(Section
, Offset
, Symbol
))
143 if (std::error_code EC
= Symbol
.getName(Name
))
145 return object_error::success
;
148 static const EnumEntry
<COFF::MachineTypes
> ImageFileMachineType
[] = {
149 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_UNKNOWN
),
150 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_AM33
),
151 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_AMD64
),
152 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_ARM
),
153 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_ARMNT
),
154 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_EBC
),
155 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_I386
),
156 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_IA64
),
157 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_M32R
),
158 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_MIPS16
),
159 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_MIPSFPU
),
160 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_MIPSFPU16
),
161 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_POWERPC
),
162 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_POWERPCFP
),
163 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_R4000
),
164 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_SH3
),
165 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_SH3DSP
),
166 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_SH4
),
167 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_SH5
),
168 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_THUMB
),
169 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_MACHINE_WCEMIPSV2
)
172 static const EnumEntry
<COFF::Characteristics
> ImageFileCharacteristics
[] = {
173 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_RELOCS_STRIPPED
),
174 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_EXECUTABLE_IMAGE
),
175 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_LINE_NUMS_STRIPPED
),
176 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_LOCAL_SYMS_STRIPPED
),
177 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_AGGRESSIVE_WS_TRIM
),
178 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_LARGE_ADDRESS_AWARE
),
179 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_BYTES_REVERSED_LO
),
180 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_32BIT_MACHINE
),
181 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_DEBUG_STRIPPED
),
182 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP
),
183 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_NET_RUN_FROM_SWAP
),
184 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_SYSTEM
),
185 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_DLL
),
186 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_UP_SYSTEM_ONLY
),
187 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_FILE_BYTES_REVERSED_HI
)
190 static const EnumEntry
<COFF::WindowsSubsystem
> PEWindowsSubsystem
[] = {
191 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SUBSYSTEM_UNKNOWN
),
192 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SUBSYSTEM_NATIVE
),
193 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SUBSYSTEM_WINDOWS_GUI
),
194 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SUBSYSTEM_WINDOWS_CUI
),
195 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SUBSYSTEM_POSIX_CUI
),
196 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI
),
197 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SUBSYSTEM_EFI_APPLICATION
),
198 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
),
199 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
),
200 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SUBSYSTEM_EFI_ROM
),
201 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SUBSYSTEM_XBOX
),
204 static const EnumEntry
<COFF::DLLCharacteristics
> PEDLLCharacteristics
[] = {
205 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA
),
206 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
),
207 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY
),
208 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
),
209 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION
),
210 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_DLL_CHARACTERISTICS_NO_SEH
),
211 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_DLL_CHARACTERISTICS_NO_BIND
),
212 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_DLL_CHARACTERISTICS_APPCONTAINER
),
213 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER
),
214 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_DLL_CHARACTERISTICS_GUARD_CF
),
215 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE
),
218 static const EnumEntry
<COFF::SectionCharacteristics
>
219 ImageSectionCharacteristics
[] = {
220 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_TYPE_NO_PAD
),
221 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_CNT_CODE
),
222 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_CNT_INITIALIZED_DATA
),
223 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_CNT_UNINITIALIZED_DATA
),
224 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_LNK_OTHER
),
225 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_LNK_INFO
),
226 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_LNK_REMOVE
),
227 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_LNK_COMDAT
),
228 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_GPREL
),
229 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_MEM_PURGEABLE
),
230 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_MEM_16BIT
),
231 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_MEM_LOCKED
),
232 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_MEM_PRELOAD
),
233 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_ALIGN_1BYTES
),
234 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_ALIGN_2BYTES
),
235 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_ALIGN_4BYTES
),
236 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_ALIGN_8BYTES
),
237 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_ALIGN_16BYTES
),
238 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_ALIGN_32BYTES
),
239 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_ALIGN_64BYTES
),
240 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_ALIGN_128BYTES
),
241 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_ALIGN_256BYTES
),
242 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_ALIGN_512BYTES
),
243 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_ALIGN_1024BYTES
),
244 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_ALIGN_2048BYTES
),
245 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_ALIGN_4096BYTES
),
246 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_ALIGN_8192BYTES
),
247 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_LNK_NRELOC_OVFL
),
248 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_MEM_DISCARDABLE
),
249 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_MEM_NOT_CACHED
),
250 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_MEM_NOT_PAGED
),
251 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_MEM_SHARED
),
252 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_MEM_EXECUTE
),
253 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_MEM_READ
),
254 LLVM_READOBJ_ENUM_ENT(COFF
, IMAGE_SCN_MEM_WRITE
)
257 static const EnumEntry
<COFF::SymbolBaseType
> ImageSymType
[] = {
258 { "Null" , COFF::IMAGE_SYM_TYPE_NULL
},
259 { "Void" , COFF::IMAGE_SYM_TYPE_VOID
},
260 { "Char" , COFF::IMAGE_SYM_TYPE_CHAR
},
261 { "Short" , COFF::IMAGE_SYM_TYPE_SHORT
},
262 { "Int" , COFF::IMAGE_SYM_TYPE_INT
},
263 { "Long" , COFF::IMAGE_SYM_TYPE_LONG
},
264 { "Float" , COFF::IMAGE_SYM_TYPE_FLOAT
},
265 { "Double", COFF::IMAGE_SYM_TYPE_DOUBLE
},
266 { "Struct", COFF::IMAGE_SYM_TYPE_STRUCT
},
267 { "Union" , COFF::IMAGE_SYM_TYPE_UNION
},
268 { "Enum" , COFF::IMAGE_SYM_TYPE_ENUM
},
269 { "MOE" , COFF::IMAGE_SYM_TYPE_MOE
},
270 { "Byte" , COFF::IMAGE_SYM_TYPE_BYTE
},
271 { "Word" , COFF::IMAGE_SYM_TYPE_WORD
},
272 { "UInt" , COFF::IMAGE_SYM_TYPE_UINT
},
273 { "DWord" , COFF::IMAGE_SYM_TYPE_DWORD
}
276 static const EnumEntry
<COFF::SymbolComplexType
> ImageSymDType
[] = {
277 { "Null" , COFF::IMAGE_SYM_DTYPE_NULL
},
278 { "Pointer" , COFF::IMAGE_SYM_DTYPE_POINTER
},
279 { "Function", COFF::IMAGE_SYM_DTYPE_FUNCTION
},
280 { "Array" , COFF::IMAGE_SYM_DTYPE_ARRAY
}
283 static const EnumEntry
<COFF::SymbolStorageClass
> ImageSymClass
[] = {
284 { "EndOfFunction" , COFF::IMAGE_SYM_CLASS_END_OF_FUNCTION
},
285 { "Null" , COFF::IMAGE_SYM_CLASS_NULL
},
286 { "Automatic" , COFF::IMAGE_SYM_CLASS_AUTOMATIC
},
287 { "External" , COFF::IMAGE_SYM_CLASS_EXTERNAL
},
288 { "Static" , COFF::IMAGE_SYM_CLASS_STATIC
},
289 { "Register" , COFF::IMAGE_SYM_CLASS_REGISTER
},
290 { "ExternalDef" , COFF::IMAGE_SYM_CLASS_EXTERNAL_DEF
},
291 { "Label" , COFF::IMAGE_SYM_CLASS_LABEL
},
292 { "UndefinedLabel" , COFF::IMAGE_SYM_CLASS_UNDEFINED_LABEL
},
293 { "MemberOfStruct" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_STRUCT
},
294 { "Argument" , COFF::IMAGE_SYM_CLASS_ARGUMENT
},
295 { "StructTag" , COFF::IMAGE_SYM_CLASS_STRUCT_TAG
},
296 { "MemberOfUnion" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_UNION
},
297 { "UnionTag" , COFF::IMAGE_SYM_CLASS_UNION_TAG
},
298 { "TypeDefinition" , COFF::IMAGE_SYM_CLASS_TYPE_DEFINITION
},
299 { "UndefinedStatic", COFF::IMAGE_SYM_CLASS_UNDEFINED_STATIC
},
300 { "EnumTag" , COFF::IMAGE_SYM_CLASS_ENUM_TAG
},
301 { "MemberOfEnum" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_ENUM
},
302 { "RegisterParam" , COFF::IMAGE_SYM_CLASS_REGISTER_PARAM
},
303 { "BitField" , COFF::IMAGE_SYM_CLASS_BIT_FIELD
},
304 { "Block" , COFF::IMAGE_SYM_CLASS_BLOCK
},
305 { "Function" , COFF::IMAGE_SYM_CLASS_FUNCTION
},
306 { "EndOfStruct" , COFF::IMAGE_SYM_CLASS_END_OF_STRUCT
},
307 { "File" , COFF::IMAGE_SYM_CLASS_FILE
},
308 { "Section" , COFF::IMAGE_SYM_CLASS_SECTION
},
309 { "WeakExternal" , COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL
},
310 { "CLRToken" , COFF::IMAGE_SYM_CLASS_CLR_TOKEN
}
313 static const EnumEntry
<COFF::COMDATType
> ImageCOMDATSelect
[] = {
314 { "NoDuplicates", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES
},
315 { "Any" , COFF::IMAGE_COMDAT_SELECT_ANY
},
316 { "SameSize" , COFF::IMAGE_COMDAT_SELECT_SAME_SIZE
},
317 { "ExactMatch" , COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH
},
318 { "Associative" , COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE
},
319 { "Largest" , COFF::IMAGE_COMDAT_SELECT_LARGEST
},
320 { "Newest" , COFF::IMAGE_COMDAT_SELECT_NEWEST
}
323 static const EnumEntry
<COFF::WeakExternalCharacteristics
>
324 WeakExternalCharacteristics
[] = {
325 { "NoLibrary", COFF::IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY
},
326 { "Library" , COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY
},
327 { "Alias" , COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS
}
330 template <typename T
>
331 static std::error_code
getSymbolAuxData(const COFFObjectFile
*Obj
,
332 COFFSymbolRef Symbol
,
333 uint8_t AuxSymbolIdx
, const T
*&Aux
) {
334 ArrayRef
<uint8_t> AuxData
= Obj
->getSymbolAuxData(Symbol
);
335 AuxData
= AuxData
.slice(AuxSymbolIdx
* Obj
->getSymbolTableEntrySize());
336 Aux
= reinterpret_cast<const T
*>(AuxData
.data());
337 return readobj_error::success
;
340 void COFFDumper::cacheRelocations() {
341 for (const SectionRef
&S
: Obj
->sections()) {
342 const coff_section
*Section
= Obj
->getCOFFSection(S
);
344 for (const RelocationRef
&Reloc
: S
.relocations())
345 RelocMap
[Section
].push_back(Reloc
);
347 // Sort relocations by address.
348 std::sort(RelocMap
[Section
].begin(), RelocMap
[Section
].end(),
353 void COFFDumper::printDataDirectory(uint32_t Index
, const std::string
&FieldName
) {
354 const data_directory
*Data
;
355 if (Obj
->getDataDirectory(Index
, Data
))
357 W
.printHex(FieldName
+ "RVA", Data
->RelativeVirtualAddress
);
358 W
.printHex(FieldName
+ "Size", Data
->Size
);
361 void COFFDumper::printFileHeaders() {
362 time_t TDS
= Obj
->getTimeDateStamp();
363 char FormattedTime
[20] = { };
364 strftime(FormattedTime
, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS
));
367 DictScope
D(W
, "ImageFileHeader");
368 W
.printEnum ("Machine", Obj
->getMachine(),
369 makeArrayRef(ImageFileMachineType
));
370 W
.printNumber("SectionCount", Obj
->getNumberOfSections());
371 W
.printHex ("TimeDateStamp", FormattedTime
, Obj
->getTimeDateStamp());
372 W
.printHex ("PointerToSymbolTable", Obj
->getPointerToSymbolTable());
373 W
.printNumber("SymbolCount", Obj
->getNumberOfSymbols());
374 W
.printNumber("OptionalHeaderSize", Obj
->getSizeOfOptionalHeader());
375 W
.printFlags ("Characteristics", Obj
->getCharacteristics(),
376 makeArrayRef(ImageFileCharacteristics
));
379 // Print PE header. This header does not exist if this is an object file and
380 // not an executable.
381 const pe32_header
*PEHeader
= nullptr;
382 if (error(Obj
->getPE32Header(PEHeader
)))
385 printPEHeader
<pe32_header
>(PEHeader
);
387 const pe32plus_header
*PEPlusHeader
= nullptr;
388 if (error(Obj
->getPE32PlusHeader(PEPlusHeader
)))
391 printPEHeader
<pe32plus_header
>(PEPlusHeader
);
393 if (const dos_header
*DH
= Obj
->getDOSHeader())
397 void COFFDumper::printDOSHeader(const dos_header
*DH
) {
398 DictScope
D(W
, "DOSHeader");
399 W
.printString("Magic", StringRef(DH
->Magic
, sizeof(DH
->Magic
)));
400 W
.printNumber("UsedBytesInTheLastPage", DH
->UsedBytesInTheLastPage
);
401 W
.printNumber("FileSizeInPages", DH
->FileSizeInPages
);
402 W
.printNumber("NumberOfRelocationItems", DH
->NumberOfRelocationItems
);
403 W
.printNumber("HeaderSizeInParagraphs", DH
->HeaderSizeInParagraphs
);
404 W
.printNumber("MinimumExtraParagraphs", DH
->MinimumExtraParagraphs
);
405 W
.printNumber("MaximumExtraParagraphs", DH
->MaximumExtraParagraphs
);
406 W
.printNumber("InitialRelativeSS", DH
->InitialRelativeSS
);
407 W
.printNumber("InitialSP", DH
->InitialSP
);
408 W
.printNumber("Checksum", DH
->Checksum
);
409 W
.printNumber("InitialIP", DH
->InitialIP
);
410 W
.printNumber("InitialRelativeCS", DH
->InitialRelativeCS
);
411 W
.printNumber("AddressOfRelocationTable", DH
->AddressOfRelocationTable
);
412 W
.printNumber("OverlayNumber", DH
->OverlayNumber
);
413 W
.printNumber("OEMid", DH
->OEMid
);
414 W
.printNumber("OEMinfo", DH
->OEMinfo
);
415 W
.printNumber("AddressOfNewExeHeader", DH
->AddressOfNewExeHeader
);
418 template <class PEHeader
>
419 void COFFDumper::printPEHeader(const PEHeader
*Hdr
) {
420 DictScope
D(W
, "ImageOptionalHeader");
421 W
.printNumber("MajorLinkerVersion", Hdr
->MajorLinkerVersion
);
422 W
.printNumber("MinorLinkerVersion", Hdr
->MinorLinkerVersion
);
423 W
.printNumber("SizeOfCode", Hdr
->SizeOfCode
);
424 W
.printNumber("SizeOfInitializedData", Hdr
->SizeOfInitializedData
);
425 W
.printNumber("SizeOfUninitializedData", Hdr
->SizeOfUninitializedData
);
426 W
.printHex ("AddressOfEntryPoint", Hdr
->AddressOfEntryPoint
);
427 W
.printHex ("BaseOfCode", Hdr
->BaseOfCode
);
428 printBaseOfDataField(Hdr
);
429 W
.printHex ("ImageBase", Hdr
->ImageBase
);
430 W
.printNumber("SectionAlignment", Hdr
->SectionAlignment
);
431 W
.printNumber("FileAlignment", Hdr
->FileAlignment
);
432 W
.printNumber("MajorOperatingSystemVersion",
433 Hdr
->MajorOperatingSystemVersion
);
434 W
.printNumber("MinorOperatingSystemVersion",
435 Hdr
->MinorOperatingSystemVersion
);
436 W
.printNumber("MajorImageVersion", Hdr
->MajorImageVersion
);
437 W
.printNumber("MinorImageVersion", Hdr
->MinorImageVersion
);
438 W
.printNumber("MajorSubsystemVersion", Hdr
->MajorSubsystemVersion
);
439 W
.printNumber("MinorSubsystemVersion", Hdr
->MinorSubsystemVersion
);
440 W
.printNumber("SizeOfImage", Hdr
->SizeOfImage
);
441 W
.printNumber("SizeOfHeaders", Hdr
->SizeOfHeaders
);
442 W
.printEnum ("Subsystem", Hdr
->Subsystem
, makeArrayRef(PEWindowsSubsystem
));
443 W
.printFlags ("Characteristics", Hdr
->DLLCharacteristics
,
444 makeArrayRef(PEDLLCharacteristics
));
445 W
.printNumber("SizeOfStackReserve", Hdr
->SizeOfStackReserve
);
446 W
.printNumber("SizeOfStackCommit", Hdr
->SizeOfStackCommit
);
447 W
.printNumber("SizeOfHeapReserve", Hdr
->SizeOfHeapReserve
);
448 W
.printNumber("SizeOfHeapCommit", Hdr
->SizeOfHeapCommit
);
449 W
.printNumber("NumberOfRvaAndSize", Hdr
->NumberOfRvaAndSize
);
451 if (Hdr
->NumberOfRvaAndSize
> 0) {
452 DictScope
D(W
, "DataDirectory");
453 static const char * const directory
[] = {
454 "ExportTable", "ImportTable", "ResourceTable", "ExceptionTable",
455 "CertificateTable", "BaseRelocationTable", "Debug", "Architecture",
456 "GlobalPtr", "TLSTable", "LoadConfigTable", "BoundImport", "IAT",
457 "DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"
460 for (uint32_t i
= 0; i
< Hdr
->NumberOfRvaAndSize
; ++i
) {
461 printDataDirectory(i
, directory
[i
]);
466 void COFFDumper::printBaseOfDataField(const pe32_header
*Hdr
) {
467 W
.printHex("BaseOfData", Hdr
->BaseOfData
);
470 void COFFDumper::printBaseOfDataField(const pe32plus_header
*) {}
472 void COFFDumper::printCodeViewLineTables(const SectionRef
&Section
) {
474 if (error(Section
.getContents(Data
)))
477 SmallVector
<StringRef
, 10> FunctionNames
;
478 StringMap
<StringRef
> FunctionLineTables
;
480 ListScope
D(W
, "CodeViewLineTables");
482 // FIXME: Add more offset correctness checks.
483 DataExtractor
DE(Data
, true, 4);
485 Magic
= DE
.getU32(&Offset
);
486 W
.printHex("Magic", Magic
);
487 if (Magic
!= COFF::DEBUG_SECTION_MAGIC
) {
488 error(object_error::parse_failed
);
492 bool Finished
= false;
493 while (DE
.isValidOffset(Offset
) && !Finished
) {
494 // The section consists of a number of subsection in the following format:
495 // |Type|PayloadSize|Payload...|
496 uint32_t SubSectionType
= DE
.getU32(&Offset
),
497 PayloadSize
= DE
.getU32(&Offset
);
498 ListScope
S(W
, "Subsection");
499 W
.printHex("Type", SubSectionType
);
500 W
.printHex("PayloadSize", PayloadSize
);
501 if (PayloadSize
> Data
.size() - Offset
) {
502 error(object_error::parse_failed
);
506 // Print the raw contents to simplify debugging if anything goes wrong
508 StringRef Contents
= Data
.substr(Offset
, PayloadSize
);
509 W
.printBinaryBlock("Contents", Contents
);
511 switch (SubSectionType
) {
512 case COFF::DEBUG_SYMBOL_SUBSECTION
:
513 printCodeViewSymbolsSubsection(Contents
, Section
, Offset
);
515 case COFF::DEBUG_LINE_TABLE_SUBSECTION
: {
516 // Holds a PC to file:line table. Some data to parse this subsection is
517 // stored in the other subsections, so just check sanity and store the
518 // pointers for deferred processing.
520 if (PayloadSize
< 12) {
521 // There should be at least three words to store two function
522 // relocations and size of the code.
523 error(object_error::parse_failed
);
527 StringRef FunctionName
;
528 if (error(resolveSymbolName(Obj
->getCOFFSection(Section
), Offset
,
531 W
.printString("FunctionName", FunctionName
);
532 if (FunctionLineTables
.count(FunctionName
) != 0) {
533 // Saw debug info for this function already?
534 error(object_error::parse_failed
);
538 FunctionLineTables
[FunctionName
] = Contents
;
539 FunctionNames
.push_back(FunctionName
);
542 case COFF::DEBUG_STRING_TABLE_SUBSECTION
:
543 if (PayloadSize
== 0 || CVStringTable
.data() != nullptr ||
544 Contents
.back() != '\0') {
545 // Empty or duplicate or non-null-terminated subsection.
546 error(object_error::parse_failed
);
549 CVStringTable
= Contents
;
551 case COFF::DEBUG_INDEX_SUBSECTION
:
552 // Holds the translation table from file indices
553 // to offsets in the string table.
555 if (PayloadSize
== 0 ||
556 CVFileIndexToStringOffsetTable
.data() != nullptr) {
557 // Empty or duplicate subsection.
558 error(object_error::parse_failed
);
561 CVFileIndexToStringOffsetTable
= Contents
;
564 Offset
+= PayloadSize
;
566 // Align the reading pointer by 4.
567 Offset
+= (-Offset
) % 4;
571 // Dump the line tables now that we've read all the subsections and know all
572 // the required information.
573 for (unsigned I
= 0, E
= FunctionNames
.size(); I
!= E
; ++I
) {
574 StringRef Name
= FunctionNames
[I
];
575 ListScope
S(W
, "FunctionLineTable");
576 W
.printString("FunctionName", Name
);
578 DataExtractor
DE(FunctionLineTables
[Name
], true, 4);
579 uint32_t Offset
= 8; // Skip relocations.
580 uint32_t FunctionSize
= DE
.getU32(&Offset
);
581 W
.printHex("CodeSize", FunctionSize
);
582 while (DE
.isValidOffset(Offset
)) {
583 // For each range of lines with the same filename, we have a segment
584 // in the line table. The filename string is accessed using double
585 // indirection to the string table subsection using the index subsection.
586 uint32_t OffsetInIndex
= DE
.getU32(&Offset
),
587 SegmentLength
= DE
.getU32(&Offset
),
588 FullSegmentSize
= DE
.getU32(&Offset
);
589 if (FullSegmentSize
!= 12 + 8 * SegmentLength
) {
590 error(object_error::parse_failed
);
594 uint32_t FilenameOffset
;
596 DataExtractor
SDE(CVFileIndexToStringOffsetTable
, true, 4);
597 uint32_t OffsetInSDE
= OffsetInIndex
;
598 if (!SDE
.isValidOffset(OffsetInSDE
)) {
599 error(object_error::parse_failed
);
602 FilenameOffset
= SDE
.getU32(&OffsetInSDE
);
605 if (FilenameOffset
== 0 || FilenameOffset
+ 1 >= CVStringTable
.size() ||
606 CVStringTable
.data()[FilenameOffset
- 1] != '\0') {
607 // Each string in an F3 subsection should be preceded by a null
609 error(object_error::parse_failed
);
613 StringRef
Filename(CVStringTable
.data() + FilenameOffset
);
614 ListScope
S(W
, "FilenameSegment");
615 W
.printString("Filename", Filename
);
616 for (unsigned J
= 0; J
!= SegmentLength
&& DE
.isValidOffset(Offset
);
618 // Then go the (PC, LineNumber) pairs. The line number is stored in the
619 // least significant 31 bits of the respective word in the table.
620 uint32_t PC
= DE
.getU32(&Offset
),
621 LineNumber
= DE
.getU32(&Offset
) & 0x7fffffff;
622 if (PC
>= FunctionSize
) {
623 error(object_error::parse_failed
);
627 format("+0x%X", PC
).snprint(Buffer
, 32);
628 W
.printNumber(Buffer
, LineNumber
);
634 void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection
,
635 const SectionRef
&Section
,
636 uint32_t OffsetInSection
) {
637 if (Subsection
.size() == 0) {
638 error(object_error::parse_failed
);
641 DataExtractor
DE(Subsection
, true, 4);
644 // Function-level subsections have "procedure start" and "procedure end"
645 // commands that should come in pairs and surround relevant info.
646 bool InFunctionScope
= false;
647 while (DE
.isValidOffset(Offset
)) {
648 // Read subsection segments one by one.
649 uint16_t Size
= DE
.getU16(&Offset
);
650 // The section size includes the size of the type identifier.
651 if (Size
< 2 || !DE
.isValidOffsetForDataOfSize(Offset
, Size
)) {
652 error(object_error::parse_failed
);
656 uint16_t Type
= DE
.getU16(&Offset
);
658 case COFF::DEBUG_SYMBOL_TYPE_PROC_START
: {
659 DictScope
S(W
, "ProcStart");
660 if (InFunctionScope
|| Size
< 36) {
661 error(object_error::parse_failed
);
664 InFunctionScope
= true;
666 // We're currently interested in a limited subset of fields in this
667 // segment, just ignore the rest of the fields for now.
669 DE
.getU8(&Offset
, Unused
, 12);
670 uint32_t CodeSize
= DE
.getU32(&Offset
);
671 DE
.getU8(&Offset
, Unused
, 12);
672 StringRef SectionName
;
673 if (error(resolveSymbolName(Obj
->getCOFFSection(Section
),
674 OffsetInSection
+ Offset
, SectionName
)))
677 DE
.getU8(&Offset
, Unused
, 3);
678 StringRef DisplayName
= DE
.getCStr(&Offset
);
679 if (!DE
.isValidOffset(Offset
)) {
680 error(object_error::parse_failed
);
683 W
.printString("DisplayName", DisplayName
);
684 W
.printString("Section", SectionName
);
685 W
.printHex("CodeSize", CodeSize
);
689 case COFF::DEBUG_SYMBOL_TYPE_PROC_END
: {
690 W
.startLine() << "ProcEnd\n";
691 if (!InFunctionScope
|| Size
> 0) {
692 error(object_error::parse_failed
);
695 InFunctionScope
= false;
705 error(object_error::parse_failed
);
708 void COFFDumper::printSections() {
709 ListScope
SectionsD(W
, "Sections");
710 int SectionNumber
= 0;
711 for (const SectionRef
&Sec
: Obj
->sections()) {
713 const coff_section
*Section
= Obj
->getCOFFSection(Sec
);
716 if (error(Sec
.getName(Name
)))
719 DictScope
D(W
, "Section");
720 W
.printNumber("Number", SectionNumber
);
721 W
.printBinary("Name", Name
, Section
->Name
);
722 W
.printHex ("VirtualSize", Section
->VirtualSize
);
723 W
.printHex ("VirtualAddress", Section
->VirtualAddress
);
724 W
.printNumber("RawDataSize", Section
->SizeOfRawData
);
725 W
.printHex ("PointerToRawData", Section
->PointerToRawData
);
726 W
.printHex ("PointerToRelocations", Section
->PointerToRelocations
);
727 W
.printHex ("PointerToLineNumbers", Section
->PointerToLinenumbers
);
728 W
.printNumber("RelocationCount", Section
->NumberOfRelocations
);
729 W
.printNumber("LineNumberCount", Section
->NumberOfLinenumbers
);
730 W
.printFlags ("Characteristics", Section
->Characteristics
,
731 makeArrayRef(ImageSectionCharacteristics
),
732 COFF::SectionCharacteristics(0x00F00000));
734 if (opts::SectionRelocations
) {
735 ListScope
D(W
, "Relocations");
736 for (const RelocationRef
&Reloc
: Sec
.relocations())
737 printRelocation(Sec
, Reloc
);
740 if (opts::SectionSymbols
) {
741 ListScope
D(W
, "Symbols");
742 for (const SymbolRef
&Symbol
: Obj
->symbols()) {
743 if (!Sec
.containsSymbol(Symbol
))
750 if (Name
== ".debug$S" && opts::CodeViewLineTables
)
751 printCodeViewLineTables(Sec
);
753 if (opts::SectionData
&&
754 !(Section
->Characteristics
& COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
)) {
756 if (error(Sec
.getContents(Data
)))
759 W
.printBinaryBlock("SectionData", Data
);
764 void COFFDumper::printRelocations() {
765 ListScope
D(W
, "Relocations");
767 int SectionNumber
= 0;
768 for (const SectionRef
&Section
: Obj
->sections()) {
771 if (error(Section
.getName(Name
)))
774 bool PrintedGroup
= false;
775 for (const RelocationRef
&Reloc
: Section
.relocations()) {
777 W
.startLine() << "Section (" << SectionNumber
<< ") " << Name
<< " {\n";
782 printRelocation(Section
, Reloc
);
787 W
.startLine() << "}\n";
792 void COFFDumper::printRelocation(const SectionRef
&Section
,
793 const RelocationRef
&Reloc
) {
796 SmallString
<32> RelocName
;
797 StringRef SymbolName
;
798 if (error(Reloc
.getOffset(Offset
)))
800 if (error(Reloc
.getType(RelocType
)))
802 if (error(Reloc
.getTypeName(RelocName
)))
804 symbol_iterator Symbol
= Reloc
.getSymbol();
805 if (Symbol
!= Obj
->symbol_end() && error(Symbol
->getName(SymbolName
)))
808 if (opts::ExpandRelocs
) {
809 DictScope
Group(W
, "Relocation");
810 W
.printHex("Offset", Offset
);
811 W
.printNumber("Type", RelocName
, RelocType
);
812 W
.printString("Symbol", SymbolName
.empty() ? "-" : SymbolName
);
814 raw_ostream
& OS
= W
.startLine();
817 << " " << (SymbolName
.empty() ? "-" : SymbolName
)
822 void COFFDumper::printSymbols() {
823 ListScope
Group(W
, "Symbols");
825 for (const SymbolRef
&Symbol
: Obj
->symbols())
829 void COFFDumper::printDynamicSymbols() { ListScope
Group(W
, "DynamicSymbols"); }
831 static ErrorOr
<StringRef
>
832 getSectionName(const llvm::object::COFFObjectFile
*Obj
, int32_t SectionNumber
,
833 const coff_section
*Section
) {
835 StringRef SectionName
;
836 if (std::error_code EC
= Obj
->getSectionName(Section
, SectionName
))
840 if (SectionNumber
== llvm::COFF::IMAGE_SYM_DEBUG
)
841 return StringRef("IMAGE_SYM_DEBUG");
842 if (SectionNumber
== llvm::COFF::IMAGE_SYM_ABSOLUTE
)
843 return StringRef("IMAGE_SYM_ABSOLUTE");
844 if (SectionNumber
== llvm::COFF::IMAGE_SYM_UNDEFINED
)
845 return StringRef("IMAGE_SYM_UNDEFINED");
846 return StringRef("");
849 void COFFDumper::printSymbol(const SymbolRef
&Sym
) {
850 DictScope
D(W
, "Symbol");
852 COFFSymbolRef Symbol
= Obj
->getCOFFSymbol(Sym
);
853 const coff_section
*Section
;
854 if (std::error_code EC
= Obj
->getSection(Symbol
.getSectionNumber(), Section
)) {
855 W
.startLine() << "Invalid section number: " << EC
.message() << "\n";
860 StringRef SymbolName
;
861 if (Obj
->getSymbolName(Symbol
, SymbolName
))
864 StringRef SectionName
= "";
865 ErrorOr
<StringRef
> Res
=
866 getSectionName(Obj
, Symbol
.getSectionNumber(), Section
);
870 W
.printString("Name", SymbolName
);
871 W
.printNumber("Value", Symbol
.getValue());
872 W
.printNumber("Section", SectionName
, Symbol
.getSectionNumber());
873 W
.printEnum ("BaseType", Symbol
.getBaseType(), makeArrayRef(ImageSymType
));
874 W
.printEnum ("ComplexType", Symbol
.getComplexType(),
875 makeArrayRef(ImageSymDType
));
876 W
.printEnum ("StorageClass", Symbol
.getStorageClass(),
877 makeArrayRef(ImageSymClass
));
878 W
.printNumber("AuxSymbolCount", Symbol
.getNumberOfAuxSymbols());
880 for (uint8_t I
= 0; I
< Symbol
.getNumberOfAuxSymbols(); ++I
) {
881 if (Symbol
.isFunctionDefinition()) {
882 const coff_aux_function_definition
*Aux
;
883 if (error(getSymbolAuxData(Obj
, Symbol
, I
, Aux
)))
886 DictScope
AS(W
, "AuxFunctionDef");
887 W
.printNumber("TagIndex", Aux
->TagIndex
);
888 W
.printNumber("TotalSize", Aux
->TotalSize
);
889 W
.printHex("PointerToLineNumber", Aux
->PointerToLinenumber
);
890 W
.printHex("PointerToNextFunction", Aux
->PointerToNextFunction
);
892 } else if (Symbol
.isAnyUndefined()) {
893 const coff_aux_weak_external
*Aux
;
894 if (error(getSymbolAuxData(Obj
, Symbol
, I
, Aux
)))
897 ErrorOr
<COFFSymbolRef
> Linked
= Obj
->getSymbol(Aux
->TagIndex
);
898 StringRef LinkedName
;
899 std::error_code EC
= Linked
.getError();
900 if (EC
|| (EC
= Obj
->getSymbolName(*Linked
, LinkedName
))) {
905 DictScope
AS(W
, "AuxWeakExternal");
906 W
.printNumber("Linked", LinkedName
, Aux
->TagIndex
);
907 W
.printEnum ("Search", Aux
->Characteristics
,
908 makeArrayRef(WeakExternalCharacteristics
));
910 } else if (Symbol
.isFileRecord()) {
911 const char *FileName
;
912 if (error(getSymbolAuxData(Obj
, Symbol
, I
, FileName
)))
915 DictScope
AS(W
, "AuxFileRecord");
917 StringRef
Name(FileName
, Symbol
.getNumberOfAuxSymbols() *
918 Obj
->getSymbolTableEntrySize());
919 W
.printString("FileName", Name
.rtrim(StringRef("\0", 1)));
921 } else if (Symbol
.isSectionDefinition()) {
922 const coff_aux_section_definition
*Aux
;
923 if (error(getSymbolAuxData(Obj
, Symbol
, I
, Aux
)))
926 int32_t AuxNumber
= Aux
->getNumber(Symbol
.isBigObj());
928 DictScope
AS(W
, "AuxSectionDef");
929 W
.printNumber("Length", Aux
->Length
);
930 W
.printNumber("RelocationCount", Aux
->NumberOfRelocations
);
931 W
.printNumber("LineNumberCount", Aux
->NumberOfLinenumbers
);
932 W
.printHex("Checksum", Aux
->CheckSum
);
933 W
.printNumber("Number", AuxNumber
);
934 W
.printEnum("Selection", Aux
->Selection
, makeArrayRef(ImageCOMDATSelect
));
936 if (Section
&& Section
->Characteristics
& COFF::IMAGE_SCN_LNK_COMDAT
937 && Aux
->Selection
== COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE
) {
938 const coff_section
*Assoc
;
939 StringRef AssocName
= "";
940 std::error_code EC
= Obj
->getSection(AuxNumber
, Assoc
);
941 ErrorOr
<StringRef
> Res
= getSectionName(Obj
, AuxNumber
, Assoc
);
951 W
.printNumber("AssocSection", AssocName
, AuxNumber
);
953 } else if (Symbol
.isCLRToken()) {
954 const coff_aux_clr_token
*Aux
;
955 if (error(getSymbolAuxData(Obj
, Symbol
, I
, Aux
)))
958 ErrorOr
<COFFSymbolRef
> ReferredSym
=
959 Obj
->getSymbol(Aux
->SymbolTableIndex
);
960 StringRef ReferredName
;
961 std::error_code EC
= ReferredSym
.getError();
962 if (EC
|| (EC
= Obj
->getSymbolName(*ReferredSym
, ReferredName
))) {
967 DictScope
AS(W
, "AuxCLRToken");
968 W
.printNumber("AuxType", Aux
->AuxType
);
969 W
.printNumber("Reserved", Aux
->Reserved
);
970 W
.printNumber("SymbolTableIndex", ReferredName
, Aux
->SymbolTableIndex
);
973 W
.startLine() << "<unhandled auxiliary record>\n";
978 void COFFDumper::printUnwindInfo() {
979 ListScope
D(W
, "UnwindInformation");
980 switch (Obj
->getMachine()) {
981 case COFF::IMAGE_FILE_MACHINE_AMD64
: {
982 Win64EH::Dumper
Dumper(W
);
983 Win64EH::Dumper::SymbolResolver
984 Resolver
= [](const object::coff_section
*Section
, uint64_t Offset
,
985 SymbolRef
&Symbol
, void *user_data
) -> std::error_code
{
986 COFFDumper
*Dumper
= reinterpret_cast<COFFDumper
*>(user_data
);
987 return Dumper
->resolveSymbol(Section
, Offset
, Symbol
);
989 Win64EH::Dumper::Context
Ctx(*Obj
, Resolver
, this);
990 Dumper
.printData(Ctx
);
993 case COFF::IMAGE_FILE_MACHINE_ARMNT
: {
994 ARM::WinEH::Decoder
Decoder(W
);
995 Decoder
.dumpProcedureData(*Obj
);
999 W
.printEnum("unsupported Image Machine", Obj
->getMachine(),
1000 makeArrayRef(ImageFileMachineType
));
1005 void COFFDumper::printImportedSymbols(
1006 iterator_range
<imported_symbol_iterator
> Range
) {
1007 for (const ImportedSymbolRef
&I
: Range
) {
1009 if (error(I
.getSymbolName(Sym
))) return;
1011 if (error(I
.getOrdinal(Ordinal
))) return;
1012 W
.printNumber("Symbol", Sym
, Ordinal
);
1016 void COFFDumper::printDelayImportedSymbols(
1017 const DelayImportDirectoryEntryRef
&I
,
1018 iterator_range
<imported_symbol_iterator
> Range
) {
1020 for (const ImportedSymbolRef
&S
: Range
) {
1021 DictScope
Import(W
, "Import");
1023 if (error(S
.getSymbolName(Sym
))) return;
1025 if (error(S
.getOrdinal(Ordinal
))) return;
1026 W
.printNumber("Symbol", Sym
, Ordinal
);
1028 if (error(I
.getImportAddress(Index
++, Addr
))) return;
1029 W
.printHex("Address", Addr
);
1033 void COFFDumper::printCOFFImports() {
1035 for (const ImportDirectoryEntryRef
&I
: Obj
->import_directories()) {
1036 DictScope
Import(W
, "Import");
1038 if (error(I
.getName(Name
))) return;
1039 W
.printString("Name", Name
);
1041 if (error(I
.getImportLookupTableRVA(Addr
))) return;
1042 W
.printHex("ImportLookupTableRVA", Addr
);
1043 if (error(I
.getImportAddressTableRVA(Addr
))) return;
1044 W
.printHex("ImportAddressTableRVA", Addr
);
1045 printImportedSymbols(I
.imported_symbols());
1049 for (const DelayImportDirectoryEntryRef
&I
: Obj
->delay_import_directories()) {
1050 DictScope
Import(W
, "DelayImport");
1052 if (error(I
.getName(Name
))) return;
1053 W
.printString("Name", Name
);
1054 const delay_import_directory_table_entry
*Table
;
1055 if (error(I
.getDelayImportTable(Table
))) return;
1056 W
.printHex("Attributes", Table
->Attributes
);
1057 W
.printHex("ModuleHandle", Table
->ModuleHandle
);
1058 W
.printHex("ImportAddressTable", Table
->DelayImportAddressTable
);
1059 W
.printHex("ImportNameTable", Table
->DelayImportNameTable
);
1060 W
.printHex("BoundDelayImportTable", Table
->BoundDelayImportTable
);
1061 W
.printHex("UnloadDelayImportTable", Table
->UnloadDelayImportTable
);
1062 printDelayImportedSymbols(I
, I
.imported_symbols());
1066 void COFFDumper::printCOFFExports() {
1067 for (const ExportDirectoryEntryRef
&E
: Obj
->export_directories()) {
1068 DictScope
Export(W
, "Export");
1071 uint32_t Ordinal
, RVA
;
1073 if (error(E
.getSymbolName(Name
)))
1075 if (error(E
.getOrdinal(Ordinal
)))
1077 if (error(E
.getExportRVA(RVA
)))
1080 W
.printNumber("Ordinal", Ordinal
);
1081 W
.printString("Name", Name
);
1082 W
.printHex("RVA", RVA
);
1086 void COFFDumper::printCOFFDirectives() {
1087 for (const SectionRef
&Section
: Obj
->sections()) {
1091 if (error(Section
.getName(Name
)))
1093 if (Name
!= ".drectve")
1096 if (error(Section
.getContents(Contents
)))
1099 W
.printString("Directive(s)", Contents
);
1103 static StringRef
getBaseRelocTypeName(uint8_t Type
) {
1105 case COFF::IMAGE_REL_BASED_ABSOLUTE
: return "ABSOLUTE";
1106 case COFF::IMAGE_REL_BASED_HIGH
: return "HIGH";
1107 case COFF::IMAGE_REL_BASED_LOW
: return "LOW";
1108 case COFF::IMAGE_REL_BASED_HIGHLOW
: return "HIGHLOW";
1109 case COFF::IMAGE_REL_BASED_HIGHADJ
: return "HIGHADJ";
1110 case COFF::IMAGE_REL_BASED_DIR64
: return "DIR64";
1111 default: return "unknown (" + llvm::utostr(Type
) + ")";
1115 void COFFDumper::printCOFFBaseReloc() {
1116 ListScope
D(W
, "BaseReloc");
1117 for (const BaseRelocRef
&I
: Obj
->base_relocs()) {
1120 if (error(I
.getRVA(RVA
)))
1122 if (error(I
.getType(Type
)))
1124 DictScope
Import(W
, "Entry");
1125 W
.printString("Type", getBaseRelocTypeName(Type
));
1126 W
.printHex("Address", RVA
);