From 2f6c0484d68270f09eecac03b7e56053153203f3 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Fri, 19 Jul 2013 23:23:29 +0000 Subject: [PATCH] Retry submitting r186623: COFFDumper: Dump data directory entries. The original change was rolled back in r186627 because of test failures on the big endian machine. I believe I fixed the issue so re-submitting. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186734 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/COFF.h | 2 + lib/Object/COFFObjectFile.cpp | 86 ++++++++++-------- .../llvm-readobj/Inputs/trivial.exe.coff-i386 | Bin 1024 -> 2560 bytes test/tools/llvm-readobj/file-headers.test | 56 +++++++++--- tools/llvm-readobj/COFFDumper.cpp | 24 +++++ 5 files changed, 120 insertions(+), 48 deletions(-) diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index c7c5c7f118d..21900675ffd 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -198,6 +198,7 @@ class COFFObjectFile : public ObjectFile { private: const coff_file_header *COFFHeader; const pe32_header *PE32Header; + const data_directory *DataDirectory; const coff_section *SectionTable; const coff_symbol *SymbolTable; const char *StringTable; @@ -283,6 +284,7 @@ public: error_code getHeader(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 getDataDirectory(uint32_t index, const data_directory *&Res) const; error_code getSection(int32_t index, const coff_section *&Res) const; error_code getSymbol(uint32_t index, const coff_symbol *&Res) const; template diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 49317e90514..f3f2532406a 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -37,18 +37,19 @@ bool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) { return true; } -// Returns false if any bytes in [addr, addr + size) fall outsize of m. -bool checkAddr(const MemoryBuffer *m, - error_code &ec, - uintptr_t addr, - uint64_t size) { - if (addr + size < addr || - addr + size < size || - addr + size > uintptr_t(m->getBufferEnd())) { - ec = object_error::unexpected_eof; - return false; +// Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. +// Returns unexpected_eof if error. +template +error_code getObject(const T *&Obj, const MemoryBuffer *M, const uint8_t *Ptr, + const size_t Size = sizeof(T)) { + uintptr_t Addr = uintptr_t(Ptr); + if (Addr + Size < Addr || + Addr + Size < Size || + Addr + Size > uintptr_t(M->getBufferEnd())) { + return object_error::unexpected_eof; } - return true; + Obj = reinterpret_cast(Addr); + return object_error::success; } } @@ -432,6 +433,7 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) : ObjectFile(Binary::ID_COFF, Object) , COFFHeader(0) , PE32Header(0) + , DataDirectory(0) , SectionTable(0) , SymbolTable(0) , StringTable(0) @@ -461,48 +463,49 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) hasPEHeader = true; } - COFFHeader = reinterpret_cast(base() + CurPtr); - if (!checkAddr(Data, ec, uintptr_t(COFFHeader), sizeof(coff_file_header))) + if ((ec = getObject(COFFHeader, Data, base() + CurPtr))) return; CurPtr += sizeof(coff_file_header); if (hasPEHeader) { - PE32Header = reinterpret_cast(base() + CurPtr); - if (!checkAddr(Data, ec, uintptr_t(PE32Header), sizeof(pe32_header))) + if ((ec = getObject(PE32Header, Data, base() + CurPtr))) return; - // 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 - // header in this file. - if (PE32Header->Magic != 0x10b) + if (PE32Header->Magic != 0x10b) { + // 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 + // header in this file. 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; } - SectionTable = - reinterpret_cast(base() + CurPtr); - if (!checkAddr(Data, ec, uintptr_t(SectionTable), - COFFHeader->NumberOfSections * sizeof(coff_section))) + if ((ec = getObject(SectionTable, Data, base() + CurPtr, + COFFHeader->NumberOfSections * sizeof(coff_section)))) return; if (COFFHeader->PointerToSymbolTable != 0) { - SymbolTable = - reinterpret_cast(base() - + COFFHeader->PointerToSymbolTable); - if (!checkAddr(Data, ec, uintptr_t(SymbolTable), - COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) + if ((ec = getObject(SymbolTable, Data, + base() + COFFHeader->PointerToSymbolTable, + COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))) return; - // Find string table. - StringTable = reinterpret_cast(base()) - + COFFHeader->PointerToSymbolTable - + COFFHeader->NumberOfSymbols * sizeof(coff_symbol); - if (!checkAddr(Data, ec, uintptr_t(StringTable), sizeof(ulittle32_t))) + // Find string table. The first four byte of the string table contains the + // total size of the string table, including the size field itself. If the + // string table is empty, the value of the first four byte would be 4. + const uint8_t *StringTableAddr = base() + COFFHeader->PointerToSymbolTable + + COFFHeader->NumberOfSymbols * sizeof(coff_symbol); + const ulittle32_t *StringTableSizePtr; + if ((ec = getObject(StringTableSizePtr, Data, StringTableAddr))) return; - - StringTableSize = *reinterpret_cast(StringTable); - if (!checkAddr(Data, ec, uintptr_t(StringTable), StringTableSize)) + StringTableSize = *StringTableSizePtr; + if ((ec = getObject(StringTable, Data, StringTableAddr, StringTableSize))) return; + // Check that the string table is null terminated if has any in it. if (StringTableSize < 4 || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) { @@ -607,6 +610,15 @@ error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { 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, const coff_section *&Result) const { // Check for special index values. diff --git a/test/tools/llvm-readobj/Inputs/trivial.exe.coff-i386 b/test/tools/llvm-readobj/Inputs/trivial.exe.coff-i386 index 3009f90da08e8951d5d1898c1381e980840a8c6d..1558d2452ecc19dbaa4f2384bb205dd5a6b53d62 100644 GIT binary patch literal 2560 zcmeZ`n!v!!z`(!)#Q*;@Fzf)*Am9Kd@e><>(tPr}_!zcuo>knz=yO&vBqOs}p`a)~ zy(lqPAvrNGFTX?~DOI7UG*2NjPr=1MSRpq*B~_1?mrDg|^uwI?TT6Lgb|T{?Kz{l| z)lLu{l$o3Xl7qPXZUzP>pa{q#ARqw63LuUHgb$Qw z195=>MuR;H)x*r-&VFIfV#v$IzjG2_A5vX z2ox9?67*6MOA>)>UZ?xa2mtF6 PP<_P$ssl#BhzkJ#F(XXv delta 217 zcmZn=Y2cX9P=E5|%A36_j(5TEG}Fkg9w2|3X%v_a%1q7x$uU4dfGY!o49VkxfmFjU?MgetDataDirectory(Index, Data)) + return; + W.printHex(FieldName + "RVA", Data->RelativeVirtualAddress); + W.printHex(FieldName + "Size", Data->Size); +} + void COFFDumper::printFileHeaders() { // Print COFF header const coff_file_header *COFFHeader = 0; @@ -621,6 +631,20 @@ void COFFDumper::printFileHeaders() { W.printNumber("SizeOfHeapReserve", PEHeader->SizeOfHeapReserve); W.printNumber("SizeOfHeapCommit", PEHeader->SizeOfHeapCommit); 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]); + } + } } } -- 2.34.1