Skip to content

Commit

Permalink
llvm-readobj: print COFF imported symbols
Browse files Browse the repository at this point in the history
This patch defines a new iterator for the imported symbols.
Make a change to COFFDumper to use that iterator to print
out imported symbols and its ordinals.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218915 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
rui314 committed Oct 2, 2014
1 parent 0917b70 commit 3d49ad0
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 4 deletions.
43 changes: 39 additions & 4 deletions include/llvm/Object/COFF.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ template <typename T> class ArrayRef;
namespace object {
class ImportDirectoryEntryRef;
class ExportDirectoryEntryRef;
class ImportedSymbolRef;
typedef content_iterator<ImportDirectoryEntryRef> import_directory_iterator;
typedef content_iterator<ExportDirectoryEntryRef> export_directory_iterator;
typedef content_iterator<ImportedSymbolRef> imported_symbol_iterator;

/// The DOS compatible header at the front of all PE/COFF executables.
struct dos_header {
Expand Down Expand Up @@ -160,10 +162,11 @@ struct import_directory_table_entry {
support::ulittle32_t ImportAddressTableRVA;
};

struct import_lookup_table_entry32 {
support::ulittle32_t data;
template <typename IntTy>
struct import_lookup_table_entry {
IntTy data;

bool isOrdinal() const { return data & 0x80000000; }
bool isOrdinal() const { return data < 0; }

uint16_t getOrdinal() const {
assert(isOrdinal() && "ILT entry is not an ordinal!");
Expand All @@ -172,10 +175,15 @@ struct import_lookup_table_entry32 {

uint32_t getHintNameRVA() const {
assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!");
return data;
return data & 0xFFFFFFFF;
}
};

typedef import_lookup_table_entry<support::little32_t>
import_lookup_table_entry32;
typedef import_lookup_table_entry<support::little64_t>
import_lookup_table_entry64;

struct export_directory_table_entry {
support::ulittle32_t ExportFlags;
support::ulittle32_t TimeDateStamp;
Expand Down Expand Up @@ -650,6 +658,10 @@ class ImportDirectoryEntryRef {

bool operator==(const ImportDirectoryEntryRef &Other) const;
void moveNext();

imported_symbol_iterator imported_symbol_begin() const;
imported_symbol_iterator imported_symbol_end() const;

std::error_code getName(StringRef &Result) const;
std::error_code getImportLookupTableRVA(uint32_t &Result) const;
std::error_code getImportAddressTableRVA(uint32_t &Result) const;
Expand Down Expand Up @@ -688,6 +700,29 @@ class ExportDirectoryEntryRef {
uint32_t Index;
const COFFObjectFile *OwningObject;
};

class ImportedSymbolRef {
public:
ImportedSymbolRef() : OwningObject(nullptr) {}
ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I,
const COFFObjectFile *Owner)
: Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {}
ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I,
const COFFObjectFile *Owner)
: Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {}

bool operator==(const ImportedSymbolRef &Other) const;
void moveNext();

std::error_code getSymbolName(StringRef &Result) const;
std::error_code getOrdinal(uint16_t &Result) const;

private:
const import_lookup_table_entry32 *Entry32;
const import_lookup_table_entry64 *Entry64;
uint32_t Index;
const COFFObjectFile *OwningObject;
};
} // end namespace object
} // end namespace llvm

Expand Down
90 changes: 90 additions & 0 deletions lib/Object/COFFObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ using namespace object;

using support::ulittle16_t;
using support::ulittle32_t;
using support::ulittle64_t;
using support::little16_t;

// Returns false if size is greater than the buffer size. And sets ec.
Expand Down Expand Up @@ -1034,6 +1035,42 @@ std::error_code ImportDirectoryEntryRef::getImportTableEntry(
return object_error::success;
}

static imported_symbol_iterator
makeImportedSymbolIterator(const COFFObjectFile *OwningObject,
uintptr_t Ptr, int Index) {
if (OwningObject->getBytesInAddress() == 4) {
auto *P = reinterpret_cast<const import_lookup_table_entry32 *>(Ptr);
return imported_symbol_iterator(ImportedSymbolRef(P, Index, OwningObject));
}
auto *P = reinterpret_cast<const import_lookup_table_entry64 *>(Ptr);
return imported_symbol_iterator(ImportedSymbolRef(P, Index, OwningObject));
}

imported_symbol_iterator
ImportDirectoryEntryRef::imported_symbol_begin() const {
uintptr_t IntPtr = 0;
OwningObject->getRvaPtr(ImportTable[Index].ImportLookupTableRVA, IntPtr);
return makeImportedSymbolIterator(OwningObject, IntPtr, 0);
}

imported_symbol_iterator
ImportDirectoryEntryRef::imported_symbol_end() const {
uintptr_t IntPtr = 0;
OwningObject->getRvaPtr(ImportTable[Index].ImportLookupTableRVA, IntPtr);
// Forward the pointer to the last entry which is null.
int Index = 0;
if (OwningObject->getBytesInAddress() == 4) {
auto *Entry = reinterpret_cast<ulittle32_t *>(IntPtr);
while (*Entry++)
++Index;
} else {
auto *Entry = reinterpret_cast<ulittle64_t *>(IntPtr);
while (*Entry++)
++Index;
}
return makeImportedSymbolIterator(OwningObject, IntPtr, Index);
}

std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
uintptr_t IntPtr = 0;
if (std::error_code EC =
Expand Down Expand Up @@ -1139,6 +1176,59 @@ ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
return object_error::success;
}

bool ImportedSymbolRef::
operator==(const ImportedSymbolRef &Other) const {
return Entry32 == Other.Entry32 && Entry64 == Other.Entry64
&& Index == Other.Index;
}

void ImportedSymbolRef::moveNext() {
++Index;
}

std::error_code
ImportedSymbolRef::getSymbolName(StringRef &Result) const {
uint32_t RVA;
if (Entry32) {
// If a symbol is imported only by ordinal, it has no name.
if (Entry32[Index].isOrdinal())
return object_error::success;
RVA = Entry32[Index].getHintNameRVA();
} else {
if (Entry64[Index].isOrdinal())
return object_error::success;
RVA = Entry64[Index].getHintNameRVA();
}
uintptr_t IntPtr = 0;
if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
return EC;
// +2 because the first two bytes is hint.
Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2));
return object_error::success;
}

std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const {
uint32_t RVA;
if (Entry32) {
if (Entry32[Index].isOrdinal()) {
Result = Entry32[Index].getOrdinal();
return object_error::success;
}
RVA = Entry32[Index].getHintNameRVA();
} else {
if (Entry64[Index].isOrdinal()) {
Result = Entry64[Index].getOrdinal();
return object_error::success;
}
RVA = Entry64[Index].getHintNameRVA();
}
uintptr_t IntPtr = 0;
if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr))
return EC;
Result = *reinterpret_cast<const ulittle16_t *>(IntPtr);
return object_error::success;
}

