[Object, COFF] An import data directory might not consist soley of imports

The last import is the penultimate entry, the last entry is nulled out.
Data beyond the null entry should not be considered to hold import
entries.

This fixes PR28302.

N.B.  I am working on a reduced testcase, the one in PR28302 is too
large.

llvm-svn: 273790
This commit is contained in:
David Majnemer 2016-06-26 04:36:32 +00:00
parent 861a19c294
commit ad7b7e73a5
3 changed files with 47 additions and 31 deletions

View File

@ -634,7 +634,6 @@ private:
const char *StringTable;
uint32_t StringTableSize;
const import_directory_table_entry *ImportDirectory;
uint32_t NumberOfImportDirectory;
const delay_import_directory_table_entry *DelayImportDirectory;
uint32_t NumberOfDelayImportDirectory;
const export_directory_table_entry *ExportDirectory;
@ -911,9 +910,6 @@ public:
std::error_code
getImportTableEntry(const import_directory_table_entry *&Result) const;
std::error_code
getImportLookupEntry(const import_lookup_table_entry32 *&Result) const;
private:
const import_directory_table_entry *ImportTable;
uint32_t Index;
@ -985,7 +981,9 @@ public:
void moveNext();
std::error_code getSymbolName(StringRef &Result) const;
std::error_code isOrdinal(bool &Result) const;
std::error_code getOrdinal(uint16_t &Result) const;
std::error_code getHintNameRVA(uint32_t &Result) const;
private:
const import_lookup_table_entry32 *Entry32;

View File

@ -529,15 +529,14 @@ std::error_code COFFObjectFile::initImportTablePtr() {
return std::error_code();
uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
// -1 because the last entry is the null entry.
NumberOfImportDirectory = DataEntry->Size /
sizeof(import_directory_table_entry) - 1;
// Find the section that contains the RVA. This is needed because the RVA is
// the import table's memory address which is different from its file offset.
uintptr_t IntPtr = 0;
if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr))
return EC;
if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size))
return EC;
ImportDirectory = reinterpret_cast<
const import_directory_table_entry *>(IntPtr);
return std::error_code();
@ -631,7 +630,7 @@ COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr),
SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0),
ImportDirectory(nullptr), NumberOfImportDirectory(0),
ImportDirectory(nullptr),
DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0),
ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr),
DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) {
@ -771,13 +770,17 @@ basic_symbol_iterator COFFObjectFile::symbol_end_impl() const {
}
import_directory_iterator COFFObjectFile::import_directory_begin() const {
if (!ImportDirectory)
return import_directory_end();
if (ImportDirectory[0].ImportLookupTableRVA == 0)
return import_directory_end();
return import_directory_iterator(
ImportDirectoryEntryRef(ImportDirectory, 0, this));
}
import_directory_iterator COFFObjectFile::import_directory_end() const {
return import_directory_iterator(
ImportDirectoryEntryRef(ImportDirectory, NumberOfImportDirectory, this));
ImportDirectoryEntryRef(nullptr, -1, this));
}
delay_import_directory_iterator
@ -1198,12 +1201,15 @@ operator==(const ImportDirectoryEntryRef &Other) const {
void ImportDirectoryEntryRef::moveNext() {
++Index;
if (ImportTable[Index].ImportLookupTableRVA == 0) {
Index = -1;
ImportTable = nullptr;
}
}
std::error_code ImportDirectoryEntryRef::getImportTableEntry(
const import_directory_table_entry *&Result) const {
Result = ImportTable + Index;
return std::error_code();
return getObject(Result, OwningObject->Data, ImportTable + Index);
}
static imported_symbol_iterator
@ -1280,16 +1286,6 @@ ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const {
return std::error_code();
}
std::error_code ImportDirectoryEntryRef::getImportLookupEntry(
const import_lookup_table_entry32 *&Result) const {
uintptr_t IntPtr = 0;
uint32_t RVA = ImportTable[Index].ImportLookupTableRVA;
if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
return EC;
Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr);
return std::error_code();
}
bool DelayImportDirectoryEntryRef::
operator==(const DelayImportDirectoryEntryRef &Other) const {
return Table == Other.Table && Index == Other.Index;
@ -1473,6 +1469,22 @@ ImportedSymbolRef::getSymbolName(StringRef &Result) const {
return std::error_code();
}
std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const {
if (Entry32)
Result = Entry32[Index].isOrdinal();
else
Result = Entry64[Index].isOrdinal();
return std::error_code();
}
std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const {
if (Entry32)
Result = Entry32[Index].getHintNameRVA();
else
Result = Entry64[Index].getHintNameRVA();
return std::error_code();
}
std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
uint32_t RVA;
if (Entry32) {

View File

@ -352,11 +352,11 @@ static void printImportTables(const COFFObjectFile *Obj) {
if (I == E)
return;
outs() << "The Import Tables:\n";
for (; I != E; I = ++I) {
for (const ImportDirectoryEntryRef &DirRef : Obj->import_directories()) {
const import_directory_table_entry *Dir;
StringRef Name;
if (I->getImportTableEntry(Dir)) return;
if (I->getName(Name)) return;
if (DirRef.getImportTableEntry(Dir)) return;
if (DirRef.getName(Name)) return;
outs() << format(" lookup %08x time %08x fwd %08x name %08x addr %08x\n\n",
static_cast<uint32_t>(Dir->ImportLookupTableRVA),
@ -366,17 +366,23 @@ static void printImportTables(const COFFObjectFile *Obj) {
static_cast<uint32_t>(Dir->ImportAddressTableRVA));
outs() << " DLL Name: " << Name << "\n";
outs() << " Hint/Ord Name\n";
const import_lookup_table_entry32 *entry;
if (I->getImportLookupEntry(entry))
return;
for (; entry->Data; ++entry) {
if (entry->isOrdinal()) {
outs() << format(" % 6d\n", entry->getOrdinal());
for (const ImportedSymbolRef &Entry : DirRef.imported_symbols()) {
bool IsOrdinal;
if (Entry.isOrdinal(IsOrdinal))
return;
if (IsOrdinal) {
uint16_t Ordinal;
if (Entry.getOrdinal(Ordinal))
return;
outs() << format(" % 6d\n", Ordinal);
continue;
}
uint32_t HintNameRVA;
if (Entry.getHintNameRVA(HintNameRVA))
return;
uint16_t Hint;
StringRef Name;
if (Obj->getHintName(entry->getHintNameRVA(), Hint, Name))
if (Obj->getHintName(HintNameRVA, Hint, Name))
return;
outs() << format(" % 6d ", Hint) << Name << "\n";
}