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