ErrorOr<std::unique_ptr<COFFObjectFile>>
ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
std::error_code EC;
Expand Down
4 changes: 4 additions & 0 deletions test/tools/llvm-readobj/imports.test
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,24 @@ X86: Import {
X86-NEXT: Name: KERNEL32.dll
X86-NEXT: ImportLookupTableRVA: 0x204C
X86-NEXT: ImportAddressTableRVA: 0x2000
X86-NEXT: Symbol: ExitProcess (337)
X86-NEXT: }
X86-NEXT: Import {
X86-NEXT: Name: USER32.dll
X86-NEXT: ImportLookupTableRVA: 0x2054
X86-NEXT: ImportAddressTableRVA: 0x2008
X86-NEXT: Symbol: MessageBoxA (582)
X86-NEXT: }

X64: Import {
X64-NEXT: Name: KERNEL32.dll
X64-NEXT: ImportLookupTableRVA: 0x2060
X64-NEXT: ImportAddressTableRVA: 0x2000
X64-NEXT: Symbol: ExitProcess (343)
X64-NEXT: }
X64-NEXT: Import {
X64-NEXT: Name: USER32.dll
X64-NEXT: ImportLookupTableRVA: 0x2070
X64-NEXT: ImportAddressTableRVA: 0x2010
X64-NEXT: Symbol: MessageBoxA (586)
X64-NEXT: }
8 changes: 8 additions & 0 deletions tools/llvm-readobj/COFFDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -895,5 +895,13 @@ void COFFDumper::printCOFFImports() {
W.printHex("ImportLookupTableRVA", Addr);
if (error(I->getImportAddressTableRVA(Addr))) return;
W.printHex("ImportAddressTableRVA", Addr);
for (auto J = I->imported_symbol_begin(), F = I->imported_symbol_end();
J != F; ++J) {
StringRef Sym;
if (error(J->getSymbolName(Sym))) return;
uint16_t Ordinal;
if (error(J->getOrdinal(Ordinal))) return;
W.printNumber("Symbol", Sym, Ordinal);
}
}
}

0 comments on commit 3d49ad0

Please sign in to comment.