llvm.org GIT mirror llvm / 1e839eb
llvm-readobj: add support for PE32+ (Windows 64 bit executable). PE32+ supports 64 bit address space, but the file format remains 32 bit. So its file format is pretty similar to PE32 (32 bit executable). The differences compared to PE32 are (1) the lack of "BaseOfData" field and (2) some of its data members are 64 bit. In this patch, I added a new member function to get a PE32+ Header object to COFFObjectFile class and made llvm-readobj to use it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@200117 91177308-0d34-0410-b5e6-96231b3b80d8 Rui Ueyama 6 years ago
5 changed file(s) with 184 addition(s) and 66 deletion(s). Raw diff Collapse all Expand all
249249 friend class ExportDirectoryEntryRef;
250250 const coff_file_header *COFFHeader;
251251 const pe32_header *PE32Header;
252 const pe32plus_header *PE32PlusHeader;
252253 const data_directory *DataDirectory;
253254 const coff_section *SectionTable;
254255 const coff_symbol *SymbolTable;
346347 error_code getHeader(const coff_file_header *&Res) const;
347348 error_code getCOFFHeader(const coff_file_header *&Res) const;
348349 error_code getPE32Header(const pe32_header *&Res) const;
350 error_code getPE32PlusHeader(const pe32plus_header *&Res) const;
349351 error_code getDataDirectory(uint32_t index, const data_directory *&Res) const;
350352 error_code getSection(int32_t index, const coff_section *&Res) const;
351353 error_code getSymbol(uint32_t index, const coff_symbol *&Res) const;
465465 COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC,
466466 bool BufferOwned)
467467 : ObjectFile(Binary::ID_COFF, Object, BufferOwned), COFFHeader(0),
468 PE32Header(0), DataDirectory(0), SectionTable(0), SymbolTable(0),
469 StringTable(0), StringTableSize(0), ImportDirectory(0),
468 PE32Header(0), PE32PlusHeader(0), DataDirectory(0), SectionTable(0),
469 SymbolTable(0), StringTable(0), StringTableSize(0), ImportDirectory(0),
470470 NumberOfImportDirectory(0), ExportDirectory(0) {
471471 // Check that we at least have enough room for a header.
472472 if (!checkSize(Data, EC, sizeof(coff_file_header))) return;
498498 CurPtr += sizeof(coff_file_header);
499499
500500 if (HasPEHeader) {
501 if ((EC = getObject(PE32Header, Data, base() + CurPtr)))
501 const pe32_header *Header;
502 if ((EC = getObject(Header, Data, base() + CurPtr)))
502503 return;
503 if (PE32Header->Magic != 0x10b) {
504 // We only support PE32. If this is PE32 (not PE32+), the magic byte
505 // should be 0x10b. If this is not PE32, continue as if there's no PE
506 // header in this file.
507 PE32Header = 0;
508 } else if (PE32Header->NumberOfRvaAndSize > 0) {
509 const uint8_t *Addr = base() + CurPtr + sizeof(pe32_header);
510 uint64_t size = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
511 if ((EC = getObject(DataDirectory, Data, Addr, size)))
512 return;
504
505 const uint8_t *DataDirAddr;
506 uint64_t DataDirSize;
507 if (Header->Magic == 0x10b) {
508 PE32Header = Header;
509 DataDirAddr = base() + CurPtr + sizeof(pe32_header);
510 DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
511 } else if (Header->Magic == 0x20b) {
512 PE32PlusHeader = reinterpret_cast(Header);
513 DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
514 DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
515 } else {
516 // It's neither PE32 nor PE32+.
517 EC = object_error::parse_failed;
518 return;
513519 }
520 if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
521 return;
514522 CurPtr += COFFHeader->SizeOfOptionalHeader;
515523 }
516524
654662 return object_error::success;
655663 }
656664
665 error_code
666 COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
667 Res = PE32PlusHeader;
668 return object_error::success;
669 }
670
657671 error_code COFFObjectFile::getDataDirectory(uint32_t Index,
658672 const data_directory *&Res) const {
659673 // Error if if there's no data directory or the index is out of range.
660 if (!DataDirectory || Index > PE32Header->NumberOfRvaAndSize)
674 if (!DataDirectory)
675 return object_error::parse_failed;
676 assert(PE32Header || PE32PlusHeader);
677 uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
678 : PE32PlusHeader->NumberOfRvaAndSize;
679 if (Index > NumEnt)
661680 return object_error::parse_failed;
662681 Res = &DataDirectory[Index];
663682 return object_error::success;
0 RUN: llvm-readobj -file-headers %p/Inputs/nop.exe.coff-x86-64 | FileCheck %s
1
2 CHECK: Format: COFF-x86-64
3 CHECK: Arch: x86_64
4 CHECK: AddressSize: 64bit
5 CHECK: ImageFileHeader {
6 CHECK: Machine: IMAGE_FILE_MACHINE_AMD64 (0x8664)
7 CHECK: SectionCount: 1
8 CHECK: TimeDateStamp: 2014-01-26 03:43:56 (0x52E4847C)
9 CHECK: PointerToSymbolTable: 0x0
10 CHECK: SymbolCount: 0
11 CHECK: OptionalHeaderSize: 240
12 CHECK: Characteristics [ (0x22)
13 CHECK: IMAGE_FILE_EXECUTABLE_IMAGE (0x2)
14 CHECK: IMAGE_FILE_LARGE_ADDRESS_AWARE (0x20)
15 CHECK: ]
16 CHECK: }
17 CHECK: ImageOptionalHeader {
18 CHECK: MajorLinkerVersion: 11
19 CHECK: MinorLinkerVersion: 0
20 CHECK: SizeOfCode: 512
21 CHECK: SizeOfInitializedData: 0
22 CHECK: SizeOfUninitializedData: 0
23 CHECK: AddressOfEntryPoint: 0x1000
24 CHECK: BaseOfCode: 0x1000
25 CHECK: ImageBase: 0x140000000
26 CHECK: SectionAlignment: 4096
27 CHECK: FileAlignment: 512
28 CHECK: MajorOperatingSystemVersion: 6
29 CHECK: MinorOperatingSystemVersion: 0
30 CHECK: MajorImageVersion: 0
31 CHECK: MinorImageVersion: 0
32 CHECK: MajorSubsystemVersion: 6
33 CHECK: MinorSubsystemVersion: 0
34 CHECK: SizeOfImage: 8192
35 CHECK: SizeOfHeaders: 512
36 CHECK: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3)
37 CHECK: Subsystem [ (0x8160)
38 CHECK: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE (0x40)
39 CHECK: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT (0x100)
40 CHECK: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE (0x8000)
41 CHECK: ]
42 CHECK: SizeOfStackReserve: 1048576
43 CHECK: SizeOfStackCommit: 4096
44 CHECK: SizeOfHeapReserve: 1048576
45 CHECK: SizeOfHeapCommit: 4096
46 CHECK: NumberOfRvaAndSize: 16
47 CHECK: DataDirectory {
48 CHECK: ExportTableRVA: 0x0
49 CHECK: ExportTableSize: 0x0
50 CHECK: ImportTableRVA: 0x0
51 CHECK: ImportTableSize: 0x0
52 CHECK: ResourceTableRVA: 0x0
53 CHECK: ResourceTableSize: 0x0
54 CHECK: ExceptionTableRVA: 0x0
55 CHECK: ExceptionTableSize: 0x0
56 CHECK: CertificateTableRVA: 0x0
57 CHECK: CertificateTableSize: 0x0
58 CHECK: BaseRelocationTableRVA: 0x0
59 CHECK: BaseRelocationTableSize: 0x0
60 CHECK: DebugRVA: 0x0
61 CHECK: DebugSize: 0x0
62 CHECK: ArchitectureRVA: 0x0
63 CHECK: ArchitectureSize: 0x0
64 CHECK: GlobalPtrRVA: 0x0
65 CHECK: GlobalPtrSize: 0x0
66 CHECK: TLSTableRVA: 0x0
67 CHECK: TLSTableSize: 0x0
68 CHECK: LoadConfigTableRVA: 0x0
69 CHECK: LoadConfigTableSize: 0x0
70 CHECK: BoundImportRVA: 0x0
71 CHECK: BoundImportSize: 0x0
72 CHECK: IATRVA: 0x0
73 CHECK: IATSize: 0x0
74 CHECK: DelayImportDescriptorRVA: 0x0
75 CHECK: DelayImportDescriptorSize: 0x0
76 CHECK: CLRRuntimeHeaderRVA: 0x0
77 CHECK: CLRRuntimeHeaderSize: 0x0
78 CHECK: ReservedRVA: 0x0
79 CHECK: ReservedSize: 0x0
80 CHECK: }
81 CHECK: }
5555
5656 private:
5757 void printSymbol(symbol_iterator SymI);
58
5958 void printRelocation(section_iterator SecI, relocation_iterator RelI);
60
6159 void printDataDirectory(uint32_t Index, const std::string &FieldName);
62
6360 void printX64UnwindInfo();
61
62 template void printPEHeader(const PEHeader *Hdr);
63 void printBaseOfDataField(const pe32_header *Hdr);
64 void printBaseOfDataField(const pe32plus_header *Hdr);
6465
6566 void printRuntimeFunction(
6667 const RuntimeFunction& RTF,
598599 const pe32_header *PEHeader = 0;
599600 if (error(Obj->getPE32Header(PEHeader)))
600601 return;
601
602 if (PEHeader) {
603 DictScope D(W, "ImageOptionalHeader");
604 W.printNumber("MajorLinkerVersion", PEHeader->MajorLinkerVersion);
605 W.printNumber("MinorLinkerVersion", PEHeader->MinorLinkerVersion);
606 W.printNumber("SizeOfCode", PEHeader->SizeOfCode);
607 W.printNumber("SizeOfInitializedData", PEHeader->SizeOfInitializedData);
608 W.printNumber("SizeOfUninitializedData", PEHeader->SizeOfUninitializedData);
609 W.printHex ("AddressOfEntryPoint", PEHeader->AddressOfEntryPoint);
610 W.printHex ("BaseOfCode", PEHeader->BaseOfCode);
611 W.printHex ("BaseOfData", PEHeader->BaseOfData);
612 W.printHex ("ImageBase", PEHeader->ImageBase);
613 W.printNumber("SectionAlignment", PEHeader->SectionAlignment);
614 W.printNumber("FileAlignment", PEHeader->FileAlignment);
615 W.printNumber("MajorOperatingSystemVersion",
616 PEHeader->MajorOperatingSystemVersion);
617 W.printNumber("MinorOperatingSystemVersion",
618 PEHeader->MinorOperatingSystemVersion);
619 W.printNumber("MajorImageVersion", PEHeader->MajorImageVersion);
620 W.printNumber("MinorImageVersion", PEHeader->MinorImageVersion);
621 W.printNumber("MajorSubsystemVersion", PEHeader->MajorSubsystemVersion);
622 W.printNumber("MinorSubsystemVersion", PEHeader->MinorSubsystemVersion);
623 W.printNumber("SizeOfImage", PEHeader->SizeOfImage);
624 W.printNumber("SizeOfHeaders", PEHeader->SizeOfHeaders);
625 W.printEnum ("Subsystem", PEHeader->Subsystem,
626 makeArrayRef(PEWindowsSubsystem));
627 W.printFlags ("Subsystem", PEHeader->DLLCharacteristics,
628 makeArrayRef(PEDLLCharacteristics));
629 W.printNumber("SizeOfStackReserve", PEHeader->SizeOfStackReserve);
630 W.printNumber("SizeOfStackCommit", PEHeader->SizeOfStackCommit);
631 W.printNumber("SizeOfHeapReserve", PEHeader->SizeOfHeapReserve);
632 W.printNumber("SizeOfHeapCommit", PEHeader->SizeOfHeapCommit);
633 W.printNumber("NumberOfRvaAndSize", PEHeader->NumberOfRvaAndSize);
634
635 if (PEHeader->NumberOfRvaAndSize > 0) {
636 DictScope D(W, "DataDirectory");
637 static const char * const directory[] = {
638 "ExportTable", "ImportTable", "ResourceTable", "ExceptionTable",
639 "CertificateTable", "BaseRelocationTable", "Debug", "Architecture",
640 "GlobalPtr", "TLSTable", "LoadConfigTable", "BoundImport", "IAT",
641 "DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"
642 };
643
644 for (uint32_t i = 0; i < PEHeader->NumberOfRvaAndSize; ++i) {
645 printDataDirectory(i, directory[i]);
646 }
647 }
648 }
649 }
602 if (PEHeader)
603 printPEHeader(PEHeader);
604
605 const pe32plus_header *PEPlusHeader = 0;
606 if (error(Obj->getPE32PlusHeader(PEPlusHeader)))
607 return;
608 if (PEPlusHeader)
609 printPEHeader(PEPlusHeader);
610 }
611
612 template
613 void COFFDumper::printPEHeader(const PEHeader *Hdr) {
614 DictScope D(W, "ImageOptionalHeader");
615 W.printNumber("MajorLinkerVersion", Hdr->MajorLinkerVersion);
616 W.printNumber("MinorLinkerVersion", Hdr->MinorLinkerVersion);
617 W.printNumber("SizeOfCode", Hdr->SizeOfCode);
618 W.printNumber("SizeOfInitializedData", Hdr->SizeOfInitializedData);
619 W.printNumber("SizeOfUninitializedData", Hdr->SizeOfUninitializedData);
620 W.printHex ("AddressOfEntryPoint", Hdr->AddressOfEntryPoint);
621 W.printHex ("BaseOfCode", Hdr->BaseOfCode);
622 printBaseOfDataField(Hdr);
623 W.printHex ("ImageBase", Hdr->ImageBase);
624 W.printNumber("SectionAlignment", Hdr->SectionAlignment);
625 W.printNumber("FileAlignment", Hdr->FileAlignment);
626 W.printNumber("MajorOperatingSystemVersion",
627 Hdr->MajorOperatingSystemVersion);
628 W.printNumber("MinorOperatingSystemVersion",
629 Hdr->MinorOperatingSystemVersion);
630 W.printNumber("MajorImageVersion", Hdr->MajorImageVersion);
631 W.printNumber("MinorImageVersion", Hdr->MinorImageVersion);
632 W.printNumber("MajorSubsystemVersion", Hdr->MajorSubsystemVersion);
633 W.printNumber("MinorSubsystemVersion", Hdr->MinorSubsystemVersion);
634 W.printNumber("SizeOfImage", Hdr->SizeOfImage);
635 W.printNumber("SizeOfHeaders", Hdr->SizeOfHeaders);
636 W.printEnum ("Subsystem", Hdr->Subsystem, makeArrayRef(PEWindowsSubsystem));
637 W.printFlags ("Subsystem", Hdr->DLLCharacteristics,
638 makeArrayRef(PEDLLCharacteristics));
639 W.printNumber("SizeOfStackReserve", Hdr->SizeOfStackReserve);
640 W.printNumber("SizeOfStackCommit", Hdr->SizeOfStackCommit);
641 W.printNumber("SizeOfHeapReserve", Hdr->SizeOfHeapReserve);
642 W.printNumber("SizeOfHeapCommit", Hdr->SizeOfHeapCommit);
643 W.printNumber("NumberOfRvaAndSize", Hdr->NumberOfRvaAndSize);
644
645 if (Hdr->NumberOfRvaAndSize > 0) {
646 DictScope D(W, "DataDirectory");
647 static const char * const directory[] = {
648 "ExportTable", "ImportTable", "ResourceTable", "ExceptionTable",
649 "CertificateTable", "BaseRelocationTable", "Debug", "Architecture",
650 "GlobalPtr", "TLSTable", "LoadConfigTable", "BoundImport", "IAT",
651 "DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"
652 };
653
654 for (uint32_t i = 0; i < Hdr->NumberOfRvaAndSize; ++i) {
655 printDataDirectory(i, directory[i]);
656 }
657 }
658 }
659
660 void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) {
661 W.printHex("BaseOfData", Hdr->BaseOfData);
662 }
663
664 void COFFDumper::printBaseOfDataField(const pe32plus_header *) {}
650665
651666 void COFFDumper::printCodeViewLineTables(section_iterator SecI) {
652667 StringRef Data;