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 {
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!");
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;
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;
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
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.
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 =
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;
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: }
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);
+ }
}
}