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