llvm-objdump: Dump COFF import table if -private-headers option is given.
llvm-svn: 191557
class ArrayRef;
namespace object {
+class ImportDirectoryEntryRef;
+typedef content_iterator<ImportDirectoryEntryRef> import_directory_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;
+
+ bool isOrdinal() const { return data & 0x80000000; }
+
+ uint16_t getOrdinal() const {
+ assert(isOrdinal() && "ILT entry is not an ordinal!");
+ return data & 0xFFFF;
+ }
+
+ uint32_t getHintNameRVA() const {
+ assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!");
+ return data;
+ }
+};
+
struct coff_symbol {
struct StringTableOffset {
support::ulittle32_t Zeroes;
class COFFObjectFile : public ObjectFile {
private:
+ friend class ImportDirectoryEntryRef;
const coff_file_header *COFFHeader;
const pe32_header *PE32Header;
const data_directory *DataDirectory;
const coff_symbol *SymbolTable;
const char *StringTable;
uint32_t StringTableSize;
+ const import_directory_table_entry *ImportDirectory;
+ uint32_t NumberOfImportDirectory;
error_code getString(uint32_t offset, StringRef &Res) const;
const coff_section *toSec(DataRefImpl Sec) const;
const coff_relocation *toRel(DataRefImpl Rel) const;
+ error_code initSymbolTablePtr();
+ error_code initImportTablePtr();
+
protected:
virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const;
virtual unsigned getArch() const;
virtual StringRef getLoadName() const;
+ import_directory_iterator getImportDirectoryBegin() const;
+ import_directory_iterator getImportDirectoryEnd() const;
+
error_code getHeader(const coff_file_header *&Res) const;
error_code getCOFFHeader(const coff_file_header *&Res) const;
error_code getPE32Header(const pe32_header *&Res) const;
error_code getSectionContents(const coff_section *Sec,
ArrayRef<uint8_t> &Res) const;
+ error_code getRvaPtr(uint32_t Rva, uintptr_t &Res) const;
+ error_code getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const;
+
static inline bool classof(const Binary *v) {
return v->isCOFF();
}
};
-}
-}
+// The iterator for the import directory table.
+class ImportDirectoryEntryRef {
+public:
+ ImportDirectoryEntryRef() : OwningObject(0) {}
+ ImportDirectoryEntryRef(DataRefImpl ImportDirectory,
+ const COFFObjectFile *Owner)
+ : ImportDirectoryPimpl(ImportDirectory), OwningObject(Owner) {}
+
+ bool operator==(const ImportDirectoryEntryRef &Other) const;
+ error_code getNext(ImportDirectoryEntryRef &Result) const;
+ error_code getName(StringRef &Result) const;
+
+ error_code
+ getImportTableEntry(const import_directory_table_entry *&Result) const;
+
+ error_code
+ getImportLookupEntry(const import_lookup_table_entry32 *&Result) const;
+
+private:
+ DataRefImpl ImportDirectoryPimpl;
+ const COFFObjectFile *OwningObject;
+};
+} // end namespace object
+} // end namespace llvm
#endif
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace object;
return relocation_iterator(RelocationRef(ret, this));
}
+// Initialize the pointer to the symbol table.
+error_code COFFObjectFile::initSymbolTablePtr() {
+ if (error_code ec = getObject(
+ SymbolTable, Data, base() + COFFHeader->PointerToSymbolTable,
+ COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))
+ return ec;
+
+ // Find string table. The first four byte of the string table contains the
+ // total size of the string table, including the size field itself. If the
+ // string table is empty, the value of the first four byte would be 4.
+ const uint8_t *StringTableAddr =
+ base() + COFFHeader->PointerToSymbolTable +
+ COFFHeader->NumberOfSymbols * sizeof(coff_symbol);
+ const ulittle32_t *StringTableSizePtr;
+ if (error_code ec = getObject(StringTableSizePtr, Data, StringTableAddr))
+ return ec;
+ StringTableSize = *StringTableSizePtr;
+ if (error_code ec =
+ getObject(StringTable, Data, StringTableAddr, StringTableSize))
+ return ec;
+
+ // Check that the string table is null terminated if has any in it.
+ if (StringTableSize < 4 ||
+ (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0))
+ return object_error::parse_failed;
+ return object_error::success;
+}
+
+// Returns the file offset for the given RVA.
+error_code COFFObjectFile::getRvaPtr(uint32_t Rva, uintptr_t &Res) const {
+ error_code ec;
+ for (section_iterator i = begin_sections(), e = end_sections(); i != e;
+ i.increment(ec)) {
+ if (ec)
+ return ec;
+ const coff_section *Section = getCOFFSection(i);
+ uint32_t SectionStart = Section->VirtualAddress;
+ uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize;
+ if (SectionStart <= Rva && Rva < SectionEnd) {
+ uint32_t Offset = Rva - SectionStart;
+ Res = uintptr_t(base()) + Section->PointerToRawData + Offset;
+ return object_error::success;
+ }
+ }
+ return object_error::parse_failed;
+}
+
+// Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name
+// table entry.
+error_code COFFObjectFile::
+getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const {
+ uintptr_t IntPtr = 0;
+ if (error_code ec = getRvaPtr(Rva, IntPtr))
+ return ec;
+ const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);
+ Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);
+ Name = StringRef(reinterpret_cast<const char *>(Ptr + 2));
+ return object_error::success;
+}
+
+// Find the import table.
+error_code COFFObjectFile::initImportTablePtr() {
+ // First, we get the RVA of the import table. If the file lacks a pointer to
+ // the import table, do nothing.
+ const data_directory *DataEntry;
+ if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry))
+ return object_error::success;
+
+ // Do nothing if the pointer to import table is NULL.
+ if (DataEntry->RelativeVirtualAddress == 0)
+ return object_error::success;
+
+ uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress;
+ NumberOfImportDirectory = DataEntry->Size /
+ sizeof(import_directory_table_entry);
+
+ // 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 (error_code ec = getRvaPtr(ImportTableRva, IntPtr))
+ return ec;
+ ImportDirectory = reinterpret_cast<
+ const import_directory_table_entry *>(IntPtr);
+
+ // It's an error if there's no section containing the Import Table RVA.
+ return object_error::parse_failed;
+}
+
COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec)
: ObjectFile(Binary::ID_COFF, Object)
, COFFHeader(0)
, SectionTable(0)
, SymbolTable(0)
, StringTable(0)
- , StringTableSize(0) {
+ , StringTableSize(0)
+ , ImportDirectory(0)
+ , NumberOfImportDirectory(0) {
// Check that we at least have enough room for a header.
if (!checkSize(Data, ec, sizeof(coff_file_header))) return;
COFFHeader->NumberOfSections * sizeof(coff_section))))
return;
- if (COFFHeader->PointerToSymbolTable != 0) {
- if ((ec = getObject(SymbolTable, Data,
- base() + COFFHeader->PointerToSymbolTable,
- COFFHeader->NumberOfSymbols * sizeof(coff_symbol))))
+ // Initialize the pointer to the symbol table.
+ if (COFFHeader->PointerToSymbolTable != 0)
+ if ((ec = initSymbolTablePtr()))
return;
- // Find string table. The first four byte of the string table contains the
- // total size of the string table, including the size field itself. If the
- // string table is empty, the value of the first four byte would be 4.
- const uint8_t *StringTableAddr = base() + COFFHeader->PointerToSymbolTable
- + COFFHeader->NumberOfSymbols * sizeof(coff_symbol);
- const ulittle32_t *StringTableSizePtr;
- if ((ec = getObject(StringTableSizePtr, Data, StringTableAddr)))
- return;
- StringTableSize = *StringTableSizePtr;
- if ((ec = getObject(StringTable, Data, StringTableAddr, StringTableSize)))
- return;
-
- // Check that the string table is null terminated if has any in it.
- if (StringTableSize < 4
- || (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) {
- ec = object_error::parse_failed;
- return;
- }
- }
+ // Initialize the pointer to the beginning of the import table.
+ if ((ec = initImportTablePtr()))
+ return;
ec = object_error::success;
}
symbol_iterator COFFObjectFile::begin_symbols() const {
DataRefImpl ret;
- ret.p = reinterpret_cast<intptr_t>(SymbolTable);
+ ret.p = reinterpret_cast<uintptr_t>(SymbolTable);
return symbol_iterator(SymbolRef(ret, this));
}
symbol_iterator COFFObjectFile::end_symbols() const {
// The symbol table ends where the string table begins.
DataRefImpl ret;
- ret.p = reinterpret_cast<intptr_t>(StringTable);
+ ret.p = reinterpret_cast<uintptr_t>(StringTable);
return symbol_iterator(SymbolRef(ret, this));
}
return "";
}
+import_directory_iterator COFFObjectFile::getImportDirectoryBegin() const {
+ DataRefImpl Imp;
+ Imp.p = reinterpret_cast<uintptr_t>(ImportDirectory);
+ return import_directory_iterator(ImportDirectoryEntryRef(Imp, this));
+}
+
+import_directory_iterator COFFObjectFile::getImportDirectoryEnd() const {
+ DataRefImpl Imp;
+ if (ImportDirectory) {
+ Imp.p = reinterpret_cast<uintptr_t>(
+ ImportDirectory + (NumberOfImportDirectory - 1));
+ } else {
+ Imp.p = 0;
+ }
+ return import_directory_iterator(ImportDirectoryEntryRef(Imp, this));
+}
section_iterator COFFObjectFile::begin_sections() const {
DataRefImpl ret;
- ret.p = reinterpret_cast<intptr_t>(SectionTable);
+ ret.p = reinterpret_cast<uintptr_t>(SectionTable);
return section_iterator(SectionRef(ret, this));
}
section_iterator COFFObjectFile::end_sections() const {
DataRefImpl ret;
- ret.p = reinterpret_cast<intptr_t>(SectionTable + COFFHeader->NumberOfSections);
+ ret.p = reinterpret_cast<uintptr_t>(SectionTable + COFFHeader->NumberOfSections);
return section_iterator(SectionRef(ret, this));
}
ArrayRef<uint8_t> COFFObjectFile::getSymbolAuxData(
const coff_symbol *symbol) const {
const uint8_t *aux = NULL;
-
+
if ( symbol->NumberOfAuxSymbols > 0 ) {
// AUX data comes immediately after the symbol in COFF
aux = reinterpret_cast<const uint8_t *>(symbol + 1);
return toRel(It->getRawDataRefImpl());
}
-
#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \
case COFF::enum: res = #enum; break;
report_fatal_error("getLibraryPath not implemented in COFFObjectFile");
}
+bool ImportDirectoryEntryRef::
+operator==(const ImportDirectoryEntryRef &Other) const {
+ return ImportDirectoryPimpl == Other.ImportDirectoryPimpl;
+}
+
+static const import_directory_table_entry *toImportEntry(DataRefImpl Imp) {
+ return reinterpret_cast<const import_directory_table_entry *>(Imp.p);
+}
+
+error_code
+ImportDirectoryEntryRef::getNext(ImportDirectoryEntryRef &Result) const {
+ const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl);
+ Dir += 1;
+ DataRefImpl Next;
+ Next.p = reinterpret_cast<uintptr_t>(Dir);
+ Result = ImportDirectoryEntryRef(Next, OwningObject);
+ return object_error::success;
+}
+
+error_code ImportDirectoryEntryRef::
+getImportTableEntry(const import_directory_table_entry *&Result) const {
+ Result = toImportEntry(ImportDirectoryPimpl);
+ return object_error::success;
+}
+
+error_code ImportDirectoryEntryRef::getName(StringRef &Result) const {
+ const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl);
+ uintptr_t IntPtr = 0;
+ if (error_code ec = OwningObject->getRvaPtr(Dir->NameRVA, IntPtr))
+ return ec;
+ const char *Ptr = reinterpret_cast<const char *>(IntPtr);
+ Result = StringRef(Ptr);
+ return object_error::success;
+}
+
+error_code ImportDirectoryEntryRef::getImportLookupEntry(
+ const import_lookup_table_entry32 *&Result) const {
+ const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl);
+ uintptr_t IntPtr = 0;
+ if (error_code ec = OwningObject->getRvaPtr(
+ Dir->ImportLookupTableRVA, IntPtr))
+ return ec;
+ Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr);
+ return object_error::success;
+}
+
namespace llvm {
ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) {
--- /dev/null
+ .text
+ .globl func
+ .def func; .scl 2; .type 32; .endef
+ .seh_proc func
+func:
+ .seh_pushframe @code
+ subq $24, %rsp
+ .seh_stackalloc 24
+ movq %rsi, 16(%rsp)
+ .seh_savereg %rsi, 16
+ movups %xmm8, (%rsp)
+ .seh_savexmm %xmm8, 0
+ pushq %rbx
+ .seh_pushreg 3
+ mov %rsp, %rbx
+ .seh_setframe 3, 0
+ .seh_endprologue
+ .seh_handler __C_specific_handler, @except
+ .seh_handlerdata
+ .long 0
+ .text
+ .seh_startchained
+ .seh_endprologue
+ .seh_endchained
+ lea (%rbx), %rsp
+ pop %rbx
+ addq $24, %rsp
+ ret
+ .seh_endproc
+
+// Test emission of small functions.
+ .globl smallFunc
+ .def smallFunc; .scl 2; .type 32; .endef
+ .seh_proc smallFunc
+smallFunc:
+ ret
+ .seh_endproc
+
+// Function with big stack allocation.
+ .globl allocFunc
+ .def allocFunc; .scl 2; .type 32; .endef
+ .seh_proc allocFunc
+allocFunc:
+ .seh_pushframe @code
+ subq $65520, %rsp
+ .seh_stackalloc 65520
+ sub $8454128, %rsp
+ .seh_stackalloc 8454128
+ .seh_endprologue
+ add $8454128, %rsp
+ addq $65520, %rsp
+ ret
+ .seh_endproc
--- /dev/null
+// RUN: llvm-objdump -p %p/Inputs/nop.exe.coff-i386 | FileCheck %s
+
+CHECK: The Import Tables:
+CHECK-NEXT: lookup 00005028 time 00000000 fwd 00000000 name 00005096 addr 00005058
+CHECK: DLL Name: KERNEL32.dll
+CHECK-NEXT: Hint/Ord Name
+CHECK-NEXT: 365 ExitProcess
+
+
+++ /dev/null
-// RUN: llvm-mc -filetype=obj -arch=x86 %s | llvm-objdump -d - \
-// RUN: | FileCheck %s -check-prefix=WITHRAW
-// RUN: llvm-mc -filetype=obj -arch=x86 %s | llvm-objdump -d -no-show-raw-insn - \
-// RUN: | FileCheck %s -check-prefix=NORAW
-
-// Expect to find the raw incoding when run with raw output (default), but not
-// when run explicitly with -no-show-raw-insn
-
-movl 0, %eax
-// WITHRAW: a1 00 00 00 00 movl
-
-// NORAW: movl
-// NORAW-NOT: a1 00
-
-
--- /dev/null
+// RUN: llvm-objdump -d %p/Inputs/trivial.obj.elf-i386 \
+// RUN: | FileCheck %s -check-prefix=WITHRAW
+// RUN: llvm-objdump -d -no-show-raw-insn %p/Inputs/trivial.obj.elf-i386 \
+// RUN: | FileCheck %s -check-prefix=NORAW
+
+// Expect to find the raw incoding when run with raw output (default), but not
+// when run explicitly with -no-show-raw-insn
+
+WITHRAW: a1 00 00 00 00 movl
+
+NORAW: movl
+NORAW-NOT: a1 00
+
+
+++ /dev/null
-targets = set(config.root.targets_to_build.split())
-if not 'X86' in targets:
- config.unsupported = True
-
+++ /dev/null
-// This test checks that the unwind data is dumped by llvm-objdump.
-// RUN: llvm-mc -triple x86_64-pc-win32 -filetype=obj %s | llvm-objdump -u - | FileCheck %s
-
-// CHECK: Unwind info:
-// CHECK: Function Table:
-// CHECK-NEXT: Start Address: func
-// CHECK-NEXT: End Address: func + 0x001b
-// CHECK-NEXT: Unwind Info Address: .xdata
-// CHECK-NEXT: Version: 1
-// CHECK-NEXT: Flags: 1 UNW_ExceptionHandler
-// CHECK-NEXT: Size of prolog: 18
-// CHECK-NEXT: Number of Codes: 8
-// CHECK-NEXT: Frame register: RBX
-// CHECK-NEXT: Frame offset: 0
-// CHECK-NEXT: Unwind Codes:
-// CHECK-NEXT: 0x12: UOP_SetFPReg
-// CHECK-NEXT: 0x0f: UOP_PushNonVol RBX
-// CHECK-NEXT: 0x0e: UOP_SaveXMM128 XMM8 [0x0000]
-// CHECK-NEXT: 0x09: UOP_SaveNonVol RSI [0x0010]
-// CHECK-NEXT: 0x04: UOP_AllocSmall 24
-// CHECK-NEXT: 0x00: UOP_PushMachFrame w/o error code
-// CHECK: Function Table:
-// CHECK-NEXT: Start Address: func + 0x0012
-// CHECK-NEXT: End Address: func + 0x0012
-// CHECK-NEXT: Unwind Info Address: .xdata + 0x001c
-// CHECK-NEXT: Version: 1
-// CHECK-NEXT: Flags: 4 UNW_ChainInfo
-// CHECK-NEXT: Size of prolog: 0
-// CHECK-NEXT: Number of Codes: 0
-// CHECK-NEXT: No frame pointer used
-// CHECK: Function Table:
-// CHECK-NEXT: Start Address: smallFunc
-// CHECK-NEXT: End Address: smallFunc + 0x0001
-// CHECK-NEXT: Unwind Info Address: .xdata + 0x002c
-// CHECK-NEXT: Version: 1
-// CHECK-NEXT: Flags: 0
-// CHECK-NEXT: Size of prolog: 0
-// CHECK-NEXT: Number of Codes: 0
-// CHECK-NEXT: No frame pointer used
-// CHECK: Function Table:
-// CHECK-NEXT: Start Address: allocFunc
-// CHECK-NEXT: End Address: allocFunc + 0x001d
-// CHECK-NEXT: Unwind Info Address: .xdata + 0x0034
-// CHECK-NEXT: Version: 1
-// CHECK-NEXT: Flags: 0
-// CHECK-NEXT: Size of prolog: 14
-// CHECK-NEXT: Number of Codes: 6
-// CHECK-NEXT: No frame pointer used
-// CHECK-NEXT: Unwind Codes:
-// CHECK-NEXT: 0x0e: UOP_AllocLarge 8454128
-// CHECK-NEXT: 0x07: UOP_AllocLarge 8190
-// CHECK-NEXT: 0x00: UOP_PushMachFrame w/o error code
-
- .text
- .globl func
- .def func; .scl 2; .type 32; .endef
- .seh_proc func
-func:
- .seh_pushframe @code
- subq $24, %rsp
- .seh_stackalloc 24
- movq %rsi, 16(%rsp)
- .seh_savereg %rsi, 16
- movups %xmm8, (%rsp)
- .seh_savexmm %xmm8, 0
- pushq %rbx
- .seh_pushreg 3
- mov %rsp, %rbx
- .seh_setframe 3, 0
- .seh_endprologue
- .seh_handler __C_specific_handler, @except
- .seh_handlerdata
- .long 0
- .text
- .seh_startchained
- .seh_endprologue
- .seh_endchained
- lea (%rbx), %rsp
- pop %rbx
- addq $24, %rsp
- ret
- .seh_endproc
-
-// Test emission of small functions.
- .globl smallFunc
- .def smallFunc; .scl 2; .type 32; .endef
- .seh_proc smallFunc
-smallFunc:
- ret
- .seh_endproc
-
-// Function with big stack allocation.
- .globl allocFunc
- .def allocFunc; .scl 2; .type 32; .endef
- .seh_proc allocFunc
-allocFunc:
- .seh_pushframe @code
- subq $65520, %rsp
- .seh_stackalloc 65520
- sub $8454128, %rsp
- .seh_stackalloc 8454128
- .seh_endprologue
- add $8454128, %rsp
- addq $65520, %rsp
- ret
- .seh_endproc
--- /dev/null
+// This test checks that the unwind data is dumped by llvm-objdump.
+// RUN: llvm-objdump -u %p/Inputs/win64-unwind.exe.coff-x86_64 | FileCheck %s
+
+CHECK: Unwind info:
+CHECK: Function Table:
+CHECK-NEXT: Start Address: func
+CHECK-NEXT: End Address: func + 0x001b
+CHECK-NEXT: Unwind Info Address: .xdata
+CHECK-NEXT: Version: 1
+CHECK-NEXT: Flags: 1 UNW_ExceptionHandler
+CHECK-NEXT: Size of prolog: 18
+CHECK-NEXT: Number of Codes: 8
+CHECK-NEXT: Frame register: RBX
+CHECK-NEXT: Frame offset: 0
+CHECK-NEXT: Unwind Codes:
+CHECK-NEXT: 0x12: UOP_SetFPReg
+CHECK-NEXT: 0x0f: UOP_PushNonVol RBX
+CHECK-NEXT: 0x0e: UOP_SaveXMM128 XMM8 [0x0000]
+CHECK-NEXT: 0x09: UOP_SaveNonVol RSI [0x0010]
+CHECK-NEXT: 0x04: UOP_AllocSmall 24
+CHECK-NEXT: 0x00: UOP_PushMachFrame w/o error code
+CHECK: Function Table:
+CHECK-NEXT: Start Address: func + 0x0012
+CHECK-NEXT: End Address: func + 0x0012
+CHECK-NEXT: Unwind Info Address: .xdata + 0x001c
+CHECK-NEXT: Version: 1
+CHECK-NEXT: Flags: 4 UNW_ChainInfo
+CHECK-NEXT: Size of prolog: 0
+CHECK-NEXT: Number of Codes: 0
+CHECK-NEXT: No frame pointer used
+CHECK: Function Table:
+CHECK-NEXT: Start Address: smallFunc
+CHECK-NEXT: End Address: smallFunc + 0x0001
+CHECK-NEXT: Unwind Info Address: .xdata + 0x002c
+CHECK-NEXT: Version: 1
+CHECK-NEXT: Flags: 0
+CHECK-NEXT: Size of prolog: 0
+CHECK-NEXT: Number of Codes: 0
+CHECK-NEXT: No frame pointer used
+CHECK: Function Table:
+CHECK-NEXT: Start Address: allocFunc
+CHECK-NEXT: End Address: allocFunc + 0x001d
+CHECK-NEXT: Unwind Info Address: .xdata + 0x0034
+CHECK-NEXT: Version: 1
+CHECK-NEXT: Flags: 0
+CHECK-NEXT: Size of prolog: 14
+CHECK-NEXT: Number of Codes: 6
+CHECK-NEXT: No frame pointer used
+CHECK-NEXT: Unwind Codes:
+CHECK-NEXT: 0x0e: UOP_AllocLarge 8454128
+CHECK-NEXT: 0x07: UOP_AllocLarge 8190
+CHECK-NEXT: 0x00: UOP_PushMachFrame w/o error code
Out << format(" + 0x%04x", Disp);
}
+// Prints import tables. The import table is a table containing the list of
+// DLL name and symbol names which will be linked by the loader.
+static void printImportTables(const COFFObjectFile *Obj) {
+ outs() << "The Import Tables:\n";
+ error_code ec;
+ for (import_directory_iterator i = Obj->getImportDirectoryBegin(),
+ e = Obj->getImportDirectoryEnd();
+ i != e; i = i.increment(ec)) {
+ if (ec)
+ return;
+
+ const import_directory_table_entry *Dir;
+ StringRef Name;
+ if (i->getImportTableEntry(Dir)) return;
+ if (i->getName(Name)) return;
+
+ outs() << format(" lookup %08x time %08x fwd %08x name %08x addr %08x\n\n",
+ static_cast<uint32_t>(Dir->ImportLookupTableRVA),
+ static_cast<uint32_t>(Dir->TimeDateStamp),
+ static_cast<uint32_t>(Dir->ForwarderChain),
+ static_cast<uint32_t>(Dir->NameRVA),
+ 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());
+ continue;
+ }
+ uint16_t Hint;
+ StringRef Name;
+ if (Obj->getHintName(entry->getHintNameRVA(), Hint, Name))
+ return;
+ outs() << format(" % 6d ", Hint) << Name << "\n";
+ }
+ outs() << "\n";
+ }
+}
+
void llvm::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
const coff_file_header *Header;
if (error(Obj->getCOFFHeader(Header))) return;
}
}
}
+
+void llvm::printCOFFFileHeader(const object::ObjectFile *Obj) {
+ printImportTables(dyn_cast<const COFFObjectFile>(Obj));
+}
}
}
+static void printPrivateFileHeader(const ObjectFile *o) {
+ if (o->isELF()) {
+ printELFFileHeader(o);
+ } else if (o->isCOFF()) {
+ printCOFFFileHeader(o);
+ }
+}
+
static void DumpObject(const ObjectFile *o) {
outs() << '\n';
outs() << o->getFileName()
PrintSymbolTable(o);
if (UnwindInfo)
PrintUnwindInfo(o);
- if (PrivateHeaders && o->isELF())
- printELFFileHeader(o);
+ if (PrivateHeaders)
+ printPrivateFileHeader(o);
}
/// @brief Dump each object file in \a a;
void DisassembleInputMachO(StringRef Filename);
void printCOFFUnwindInfo(const object::COFFObjectFile* o);
void printELFFileHeader(const object::ObjectFile *o);
+void printCOFFFileHeader(const object::ObjectFile *o);
-}
+} // end namespace llvm
#endif