mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-18 11:24:01 +00:00
llvm-readobj: print COFF imported symbols
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
This commit is contained in:
@ -26,8 +26,10 @@ template <typename T> class ArrayRef;
|
|||||||
namespace object {
|
namespace object {
|
||||||
class ImportDirectoryEntryRef;
|
class ImportDirectoryEntryRef;
|
||||||
class ExportDirectoryEntryRef;
|
class ExportDirectoryEntryRef;
|
||||||
|
class ImportedSymbolRef;
|
||||||
typedef content_iterator<ImportDirectoryEntryRef> import_directory_iterator;
|
typedef content_iterator<ImportDirectoryEntryRef> import_directory_iterator;
|
||||||
typedef content_iterator<ExportDirectoryEntryRef> export_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.
|
/// The DOS compatible header at the front of all PE/COFF executables.
|
||||||
struct dos_header {
|
struct dos_header {
|
||||||
@ -160,10 +162,11 @@ struct import_directory_table_entry {
|
|||||||
support::ulittle32_t ImportAddressTableRVA;
|
support::ulittle32_t ImportAddressTableRVA;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct import_lookup_table_entry32 {
|
template <typename IntTy>
|
||||||
support::ulittle32_t data;
|
struct import_lookup_table_entry {
|
||||||
|
IntTy data;
|
||||||
|
|
||||||
bool isOrdinal() const { return data & 0x80000000; }
|
bool isOrdinal() const { return data < 0; }
|
||||||
|
|
||||||
uint16_t getOrdinal() const {
|
uint16_t getOrdinal() const {
|
||||||
assert(isOrdinal() && "ILT entry is not an ordinal!");
|
assert(isOrdinal() && "ILT entry is not an ordinal!");
|
||||||
@ -172,10 +175,15 @@ struct import_lookup_table_entry32 {
|
|||||||
|
|
||||||
uint32_t getHintNameRVA() const {
|
uint32_t getHintNameRVA() const {
|
||||||
assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!");
|
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 {
|
struct export_directory_table_entry {
|
||||||
support::ulittle32_t ExportFlags;
|
support::ulittle32_t ExportFlags;
|
||||||
support::ulittle32_t TimeDateStamp;
|
support::ulittle32_t TimeDateStamp;
|
||||||
@ -650,6 +658,10 @@ public:
|
|||||||
|
|
||||||
bool operator==(const ImportDirectoryEntryRef &Other) const;
|
bool operator==(const ImportDirectoryEntryRef &Other) const;
|
||||||
void moveNext();
|
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 getName(StringRef &Result) const;
|
||||||
std::error_code getImportLookupTableRVA(uint32_t &Result) const;
|
std::error_code getImportLookupTableRVA(uint32_t &Result) const;
|
||||||
std::error_code getImportAddressTableRVA(uint32_t &Result) const;
|
std::error_code getImportAddressTableRVA(uint32_t &Result) const;
|
||||||
@ -688,6 +700,29 @@ private:
|
|||||||
uint32_t Index;
|
uint32_t Index;
|
||||||
const COFFObjectFile *OwningObject;
|
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 object
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ using namespace object;
|
|||||||
|
|
||||||
using support::ulittle16_t;
|
using support::ulittle16_t;
|
||||||
using support::ulittle32_t;
|
using support::ulittle32_t;
|
||||||
|
using support::ulittle64_t;
|
||||||
using support::little16_t;
|
using support::little16_t;
|
||||||
|
|
||||||
// Returns false if size is greater than the buffer size. And sets ec.
|
// Returns false if size is greater than the buffer size. And sets ec.
|
||||||
@ -1034,6 +1035,42 @@ std::error_code ImportDirectoryEntryRef::getImportTableEntry(
|
|||||||
return object_error::success;
|
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 {
|
std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
|
||||||
uintptr_t IntPtr = 0;
|
uintptr_t IntPtr = 0;
|
||||||
if (std::error_code EC =
|
if (std::error_code EC =
|
||||||
@ -1139,6 +1176,59 @@ ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const {
|
|||||||
return object_error::success;
|
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>>
|
ErrorOr<std::unique_ptr<COFFObjectFile>>
|
||||||
ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
|
ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) {
|
||||||
std::error_code EC;
|
std::error_code EC;
|
||||||
|
@ -5,20 +5,24 @@ X86: Import {
|
|||||||
X86-NEXT: Name: KERNEL32.dll
|
X86-NEXT: Name: KERNEL32.dll
|
||||||
X86-NEXT: ImportLookupTableRVA: 0x204C
|
X86-NEXT: ImportLookupTableRVA: 0x204C
|
||||||
X86-NEXT: ImportAddressTableRVA: 0x2000
|
X86-NEXT: ImportAddressTableRVA: 0x2000
|
||||||
|
X86-NEXT: Symbol: ExitProcess (337)
|
||||||
X86-NEXT: }
|
X86-NEXT: }
|
||||||
X86-NEXT: Import {
|
X86-NEXT: Import {
|
||||||
X86-NEXT: Name: USER32.dll
|
X86-NEXT: Name: USER32.dll
|
||||||
X86-NEXT: ImportLookupTableRVA: 0x2054
|
X86-NEXT: ImportLookupTableRVA: 0x2054
|
||||||
X86-NEXT: ImportAddressTableRVA: 0x2008
|
X86-NEXT: ImportAddressTableRVA: 0x2008
|
||||||
|
X86-NEXT: Symbol: MessageBoxA (582)
|
||||||
X86-NEXT: }
|
X86-NEXT: }
|
||||||
|
|
||||||
X64: Import {
|
X64: Import {
|
||||||
X64-NEXT: Name: KERNEL32.dll
|
X64-NEXT: Name: KERNEL32.dll
|
||||||
X64-NEXT: ImportLookupTableRVA: 0x2060
|
X64-NEXT: ImportLookupTableRVA: 0x2060
|
||||||
X64-NEXT: ImportAddressTableRVA: 0x2000
|
X64-NEXT: ImportAddressTableRVA: 0x2000
|
||||||
|
X64-NEXT: Symbol: ExitProcess (343)
|
||||||
X64-NEXT: }
|
X64-NEXT: }
|
||||||
X64-NEXT: Import {
|
X64-NEXT: Import {
|
||||||
X64-NEXT: Name: USER32.dll
|
X64-NEXT: Name: USER32.dll
|
||||||
X64-NEXT: ImportLookupTableRVA: 0x2070
|
X64-NEXT: ImportLookupTableRVA: 0x2070
|
||||||
X64-NEXT: ImportAddressTableRVA: 0x2010
|
X64-NEXT: ImportAddressTableRVA: 0x2010
|
||||||
|
X64-NEXT: Symbol: MessageBoxA (586)
|
||||||
X64-NEXT: }
|
X64-NEXT: }
|
||||||
|
@ -895,5 +895,13 @@ void COFFDumper::printCOFFImports() {
|
|||||||
W.printHex("ImportLookupTableRVA", Addr);
|
W.printHex("ImportLookupTableRVA", Addr);
|
||||||
if (error(I->getImportAddressTableRVA(Addr))) return;
|
if (error(I->getImportAddressTableRVA(Addr))) return;
|
||||||
W.printHex("ImportAddressTableRVA", Addr);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user