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