- Adds support for sniffing PE/COFF files on win32 (.exe and .dll)
which are COFF files that have an MS-DOS compatibility stub on
the front of them.
- Fixes a bug in the COFFObjectFile's support for the Microsoft COFF
extension for long symbol names, wherein it was attempting to parse
the leading '/' in an extended symbol name reference as part of the
integer offset.
- Fixes bugs in COFFObjectFile and ELFObjectFile wherein section
and symbol iterators were being returned with uninitialized bytes;
the type DataRefImpl is a union between 2 32-bit words (d.a and d.b)
and a single intptr_t word (p). Only p was being initialized, so in
32-bit builds the result would be iterators with random upper 32-bit
words in their DataRefImpls. This caused random failures when
seeking around in object files.
Patch by Graydon Hoare!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128799
91177308-0d34-0410-b5e6-
96231b3b80d8
namespace {
class COFFObjectFile : public ObjectFile {
private:
namespace {
class COFFObjectFile : public ObjectFile {
private:
const coff_file_header *Header;
const coff_section *SectionTable;
const coff_symbol *SymbolTable;
const coff_file_header *Header;
const coff_section *SectionTable;
const coff_symbol *SymbolTable;
// Check for string table entry. First byte is '/'.
if (name[0] == '/') {
uint32_t Offset;
// Check for string table entry. First byte is '/'.
if (name[0] == '/') {
uint32_t Offset;
- name.getAsInteger(10, Offset);
+ name.substr(1).getAsInteger(10, Offset);
return StringRef(getString(Offset));
}
return StringRef(getString(Offset));
}
COFFObjectFile::COFFObjectFile(MemoryBuffer *Object)
: ObjectFile(Object) {
COFFObjectFile::COFFObjectFile(MemoryBuffer *Object)
: ObjectFile(Object) {
- Header = reinterpret_cast<const coff_file_header *>(base);
+
+ HeaderOff = 0;
+
+ if (base[0] == 0x4d && base[1] == 0x5a) {
+ // PE/COFF, seek through MS-DOS compatibility stub and 4-byte
+ // PE signature to find 'normal' COFF header.
+ HeaderOff += *reinterpret_cast<const ulittle32_t *>(base + 0x3c);
+ HeaderOff += 4;
+ }
+
+ Header = reinterpret_cast<const coff_file_header *>(base + HeaderOff);
SectionTable =
reinterpret_cast<const coff_section *>( base
SectionTable =
reinterpret_cast<const coff_section *>( base
+ sizeof(coff_file_header)
+ Header->SizeOfOptionalHeader);
SymbolTable =
+ sizeof(coff_file_header)
+ Header->SizeOfOptionalHeader);
SymbolTable =
ObjectFile::symbol_iterator COFFObjectFile::begin_symbols() const {
DataRefImpl ret;
ObjectFile::symbol_iterator COFFObjectFile::begin_symbols() const {
DataRefImpl ret;
+ memset(&ret, 0, sizeof(DataRefImpl));
ret.p = reinterpret_cast<intptr_t>(SymbolTable);
return symbol_iterator(SymbolRef(ret, this));
}
ret.p = reinterpret_cast<intptr_t>(SymbolTable);
return symbol_iterator(SymbolRef(ret, this));
}
ObjectFile::symbol_iterator COFFObjectFile::end_symbols() const {
// The symbol table ends where the string table begins.
DataRefImpl ret;
ObjectFile::symbol_iterator COFFObjectFile::end_symbols() const {
// The symbol table ends where the string table begins.
DataRefImpl ret;
+ memset(&ret, 0, sizeof(DataRefImpl));
ret.p = reinterpret_cast<intptr_t>(StringTable);
return symbol_iterator(SymbolRef(ret, this));
}
ObjectFile::section_iterator COFFObjectFile::begin_sections() const {
DataRefImpl ret;
ret.p = reinterpret_cast<intptr_t>(StringTable);
return symbol_iterator(SymbolRef(ret, this));
}
ObjectFile::section_iterator COFFObjectFile::begin_sections() const {
DataRefImpl ret;
+ memset(&ret, 0, sizeof(DataRefImpl));
ret.p = reinterpret_cast<intptr_t>(SectionTable);
return section_iterator(SectionRef(ret, this));
}
ObjectFile::section_iterator COFFObjectFile::end_sections() const {
DataRefImpl ret;
ret.p = reinterpret_cast<intptr_t>(SectionTable);
return section_iterator(SectionRef(ret, this));
}
ObjectFile::section_iterator COFFObjectFile::end_sections() const {
DataRefImpl ret;
+ memset(&ret, 0, sizeof(DataRefImpl));
ret.p = reinterpret_cast<intptr_t>(SectionTable + Header->NumberOfSections);
return section_iterator(SectionRef(ret, this));
}
ret.p = reinterpret_cast<intptr_t>(SectionTable + Header->NumberOfSections);
return section_iterator(SectionRef(ret, this));
}
ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits>
::begin_sections() const {
DataRefImpl ret;
ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits>
::begin_sections() const {
DataRefImpl ret;
+ memset(&ret, 0, sizeof(DataRefImpl));
ret.p = reinterpret_cast<intptr_t>(base + Header->e_shoff);
return section_iterator(SectionRef(ret, this));
}
ret.p = reinterpret_cast<intptr_t>(base + Header->e_shoff);
return section_iterator(SectionRef(ret, this));
}
ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits>
::end_sections() const {
DataRefImpl ret;
ObjectFile::section_iterator ELFObjectFile<target_endianness, is64Bits>
::end_sections() const {
DataRefImpl ret;
+ memset(&ret, 0, sizeof(DataRefImpl));
ret.p = reinterpret_cast<intptr_t>(base
+ Header->e_shoff
+ (Header->e_shentsize * Header->e_shnum));
ret.p = reinterpret_cast<intptr_t>(base
+ Header->e_shoff
+ (Header->e_shentsize * Header->e_shnum));
#include "llvm/Support/FileSystem.h"
#include "llvm/Config/config.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Config/config.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Endian.h"
#include <cassert>
#include <cstring>
#include <ostream>
using namespace llvm;
using namespace sys;
#include <cassert>
#include <cstring>
#include <ostream>
using namespace llvm;
using namespace sys;
+namespace {
+using support::ulittle32_t;
+}
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only TRULY operating system
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only TRULY operating system
if (magic[1] == 0x02)
return COFF_FileType;
break;
if (magic[1] == 0x02)
return COFF_FileType;
break;
+
+ case 0x4d: // Possible MS-DOS stub on Windows PE file
+ if (magic[1] == 0x5a) {
+ uint32_t off = *reinterpret_cast<const ulittle32_t *>(magic + 0x3c);
+ // PE/COFF file, either EXE or DLL.
+ if (off < length && memcmp(magic + off, "PE\0\0",4) == 0)
+ return COFF_FileType;
+ }
+ break;
+
case 0x64: // x86-64 Windows.
if (magic[1] == char(0x86))
return COFF_FileType;
case 0x64: // x86-64 Windows.
if (magic[1] == char(0x86))
return COFF_FileType;