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