llvm.org GIT mirror llvm / 4bf771b
readobj: Dump PE/COFF optional records. These records are mandatory for executables and are used by the loader. Reviewers: rafael CC: llvm-commits Differential Revision: http://llvm-reviews.chandlerc.com/D939 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@183852 91177308-0d34-0410-b5e6-96231b3b80d8 Rui Ueyama 7 years ago
8 changed file(s) with 203 addition(s) and 54 deletion(s). Raw diff Collapse all Expand all
187187
188188 class COFFObjectFile : public ObjectFile {
189189 private:
190 const coff_file_header *Header;
190 const coff_file_header *COFFHeader;
191 const pe32_header *PE32Header;
191192 const coff_section *SectionTable;
192193 const coff_symbol *SymbolTable;
193194 const char *StringTable;
271272 virtual StringRef getLoadName() const;
272273
273274 error_code getHeader(const coff_file_header *&Res) const;
275 error_code getCOFFHeader(const coff_file_header *&Res) const;
276 error_code getPE32Header(const pe32_header *&Res) const;
274277 error_code getSection(int32_t index, const coff_section *&Res) const;
275278 error_code getSymbol(uint32_t index, const coff_symbol *&Res) const;
276279 template
8383 }
8484 case sys::fs::file_magic::coff_object:
8585 case sys::fs::file_magic::pecoff_executable: {
86 OwningPtr ret(new COFFObjectFile(scopedSource.take(), ec));
87 if (ec) return ec;
86 OwningPtr ret(
87 ObjectFile::createCOFFObjectFile(scopedSource.take()));
88 if (!ret)
89 return object_error::invalid_file_type;
8890 Result.swap(ret);
8991 return object_error::success;
9092 }
5757 # ifndef NDEBUG
5858 // Verify that the symbol points to a valid entry in the symbol table.
5959 uintptr_t offset = uintptr_t(addr) - uintptr_t(base());
60 if (offset < Header->PointerToSymbolTable
61 || offset >= Header->PointerToSymbolTable
62 + (Header->NumberOfSymbols * sizeof(coff_symbol)))
60 if (offset < COFFHeader->PointerToSymbolTable
61 || offset >= COFFHeader->PointerToSymbolTable
62 + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
6363 report_fatal_error("Symbol was outside of symbol table.");
6464
65 assert((offset - Header->PointerToSymbolTable) % sizeof(coff_symbol)
65 assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol)
6666 == 0 && "Symbol did not point to the beginning of a symbol");
6767 # endif
6868
7575 # ifndef NDEBUG
7676 // Verify that the section points to a valid entry in the section table.
7777 if (addr < SectionTable
78 || addr >= (SectionTable + Header->NumberOfSections))
78 || addr >= (SectionTable + COFFHeader->NumberOfSections))
7979 report_fatal_error("Section was outside of section table.");
8080
8181 uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable);
429429
430430 COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec)
431431 : ObjectFile(Binary::ID_COFF, Object)
432 , Header(0)
432 , COFFHeader(0)
433 , PE32Header(0)
433434 , SectionTable(0)
434435 , SymbolTable(0)
435436 , StringTable(0)
437438 // Check that we at least have enough room for a header.
438439 if (!checkSize(Data, ec, sizeof(coff_file_header))) return;
439440
440 // The actual starting location of the COFF header in the file. This can be
441 // non-zero in PE/COFF files.
442 uint64_t HeaderStart = 0;
441 // The current location in the file where we are looking at.
442 uint64_t CurPtr = 0;
443
444 // PE header is optional and is present only in executables. If it exists,
445 // it is placed right after COFF header.
446 bool hasPEHeader = false;
443447
444448 // Check if this is a PE/COFF file.
445449 if (base()[0] == 0x4d && base()[1] == 0x5a) {
446450 // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
447451 // PE signature to find 'normal' COFF header.
448452 if (!checkSize(Data, ec, 0x3c + 8)) return;
449 HeaderStart = *reinterpret_cast(base() + 0x3c);
450 // Check the PE header. ("PE\0\0")
451 if (std::memcmp(base() + HeaderStart, "PE\0\0", 4) != 0) {
453 CurPtr = *reinterpret_cast(base() + 0x3c);
454 // Check the PE magic bytes. ("PE\0\0")
455 if (std::memcmp(base() + CurPtr, "PE\0\0", 4) != 0) {
452456 ec = object_error::parse_failed;
453457 return;
454458 }
455 HeaderStart += 4; // Skip the PE Header.
456 }
457
458 Header = reinterpret_cast(base() + HeaderStart);
459 if (!checkAddr(Data, ec, uintptr_t(Header), sizeof(coff_file_header)))
459 CurPtr += 4; // Skip the PE magic bytes.
460 hasPEHeader = true;
461 }
462
463 COFFHeader = reinterpret_cast(base() + CurPtr);
464 if (!checkAddr(Data, ec, uintptr_t(COFFHeader), sizeof(coff_file_header)))
460465 return;
466 CurPtr += sizeof(coff_file_header);
467
468 if (hasPEHeader) {
469 PE32Header = reinterpret_cast(base() + CurPtr);
470 if (!checkAddr(Data, ec, uintptr_t(PE32Header), sizeof(pe32_header)))
471 return;
472 // We only support PE32. If this is PE32 (not PE32+), the magic byte
473 // should be 0x10b. If this is not PE32, continue as if there's no PE
474 // header in this file.
475 if (PE32Header->Magic != 0x10b)
476 PE32Header = 0;
477 // There may be optional data directory after PE header. Skip them.
478 CurPtr += COFFHeader->SizeOfOptionalHeader;
479 }
461480
462481 SectionTable =
463 reinterpret_cast( base()
464 + HeaderStart
465 + sizeof(coff_file_header)
466 + Header->SizeOfOptionalHeader);
482 reinterpret_cast(base() + CurPtr);
467483 if (!checkAddr(Data, ec, uintptr_t(SectionTable),
468 Header->NumberOfSections * sizeof(coff_section)))
484 COFFHeader->NumberOfSections * sizeof(coff_section)))
469485 return;
470486
471 if (Header->PointerToSymbolTable != 0) {
487 if (COFFHeader->PointerToSymbolTable != 0) {
472488 SymbolTable =
473489 reinterpret_cast(base()
474 + Header->PointerToSymbolTable);
490 + COFFHeader->PointerToSymbolTable);
475491 if (!checkAddr(Data, ec, uintptr_t(SymbolTable),
476 Header->NumberOfSymbols * sizeof(coff_symbol)))
492 COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
477493 return;
478494
479495 // Find string table.
480496 StringTable = reinterpret_cast(base())
481 + Header->PointerToSymbolTable
482 + Header->NumberOfSymbols * sizeof(coff_symbol);
497 + COFFHeader->PointerToSymbolTable
498 + COFFHeader->NumberOfSymbols * sizeof(coff_symbol);
483499 if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t)))
484500 return;
485501
544560
545561 section_iterator COFFObjectFile::end_sections() const {
546562 DataRefImpl ret;
547 ret.p = reinterpret_cast(SectionTable + Header->NumberOfSections);
563 ret.p = reinterpret_cast(SectionTable + COFFHeader->NumberOfSections);
548564 return section_iterator(SectionRef(ret, this));
549565 }
550566
553569 }
554570
555571 StringRef COFFObjectFile::getFileFormatName() const {
556 switch(Header->Machine) {
572 switch(COFFHeader->Machine) {
557573 case COFF::IMAGE_FILE_MACHINE_I386:
558574 return "COFF-i386";
559575 case COFF::IMAGE_FILE_MACHINE_AMD64:
564580 }
565581
566582 unsigned COFFObjectFile::getArch() const {
567 switch(Header->Machine) {
583 switch(COFFHeader->Machine) {
568584 case COFF::IMAGE_FILE_MACHINE_I386:
569585 return Triple::x86;
570586 case COFF::IMAGE_FILE_MACHINE_AMD64:
574590 }
575591 }
576592
593 // This method is kept here because lld uses this. As soon as we make
594 // lld to use getCOFFHeader, this method will be removed.
577595 error_code COFFObjectFile::getHeader(const coff_file_header *&Res) const {
578 Res = Header;
596 return getCOFFHeader(Res);
597 }
598
599 error_code COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const {
600 Res = COFFHeader;
601 return object_error::success;
602 }
603
604 error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
605 Res = PE32Header;
579606 return object_error::success;
580607 }
581608
586613 index == COFF::IMAGE_SYM_ABSOLUTE ||
587614 index == COFF::IMAGE_SYM_DEBUG)
588615 Result = NULL;
589 else if (index > 0 && index <= Header->NumberOfSections)
616 else if (index > 0 && index <= COFFHeader->NumberOfSections)
590617 // We already verified the section table data, so no need to check again.
591618 Result = SectionTable + (index - 1);
592619 else
607634
608635 error_code COFFObjectFile::getSymbol(uint32_t index,
609636 const coff_symbol *&Result) const {
610 if (index < Header->NumberOfSymbols)
637 if (index < COFFHeader->NumberOfSymbols)
611638 Result = SymbolTable + index;
612639 else
613640 return object_error::parse_failed;
643670 # ifndef NDEBUG
644671 // Verify that the aux symbol points to a valid entry in the symbol table.
645672 uintptr_t offset = uintptr_t(aux) - uintptr_t(base());
646 if (offset < Header->PointerToSymbolTable
647 || offset >= Header->PointerToSymbolTable
648 + (Header->NumberOfSymbols * sizeof(coff_symbol)))
673 if (offset < COFFHeader->PointerToSymbolTable
674 || offset >= COFFHeader->PointerToSymbolTable
675 + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
649676 report_fatal_error("Aux Symbol data was outside of symbol table.");
650677
651 assert((offset - Header->PointerToSymbolTable) % sizeof(coff_symbol)
678 assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol)
652679 == 0 && "Aux Symbol data did not point to the beginning of a symbol");
653680 # endif
654681 }
745772 SmallVectorImpl &Result) const {
746773 const coff_relocation *reloc = toRel(Rel);
747774 StringRef res;
748 switch (Header->Machine) {
775 switch (COFFHeader->Machine) {
749776 case COFF::IMAGE_FILE_MACHINE_AMD64:
750777 switch (reloc->Type) {
751778 LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);
11 RUN: | FileCheck %s -check-prefix COFF32
22 RUN: llvm-readobj -h %p/Inputs/trivial.obj.coff-x86-64 \
33 RUN: | FileCheck %s -check-prefix COFF64
4 RUN: llvm-readobj -h %p/Inputs/trivial.exe.coff-i386 \
5 RUN: | FileCheck %s -check-prefix PE32
46 RUN: llvm-readobj -h %p/Inputs/trivial.obj.elf-i386 \
57 RUN: | FileCheck %s -check-prefix ELF32
68 RUN: llvm-readobj -h %p/Inputs/trivial.obj.elf-x86-64 \
9799 ELF64-NEXT: SectionHeaderCount: 10
98100 ELF64-NEXT: StringTableSectionIndex: 7
99101 ELF64-NEXT: }
102
103 PE32: File: {{(.*[/\\])?}}trivial.exe.coff-i386
104 PE32-NEXT: Format: COFF-i386
105 PE32-NEXT: Arch: i386
106 PE32-NEXT: AddressSize: 32bit
107 PE32-NEXT: ImageFileHeader {
108 PE32-NEXT: Machine: IMAGE_FILE_MACHINE_I386 (0x14C)
109 PE32-NEXT: SectionCount: 1
110 PE32-NEXT: TimeDateStamp: 2013-05-24 21:24:34 (0x519FDA92)
111 PE32-NEXT: PointerToSymbolTable: 0x0
112 PE32-NEXT: SymbolCount: 0
113 PE32-NEXT: OptionalHeaderSize: 224
114 PE32-NEXT: Characteristics [ (0x102)
115 PE32-NEXT: IMAGE_FILE_32BIT_MACHINE (0x100)
116 PE32-NEXT: IMAGE_FILE_EXECUTABLE_IMAGE (0x2)
117 PE32-NEXT: ]
118 PE32-NEXT: }
119 PE32-NEXT: ImageOptionalHeader {
120 PE32-NEXT: MajorLinkerVersion: 10
121 PE32-NEXT: MinorLinkerVersion: 0
122 PE32-NEXT: SizeOfCode: 512
123 PE32-NEXT: SizeOfInitializedData: 0
124 PE32-NEXT: SizeOfUninitializedData: 0
125 PE32-NEXT: AddressOfEntryPoint: 0x1000
126 PE32-NEXT: BaseOfCode: 0x1000
127 PE32-NEXT: BaseOfData: 0x2000
128 PE32-NEXT: ImageBase: 0x400000
129 PE32-NEXT: SectionAlignment: 4096
130 PE32-NEXT: FileAlignment: 512
131 PE32-NEXT: MajorOperatingSystemVersion: 5
132 PE32-NEXT: MinorOperatingSystemVersion: 1
133 PE32-NEXT: MajorImageVersion: 0
134 PE32-NEXT: MinorImageVersion: 0
135 PE32-NEXT: MajorSubsystemVersion: 5
136 PE32-NEXT: MinorSubsystemVersion: 1
137 PE32-NEXT: SizeOfImage: 8192
138 PE32-NEXT: SizeOfHeaders: 512
139 PE32-NEXT: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI (0x2)
140 PE32-NEXT: Subsystem [ (0x8140)
141 PE32-NEXT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE (0x40)
142 PE32-NEXT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT (0x100)
143 PE32-NEXT: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE (0x8000)
144 PE32-NEXT: ]
145 PE32-NEXT: SizeOfStackReserve: 1048576
146 PE32-NEXT: SizeOfStackCommit: 4096
147 PE32-NEXT: SizeOfHeapReserve: 1048576
148 PE32-NEXT: SizeOfHeapCommit: 4096
149 PE32-NEXT: NumberOfRvaAndSize: 16
150 PE32-NEXT: }
228228
229229 void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
230230 const coff_file_header *Header;
231 if (error(Obj->getHeader(Header))) return;
231 if (error(Obj->getCOFFHeader(Header))) return;
232232
233233 if (Header->Machine != COFF::IMAGE_FILE_MACHINE_AMD64) {
234234 errs() << "Unsupported image machine type "
259259 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_DLL ),
260260 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_UP_SYSTEM_ONLY ),
261261 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_BYTES_REVERSED_HI )
262 };
263
264 static const EnumEntry PEWindowsSubsystem[] = {
265 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_UNKNOWN ),
266 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_NATIVE ),
267 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_GUI ),
268 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CUI ),
269 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_POSIX_CUI ),
270 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI ),
271 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_APPLICATION ),
272 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER),
273 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER ),
274 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_ROM ),
275 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_XBOX ),
276 };
277
278 static const EnumEntry PEDLLCharacteristics[] = {
279 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE ),
280 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY ),
281 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT ),
282 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION ),
283 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_SEH ),
284 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_BIND ),
285 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER ),
286 LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE),
262287 };
263288
264289 static const EnumEntry
535560 }
536561
537562 void COFFDumper::printFileHeaders() {
538 const coff_file_header *Header = 0;
539 if (error(Obj->getHeader(Header)))
563 // Print COFF header
564 const coff_file_header *COFFHeader = 0;
565 if (error(Obj->getCOFFHeader(COFFHeader)))
540566 return;
541567
542 time_t TDS = Header->TimeDateStamp;
568 time_t TDS = COFFHeader->TimeDateStamp;
543569 char FormattedTime[20] = { };
544570 strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS));
545571
546572 {
547573 DictScope D(W, "ImageFileHeader");
548 W.printEnum ("Machine", Header->Machine,
574 W.printEnum ("Machine", COFFHeader->Machine,
549575 makeArrayRef(ImageFileMachineType));
550 W.printNumber("SectionCount", Header->NumberOfSections);
551 W.printHex ("TimeDateStamp", FormattedTime, Header->TimeDateStamp);
552 W.printHex ("PointerToSymbolTable", Header->PointerToSymbolTable);
553 W.printNumber("SymbolCount", Header->NumberOfSymbols);
554 W.printNumber("OptionalHeaderSize", Header->SizeOfOptionalHeader);
555 W.printFlags ("Characteristics", Header->Characteristics,
576 W.printNumber("SectionCount", COFFHeader->NumberOfSections);
577 W.printHex ("TimeDateStamp", FormattedTime, COFFHeader->TimeDateStamp);
578 W.printHex ("PointerToSymbolTable", COFFHeader->PointerToSymbolTable);
579 W.printNumber("SymbolCount", COFFHeader->NumberOfSymbols);
580 W.printNumber("OptionalHeaderSize", COFFHeader->SizeOfOptionalHeader);
581 W.printFlags ("Characteristics", COFFHeader->Characteristics,
556582 makeArrayRef(ImageFileCharacteristics));
583 }
584
585 // Print PE header. This header does not exist if this is an object file and
586 // not an executable.
587 const pe32_header *PEHeader = 0;
588 if (error(Obj->getPE32Header(PEHeader)))
589 return;
590
591 if (PEHeader) {
592 DictScope D(W, "ImageOptionalHeader");
593 W.printNumber("MajorLinkerVersion", PEHeader->MajorLinkerVersion);
594 W.printNumber("MinorLinkerVersion", PEHeader->MinorLinkerVersion);
595 W.printNumber("SizeOfCode", PEHeader->SizeOfCode);
596 W.printNumber("SizeOfInitializedData", PEHeader->SizeOfInitializedData);
597 W.printNumber("SizeOfUninitializedData", PEHeader->SizeOfUninitializedData);
598 W.printHex ("AddressOfEntryPoint", PEHeader->AddressOfEntryPoint);
599 W.printHex ("BaseOfCode", PEHeader->BaseOfCode);
600 W.printHex ("BaseOfData", PEHeader->BaseOfData);
601 W.printHex ("ImageBase", PEHeader->ImageBase);
602 W.printNumber("SectionAlignment", PEHeader->SectionAlignment);
603 W.printNumber("FileAlignment", PEHeader->FileAlignment);
604 W.printNumber("MajorOperatingSystemVersion",
605 PEHeader->MajorOperatingSystemVersion);
606 W.printNumber("MinorOperatingSystemVersion",
607 PEHeader->MinorOperatingSystemVersion);
608 W.printNumber("MajorImageVersion", PEHeader->MajorImageVersion);
609 W.printNumber("MinorImageVersion", PEHeader->MinorImageVersion);
610 W.printNumber("MajorSubsystemVersion", PEHeader->MajorSubsystemVersion);
611 W.printNumber("MinorSubsystemVersion", PEHeader->MinorSubsystemVersion);
612 W.printNumber("SizeOfImage", PEHeader->SizeOfImage);
613 W.printNumber("SizeOfHeaders", PEHeader->SizeOfHeaders);
614 W.printEnum ("Subsystem", PEHeader->Subsystem,
615 makeArrayRef(PEWindowsSubsystem));
616 W.printFlags ("Subsystem", PEHeader->DLLCharacteristics,
617 makeArrayRef(PEDLLCharacteristics));
618 W.printNumber("SizeOfStackReserve", PEHeader->SizeOfStackReserve);
619 W.printNumber("SizeOfStackCommit", PEHeader->SizeOfStackCommit);
620 W.printNumber("SizeOfHeapReserve", PEHeader->SizeOfHeapReserve);
621 W.printNumber("SizeOfHeapCommit", PEHeader->SizeOfHeapCommit);
622 W.printNumber("NumberOfRvaAndSize", PEHeader->NumberOfRvaAndSize);
557623 }
558624 }
559625
833899
834900 void COFFDumper::printUnwindInfo() {
835901 const coff_file_header *Header;
836 if (error(Obj->getHeader(Header)))
902 if (error(Obj->getCOFFHeader(Header)))
837903 return;
838904
839905 ListScope D(W, "UnwindInformation");
3737
3838 COFFDumper::COFFDumper(const object::COFFObjectFile &Obj) : Obj(Obj) {
3939 const object::coff_file_header *Header;
40 check(Obj.getHeader(Header));
40 check(Obj.getCOFFHeader(Header));
4141 dumpHeader(Header);
4242 dumpSections(Header->NumberOfSections);
4343 dumpSymbols(Header->NumberOfSymbols);