mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-26 07:29:55 +00:00
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
This commit is contained in:
parent
07f1de473f
commit
1e839eb2cd
@ -250,6 +250,7 @@ private:
|
|||||||
friend class ExportDirectoryEntryRef;
|
friend class ExportDirectoryEntryRef;
|
||||||
const coff_file_header *COFFHeader;
|
const coff_file_header *COFFHeader;
|
||||||
const pe32_header *PE32Header;
|
const pe32_header *PE32Header;
|
||||||
|
const pe32plus_header *PE32PlusHeader;
|
||||||
const data_directory *DataDirectory;
|
const data_directory *DataDirectory;
|
||||||
const coff_section *SectionTable;
|
const coff_section *SectionTable;
|
||||||
const coff_symbol *SymbolTable;
|
const coff_symbol *SymbolTable;
|
||||||
@ -347,6 +348,7 @@ public:
|
|||||||
error_code getHeader(const coff_file_header *&Res) const;
|
error_code getHeader(const coff_file_header *&Res) const;
|
||||||
error_code getCOFFHeader(const coff_file_header *&Res) const;
|
error_code getCOFFHeader(const coff_file_header *&Res) const;
|
||||||
error_code getPE32Header(const pe32_header *&Res) const;
|
error_code getPE32Header(const pe32_header *&Res) const;
|
||||||
|
error_code getPE32PlusHeader(const pe32plus_header *&Res) const;
|
||||||
error_code getDataDirectory(uint32_t index, const data_directory *&Res) const;
|
error_code getDataDirectory(uint32_t index, const data_directory *&Res) const;
|
||||||
error_code getSection(int32_t index, const coff_section *&Res) const;
|
error_code getSection(int32_t index, const coff_section *&Res) const;
|
||||||
error_code getSymbol(uint32_t index, const coff_symbol *&Res) const;
|
error_code getSymbol(uint32_t index, const coff_symbol *&Res) const;
|
||||||
|
@ -466,8 +466,8 @@ error_code COFFObjectFile::initExportTablePtr() {
|
|||||||
COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC,
|
COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC,
|
||||||
bool BufferOwned)
|
bool BufferOwned)
|
||||||
: ObjectFile(Binary::ID_COFF, Object, BufferOwned), COFFHeader(0),
|
: ObjectFile(Binary::ID_COFF, Object, BufferOwned), COFFHeader(0),
|
||||||
PE32Header(0), DataDirectory(0), SectionTable(0), SymbolTable(0),
|
PE32Header(0), PE32PlusHeader(0), DataDirectory(0), SectionTable(0),
|
||||||
StringTable(0), StringTableSize(0), ImportDirectory(0),
|
SymbolTable(0), StringTable(0), StringTableSize(0), ImportDirectory(0),
|
||||||
NumberOfImportDirectory(0), ExportDirectory(0) {
|
NumberOfImportDirectory(0), ExportDirectory(0) {
|
||||||
// Check that we at least have enough room for a header.
|
// Check that we at least have enough room for a header.
|
||||||
if (!checkSize(Data, EC, sizeof(coff_file_header))) return;
|
if (!checkSize(Data, EC, sizeof(coff_file_header))) return;
|
||||||
@ -499,19 +499,27 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC,
|
|||||||
CurPtr += sizeof(coff_file_header);
|
CurPtr += sizeof(coff_file_header);
|
||||||
|
|
||||||
if (HasPEHeader) {
|
if (HasPEHeader) {
|
||||||
if ((EC = getObject(PE32Header, Data, base() + CurPtr)))
|
const pe32_header *Header;
|
||||||
|
if ((EC = getObject(Header, Data, base() + CurPtr)))
|
||||||
return;
|
return;
|
||||||
if (PE32Header->Magic != 0x10b) {
|
|
||||||
// We only support PE32. If this is PE32 (not PE32+), the magic byte
|
const uint8_t *DataDirAddr;
|
||||||
// should be 0x10b. If this is not PE32, continue as if there's no PE
|
uint64_t DataDirSize;
|
||||||
// header in this file.
|
if (Header->Magic == 0x10b) {
|
||||||
PE32Header = 0;
|
PE32Header = Header;
|
||||||
} else if (PE32Header->NumberOfRvaAndSize > 0) {
|
DataDirAddr = base() + CurPtr + sizeof(pe32_header);
|
||||||
const uint8_t *Addr = base() + CurPtr + sizeof(pe32_header);
|
DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
|
||||||
uint64_t size = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
|
} else if (Header->Magic == 0x20b) {
|
||||||
if ((EC = getObject(DataDirectory, Data, Addr, size)))
|
PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header);
|
||||||
|
DataDirAddr = base() + CurPtr + sizeof(pe32plus_header);
|
||||||
|
DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize;
|
||||||
|
} else {
|
||||||
|
// It's neither PE32 nor PE32+.
|
||||||
|
EC = object_error::parse_failed;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize)))
|
||||||
|
return;
|
||||||
CurPtr += COFFHeader->SizeOfOptionalHeader;
|
CurPtr += COFFHeader->SizeOfOptionalHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -655,10 +663,21 @@ error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
|
|||||||
return object_error::success;
|
return object_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error_code
|
||||||
|
COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const {
|
||||||
|
Res = PE32PlusHeader;
|
||||||
|
return object_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
error_code COFFObjectFile::getDataDirectory(uint32_t Index,
|
error_code COFFObjectFile::getDataDirectory(uint32_t Index,
|
||||||
const data_directory *&Res) const {
|
const data_directory *&Res) const {
|
||||||
// Error if if there's no data directory or the index is out of range.
|
// Error if if there's no data directory or the index is out of range.
|
||||||
if (!DataDirectory || Index > PE32Header->NumberOfRvaAndSize)
|
if (!DataDirectory)
|
||||||
|
return object_error::parse_failed;
|
||||||
|
assert(PE32Header || PE32PlusHeader);
|
||||||
|
uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize
|
||||||
|
: PE32PlusHeader->NumberOfRvaAndSize;
|
||||||
|
if (Index > NumEnt)
|
||||||
return object_error::parse_failed;
|
return object_error::parse_failed;
|
||||||
Res = &DataDirectory[Index];
|
Res = &DataDirectory[Index];
|
||||||
return object_error::success;
|
return object_error::success;
|
||||||
|
BIN
test/tools/llvm-readobj/Inputs/nop.exe.coff-x86-64
Normal file
BIN
test/tools/llvm-readobj/Inputs/nop.exe.coff-x86-64
Normal file
Binary file not shown.
82
test/tools/llvm-readobj/peplus.test
Normal file
82
test/tools/llvm-readobj/peplus.test
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
RUN: llvm-readobj -file-headers %p/Inputs/nop.exe.coff-x86-64 | FileCheck %s
|
||||||
|
|
||||||
|
CHECK: Format: COFF-x86-64
|
||||||
|
CHECK: Arch: x86_64
|
||||||
|
CHECK: AddressSize: 64bit
|
||||||
|
CHECK: ImageFileHeader {
|
||||||
|
CHECK: Machine: IMAGE_FILE_MACHINE_AMD64 (0x8664)
|
||||||
|
CHECK: SectionCount: 1
|
||||||
|
CHECK: TimeDateStamp: 2014-01-26 03:43:56 (0x52E4847C)
|
||||||
|
CHECK: PointerToSymbolTable: 0x0
|
||||||
|
CHECK: SymbolCount: 0
|
||||||
|
CHECK: OptionalHeaderSize: 240
|
||||||
|
CHECK: Characteristics [ (0x22)
|
||||||
|
CHECK: IMAGE_FILE_EXECUTABLE_IMAGE (0x2)
|
||||||
|
CHECK: IMAGE_FILE_LARGE_ADDRESS_AWARE (0x20)
|
||||||
|
CHECK: ]
|
||||||
|
CHECK: }
|
||||||
|
CHECK: ImageOptionalHeader {
|
||||||
|
CHECK: MajorLinkerVersion: 11
|
||||||
|
CHECK: MinorLinkerVersion: 0
|
||||||
|
CHECK: SizeOfCode: 512
|
||||||
|
CHECK: SizeOfInitializedData: 0
|
||||||
|
CHECK: SizeOfUninitializedData: 0
|
||||||
|
CHECK: AddressOfEntryPoint: 0x1000
|
||||||
|
CHECK: BaseOfCode: 0x1000
|
||||||
|
CHECK: ImageBase: 0x140000000
|
||||||
|
CHECK: SectionAlignment: 4096
|
||||||
|
CHECK: FileAlignment: 512
|
||||||
|
CHECK: MajorOperatingSystemVersion: 6
|
||||||
|
CHECK: MinorOperatingSystemVersion: 0
|
||||||
|
CHECK: MajorImageVersion: 0
|
||||||
|
CHECK: MinorImageVersion: 0
|
||||||
|
CHECK: MajorSubsystemVersion: 6
|
||||||
|
CHECK: MinorSubsystemVersion: 0
|
||||||
|
CHECK: SizeOfImage: 8192
|
||||||
|
CHECK: SizeOfHeaders: 512
|
||||||
|
CHECK: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3)
|
||||||
|
CHECK: Subsystem [ (0x8160)
|
||||||
|
CHECK: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE (0x40)
|
||||||
|
CHECK: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT (0x100)
|
||||||
|
CHECK: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE (0x8000)
|
||||||
|
CHECK: ]
|
||||||
|
CHECK: SizeOfStackReserve: 1048576
|
||||||
|
CHECK: SizeOfStackCommit: 4096
|
||||||
|
CHECK: SizeOfHeapReserve: 1048576
|
||||||
|
CHECK: SizeOfHeapCommit: 4096
|
||||||
|
CHECK: NumberOfRvaAndSize: 16
|
||||||
|
CHECK: DataDirectory {
|
||||||
|
CHECK: ExportTableRVA: 0x0
|
||||||
|
CHECK: ExportTableSize: 0x0
|
||||||
|
CHECK: ImportTableRVA: 0x0
|
||||||
|
CHECK: ImportTableSize: 0x0
|
||||||
|
CHECK: ResourceTableRVA: 0x0
|
||||||
|
CHECK: ResourceTableSize: 0x0
|
||||||
|
CHECK: ExceptionTableRVA: 0x0
|
||||||
|
CHECK: ExceptionTableSize: 0x0
|
||||||
|
CHECK: CertificateTableRVA: 0x0
|
||||||
|
CHECK: CertificateTableSize: 0x0
|
||||||
|
CHECK: BaseRelocationTableRVA: 0x0
|
||||||
|
CHECK: BaseRelocationTableSize: 0x0
|
||||||
|
CHECK: DebugRVA: 0x0
|
||||||
|
CHECK: DebugSize: 0x0
|
||||||
|
CHECK: ArchitectureRVA: 0x0
|
||||||
|
CHECK: ArchitectureSize: 0x0
|
||||||
|
CHECK: GlobalPtrRVA: 0x0
|
||||||
|
CHECK: GlobalPtrSize: 0x0
|
||||||
|
CHECK: TLSTableRVA: 0x0
|
||||||
|
CHECK: TLSTableSize: 0x0
|
||||||
|
CHECK: LoadConfigTableRVA: 0x0
|
||||||
|
CHECK: LoadConfigTableSize: 0x0
|
||||||
|
CHECK: BoundImportRVA: 0x0
|
||||||
|
CHECK: BoundImportSize: 0x0
|
||||||
|
CHECK: IATRVA: 0x0
|
||||||
|
CHECK: IATSize: 0x0
|
||||||
|
CHECK: DelayImportDescriptorRVA: 0x0
|
||||||
|
CHECK: DelayImportDescriptorSize: 0x0
|
||||||
|
CHECK: CLRRuntimeHeaderRVA: 0x0
|
||||||
|
CHECK: CLRRuntimeHeaderSize: 0x0
|
||||||
|
CHECK: ReservedRVA: 0x0
|
||||||
|
CHECK: ReservedSize: 0x0
|
||||||
|
CHECK: }
|
||||||
|
CHECK: }
|
@ -56,13 +56,14 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void printSymbol(symbol_iterator SymI);
|
void printSymbol(symbol_iterator SymI);
|
||||||
|
|
||||||
void printRelocation(section_iterator SecI, relocation_iterator RelI);
|
void printRelocation(section_iterator SecI, relocation_iterator RelI);
|
||||||
|
|
||||||
void printDataDirectory(uint32_t Index, const std::string &FieldName);
|
void printDataDirectory(uint32_t Index, const std::string &FieldName);
|
||||||
|
|
||||||
void printX64UnwindInfo();
|
void printX64UnwindInfo();
|
||||||
|
|
||||||
|
template <class PEHeader> void printPEHeader(const PEHeader *Hdr);
|
||||||
|
void printBaseOfDataField(const pe32_header *Hdr);
|
||||||
|
void printBaseOfDataField(const pe32plus_header *Hdr);
|
||||||
|
|
||||||
void printRuntimeFunction(
|
void printRuntimeFunction(
|
||||||
const RuntimeFunction& RTF,
|
const RuntimeFunction& RTF,
|
||||||
uint64_t OffsetInSection,
|
uint64_t OffsetInSection,
|
||||||
@ -599,41 +600,50 @@ void COFFDumper::printFileHeaders() {
|
|||||||
const pe32_header *PEHeader = 0;
|
const pe32_header *PEHeader = 0;
|
||||||
if (error(Obj->getPE32Header(PEHeader)))
|
if (error(Obj->getPE32Header(PEHeader)))
|
||||||
return;
|
return;
|
||||||
|
if (PEHeader)
|
||||||
|
printPEHeader<pe32_header>(PEHeader);
|
||||||
|
|
||||||
if (PEHeader) {
|
const pe32plus_header *PEPlusHeader = 0;
|
||||||
|
if (error(Obj->getPE32PlusHeader(PEPlusHeader)))
|
||||||
|
return;
|
||||||
|
if (PEPlusHeader)
|
||||||
|
printPEHeader<pe32plus_header>(PEPlusHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class PEHeader>
|
||||||
|
void COFFDumper::printPEHeader(const PEHeader *Hdr) {
|
||||||
DictScope D(W, "ImageOptionalHeader");
|
DictScope D(W, "ImageOptionalHeader");
|
||||||
W.printNumber("MajorLinkerVersion", PEHeader->MajorLinkerVersion);
|
W.printNumber("MajorLinkerVersion", Hdr->MajorLinkerVersion);
|
||||||
W.printNumber("MinorLinkerVersion", PEHeader->MinorLinkerVersion);
|
W.printNumber("MinorLinkerVersion", Hdr->MinorLinkerVersion);
|
||||||
W.printNumber("SizeOfCode", PEHeader->SizeOfCode);
|
W.printNumber("SizeOfCode", Hdr->SizeOfCode);
|
||||||
W.printNumber("SizeOfInitializedData", PEHeader->SizeOfInitializedData);
|
W.printNumber("SizeOfInitializedData", Hdr->SizeOfInitializedData);
|
||||||
W.printNumber("SizeOfUninitializedData", PEHeader->SizeOfUninitializedData);
|
W.printNumber("SizeOfUninitializedData", Hdr->SizeOfUninitializedData);
|
||||||
W.printHex ("AddressOfEntryPoint", PEHeader->AddressOfEntryPoint);
|
W.printHex ("AddressOfEntryPoint", Hdr->AddressOfEntryPoint);
|
||||||
W.printHex ("BaseOfCode", PEHeader->BaseOfCode);
|
W.printHex ("BaseOfCode", Hdr->BaseOfCode);
|
||||||
W.printHex ("BaseOfData", PEHeader->BaseOfData);
|
printBaseOfDataField(Hdr);
|
||||||
W.printHex ("ImageBase", PEHeader->ImageBase);
|
W.printHex ("ImageBase", Hdr->ImageBase);
|
||||||
W.printNumber("SectionAlignment", PEHeader->SectionAlignment);
|
W.printNumber("SectionAlignment", Hdr->SectionAlignment);
|
||||||
W.printNumber("FileAlignment", PEHeader->FileAlignment);
|
W.printNumber("FileAlignment", Hdr->FileAlignment);
|
||||||
W.printNumber("MajorOperatingSystemVersion",
|
W.printNumber("MajorOperatingSystemVersion",
|
||||||
PEHeader->MajorOperatingSystemVersion);
|
Hdr->MajorOperatingSystemVersion);
|
||||||
W.printNumber("MinorOperatingSystemVersion",
|
W.printNumber("MinorOperatingSystemVersion",
|
||||||
PEHeader->MinorOperatingSystemVersion);
|
Hdr->MinorOperatingSystemVersion);
|
||||||
W.printNumber("MajorImageVersion", PEHeader->MajorImageVersion);
|
W.printNumber("MajorImageVersion", Hdr->MajorImageVersion);
|
||||||
W.printNumber("MinorImageVersion", PEHeader->MinorImageVersion);
|
W.printNumber("MinorImageVersion", Hdr->MinorImageVersion);
|
||||||
W.printNumber("MajorSubsystemVersion", PEHeader->MajorSubsystemVersion);
|
W.printNumber("MajorSubsystemVersion", Hdr->MajorSubsystemVersion);
|
||||||
W.printNumber("MinorSubsystemVersion", PEHeader->MinorSubsystemVersion);
|
W.printNumber("MinorSubsystemVersion", Hdr->MinorSubsystemVersion);
|
||||||
W.printNumber("SizeOfImage", PEHeader->SizeOfImage);
|
W.printNumber("SizeOfImage", Hdr->SizeOfImage);
|
||||||
W.printNumber("SizeOfHeaders", PEHeader->SizeOfHeaders);
|
W.printNumber("SizeOfHeaders", Hdr->SizeOfHeaders);
|
||||||
W.printEnum ("Subsystem", PEHeader->Subsystem,
|
W.printEnum ("Subsystem", Hdr->Subsystem, makeArrayRef(PEWindowsSubsystem));
|
||||||
makeArrayRef(PEWindowsSubsystem));
|
W.printFlags ("Subsystem", Hdr->DLLCharacteristics,
|
||||||
W.printFlags ("Subsystem", PEHeader->DLLCharacteristics,
|
|
||||||
makeArrayRef(PEDLLCharacteristics));
|
makeArrayRef(PEDLLCharacteristics));
|
||||||
W.printNumber("SizeOfStackReserve", PEHeader->SizeOfStackReserve);
|
W.printNumber("SizeOfStackReserve", Hdr->SizeOfStackReserve);
|
||||||
W.printNumber("SizeOfStackCommit", PEHeader->SizeOfStackCommit);
|
W.printNumber("SizeOfStackCommit", Hdr->SizeOfStackCommit);
|
||||||
W.printNumber("SizeOfHeapReserve", PEHeader->SizeOfHeapReserve);
|
W.printNumber("SizeOfHeapReserve", Hdr->SizeOfHeapReserve);
|
||||||
W.printNumber("SizeOfHeapCommit", PEHeader->SizeOfHeapCommit);
|
W.printNumber("SizeOfHeapCommit", Hdr->SizeOfHeapCommit);
|
||||||
W.printNumber("NumberOfRvaAndSize", PEHeader->NumberOfRvaAndSize);
|
W.printNumber("NumberOfRvaAndSize", Hdr->NumberOfRvaAndSize);
|
||||||
|
|
||||||
if (PEHeader->NumberOfRvaAndSize > 0) {
|
if (Hdr->NumberOfRvaAndSize > 0) {
|
||||||
DictScope D(W, "DataDirectory");
|
DictScope D(W, "DataDirectory");
|
||||||
static const char * const directory[] = {
|
static const char * const directory[] = {
|
||||||
"ExportTable", "ImportTable", "ResourceTable", "ExceptionTable",
|
"ExportTable", "ImportTable", "ResourceTable", "ExceptionTable",
|
||||||
@ -642,13 +652,18 @@ void COFFDumper::printFileHeaders() {
|
|||||||
"DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"
|
"DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"
|
||||||
};
|
};
|
||||||
|
|
||||||
for (uint32_t i = 0; i < PEHeader->NumberOfRvaAndSize; ++i) {
|
for (uint32_t i = 0; i < Hdr->NumberOfRvaAndSize; ++i) {
|
||||||
printDataDirectory(i, directory[i]);
|
printDataDirectory(i, directory[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) {
|
||||||
|
W.printHex("BaseOfData", Hdr->BaseOfData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void COFFDumper::printBaseOfDataField(const pe32plus_header *) {}
|
||||||
|
|
||||||
void COFFDumper::printCodeViewLineTables(section_iterator SecI) {
|
void COFFDumper::printCodeViewLineTables(section_iterator SecI) {
|
||||||
StringRef Data;
|
StringRef Data;
|
||||||
if (error(SecI->getContents(Data))) return;
|
if (error(SecI->getContents(Data))) return;
|
||||||
|
Loading…
Reference in New Issue
Block a user