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