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 case UOP_Epilog: 244 return 1; 245 case UOP_SaveNonVol: 246 case UOP_SaveXMM128: 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, bool &SeenFirstEpilog) { 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 case UOP_Epilog: 306 if (SeenFirstEpilog) { 307 uint32_t Offset = UCs[0].getEpilogOffset(); 308 if (Offset == 0) { 309 outs() << " padding"; 310 } else { 311 outs() << " offset=" << format("0x%X", Offset); 312 } 313 } else { 314 SeenFirstEpilog = true; 315 bool AtEnd = (UCs[0].getOpInfo() & 0x1) != 0; 316 uint32_t Length = UCs[0].u.CodeOffset; 317 outs() << " atend=" << (AtEnd ? "yes" : "no") 318 << ", length=" << format("0x%X", Length); 319 } 320 break; 321 } 322 outs() << "\n"; 323 } 324 325 static void printAllUnwindCodes(ArrayRef<UnwindCode> UCs) { 326 bool SeenFirstEpilog = false; 327 for (const UnwindCode *I = UCs.begin(), *E = UCs.end(); I < E; ) { 328 unsigned UsedSlots = getNumUsedSlots(*I); 329 if (UsedSlots > UCs.size()) { 330 outs() << "Unwind data corrupted: Encountered unwind op " 331 << getUnwindCodeTypeName((*I).getUnwindOp()) 332 << " which requires " << UsedSlots 333 << " slots, but only " << UCs.size() 334 << " remaining in buffer"; 335 return ; 336 } 337 printUnwindCode(ArrayRef(I, E), SeenFirstEpilog); 338 I += UsedSlots; 339 } 340 } 341 342 // Given a symbol sym this functions returns the address and section of it. 343 static Error resolveSectionAndAddress(const COFFObjectFile *Obj, 344 const SymbolRef &Sym, 345 const coff_section *&ResolvedSection, 346 uint64_t &ResolvedAddr) { 347 Expected<uint64_t> ResolvedAddrOrErr = Sym.getAddress(); 348 if (!ResolvedAddrOrErr) 349 return ResolvedAddrOrErr.takeError(); 350 ResolvedAddr = *ResolvedAddrOrErr; 351 Expected<section_iterator> Iter = Sym.getSection(); 352 if (!Iter) 353 return Iter.takeError(); 354 ResolvedSection = Obj->getCOFFSection(**Iter); 355 return Error::success(); 356 } 357 358 // Given a vector of relocations for a section and an offset into this section 359 // the function returns the symbol used for the relocation at the offset. 360 static Error resolveSymbol(const std::vector<RelocationRef> &Rels, 361 uint64_t Offset, SymbolRef &Sym) { 362 for (auto &R : Rels) { 363 uint64_t Ofs = R.getOffset(); 364 if (Ofs == Offset) { 365 Sym = *R.getSymbol(); 366 return Error::success(); 367 } 368 } 369 return make_error<BinaryError>(); 370 } 371 372 // Given a vector of relocations for a section and an offset into this section 373 // the function resolves the symbol used for the relocation at the offset and 374 // returns the section content and the address inside the content pointed to 375 // by the symbol. 376 static Error 377 getSectionContents(const COFFObjectFile *Obj, 378 const std::vector<RelocationRef> &Rels, uint64_t Offset, 379 ArrayRef<uint8_t> &Contents, uint64_t &Addr) { 380 SymbolRef Sym; 381 if (Error E = resolveSymbol(Rels, Offset, Sym)) 382 return E; 383 const coff_section *Section; 384 if (Error E = resolveSectionAndAddress(Obj, Sym, Section, Addr)) 385 return E; 386 return Obj->getSectionContents(Section, Contents); 387 } 388 389 // Given a vector of relocations for a section and an offset into this section 390 // the function returns the name of the symbol used for the relocation at the 391 // offset. 392 static Error resolveSymbolName(const std::vector<RelocationRef> &Rels, 393 uint64_t Offset, StringRef &Name) { 394 SymbolRef Sym; 395 if (Error EC = resolveSymbol(Rels, Offset, Sym)) 396 return EC; 397 Expected<StringRef> NameOrErr = Sym.getName(); 398 if (!NameOrErr) 399 return NameOrErr.takeError(); 400 Name = *NameOrErr; 401 return Error::success(); 402 } 403 404 static void printCOFFSymbolAddress(raw_ostream &Out, 405 const std::vector<RelocationRef> &Rels, 406 uint64_t Offset, uint32_t Disp) { 407 StringRef Sym; 408 if (!resolveSymbolName(Rels, Offset, Sym)) { 409 Out << Sym; 410 if (Disp > 0) 411 Out << format(" + 0x%04x", Disp); 412 } else { 413 Out << format("0x%04x", Disp); 414 } 415 } 416 417 static void 418 printSEHTable(const COFFObjectFile *Obj, uint32_t TableVA, int Count) { 419 if (Count == 0) 420 return; 421 422 uintptr_t IntPtr = 0; 423 if (Error E = Obj->getVaPtr(TableVA, IntPtr)) 424 reportError(std::move(E), Obj->getFileName()); 425 426 const support::ulittle32_t *P = (const support::ulittle32_t *)IntPtr; 427 outs() << "SEH Table:"; 428 for (int I = 0; I < Count; ++I) 429 outs() << format(" 0x%x", P[I] + Obj->getPE32Header()->ImageBase); 430 outs() << "\n\n"; 431 } 432 433 template <typename T> 434 static void printTLSDirectoryT(const coff_tls_directory<T> *TLSDir) { 435 size_t FormatWidth = sizeof(T) * 2; 436 outs() << "TLS directory:" 437 << "\n StartAddressOfRawData: " 438 << format_hex(TLSDir->StartAddressOfRawData, FormatWidth) 439 << "\n EndAddressOfRawData: " 440 << format_hex(TLSDir->EndAddressOfRawData, FormatWidth) 441 << "\n AddressOfIndex: " 442 << format_hex(TLSDir->AddressOfIndex, FormatWidth) 443 << "\n AddressOfCallBacks: " 444 << format_hex(TLSDir->AddressOfCallBacks, FormatWidth) 445 << "\n SizeOfZeroFill: " 446 << TLSDir->SizeOfZeroFill 447 << "\n Characteristics: " 448 << TLSDir->Characteristics 449 << "\n Alignment: " 450 << TLSDir->getAlignment() 451 << "\n\n"; 452 } 453 454 static void printTLSDirectory(const COFFObjectFile *Obj) { 455 const pe32_header *PE32Header = Obj->getPE32Header(); 456 const pe32plus_header *PE32PlusHeader = Obj->getPE32PlusHeader(); 457 458 // Skip if it's not executable. 459 if (!PE32Header && !PE32PlusHeader) 460 return; 461 462 if (PE32Header) { 463 if (auto *TLSDir = Obj->getTLSDirectory32()) 464 printTLSDirectoryT(TLSDir); 465 } else { 466 if (auto *TLSDir = Obj->getTLSDirectory64()) 467 printTLSDirectoryT(TLSDir); 468 } 469 470 outs() << "\n"; 471 } 472 473 static void printLoadConfiguration(const COFFObjectFile *Obj) { 474 // Skip if it's not executable. 475 if (!Obj->getPE32Header()) 476 return; 477 478 // Currently only x86 is supported 479 if (Obj->getMachine() != COFF::IMAGE_FILE_MACHINE_I386) 480 return; 481 482 auto *LoadConf = Obj->getLoadConfig32(); 483 if (!LoadConf) 484 return; 485 486 outs() << "Load configuration:" 487 << "\n Timestamp: " << LoadConf->TimeDateStamp 488 << "\n Major Version: " << LoadConf->MajorVersion 489 << "\n Minor Version: " << LoadConf->MinorVersion 490 << "\n GlobalFlags Clear: " << LoadConf->GlobalFlagsClear 491 << "\n GlobalFlags Set: " << LoadConf->GlobalFlagsSet 492 << "\n Critical Section Default Timeout: " << LoadConf->CriticalSectionDefaultTimeout 493 << "\n Decommit Free Block Threshold: " << LoadConf->DeCommitFreeBlockThreshold 494 << "\n Decommit Total Free Threshold: " << LoadConf->DeCommitTotalFreeThreshold 495 << "\n Lock Prefix Table: " << LoadConf->LockPrefixTable 496 << "\n Maximum Allocation Size: " << LoadConf->MaximumAllocationSize 497 << "\n Virtual Memory Threshold: " << LoadConf->VirtualMemoryThreshold 498 << "\n Process Affinity Mask: " << LoadConf->ProcessAffinityMask 499 << "\n Process Heap Flags: " << LoadConf->ProcessHeapFlags 500 << "\n CSD Version: " << LoadConf->CSDVersion 501 << "\n Security Cookie: " << LoadConf->SecurityCookie 502 << "\n SEH Table: " << LoadConf->SEHandlerTable 503 << "\n SEH Count: " << LoadConf->SEHandlerCount 504 << "\n\n"; 505 printSEHTable(Obj, LoadConf->SEHandlerTable, LoadConf->SEHandlerCount); 506 outs() << "\n"; 507 } 508 509 // Prints import tables. The import table is a table containing the list of 510 // DLL name and symbol names which will be linked by the loader. 511 static void printImportTables(const COFFObjectFile *Obj) { 512 import_directory_iterator I = Obj->import_directory_begin(); 513 import_directory_iterator E = Obj->import_directory_end(); 514 if (I == E) 515 return; 516 outs() << "The Import Tables:\n"; 517 for (const ImportDirectoryEntryRef &DirRef : Obj->import_directories()) { 518 const coff_import_directory_table_entry *Dir; 519 StringRef Name; 520 if (DirRef.getImportTableEntry(Dir)) return; 521 if (DirRef.getName(Name)) return; 522 523 outs() << format(" lookup %08x time %08x fwd %08x name %08x addr %08x\n\n", 524 static_cast<uint32_t>(Dir->ImportLookupTableRVA), 525 static_cast<uint32_t>(Dir->TimeDateStamp), 526 static_cast<uint32_t>(Dir->ForwarderChain), 527 static_cast<uint32_t>(Dir->NameRVA), 528 static_cast<uint32_t>(Dir->ImportAddressTableRVA)); 529 outs() << " DLL Name: " << Name << "\n"; 530 outs() << " Hint/Ord Name\n"; 531 for (const ImportedSymbolRef &Entry : DirRef.imported_symbols()) { 532 bool IsOrdinal; 533 if (Entry.isOrdinal(IsOrdinal)) 534 return; 535 if (IsOrdinal) { 536 uint16_t Ordinal; 537 if (Entry.getOrdinal(Ordinal)) 538 return; 539 outs() << format(" % 6d\n", Ordinal); 540 continue; 541 } 542 uint32_t HintNameRVA; 543 if (Entry.getHintNameRVA(HintNameRVA)) 544 return; 545 uint16_t Hint; 546 StringRef Name; 547 if (Obj->getHintName(HintNameRVA, Hint, Name)) 548 return; 549 outs() << format(" % 6d ", Hint) << Name << "\n"; 550 } 551 outs() << "\n"; 552 } 553 } 554 555 // Prints export tables. The export table is a table containing the list of 556 // exported symbol from the DLL. 557 static void printExportTable(const COFFObjectFile *Obj) { 558 export_directory_iterator I = Obj->export_directory_begin(); 559 export_directory_iterator E = Obj->export_directory_end(); 560 if (I == E) 561 return; 562 outs() << "Export Table:\n"; 563 StringRef DllName; 564 uint32_t OrdinalBase; 565 if (I->getDllName(DllName)) 566 return; 567 if (I->getOrdinalBase(OrdinalBase)) 568 return; 569 outs() << " DLL name: " << DllName << "\n"; 570 outs() << " Ordinal base: " << OrdinalBase << "\n"; 571 outs() << " Ordinal RVA Name\n"; 572 for (; I != E; I = ++I) { 573 uint32_t RVA; 574 if (I->getExportRVA(RVA)) 575 return; 576 StringRef Name; 577 if (I->getSymbolName(Name)) 578 continue; 579 if (!RVA && Name.empty()) 580 continue; 581 582 uint32_t Ordinal; 583 if (I->getOrdinal(Ordinal)) 584 return; 585 bool IsForwarder; 586 if (I->isForwarder(IsForwarder)) 587 return; 588 589 if (IsForwarder) { 590 // Export table entries can be used to re-export symbols that 591 // this COFF file is imported from some DLLs. This is rare. 592 // In most cases IsForwarder is false. 593 outs() << format(" %5d ", Ordinal); 594 } else { 595 outs() << format(" %5d %# 8x", Ordinal, RVA); 596 } 597 598 if (!Name.empty()) 599 outs() << " " << Name; 600 if (IsForwarder) { 601 StringRef S; 602 if (I->getForwardTo(S)) 603 return; 604 outs() << " (forwarded to " << S << ")"; 605 } 606 outs() << "\n"; 607 } 608 } 609 610 // Given the COFF object file, this function returns the relocations for .pdata 611 // and the pointer to "runtime function" structs. 612 static bool getPDataSection(const COFFObjectFile *Obj, 613 std::vector<RelocationRef> &Rels, 614 const RuntimeFunction *&RFStart, int &NumRFs) { 615 for (const SectionRef &Section : Obj->sections()) { 616 StringRef Name = unwrapOrError(Section.getName(), Obj->getFileName()); 617 if (Name != ".pdata") 618 continue; 619 620 const coff_section *Pdata = Obj->getCOFFSection(Section); 621 append_range(Rels, Section.relocations()); 622 623 // Sort relocations by address. 624 llvm::sort(Rels, isRelocAddressLess); 625 626 ArrayRef<uint8_t> Contents; 627 if (Error E = Obj->getSectionContents(Pdata, Contents)) 628 reportError(std::move(E), Obj->getFileName()); 629 630 if (Contents.empty()) 631 continue; 632 633 RFStart = reinterpret_cast<const RuntimeFunction *>(Contents.data()); 634 NumRFs = Contents.size() / sizeof(RuntimeFunction); 635 return true; 636 } 637 return false; 638 } 639 640 Error objdump::getCOFFRelocationValueString(const COFFObjectFile *Obj, 641 const RelocationRef &Rel, 642 SmallVectorImpl<char> &Result) { 643 symbol_iterator SymI = Rel.getSymbol(); 644 Expected<StringRef> SymNameOrErr = SymI->getName(); 645 if (!SymNameOrErr) 646 return SymNameOrErr.takeError(); 647 StringRef SymName = *SymNameOrErr; 648 Result.append(SymName.begin(), SymName.end()); 649 return Error::success(); 650 } 651 652 static void printWin64EHUnwindInfo(const Win64EH::UnwindInfo *UI) { 653 // The casts to int are required in order to output the value as number. 654 // Without the casts the value would be interpreted as char data (which 655 // results in garbage output). 656 outs() << " Version: " << static_cast<int>(UI->getVersion()) << "\n"; 657 outs() << " Flags: " << static_cast<int>(UI->getFlags()); 658 if (UI->getFlags()) { 659 if (UI->getFlags() & UNW_ExceptionHandler) 660 outs() << " UNW_ExceptionHandler"; 661 if (UI->getFlags() & UNW_TerminateHandler) 662 outs() << " UNW_TerminateHandler"; 663 if (UI->getFlags() & UNW_ChainInfo) 664 outs() << " UNW_ChainInfo"; 665 } 666 outs() << "\n"; 667 outs() << " Size of prolog: " << static_cast<int>(UI->PrologSize) << "\n"; 668 outs() << " Number of Codes: " << static_cast<int>(UI->NumCodes) << "\n"; 669 // Maybe this should move to output of UOP_SetFPReg? 670 if (UI->getFrameRegister()) { 671 outs() << " Frame register: " 672 << getUnwindRegisterName(UI->getFrameRegister()) << "\n"; 673 outs() << " Frame offset: " << 16 * UI->getFrameOffset() << "\n"; 674 } else { 675 outs() << " No frame pointer used\n"; 676 } 677 if (UI->getFlags() & (UNW_ExceptionHandler | UNW_TerminateHandler)) { 678 // FIXME: Output exception handler data 679 } else if (UI->getFlags() & UNW_ChainInfo) { 680 // FIXME: Output chained unwind info 681 } 682 683 if (UI->NumCodes) 684 outs() << " Unwind Codes:\n"; 685 686 printAllUnwindCodes(ArrayRef(&UI->UnwindCodes[0], UI->NumCodes)); 687 688 outs() << "\n"; 689 outs().flush(); 690 } 691 692 /// Prints out the given RuntimeFunction struct for x64, assuming that Obj is 693 /// pointing to an executable file. 694 static void printRuntimeFunction(const COFFObjectFile *Obj, 695 const RuntimeFunction &RF) { 696 if (!RF.StartAddress) 697 return; 698 outs() << "Function Table:\n" 699 << format(" Start Address: 0x%04x\n", 700 static_cast<uint32_t>(RF.StartAddress)) 701 << format(" End Address: 0x%04x\n", 702 static_cast<uint32_t>(RF.EndAddress)) 703 << format(" Unwind Info Address: 0x%04x\n", 704 static_cast<uint32_t>(RF.UnwindInfoOffset)); 705 uintptr_t addr; 706 if (Obj->getRvaPtr(RF.UnwindInfoOffset, addr)) 707 return; 708 printWin64EHUnwindInfo(reinterpret_cast<const Win64EH::UnwindInfo *>(addr)); 709 } 710 711 /// Prints out the given RuntimeFunction struct for x64, assuming that Obj is 712 /// pointing to an object file. Unlike executable, fields in RuntimeFunction 713 /// struct are filled with zeros, but instead there are relocations pointing to 714 /// them so that the linker will fill targets' RVAs to the fields at link 715 /// time. This function interprets the relocations to find the data to be used 716 /// in the resulting executable. 717 static void printRuntimeFunctionRels(const COFFObjectFile *Obj, 718 const RuntimeFunction &RF, 719 uint64_t SectionOffset, 720 const std::vector<RelocationRef> &Rels) { 721 outs() << "Function Table:\n"; 722 outs() << " Start Address: "; 723 printCOFFSymbolAddress(outs(), Rels, 724 SectionOffset + 725 /*offsetof(RuntimeFunction, StartAddress)*/ 0, 726 RF.StartAddress); 727 outs() << "\n"; 728 729 outs() << " End Address: "; 730 printCOFFSymbolAddress(outs(), Rels, 731 SectionOffset + 732 /*offsetof(RuntimeFunction, EndAddress)*/ 4, 733 RF.EndAddress); 734 outs() << "\n"; 735 736 outs() << " Unwind Info Address: "; 737 printCOFFSymbolAddress(outs(), Rels, 738 SectionOffset + 739 /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8, 740 RF.UnwindInfoOffset); 741 outs() << "\n"; 742 743 ArrayRef<uint8_t> XContents; 744 uint64_t UnwindInfoOffset = 0; 745 if (Error E = getSectionContents( 746 Obj, Rels, 747 SectionOffset + 748 /*offsetof(RuntimeFunction, UnwindInfoOffset)*/ 8, 749 XContents, UnwindInfoOffset)) 750 reportError(std::move(E), Obj->getFileName()); 751 if (XContents.empty()) 752 return; 753 754 UnwindInfoOffset += RF.UnwindInfoOffset; 755 if (UnwindInfoOffset > XContents.size()) 756 return; 757 758 auto *UI = reinterpret_cast<const Win64EH::UnwindInfo *>(XContents.data() + 759 UnwindInfoOffset); 760 printWin64EHUnwindInfo(UI); 761 } 762 763 void objdump::printCOFFUnwindInfo(const COFFObjectFile *Obj) { 764 if (Obj->getMachine() != COFF::IMAGE_FILE_MACHINE_AMD64) { 765 WithColor::error(errs(), "llvm-objdump") 766 << "unsupported image machine type " 767 "(currently only AMD64 is supported).\n"; 768 return; 769 } 770 771 std::vector<RelocationRef> Rels; 772 const RuntimeFunction *RFStart; 773 int NumRFs; 774 if (!getPDataSection(Obj, Rels, RFStart, NumRFs)) 775 return; 776 ArrayRef<RuntimeFunction> RFs(RFStart, NumRFs); 777 778 bool IsExecutable = Rels.empty(); 779 if (IsExecutable) { 780 for (const RuntimeFunction &RF : RFs) 781 printRuntimeFunction(Obj, RF); 782 return; 783 } 784 785 for (const RuntimeFunction &RF : RFs) { 786 uint64_t SectionOffset = 787 std::distance(RFs.begin(), &RF) * sizeof(RuntimeFunction); 788 printRuntimeFunctionRels(Obj, RF, SectionOffset, Rels); 789 } 790 } 791 792 void COFFDumper::printPrivateHeaders() { 793 COFFDumper CD(Obj); 794 const uint16_t Cha = Obj.getCharacteristics(); 795 outs() << "Characteristics 0x" << Twine::utohexstr(Cha) << '\n'; 796 #define FLAG(F, Name) \ 797 if (Cha & F) \ 798 outs() << '\t' << Name << '\n'; 799 FLAG(COFF::IMAGE_FILE_RELOCS_STRIPPED, "relocations stripped"); 800 FLAG(COFF::IMAGE_FILE_EXECUTABLE_IMAGE, "executable"); 801 FLAG(COFF::IMAGE_FILE_LINE_NUMS_STRIPPED, "line numbers stripped"); 802 FLAG(COFF::IMAGE_FILE_LOCAL_SYMS_STRIPPED, "symbols stripped"); 803 FLAG(COFF::IMAGE_FILE_LARGE_ADDRESS_AWARE, "large address aware"); 804 FLAG(COFF::IMAGE_FILE_BYTES_REVERSED_LO, "little endian"); 805 FLAG(COFF::IMAGE_FILE_32BIT_MACHINE, "32 bit words"); 806 FLAG(COFF::IMAGE_FILE_DEBUG_STRIPPED, "debugging information removed"); 807 FLAG(COFF::IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP, 808 "copy to swap file if on removable media"); 809 FLAG(COFF::IMAGE_FILE_NET_RUN_FROM_SWAP, 810 "copy to swap file if on network media"); 811 FLAG(COFF::IMAGE_FILE_SYSTEM, "system file"); 812 FLAG(COFF::IMAGE_FILE_DLL, "DLL"); 813 FLAG(COFF::IMAGE_FILE_UP_SYSTEM_ONLY, "run only on uniprocessor machine"); 814 FLAG(COFF::IMAGE_FILE_BYTES_REVERSED_HI, "big endian"); 815 #undef FLAG 816 817 // TODO Support PE_IMAGE_DEBUG_TYPE_REPRO. 818 // Since ctime(3) returns a 26 character string of the form: 819 // "Sun Sep 16 01:03:52 1973\n\0" 820 // just print 24 characters. 821 const time_t Timestamp = Obj.getTimeDateStamp(); 822 outs() << format("\nTime/Date %.24s\n", ctime(&Timestamp)); 823 824 if (const pe32_header *Hdr = Obj.getPE32Header()) 825 CD.printPEHeader<pe32_header>(*Hdr); 826 else if (const pe32plus_header *Hdr = Obj.getPE32PlusHeader()) 827 CD.printPEHeader<pe32plus_header>(*Hdr); 828 829 printTLSDirectory(&Obj); 830 printLoadConfiguration(&Obj); 831 printImportTables(&Obj); 832 printExportTable(&Obj); 833 } 834 835 void objdump::printCOFFSymbolTable(const object::COFFImportFile &i) { 836 unsigned Index = 0; 837 bool IsCode = i.getCOFFImportHeader()->getType() == COFF::IMPORT_CODE; 838 839 for (const object::BasicSymbolRef &Sym : i.symbols()) { 840 std::string Name; 841 raw_string_ostream NS(Name); 842 843 cantFail(Sym.printName(NS)); 844 NS.flush(); 845 846 outs() << "[" << format("%2d", Index) << "]" 847 << "(sec " << format("%2d", 0) << ")" 848 << "(fl 0x00)" // Flag bits, which COFF doesn't have. 849 << "(ty " << format("%3x", (IsCode && Index) ? 32 : 0) << ")" 850 << "(scl " << format("%3x", 0) << ") " 851 << "(nx " << 0 << ") " 852 << "0x" << format("%08x", 0) << " " << Name << '\n'; 853 854 ++Index; 855 } 856 } 857 858 void objdump::printCOFFSymbolTable(const COFFObjectFile &coff) { 859 for (unsigned SI = 0, SE = coff.getNumberOfSymbols(); SI != SE; ++SI) { 860 Expected<COFFSymbolRef> Symbol = coff.getSymbol(SI); 861 if (!Symbol) 862 reportError(Symbol.takeError(), coff.getFileName()); 863 864 Expected<StringRef> NameOrErr = coff.getSymbolName(*Symbol); 865 if (!NameOrErr) 866 reportError(NameOrErr.takeError(), coff.getFileName()); 867 StringRef Name = *NameOrErr; 868 869 outs() << "[" << format("%2d", SI) << "]" 870 << "(sec " << format("%2d", int(Symbol->getSectionNumber())) << ")" 871 << "(fl 0x00)" // Flag bits, which COFF doesn't have. 872 << "(ty " << format("%3x", unsigned(Symbol->getType())) << ")" 873 << "(scl " << format("%3x", unsigned(Symbol->getStorageClass())) 874 << ") " 875 << "(nx " << unsigned(Symbol->getNumberOfAuxSymbols()) << ") " 876 << "0x" << format("%08x", unsigned(Symbol->getValue())) << " " 877 << Name; 878 if (Demangle && Name.starts_with("?")) { 879 int Status = -1; 880 char *DemangledSymbol = microsoftDemangle(Name, nullptr, &Status); 881 882 if (Status == 0 && DemangledSymbol) { 883 outs() << " (" << StringRef(DemangledSymbol) << ")"; 884 std::free(DemangledSymbol); 885 } else { 886 outs() << " (invalid mangled name)"; 887 } 888 } 889 outs() << "\n"; 890 891 for (unsigned AI = 0, AE = Symbol->getNumberOfAuxSymbols(); AI < AE; ++AI, ++SI) { 892 if (Symbol->isSectionDefinition()) { 893 const coff_aux_section_definition *asd; 894 if (Error E = 895 coff.getAuxSymbol<coff_aux_section_definition>(SI + 1, asd)) 896 reportError(std::move(E), coff.getFileName()); 897 898 int32_t AuxNumber = asd->getNumber(Symbol->isBigObj()); 899 900 outs() << "AUX " 901 << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x " 902 , unsigned(asd->Length) 903 , unsigned(asd->NumberOfRelocations) 904 , unsigned(asd->NumberOfLinenumbers) 905 , unsigned(asd->CheckSum)) 906 << format("assoc %d comdat %d\n" 907 , unsigned(AuxNumber) 908 , unsigned(asd->Selection)); 909 } else if (Symbol->isFileRecord()) { 910 const char *FileName; 911 if (Error E = coff.getAuxSymbol<char>(SI + 1, FileName)) 912 reportError(std::move(E), coff.getFileName()); 913 914 StringRef Name(FileName, Symbol->getNumberOfAuxSymbols() * 915 coff.getSymbolTableEntrySize()); 916 outs() << "AUX " << Name.rtrim(StringRef("\0", 1)) << '\n'; 917 918 SI = SI + Symbol->getNumberOfAuxSymbols(); 919 break; 920 } else if (Symbol->isWeakExternal()) { 921 const coff_aux_weak_external *awe; 922 if (Error E = coff.getAuxSymbol<coff_aux_weak_external>(SI + 1, awe)) 923 reportError(std::move(E), coff.getFileName()); 924 925 outs() << "AUX " << format("indx %d srch %d\n", 926 static_cast<uint32_t>(awe->TagIndex), 927 static_cast<uint32_t>(awe->Characteristics)); 928 } else { 929 outs() << "AUX Unknown\n"; 930 } 931 } 932 } 933 } 934