COFFDumper: Dump data directory entries.

Summary:
Dump optional data directory entries in the PE/COFF header, so that
we can test the output of LLD linker. This patch updates the test binary
file, but the source of the binary is the same. I just re-linked the file.
I don't know how the previous file was linked, but the previous file did
not have any data directory entries for some reason.

Reviewers: rafael

CC: llvm-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D1148

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186623 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rui Ueyama
2013-07-18 22:44:20 +00:00
parent b05ad799e7
commit 06bd2061fc
5 changed files with 117 additions and 47 deletions

View File

@ -198,6 +198,7 @@ class COFFObjectFile : public ObjectFile {
private: private:
const coff_file_header *COFFHeader; const coff_file_header *COFFHeader;
const pe32_header *PE32Header; const pe32_header *PE32Header;
const data_directory *DataDirectory;
const coff_section *SectionTable; const coff_section *SectionTable;
const coff_symbol *SymbolTable; const coff_symbol *SymbolTable;
const char *StringTable; const char *StringTable;
@ -283,6 +284,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 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;
template <typename T> template <typename T>

View File

@ -37,18 +37,19 @@ bool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) {
return true; return true;
} }
// Returns false if any bytes in [addr, addr + size) fall outsize of m. // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.
bool checkAddr(const MemoryBuffer *m, // Returns unexpected_eof if error.
error_code &ec, template<typename T>
uintptr_t addr, error_code getObject(const T *&Obj, const MemoryBuffer *M, const uint8_t *Ptr,
uint64_t size) { const size_t Size = sizeof(T)) {
if (addr + size < addr || uintptr_t Addr = uintptr_t(Ptr);
addr + size < size || if (Addr + Size < Addr ||
addr + size > uintptr_t(m->getBufferEnd())) { Addr + Size < Size ||
ec = object_error::unexpected_eof; Addr + Size > uintptr_t(M->getBufferEnd())) {
return false; return object_error::unexpected_eof;
} }
return true; Obj = reinterpret_cast<const T *>(Addr);
return object_error::success;
} }
} }
@ -432,6 +433,7 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec)
: ObjectFile(Binary::ID_COFF, Object) : ObjectFile(Binary::ID_COFF, Object)
, COFFHeader(0) , COFFHeader(0)
, PE32Header(0) , PE32Header(0)
, DataDirectory(0)
, SectionTable(0) , SectionTable(0)
, SymbolTable(0) , SymbolTable(0)
, StringTable(0) , StringTable(0)
@ -461,48 +463,47 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec)
hasPEHeader = true; hasPEHeader = true;
} }
COFFHeader = reinterpret_cast<const coff_file_header *>(base() + CurPtr); if ((ec = getObject(COFFHeader, Data, base() + CurPtr)))
if (!checkAddr(Data, ec, uintptr_t(COFFHeader), sizeof(coff_file_header)))
return; return;
CurPtr += sizeof(coff_file_header); CurPtr += sizeof(coff_file_header);
if (hasPEHeader) { if (hasPEHeader) {
PE32Header = reinterpret_cast<const pe32_header *>(base() + CurPtr); if ((ec = getObject(PE32Header, Data, base() + CurPtr)))
if (!checkAddr(Data, ec, uintptr_t(PE32Header), sizeof(pe32_header)))
return; return;
if (PE32Header->Magic != 0x10b) {
// We only support PE32. If this is PE32 (not PE32+), the magic byte // We only support PE32. If this is PE32 (not PE32+), the magic byte
// should be 0x10b. If this is not PE32, continue as if there's no PE // should be 0x10b. If this is not PE32, continue as if there's no PE
// header in this file. // header in this file.
if (PE32Header->Magic != 0x10b)
PE32Header = 0; PE32Header = 0;
// There may be optional data directory after PE header. Skip them. } else if (PE32Header->NumberOfRvaAndSize > 0) {
const uint8_t *addr = base() + CurPtr + sizeof(pe32_header);
uint64_t size = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize;
if ((ec = getObject(DataDirectory, Data, addr, size)))
return;
}
CurPtr += COFFHeader->SizeOfOptionalHeader; CurPtr += COFFHeader->SizeOfOptionalHeader;
} }
SectionTable = if ((ec = getObject(SectionTable, Data, base() + CurPtr,
reinterpret_cast<const coff_section *>(base() + CurPtr); COFFHeader->NumberOfSections * sizeof(coff_section))))
if (!checkAddr(Data, ec, uintptr_t(SectionTable),
COFFHeader->NumberOfSections * sizeof(coff_section)))
return; return;
if (COFFHeader->PointerToSymbolTable != 0) { if (COFFHeader->PointerToSymbolTable != 0) {
SymbolTable = if ((ec = getObject(SymbolTable, Data,
reinterpret_cast<const coff_symbol *>(base() base() + COFFHeader->PointerToSymbolTable,
+ COFFHeader->PointerToSymbolTable); COFFHeader->NumberOfSymbols * sizeof(coff_symbol))))
if (!checkAddr(Data, ec, uintptr_t(SymbolTable),
COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
return; return;
// Find string table. // Find string table.
StringTable = reinterpret_cast<const char *>(base()) const uint8_t *StringTableAddr = base() + COFFHeader->PointerToSymbolTable
+ COFFHeader->PointerToSymbolTable
+ COFFHeader->NumberOfSymbols * sizeof(coff_symbol); + COFFHeader->NumberOfSymbols * sizeof(coff_symbol);
if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t))) const uint32_t *StringTableSizePtr;
if ((ec = getObject(StringTableSizePtr, Data, StringTableAddr)))
return;
StringTableSize = *StringTableSizePtr;
if ((ec = getObject(StringTable, Data, StringTableAddr, StringTableSize)))
return; return;
StringTableSize = *reinterpret_cast<const ulittle32_t *>(StringTable);
if (!checkAddr(Data, ec, uintptr_t(StringTable), StringTableSize))
return;
// Check that the string table is null terminated if has any in it. // Check that the string table is null terminated if has any in it.
if (StringTableSize < 4 if (StringTableSize < 4
|| (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) { || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) {
@ -607,6 +608,15 @@ error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {
return object_error::success; return object_error::success;
} }
error_code COFFObjectFile::getDataDirectory(uint32_t index,
const data_directory *&Res) const {
// Error if if there's no data directory or the index is out of range.
if (!DataDirectory || index > PE32Header->NumberOfRvaAndSize)
return object_error::parse_failed;
Res = &DataDirectory[index];
return object_error::success;
}
error_code COFFObjectFile::getSection(int32_t index, error_code COFFObjectFile::getSection(int32_t index,
const coff_section *&Result) const { const coff_section *&Result) const {
// Check for special index values. // Check for special index values.

View File

@ -107,8 +107,8 @@ PE32-NEXT: Arch: i386
PE32-NEXT: AddressSize: 32bit PE32-NEXT: AddressSize: 32bit
PE32-NEXT: ImageFileHeader { PE32-NEXT: ImageFileHeader {
PE32-NEXT: Machine: IMAGE_FILE_MACHINE_I386 (0x14C) PE32-NEXT: Machine: IMAGE_FILE_MACHINE_I386 (0x14C)
PE32-NEXT: SectionCount: 1 PE32-NEXT: SectionCount: 3
PE32-NEXT: TimeDateStamp: 2013-05-24 21:24:34 (0x519FDA92) PE32-NEXT: TimeDateStamp: 2013-07-16 00:39:15 (0x51E49633)
PE32-NEXT: PointerToSymbolTable: 0x0 PE32-NEXT: PointerToSymbolTable: 0x0
PE32-NEXT: SymbolCount: 0 PE32-NEXT: SymbolCount: 0
PE32-NEXT: OptionalHeaderSize: 224 PE32-NEXT: OptionalHeaderSize: 224
@ -118,10 +118,10 @@ PE32-NEXT: IMAGE_FILE_EXECUTABLE_IMAGE (0x2)
PE32-NEXT: ] PE32-NEXT: ]
PE32-NEXT: } PE32-NEXT: }
PE32-NEXT: ImageOptionalHeader { PE32-NEXT: ImageOptionalHeader {
PE32-NEXT: MajorLinkerVersion: 10 PE32-NEXT: MajorLinkerVersion: 11
PE32-NEXT: MinorLinkerVersion: 0 PE32-NEXT: MinorLinkerVersion: 0
PE32-NEXT: SizeOfCode: 512 PE32-NEXT: SizeOfCode: 512
PE32-NEXT: SizeOfInitializedData: 0 PE32-NEXT: SizeOfInitializedData: 1024
PE32-NEXT: SizeOfUninitializedData: 0 PE32-NEXT: SizeOfUninitializedData: 0
PE32-NEXT: AddressOfEntryPoint: 0x1000 PE32-NEXT: AddressOfEntryPoint: 0x1000
PE32-NEXT: BaseOfCode: 0x1000 PE32-NEXT: BaseOfCode: 0x1000
@ -129,15 +129,15 @@ PE32-NEXT: BaseOfData: 0x2000
PE32-NEXT: ImageBase: 0x400000 PE32-NEXT: ImageBase: 0x400000
PE32-NEXT: SectionAlignment: 4096 PE32-NEXT: SectionAlignment: 4096
PE32-NEXT: FileAlignment: 512 PE32-NEXT: FileAlignment: 512
PE32-NEXT: MajorOperatingSystemVersion: 5 PE32-NEXT: MajorOperatingSystemVersion: 6
PE32-NEXT: MinorOperatingSystemVersion: 1 PE32-NEXT: MinorOperatingSystemVersion: 0
PE32-NEXT: MajorImageVersion: 0 PE32-NEXT: MajorImageVersion: 0
PE32-NEXT: MinorImageVersion: 0 PE32-NEXT: MinorImageVersion: 0
PE32-NEXT: MajorSubsystemVersion: 5 PE32-NEXT: MajorSubsystemVersion: 6
PE32-NEXT: MinorSubsystemVersion: 1 PE32-NEXT: MinorSubsystemVersion: 0
PE32-NEXT: SizeOfImage: 8192 PE32-NEXT: SizeOfImage: 16384
PE32-NEXT: SizeOfHeaders: 512 PE32-NEXT: SizeOfHeaders: 1024
PE32-NEXT: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI (0x2) PE32-NEXT: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3)
PE32-NEXT: Subsystem [ (0x8140) PE32-NEXT: Subsystem [ (0x8140)
PE32-NEXT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE (0x40) PE32-NEXT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE (0x40)
PE32-NEXT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT (0x100) PE32-NEXT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT (0x100)
@ -148,4 +148,38 @@ PE32-NEXT: SizeOfStackCommit: 4096
PE32-NEXT: SizeOfHeapReserve: 1048576 PE32-NEXT: SizeOfHeapReserve: 1048576
PE32-NEXT: SizeOfHeapCommit: 4096 PE32-NEXT: SizeOfHeapCommit: 4096
PE32-NEXT: NumberOfRvaAndSize: 16 PE32-NEXT: NumberOfRvaAndSize: 16
PE32-NEXT: DataDirectory {
PE32-NEXT: ExportTableRVA: 0x0
PE32-NEXT: ExportTableSize: 0x0
PE32-NEXT: ImportTableRVA: 0x0
PE32-NEXT: ImportTableSize: 0x0
PE32-NEXT: ResourceTableRVA: 0x0
PE32-NEXT: ResourceTableSize: 0x0
PE32-NEXT: ExceptionTableRVA: 0x0
PE32-NEXT: ExceptionTableSize: 0x0
PE32-NEXT: CertificateTableRVA: 0x0
PE32-NEXT: CertificateTableSize: 0x0
PE32-NEXT: BaseRelocationTableRVA: 0x3000
PE32-NEXT: BaseRelocationTableSize: 0xC
PE32-NEXT: DebugRVA: 0x0
PE32-NEXT: DebugSize: 0x0
PE32-NEXT: ArchitectureRVA: 0x0
PE32-NEXT: ArchitectureSize: 0x0
PE32-NEXT: GlobalPtrRVA: 0x0
PE32-NEXT: GlobalPtrSize: 0x0
PE32-NEXT: TLSTableRVA: 0x0
PE32-NEXT: TLSTableSize: 0x0
PE32-NEXT: LoadConfigTableRVA: 0x0
PE32-NEXT: LoadConfigTableSize: 0x0
PE32-NEXT: BoundImportRVA: 0x0
PE32-NEXT: BoundImportSize: 0x0
PE32-NEXT: IATRVA: 0x0
PE32-NEXT: IATSize: 0x0
PE32-NEXT: DelayImportDescriptorRVA: 0x0
PE32-NEXT: DelayImportDescriptorSize: 0x0
PE32-NEXT: CLRRuntimeHeaderRVA: 0x0
PE32-NEXT: CLRRuntimeHeaderSize: 0x0
PE32-NEXT: ReservedRVA: 0x0
PE32-NEXT: ReservedSize: 0x0
PE32-NEXT: }
PE32-NEXT: } PE32-NEXT: }

View File

@ -60,6 +60,8 @@ private:
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 printX64UnwindInfo(); void printX64UnwindInfo();
void printRuntimeFunction( void printRuntimeFunction(
@ -560,6 +562,14 @@ void COFFDumper::cacheRelocations() {
} }
} }
void COFFDumper::printDataDirectory(uint32_t Index, const std::string &FieldName) {
const data_directory *Data;
if (Obj->getDataDirectory(Index, Data))
return;
W.printHex(FieldName + "RVA", Data->RelativeVirtualAddress);
W.printHex(FieldName + "Size", Data->Size);
}
void COFFDumper::printFileHeaders() { void COFFDumper::printFileHeaders() {
// Print COFF header // Print COFF header
const coff_file_header *COFFHeader = 0; const coff_file_header *COFFHeader = 0;
@ -621,6 +631,20 @@ void COFFDumper::printFileHeaders() {
W.printNumber("SizeOfHeapReserve", PEHeader->SizeOfHeapReserve); W.printNumber("SizeOfHeapReserve", PEHeader->SizeOfHeapReserve);
W.printNumber("SizeOfHeapCommit", PEHeader->SizeOfHeapCommit); W.printNumber("SizeOfHeapCommit", PEHeader->SizeOfHeapCommit);
W.printNumber("NumberOfRvaAndSize", PEHeader->NumberOfRvaAndSize); W.printNumber("NumberOfRvaAndSize", PEHeader->NumberOfRvaAndSize);
if (PEHeader->NumberOfRvaAndSize > 0) {
DictScope D(W, "DataDirectory");
static const char * const directory[] = {
"ExportTable", "ImportTable", "ResourceTable", "ExceptionTable",
"CertificateTable", "BaseRelocationTable", "Debug", "Architecture",
"GlobalPtr", "TLSTable", "LoadConfigTable", "BoundImport", "IAT",
"DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"
};
for (uint32_t i = 0; i < PEHeader->NumberOfRvaAndSize; ++i) {
printDataDirectory(i, directory[i]);
}
}
} }
} }