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