1 //===-- COFFDump.cpp - COFF-specific dumper ---------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// This file implements the COFF-specific dumper for llvm-objdump. 11 /// It outputs the Win64 EH data structures as plain text. 12 /// The encoding of the unwind codes is described in MSDN: 13 /// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx 14 /// 15 //===----------------------------------------------------------------------===// 16 17 #include "COFFDump.h" 18 19 #include "llvm-objdump.h" 20 #include "llvm/Demangle/Demangle.h" 21 #include "llvm/Object/COFF.h" 22 #include "llvm/Object/COFFImportFile.h" 23 #include "llvm/Object/ObjectFile.h" 24 #include "llvm/Support/Format.h" 25 #include "llvm/Support/Win64EH.h" 26 #include "llvm/Support/WithColor.h" 27 #include "llvm/Support/raw_ostream.h" 28 29 using namespace llvm; 30 using namespace llvm::objdump; 31 using namespace llvm::object; 32 using namespace llvm::Win64EH; 33 34 namespace { 35 template <typename T> struct EnumEntry { 36 T Value; 37 StringRef Name; 38 }; 39 40 class COFFDumper { 41 public: 42 explicit COFFDumper(const llvm::object::COFFObjectFile &Obj) : Obj(Obj) { 43 Is64 = !Obj.getPE32Header(); 44 } 45 46 template <class PEHeader> void printPEHeader(const PEHeader &Hdr) const; 47 48 private: 49 template <typename T> FormattedNumber formatAddr(T V) const { 50 return format_hex_no_prefix(V, Is64 ? 16 : 8); 51 } 52 53 uint32_t getBaseOfData(const void *Hdr) const { 54 return Is64 ? 0 : static_cast<const pe32_header *>(Hdr)->BaseOfData; 55 } 56 57 const llvm::object::COFFObjectFile &Obj; 58 bool Is64; 59 }; 60 } // namespace 61 62 constexpr EnumEntry<uint16_t> PEHeaderMagic[] = { 63 {uint16_t(COFF::PE32Header::PE32), "PE32"}, 64 {uint16_t(COFF::PE32Header::PE32_PLUS), "PE32+"}, 65 }; 66 67 constexpr EnumEntry<COFF::WindowsSubsystem> PEWindowsSubsystem[] = { 68 {COFF::IMAGE_SUBSYSTEM_UNKNOWN, "unspecified"}, 69 {COFF::IMAGE_SUBSYSTEM_NATIVE, "NT native"}, 70 {COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI, "Windows GUI"}, 71 {COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, "Windows CUI"}, 72 {COFF::IMAGE_SUBSYSTEM_POSIX_CUI, "POSIX CUI"}, 73 {COFF::IMAGE_SUBSYSTEM_WINDOWS_CE_GUI, "Wince CUI"}, 74 {COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION, "EFI application"}, 75 {COFF::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, "EFI boot service driver"}, 76 {COFF::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER, "EFI runtime driver"}, 77 {COFF::IMAGE_SUBSYSTEM_EFI_ROM, "SAL runtime driver"}, 78 {COFF::IMAGE_SUBSYSTEM_XBOX, "XBOX"}, 79 }; 80 81 template <typename T, typename TEnum> 82 static void printOptionalEnumName(T Value, 83 ArrayRef<EnumEntry<TEnum>> EnumValues) { 84 for (const EnumEntry<TEnum> &I : EnumValues) 85 if (I.Value == Value) { 86 outs() << "\t(" << I.Name << ')'; 87 return; 88 } 89 } 90 91 template <class PEHeader> 92 void COFFDumper::printPEHeader(const PEHeader &Hdr) const { 93 auto print = [](const char *K, auto V, const char *Fmt = "%d\n") { 94 outs() << format("%-23s ", K) << format(Fmt, V); 95 }; 96 auto printU16 = [&](const char *K, support::ulittle16_t V, 97 const char *Fmt = "%d\n") { print(K, uint16_t(V), Fmt); }; 98 auto printU32 = [&](const char *K, support::ulittle32_t V, 99 const char *Fmt = "%d\n") { print(K, uint32_t(V), Fmt); }; 100 auto printAddr = [=](const char *K, uint64_t V) { 101 outs() << format("%-23s ", K) << formatAddr(V) << '\n'; 102 }; 103 104 printU16("Magic", Hdr.Magic, "%04x"); 105 printOptionalEnumName(Hdr.Magic, makeArrayRef(PEHeaderMagic)); 106 outs() << '\n'; 107 print("MajorLinkerVersion", Hdr.MajorLinkerVersion); 108 print("MinorLinkerVersion", Hdr.MinorLinkerVersion); 109 printAddr("SizeOfCode", Hdr.SizeOfCode); 110 printAddr("SizeOfInitializedData", Hdr.SizeOfInitializedData); 111 printAddr("SizeOfUninitializedData", Hdr.SizeOfUninitializedData); 112 printAddr("AddressOfEntryPoint", Hdr.AddressOfEntryPoint); 113 printAddr("BaseOfCode", Hdr.BaseOfCode); 114 if (!Is64) 115 printAddr("BaseOfData", getBaseOfData(&Hdr)); 116 printAddr("ImageBase", Hdr.ImageBase); 117 printU32("SectionAlignment", Hdr.SectionAlignment, "%08x\n"); 118 printU32("FileAlignment", Hdr.FileAlignment, "%08x\n"); 119 printU16("MajorOSystemVersion", Hdr.MajorOperatingSystemVersion); 120 printU16("MinorOSystemVersion", Hdr.MinorOperatingSystemVersion); 121 printU16("MajorImageVersion", Hdr.MajorImageVersion); 122 printU16("MinorImageVersion", Hdr.MinorImageVersion); 123 printU16("MajorSubsystemVersion", Hdr.MajorSubsystemVersion); 124 printU16("MinorSubsystemVersion", Hdr.MinorSubsystemVersion); 125 printU32("Win32Version", Hdr.Win32VersionValue, "%08x\n"); 126 printU32("SizeOfImage", Hdr.SizeOfImage, "%08x\n"); 127 printU32("SizeOfHeaders", Hdr.SizeOfHeaders, "%08x\n"); 128 printU32("CheckSum", Hdr.CheckSum, "%08x\n"); 129 printU16("Subsystem", Hdr.Subsystem, "%08x"); 130 printOptionalEnumName(Hdr.Subsystem, makeArrayRef(PEWindowsSubsystem)); 131 outs() << '\n'; 132 133 printU16("DllCharacteristics", Hdr.DLLCharacteristics, "%08x\n"); 134 #define FLAG(Name) \ 135 if (Hdr.DLLCharacteristics & COFF::IMAGE_DLL_CHARACTERISTICS_##Name) \ 136 outs() << "\t\t\t\t\t" << #Name << '\n'; 137 FLAG(HIGH_ENTROPY_VA); 138 FLAG(DYNAMIC_BASE); 139 FLAG(FORCE_INTEGRITY); 140 FLAG(NX_COMPAT); 141 FLAG(NO_ISOLATION); 142 FLAG(NO_SEH); 143 FLAG(NO_BIND); 144 FLAG(APPCONTAINER); 145 FLAG(WDM_DRIVER); 146 FLAG(GUARD_CF); 147 FLAG(TERMINAL_SERVER_AWARE); 148 #undef FLAG 149 150 printAddr("SizeOfStackReserve", Hdr.SizeOfStackReserve); 151 printAddr("SizeOfStackCommit", Hdr.SizeOfStackCommit); 152 printAddr("SizeOfHeapReserve", Hdr.SizeOfHeapReserve); 153 printAddr("SizeOfHeapCommit", Hdr.SizeOfHeapCommit); 154 printU32("LoaderFlags", Hdr.LoaderFlags, "%08x\n"); 155 printU32("NumberOfRvaAndSizes", Hdr.NumberOfRvaAndSize, "%08x\n"); 156 157 static const char *DirName[COFF::NUM_DATA_DIRECTORIES + 1] = { 158 "Export Directory [.edata (or where ever we found it)]", 159 "Import Directory [parts of .idata]", 160 "Resource Directory [.rsrc]", 161 "Exception Directory [.pdata]", 162 "Security Directory", 163 "Base Relocation Directory [.reloc]", 164 "Debug Directory", 165 "Description Directory", 166 "Special Directory", 167 "Thread Storage Directory [.tls]", 168 "Load Configuration Directory", 169 "Bound Import Directory", 170 "Import Address Table Directory", 171 "Delay Import Directory", 172 "CLR Runtime Header", 173 "Reserved", 174 }; 175 outs() << "\nThe Data Directory\n"; 176 for (uint32_t I = 0; I != array_lengthof(DirName); ++I) { 177 uint32_t Addr = 0, Size = 0; 178 if (const data_directory *Data = Obj.getDataDirectory(I)) { 179 Addr = Data->RelativeVirtualAddress; 180 Size = Data->Size; 181 } 182 outs() << format("Entry %x ", I) << formatAddr(Addr) 183 << format(" %08x %s\n", uint32_t(Size), DirName[I]); 184 } 185 } 186 187 // Returns the name of the unwind code. 188 static StringRef getUnwindCodeTypeName(uint8_t Code) { 189 switch(Code) { 190 default: llvm_unreachable("Invalid unwind code"); 191 case UOP_PushNonVol: return "UOP_PushNonVol"; 192 case UOP_AllocLarge: return "UOP_AllocLarge"; 193 case UOP_AllocSmall: return "UOP_AllocSmall"; 194 case UOP_SetFPReg: return "UOP_SetFPReg"; 195 case UOP_SaveNonVol: return "UOP_SaveNonVol"; 196 case UOP_SaveNonVolBig: return "UOP_SaveNonVolBig"; 197 case UOP_SaveXMM128: return "UOP_SaveXMM128"; 198 case UOP_SaveXMM128Big: return "UOP_SaveXMM128Big"; 199 case UOP_PushMachFrame: return "UOP_PushMachFrame"; 200 } 201 } 202 203 // Returns the name of a referenced register. 204 static StringRef getUnwindRegisterName(uint8_t Reg) { 205 switch(Reg) { 206 default: llvm_unreachable("Invalid register"); 207 case 0: return "RAX"; 208 case 1: return "RCX"; 209 case 2: return "RDX"; 210 case 3: return "RBX"; 211 case 4: return "RSP"; 212 case 5: return "RBP"; 213 case 6: return "RSI"; 214 case 7: return "RDI"; 215 case 8: return "R8"; 216 case 9: return "R9"; 217 case 10: return "R10"; 218 case 11: return "R11"; 219 case 12: return "R12"; 220 case 13: return "R13"; 221 case 14: return "R14"; 222 case 15: return "R15"; 223 } 224 } 225 226 // Calculates the number of array slots required for the unwind code. 227 static unsigned getNumUsedSlots(const UnwindCode &UnwindCode) { 228 switch (UnwindCode.getUnwindOp()) { 229 default: llvm_unreachable("Invalid unwind code"); 230 case UOP_PushNonVol: 231 case UOP_AllocSmall: 232 case UOP_SetFPReg: 233 case UOP_PushMachFrame: 234 return 1; 235 case UOP_SaveNonVol: 236 case UOP_SaveXMM128: 237 return 2; 238 case UOP_SaveNonVolBig: 239 case UOP_SaveXMM128Big: 240 return 3; 241 case UOP_AllocLarge: 242 return (UnwindCode.getOpInfo() == 0) ? 2 : 3; 243 } 244 } 245 246 // Prints one unwind code. Because an unwind code can occupy up to 3 slots in 247 // the unwind codes array, this function requires that the correct number of 248 // slots is provided. 249 static void printUnwindCode(ArrayRef<UnwindCode> UCs) { 250 assert(UCs.size() >= getNumUsedSlots(UCs[0])); 251 outs() << format(" 0x%02x: ", unsigned(UCs[0].u.CodeOffset)) 252 << getUnwindCodeTypeName(UCs[0].getUnwindOp()); 253 switch (UCs[0].getUnwindOp()) { 254 case UOP_PushNonVol: 255 outs() << " " << getUnwindRegisterName(UCs[0].getOpInfo()); 256 break; 257 case UOP_AllocLarge: 258 if (UCs[0].getOpInfo() == 0) { 259 outs() << " " << UCs[1].FrameOffset; 260 } else { 261 outs() << " " << UCs[1].FrameOffset 262 + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16); 263 } 264 break; 265 case UOP_AllocSmall: 266 outs() << " " << ((UCs[0].getOpInfo() + 1) * 8); 267 break; 268 case UOP_SetFPReg: 269 outs() << " "; 270 break; 271 case UOP_SaveNonVol: 272 outs() << " " << getUnwindRegisterName(UCs[0].getOpInfo()) 273 << format(" [0x%04x]", 8 * UCs[1].FrameOffset); 274 break; 275 case UOP_SaveNonVolBig: 276 outs() << " " << getUnwindRegisterName(UCs[0].getOpInfo()) 277 << format(" [0x%08x]", UCs[1].FrameOffset 278 + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16)); 279 break; 280 case UOP_SaveXMM128: 281 outs() << " XMM" << static_cast<uint32_t>(UCs[0].getOpInfo()) 282 << format(" [0x%04x]", 16 * UCs[1].FrameOffset); 283 break; 284 case UOP_SaveXMM128Big: 285 outs() << " XMM" << UCs[0].getOpInfo() 286 << format(" [0x%08x]", UCs[1].FrameOffset 287 + (static_cast<uint32_t>(UCs[2].FrameOffset) << 16)); 288 break; 289 case UOP_PushMachFrame: 290 outs() << " " << (UCs[0].getOpInfo() ? "w/o" : "w") 291 << " error code"; 292 break; 293 } 294 outs() << "\n"; 295 } 296 297 static void printAllUnwindCodes(ArrayRef<UnwindCode> UCs) { 298 for (const UnwindCode *I = UCs.begin(), *E = UCs.end(); I < E; ) { 299 unsigned UsedSlots = getNumUsedSlots(*I); 300 if (UsedSlots > UCs.size()) { 301 outs() << "Unwind data corrupted: Encountered unwind op " 302 << getUnwindCodeTypeName((*I).getUnwindOp()) 303 << " which requires " << UsedSlots 304 << " slots, but only " << UCs.size() 305 << " remaining in buffer"; 306 return ; 307 } 308 printUnwindCode(makeArrayRef(I, E)); 309 I += UsedSlots; 310 } 311 } 312 313 // Given a symbol sym this functions returns the address and section of it. 314 static Error resolveSectionAndAddress(const COFFObjectFile *Obj, 315 const SymbolRef &Sym, 316 const coff_section *&ResolvedSection, 317 uint64_t &ResolvedAddr) { 318 Expected<uint64_t> ResolvedAddrOrErr = Sym.getAddress(); 319 if (!ResolvedAddrOrErr) 320 return ResolvedAddrOrErr.takeError(); 321 ResolvedAddr = *ResolvedAddrOrErr; 322 Expected<section_iterator> Iter = Sym.getSection(); 323 if (!Iter) 324 return Iter.takeError(); 325 ResolvedSection = Obj->getCOFFSection(**Iter); 326 return Error::success(); 327 } 328 329 // Given a vector of relocations for a section and an offset into this section 330 // the function returns the symbol used for the relocation at the offset. 331 static Error resolveSymbol(const std::vector<RelocationRef> &Rels, 332 uint64_t Offset, SymbolRef &Sym) { 333 for (auto &R : Rels) { 334 uint64_t Ofs = R.getOffset(); 335 if (Ofs == Offset) { 336 Sym = *R.getSymbol(); 337 return Error::success(); 338 } 339 } 340 return make_error<BinaryError>(); 341 } 342 343 // Given a vector of relocations for a section and an offset into this section 344 // the function resolves the symbol used for the relocation at the offset and 345 // returns the section content and the address inside the content pointed to 346 // by the symbol. 347 static Error 348 getSectionContents(const COFFObjectFile *Obj, 349 const std::vector<RelocationRef> &Rels, uint64_t Offset, 350 ArrayRef<uint8_t> &Contents, uint64_t &Addr) { 351 SymbolRef Sym; 352 if (Error E = resolveSymbol(Rels, Offset, Sym)) 353 return E; 354 const coff_section *Section; 355 if (Error E = resolveSectionAndAddress(Obj, Sym, Section, Addr)) 356 return E; 357 return Obj->getSectionContents(Section, Contents); 358 } 359 360 // Given a vector of relocations for a section and an offset into this section 361 // the function returns the name of the symbol used for the relocation at the 362 // offset. 363 static Error resolveSymbolName(const std::vector<RelocationRef> &Rels, 364 uint64_t Offset, StringRef &Name) { 365 SymbolRef Sym; 366 if (Error EC = resolveSymbol(Rels, Offset, Sym)) 367 return EC; 368 Expected<StringRef> NameOrErr = Sym.getName(); 369 if (!NameOrErr) 370 return NameOrErr.takeError(); 371 Name = *NameOrErr; 372 return Error::success(); 373 } 374 375 static void printCOFFSymbolAddress(raw_ostream &Out, 376 const std::vector<RelocationRef> &Rels, 377 uint64_t Offset, uint32_t Disp) { 378 StringRef Sym; 379 if (!resolveSymbolName(Rels, Offset, Sym)) { 380 Out << Sym; 381 if (Disp > 0) 382 Out << format(" + 0x%04x", Disp); 383 } else { 384 Out << format("0x%04x", Disp); 385 } 386 } 387 388 static void 389 printSEHTable(const COFFObjectFile *Obj, uint32_t TableVA, int Count) { 390 if (Count == 0) 391 return; 392 393 uintptr_t IntPtr = 0; 394 if (Error E = Obj->getVaPtr(TableVA, IntPtr)) 395 reportError(std::move(E), Obj->getFileName()); 396 397 const support::ulittle32_t *P = (const support::ulittle32_t *)IntPtr; 398 outs() << "SEH Table:"; 399 for (int I = 0; I < Count; ++I) 400 outs() << format(" 0x%x", P[I] + Obj->getPE32Header()->ImageBase); 401 outs() << "\n\n"; 402 } 403 404 template <typename T> 405 static void printTLSDirectoryT(const coff_tls_directory<T> *TLSDir) { 406 size_t FormatWidth = sizeof(T) * 2; 407 outs() << "TLS directory:" 408 << "\n StartAddressOfRawData: " 409 << format_hex(TLSDir->StartAddressOfRawData, FormatWidth) 410 << "\n EndAddressOfRawData: " 411 << format_hex(TLSDir->EndAddressOfRawData, FormatWidth) 412 << "\n AddressOfIndex: " 413 << format_hex(TLSDir->AddressOfIndex, FormatWidth) 414 << "\n AddressOfCallBacks: " 415 << format_hex(TLSDir->AddressOfCallBacks, FormatWidth) 416 << "\n SizeOfZeroFill: " 417 << TLSDir->SizeOfZeroFill 418 << "\n Characteristics: " 419 << TLSDir->Characteristics 420 << "\n Alignment: " 421 << TLSDir->getAlignment() 422 << "\n\n"; 423 } 424 425 static void printTLSDirectory(const COFFObjectFile *Obj) { 426 const pe32_header *PE32Header = Obj->getPE32Header(); 427 const pe32plus_header *PE32PlusHeader = Obj->getPE32PlusHeader(); 428 429 // Skip if it's not executable. 430 if (!PE32Header && !PE32PlusHeader) 431 return; 432 433 if (PE32Header) { 434 if (auto *TLSDir = Obj->getTLSDirectory32()) 435 printTLSDirectoryT(TLSDir); 436 } else { 437 if (auto *TLSDir = Obj->getTLSDirectory64()) 438 printTLSDirectoryT(TLSDir); 439 } 440 441 outs() << "\n"; 442 } 443 444 static void printLoadConfiguration(const COFFObjectFile *Obj) { 445 // Skip if it's not executable. 446 if (!Obj->getPE32Header()) 447 return; 448 449 // Currently only x86 is supported 450 if (Obj->getMachine() != COFF::IMAGE_FILE_MACHINE_I386) 451 return; 452 453 auto *LoadConf = Obj->getLoadConfig32(); 454 if (!LoadConf) 455 return; 456 457 outs() << "Load configuration:" 458 << "\n Timestamp: " << LoadConf->TimeDateStamp 459 << "\n Major Version: " << LoadConf->MajorVersion 460 << "\n Minor Version: " << LoadConf->MinorVersion 461 << "\n GlobalFlags Clear: " << LoadConf->GlobalFlagsClear 462 << "\n GlobalFlags Set: " << LoadConf->GlobalFlagsSet 463 << "\n Critical Section Default Timeout: " << LoadConf->CriticalSectionDefaultTimeout 464 << "\n Decommit Free Block Threshold: " << LoadConf->DeCommitFreeBlockThreshold 465 << "\n Decommit Total Free Threshold: " << LoadConf->DeCommitTotalFreeThreshold 466 << "\n Lock Prefix Table: " << LoadConf->LockPrefixTable 467 << "\n Maximum Allocation Size: " << LoadConf->MaximumAllocationSize 468 << "\n Virtual Memory Threshold: " << LoadConf->VirtualMemoryThreshold 469 << "\n Process Affinity Mask: " << LoadConf->ProcessAffinityMask 470 << "\n Process Heap Flags: " << LoadConf->ProcessHeapFlags 471 << "\n CSD Version: " << LoadConf->CSDVersion 472 << "\n Security Cookie: " << LoadConf->SecurityCookie 473 << "\n SEH Table: " << LoadConf->SEHandlerTable 474 << "\n SEH Count: " << LoadConf->SEHandlerCount 475 << "\n\n"; 476 printSEHTable(Obj, LoadConf->SEHandlerTable, LoadConf->SEHandlerCount); 477 outs() << "\n"; 478 } 479 480 // Prints import tables. The import table is a table containing the list of 481 // DLL name and symbol names which will be linked by the loader. 482 static void printImportTables(const COFFObjectFile *Obj) { 483 import_directory_iterator I = Obj->import_directory_begin(); 484 import_directory_iterator E = Obj->import_directory_end(); 485 if (I == E) 486 return; 487 outs() << "The Import Tables:\n"; 488 for (const ImportDirectoryEntryRef &DirRef : Obj->import_directories()) { 489 const coff_import_directory_table_entry *Dir; 490 StringRef Name; 491 if (DirRef.getImportTableEntry(Dir)) return; 492 if (DirRef.getName(Name)) return; 493 494 outs() << format(" lookup %08x time %08x fwd %08x name %08x addr %08x\n\n", 495 static_cast<uint32_t>(Dir->ImportLookupTableRVA), 496 static_cast<uint32_t>(Dir->TimeDateStamp), 497 static_cast<uint32_t>(Dir->ForwarderChain), 498 static_cast<uint32_t>(Dir->NameRVA), 499 static_cast<uint32_t>(Dir->ImportAddressTableRVA)); 500 outs() << " DLL Name: " << Name << "\n"; 501 outs() << " Hint/Ord Name\n"; 502 for (const ImportedSymbolRef &Entry : DirRef.imported_symbols()) { 503 bool IsOrdinal; 504 if (Entry.isOrdinal(IsOrdinal)) 505 return; 506 if (IsOrdinal) { 507 uint16_t Ordinal; 508 if (Entry.getOrdinal(Ordinal)) 509 return; 510 outs() << format(" % 6d\n", Ordinal); 511 continue; 512 } 513 uint32_t HintNameRVA; 514 if (Entry.getHintNameRVA(HintNameRVA)) 515 return; 516 uint16_t Hint; 517 StringRef Name; 518 if (Obj->getHintName(HintNameRVA, Hint, Name)) 519 return; 520 outs() << format(" % 6d ", Hint) << Name << "\n"; 521 } 522 outs() << "\n"; 523 } 524 } 525 526 // Prints export tables. The export table is a table containing the list of 527 // exported symbol from the DLL. 528 static void printExportTable(const COFFObjectFile *Obj) { 529 export_directory_iterator I = Obj->export_directory_begin(); 530 export_directory_iterator E = Obj->export_directory_end(); 531 if (I == E) 532 return; 533 outs() << "Export Table:\n"; 534 StringRef DllName; 535 uint32_t OrdinalBase; 536 if (I->getDllName(DllName)) 537 return; 538 if (I->getOrdinalBase(OrdinalBase)) 539 return; 540 outs() << " DLL name: " << DllName << "\n"; 541 outs() << " Ordinal base: " << OrdinalBase << "\n"; 542 outs() << " Ordinal RVA Name\n"; 543 for (; I != E; I = ++I) { 544 uint32_t Ordinal; 545 if (I->getOrdinal(Ordinal)) 546 return; 547 uint32_t RVA; 548 if (I->getExportRVA(RVA)) 549 return; 550 bool IsForwarder; 551 if (I->isForwarder(IsForwarder)) 552 return; 553 554 if (IsForwarder) { 555 // Export table entries can be used to re-export symbols that 556 // this COFF file is imported from some DLLs. This is rare. 557 // In most cases IsForwarder is false. 558 outs() << format(" % 4d ", Ordinal); 559 } else { 560 outs() << format(" % 4d %# 8x", Ordinal, RVA); 561 } 562 563 StringRef Name; 564 if (I->getSymbolName(Name)) 565 continue; 566 if (!Name.empty()) 567 outs() << " " << Name; 568 if (IsForwarder) { 569 StringRef S; 570 if (I->getForwardTo(S)) 571 return; 572 outs() << " (forwarded to " << S << ")"; 573 } 574 outs() << "\n"; 575 } 576 } 577 578 // Given the COFF object file, this function returns the relocations for .pdata 579 // and the pointer to "runtime function" structs. 580 static bool getPDataSection(const COFFObjectFile *Obj, 581 std::vector<RelocationRef> &Rels, 582 const RuntimeFunction *&RFStart, int &NumRFs) { 583 for (const SectionRef &Section : Obj->sections()) { 584 StringRef Name = unwrapOrError(Section.getName(), Obj->getFileName()); 585 if (Name != ".pdata") 586 continue; 587 588 const coff_section *Pdata = Obj->getCOFFSection(Section); 589 append_range(Rels, Section.relocations()); 590 591 // Sort relocations by address. 592 llvm::sort(Rels, isRelocAddressLess); 593 594 ArrayRef<uint8_t> Contents; 595 if (Error E = Obj->getSectionContents(Pdata, Contents)) 596 reportError(std::move(E), Obj->getFileName()); 597 598 if (Contents.empty()) 599 continue; 600 601 RFStart = reinterpret_cast<const RuntimeFunction *>(Contents.data()); 602 NumRFs = Contents.size() / sizeof(RuntimeFunction); 603 return true; 604 } 605 return false; 606 } 607 608 Error objdump::getCOFFRelocationValueString(const COFFObjectFile *Obj, 609 const RelocationRef &Rel, 610 SmallVectorImpl<char> &Result) { 611 symbol_iterator SymI = Rel.getSymbol(); 612 Expected<StringRef> SymNameOrErr = SymI->getName(); 613 if (!SymNameOrErr) 614 return SymNameOrErr.takeError(); 615 StringRef SymName = *SymNameOrErr; 616 Result.append(SymName.begin(), SymName.end()); 617 return Error::success(); 618 } 619 620 static void printWin64EHUnwindInfo(const Win64EH::UnwindInfo *UI) { 621 // The casts to int are required in order to output the value as number. 622 // Without the casts the value would be interpreted as char data (which 623 // results in garbage output). 624 outs() << " Version: " << static_cast<int>(UI->getVersion()) << "\n"; 625 outs() << " Flags: " << static_cast<int>(UI->getFlags()); 626 if (UI->getFlags()) { 627 if (UI->getFlags() & UNW_ExceptionHandler) 628 outs() << " UNW_ExceptionHandler"; 629 if (UI->getFlags() & UNW_TerminateHandler) 630 outs() << " UNW_TerminateHandler"; 631 if (UI->getFlags() & UNW_ChainInfo) 632 outs() << " UNW_ChainInfo"; 633 } 634 outs() << "\n"; 635 outs() << " Size of prolog: " << static_cast<int>(UI->PrologSize) << "\n"; 636 outs() << " Number of Codes: " << static_cast<int>(UI->NumCodes) << "\n"; 637 // Maybe this should move to output of UOP_SetFPReg? 638 if (UI->getFrameRegister()) { 639 outs() << " Frame register: " 640 << getUnwindRegisterName(UI->getFrameRegister()) << "\n"; 641 outs() << " Frame offset: " << 16 * UI->getFrameOffset() << "\n"; 642 } else { 643 outs() << " No frame pointer used\n"; 644 } 645 if (UI->getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) { 646 // FIXME: Output exception handler data 647 } else if (UI->getFlags() & UNW_ChainInfo) { 648 // FIXME: Output chained unwind info 649 } 650 651 if (UI->NumCodes) 652 outs() << " Unwind Codes:\n"; 653 654 printAllUnwindCodes(makeArrayRef(&UI->UnwindCodes[0], UI->NumCodes)); 655 656 outs() << "\n"; 657 outs().flush(); 658 } 659 660 /// Prints out the given RuntimeFunction struct for x64, assuming that Obj is 661 /// pointing to an executable file. 662 static void printRuntimeFunction(const COFFObjectFile *Obj, 663 const RuntimeFunction &RF) { 664 if (!RF.StartAddress) 665 return; 666 outs() << "Function Table:\n" 667 << format(" Start Address: 0x%04x\n", 668 static_cast<uint32_t>(RF.StartAddress)) 669 << format(" End Address: 0x%04x\n", 670 static_cast<uint32_t>(RF.EndAddress)) 671 << format(" Unwind Info Address: 0x%04x\n", 672 static_cast<uint32_t>(RF.UnwindInfoOffset)); 673 uintptr_t addr; 674 if (Obj->getRvaPtr(RF.UnwindInfoOffset, addr)) 675 return; 676 printWin64EHUnwindInfo(reinterpret_cast<const Win64EH::UnwindInfo *>(addr)); 677 } 678 679 /// Prints out the given RuntimeFunction struct for x64, assuming that Obj is 680 /// pointing to an object file. Unlike executable, fields in RuntimeFunction 681 /// struct are filled with zeros, but instead there are relocations pointing to 682 /// them so that the linker will fill targets' RVAs to the fields at link 683 /// time. This function interprets the relocations to find the data to be used 684 /// in the resulting executable. 685 static void printRuntimeFunctionRels(const COFFObjectFile *Obj, 686 const RuntimeFunction &RF, 687 uint64_t SectionOffset, 688 const std::vector<RelocationRef> &Rels) { 689 outs() << "Function Table:\n"; 690 outs() << " Start Address: "; 691 printCOFFSymbolAddress(outs(), Rels, 692 SectionOffset + 693 /*offsetof(RuntimeFunction, StartAddress)*/ 0, 694 RF.StartAddress); 695 outs() << "\n"; 696 697 outs() << " End Address: "; 698 printCOFFSymbolAddress(outs(), Rels, 699 SectionOffset + 700 /*offsetof(RuntimeFunction, EndAddress)*/ 4, 701 RF.EndAddress); 702 outs() << "\n"; 703 704 outs() << " Unwind Info Address: "; 705 printCOFFSymbolAddress(outs(), Rels, 706 SectionOffset + 707 /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8, 708 RF.UnwindInfoOffset); 709 outs() << "\n"; 710 711 ArrayRef<uint8_t> XContents; 712 uint64_t UnwindInfoOffset = 0; 713 if (Error E = getSectionContents( 714 Obj, Rels, 715 SectionOffset + 716 /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8, 717 XContents, UnwindInfoOffset)) 718 reportError(std::move(E), Obj->getFileName()); 719 if (XContents.empty()) 720 return; 721 722 UnwindInfoOffset += RF.UnwindInfoOffset; 723 if (UnwindInfoOffset > XContents.size()) 724 return; 725 726 auto *UI = reinterpret_cast<const Win64EH::UnwindInfo *>(XContents.data() + 727 UnwindInfoOffset); 728 printWin64EHUnwindInfo(UI); 729 } 730 731 void objdump::printCOFFUnwindInfo(const COFFObjectFile *Obj) { 732 if (Obj->getMachine() != COFF::IMAGE_FILE_MACHINE_AMD64) { 733 WithColor::error(errs(), "llvm-objdump") 734 << "unsupported image machine type " 735 "(currently only AMD64 is supported).\n"; 736 return; 737 } 738 739 std::vector<RelocationRef> Rels; 740 const RuntimeFunction *RFStart; 741 int NumRFs; 742 if (!getPDataSection(Obj, Rels, RFStart, NumRFs)) 743 return; 744 ArrayRef<RuntimeFunction> RFs(RFStart, NumRFs); 745 746 bool IsExecutable = Rels.empty(); 747 if (IsExecutable) { 748 for (const RuntimeFunction &RF : RFs) 749 printRuntimeFunction(Obj, RF); 750 return; 751 } 752 753 for (const RuntimeFunction &RF : RFs) { 754 uint64_t SectionOffset = 755 std::distance(RFs.begin(), &RF) * sizeof(RuntimeFunction); 756 printRuntimeFunctionRels(Obj, RF, SectionOffset, Rels); 757 } 758 } 759 760 void objdump::printCOFFFileHeader(const COFFObjectFile &Obj) { 761 COFFDumper CD(Obj); 762 const uint16_t Cha = Obj.getCharacteristics(); 763 outs() << "Characteristics 0x" << Twine::utohexstr(Cha) << '\n'; 764 #define FLAG(F, Name) \ 765 if (Cha & F) \ 766 outs() << '\t' << Name << '\n'; 767 FLAG(COFF::IMAGE_FILE_RELOCS_STRIPPED, "relocations stripped"); 768 FLAG(COFF::IMAGE_FILE_EXECUTABLE_IMAGE, "executable"); 769 FLAG(COFF::IMAGE_FILE_LINE_NUMS_STRIPPED, "line numbers stripped"); 770 FLAG(COFF::IMAGE_FILE_LOCAL_SYMS_STRIPPED, "symbols stripped"); 771 FLAG(COFF::IMAGE_FILE_LARGE_ADDRESS_AWARE, "large address aware"); 772 FLAG(COFF::IMAGE_FILE_BYTES_REVERSED_LO, "little endian"); 773 FLAG(COFF::IMAGE_FILE_32BIT_MACHINE, "32 bit words"); 774 FLAG(COFF::IMAGE_FILE_DEBUG_STRIPPED, "debugging information removed"); 775 FLAG(COFF::IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP, 776 "copy to swap file if on removable media"); 777 FLAG(COFF::IMAGE_FILE_NET_RUN_FROM_SWAP, 778 "copy to swap file if on network media"); 779 FLAG(COFF::IMAGE_FILE_SYSTEM, "system file"); 780 FLAG(COFF::IMAGE_FILE_DLL, "DLL"); 781 FLAG(COFF::IMAGE_FILE_UP_SYSTEM_ONLY, "run only on uniprocessor machine"); 782 FLAG(COFF::IMAGE_FILE_BYTES_REVERSED_HI, "big endian"); 783 #undef FLAG 784 785 // TODO Support PE_IMAGE_DEBUG_TYPE_REPRO. 786 // Since ctime(3) returns a 26 character string of the form: 787 // "Sun Sep 16 01:03:52 1973\n\0" 788 // just print 24 characters. 789 const time_t Timestamp = Obj.getTimeDateStamp(); 790 outs() << format("\nTime/Date %.24s\n", ctime(&Timestamp)); 791 792 if (const pe32_header *Hdr = Obj.getPE32Header()) 793 CD.printPEHeader<pe32_header>(*Hdr); 794 else if (const pe32plus_header *Hdr = Obj.getPE32PlusHeader()) 795 CD.printPEHeader<pe32plus_header>(*Hdr); 796 797 printTLSDirectory(&Obj); 798 printLoadConfiguration(&Obj); 799 printImportTables(&Obj); 800 printExportTable(&Obj); 801 } 802 803 void objdump::printCOFFSymbolTable(const object::COFFImportFile &i) { 804 unsigned Index = 0; 805 bool IsCode = i.getCOFFImportHeader()->getType() == COFF::IMPORT_CODE; 806 807 for (const object::BasicSymbolRef &Sym : i.symbols()) { 808 std::string Name; 809 raw_string_ostream NS(Name); 810 811 cantFail(Sym.printName(NS)); 812 NS.flush(); 813 814 outs() << "[" << format("%2d", Index) << "]" 815 << "(sec " << format("%2d", 0) << ")" 816 << "(fl 0x00)" // Flag bits, which COFF doesn't have. 817 << "(ty " << format("%3x", (IsCode && Index) ? 32 : 0) << ")" 818 << "(scl " << format("%3x", 0) << ") " 819 << "(nx " << 0 << ") " 820 << "0x" << format("%08x", 0) << " " << Name << '\n'; 821 822 ++Index; 823 } 824 } 825 826 void objdump::printCOFFSymbolTable(const COFFObjectFile &coff) { 827 for (unsigned SI = 0, SE = coff.getNumberOfSymbols(); SI != SE; ++SI) { 828 Expected<COFFSymbolRef> Symbol = coff.getSymbol(SI); 829 if (!Symbol) 830 reportError(Symbol.takeError(), coff.getFileName()); 831 832 Expected<StringRef> NameOrErr = coff.getSymbolName(*Symbol); 833 if (!NameOrErr) 834 reportError(NameOrErr.takeError(), coff.getFileName()); 835 StringRef Name = *NameOrErr; 836 837 outs() << "[" << format("%2d", SI) << "]" 838 << "(sec " << format("%2d", int(Symbol->getSectionNumber())) << ")" 839 << "(fl 0x00)" // Flag bits, which COFF doesn't have. 840 << "(ty " << format("%3x", unsigned(Symbol->getType())) << ")" 841 << "(scl " << format("%3x", unsigned(Symbol->getStorageClass())) 842 << ") " 843 << "(nx " << unsigned(Symbol->getNumberOfAuxSymbols()) << ") " 844 << "0x" << format("%08x", unsigned(Symbol->getValue())) << " " 845 << Name; 846 if (Demangle && Name.startswith("?")) { 847 int Status = -1; 848 char *DemangledSymbol = 849 microsoftDemangle(Name.data(), nullptr, nullptr, nullptr, &Status); 850 851 if (Status == 0 && DemangledSymbol) { 852 outs() << " (" << StringRef(DemangledSymbol) << ")"; 853 std::free(DemangledSymbol); 854 } else { 855 outs() << " (invalid mangled name)"; 856 } 857 } 858 outs() << "\n"; 859 860 for (unsigned AI = 0, AE = Symbol->getNumberOfAuxSymbols(); AI < AE; ++AI, ++SI) { 861 if (Symbol->isSectionDefinition()) { 862 const coff_aux_section_definition *asd; 863 if (Error E = 864 coff.getAuxSymbol<coff_aux_section_definition>(SI + 1, asd)) 865 reportError(std::move(E), coff.getFileName()); 866 867 int32_t AuxNumber = asd->getNumber(Symbol->isBigObj()); 868 869 outs() << "AUX " 870 << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x " 871 , unsigned(asd->Length) 872 , unsigned(asd->NumberOfRelocations) 873 , unsigned(asd->NumberOfLinenumbers) 874 , unsigned(asd->CheckSum)) 875 << format("assoc %d comdat %d\n" 876 , unsigned(AuxNumber) 877 , unsigned(asd->Selection)); 878 } else if (Symbol->isFileRecord()) { 879 const char *FileName; 880 if (Error E = coff.getAuxSymbol<char>(SI + 1, FileName)) 881 reportError(std::move(E), coff.getFileName()); 882 883 StringRef Name(FileName, Symbol->getNumberOfAuxSymbols() * 884 coff.getSymbolTableEntrySize()); 885 outs() << "AUX " << Name.rtrim(StringRef("\0", 1)) << '\n'; 886 887 SI = SI + Symbol->getNumberOfAuxSymbols(); 888 break; 889 } else if (Symbol->isWeakExternal()) { 890 const coff_aux_weak_external *awe; 891 if (Error E = coff.getAuxSymbol<coff_aux_weak_external>(SI + 1, awe)) 892 reportError(std::move(E), coff.getFileName()); 893 894 outs() << "AUX " << format("indx %d srch %d\n", 895 static_cast<uint32_t>(awe->TagIndex), 896 static_cast<uint32_t>(awe->Characteristics)); 897 } else { 898 outs() << "AUX Unknown\n"; 899 } 900 } 901 } 902 } 903