From 4787059b2fa0180c9601df718efcd7ea57c1cfcc Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 5 Nov 2014 06:24:35 +0000 Subject: [PATCH] llvm-readobj: Add support for dumping the DOS header in PE files git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@221333 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/COFF.h | 7 +++++- lib/Object/COFFObjectFile.cpp | 26 +++++++++++------------ lib/Support/Path.cpp | 7 +++--- test/tools/llvm-readobj/file-headers.test | 19 +++++++++++++++++ tools/llvm-readobj/COFFDumper.cpp | 25 ++++++++++++++++++++++ 5 files changed, 67 insertions(+), 17 deletions(-) diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index a647ea89684..d9c0cd3870d 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -36,7 +36,7 @@ typedef content_iterator imported_symbol_iterator; /// The DOS compatible header at the front of all PE/COFF executables. struct dos_header { - support::ulittle16_t Magic; + char Magic[2]; support::ulittle16_t UsedBytesInTheLastPage; support::ulittle16_t FileSizeInPages; support::ulittle16_t NumberOfRelocationItems; @@ -621,6 +621,11 @@ public: delay_import_directories() const; iterator_range export_directories() const; + const dos_header *getDOSHeader() const { + if (!PE32Header && !PE32PlusHeader) + return nullptr; + return reinterpret_cast(base()); + } std::error_code getPE32Header(const pe32_header *&Res) const; std::error_code getPE32PlusHeader(const pe32plus_header *&Res) const; std::error_code getDataDirectory(uint32_t index, diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index a8ae5f15c41..4fbb78254ea 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -572,20 +572,20 @@ COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) bool HasPEHeader = false; // Check if this is a PE/COFF file. - if (base()[0] == 0x4d && base()[1] == 0x5a) { + if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { // PE/COFF, seek through MS-DOS compatibility stub and 4-byte // PE signature to find 'normal' COFF header. - if (!checkSize(Data, EC, 0x3c + 8)) - return; - CurPtr = *reinterpret_cast(base() + 0x3c); - // Check the PE magic bytes. ("PE\0\0") - if (std::memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != - 0) { - EC = object_error::parse_failed; - return; + const auto *DH = reinterpret_cast(base()); + if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { + CurPtr = DH->AddressOfNewExeHeader; + // Check the PE magic bytes. ("PE\0\0") + if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { + EC = object_error::parse_failed; + return; + } + CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. + HasPEHeader = true; } - CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. - HasPEHeader = true; } if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) @@ -627,11 +627,11 @@ COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) const uint8_t *DataDirAddr; uint64_t DataDirSize; - if (Header->Magic == 0x10b) { + if (Header->Magic == COFF::PE32Header::PE32) { PE32Header = Header; DataDirAddr = base() + CurPtr + sizeof(pe32_header); DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; - } else if (Header->Magic == 0x20b) { + } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { PE32PlusHeader = reinterpret_cast(Header); DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp index 7e02f5fecc3..9937978c748 100644 --- a/lib/Support/Path.cpp +++ b/lib/Support/Path.cpp @@ -1020,12 +1020,13 @@ file_magic identify_magic(StringRef Magic) { return file_magic::coff_object; break; - case 0x4d: // Possible MS-DOS stub on Windows PE file - if (Magic[1] == 0x5a) { + case 'M': // Possible MS-DOS stub on Windows PE file + if (Magic[1] == 'Z') { uint32_t off = *reinterpret_cast(Magic.data() + 0x3c); // PE/COFF file, either EXE or DLL. - if (off < Magic.size() && memcmp(Magic.data() + off, "PE\0\0",4) == 0) + if (off < Magic.size() && + memcmp(Magic.data()+off, COFF::PEMagic, sizeof(COFF::PEMagic)) == 0) return file_magic::pecoff_executable; } break; diff --git a/test/tools/llvm-readobj/file-headers.test b/test/tools/llvm-readobj/file-headers.test index 39a8c0ef899..8760be78647 100644 --- a/test/tools/llvm-readobj/file-headers.test +++ b/test/tools/llvm-readobj/file-headers.test @@ -204,6 +204,25 @@ PE32-NEXT: ReservedRVA: 0x0 PE32-NEXT: ReservedSize: 0x0 PE32-NEXT: } PE32-NEXT: } +PE32-NEXT: DOSHeader { +PE32-NEXT: Magic: MZ +PE32-NEXT: UsedBytesInTheLastPage: 144 +PE32-NEXT: FileSizeInPages: 3 +PE32-NEXT: NumberOfRelocationItems: 0 +PE32-NEXT: HeaderSizeInParagraphs: 4 +PE32-NEXT: MinimumExtraParagraphs: 0 +PE32-NEXT: MaximumExtraParagraphs: 65535 +PE32-NEXT: InitialRelativeSS: 0 +PE32-NEXT: InitialSP: 184 +PE32-NEXT: Checksum: 0 +PE32-NEXT: InitialIP: 0 +PE32-NEXT: InitialRelativeCS: 0 +PE32-NEXT: AddressOfRelocationTable: 64 +PE32-NEXT: OverlayNumber: 0 +PE32-NEXT: OEMid: 0 +PE32-NEXT: OEMinfo: 0 +PE32-NEXT: AddressOfNewExeHeader: 176 +PE32-NEXT: } COFF-UNKNOWN: Format: COFF- COFF-UNKNOWN-NEXT: Arch: unknown diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index b4cfa3a8944..1fd38849f32 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -63,6 +63,7 @@ private: void printRelocation(const SectionRef &Section, const RelocationRef &Reloc); void printDataDirectory(uint32_t Index, const std::string &FieldName); + void printDOSHeader(const dos_header *DH); template void printPEHeader(const PEHeader *Hdr); void printBaseOfDataField(const pe32_header *Hdr); void printBaseOfDataField(const pe32plus_header *Hdr); @@ -382,6 +383,30 @@ void COFFDumper::printFileHeaders() { return; if (PEPlusHeader) printPEHeader(PEPlusHeader); + + if (const dos_header *DH = Obj->getDOSHeader()) + printDOSHeader(DH); +} + +void COFFDumper::printDOSHeader(const dos_header *DH) { + DictScope D(W, "DOSHeader"); + W.printString("Magic", StringRef(DH->Magic, sizeof(DH->Magic))); + W.printNumber("UsedBytesInTheLastPage", DH->UsedBytesInTheLastPage); + W.printNumber("FileSizeInPages", DH->FileSizeInPages); + W.printNumber("NumberOfRelocationItems", DH->NumberOfRelocationItems); + W.printNumber("HeaderSizeInParagraphs", DH->HeaderSizeInParagraphs); + W.printNumber("MinimumExtraParagraphs", DH->MinimumExtraParagraphs); + W.printNumber("MaximumExtraParagraphs", DH->MaximumExtraParagraphs); + W.printNumber("InitialRelativeSS", DH->InitialRelativeSS); + W.printNumber("InitialSP", DH->InitialSP); + W.printNumber("Checksum", DH->Checksum); + W.printNumber("InitialIP", DH->InitialIP); + W.printNumber("InitialRelativeCS", DH->InitialRelativeCS); + W.printNumber("AddressOfRelocationTable", DH->AddressOfRelocationTable); + W.printNumber("OverlayNumber", DH->OverlayNumber); + W.printNumber("OEMid", DH->OEMid); + W.printNumber("OEMinfo", DH->OEMinfo); + W.printNumber("AddressOfNewExeHeader", DH->AddressOfNewExeHeader); } template -- 2.34.1