write32le(Buf + FileOff, HintName->getRVA());
}
+void OrdinalOnlyChunk::writeTo(uint8_t *Buf) {
+ // An import-by-ordinal slot has MSB 1 to indicate that
+ // this is import-by-ordinal (and not import-by-name).
+ write64le(Buf + FileOff, (uint64_t(1) << 63) | Ordinal);
+}
+
void DirectoryChunk::applyRelocations(uint8_t *Buf) {
auto *E = (coff_import_directory_table_entry *)(Buf + FileOff);
E->ImportLookupTableRVA = LookupTab->getRVA();
ImportTable::ImportTable(StringRef N,
std::vector<DefinedImportData *> &Symbols) {
+ // Create the import table hader.
DLLName = new StringChunk(N);
DirTab = new DirectoryChunk(DLLName);
- for (DefinedImportData *S : Symbols)
- HintNameTables.push_back(
- new HintNameChunk(S->getExportName(), S->getOrdinal()));
- for (Chunk *H : HintNameTables) {
- LookupTables.push_back(new LookupChunk(H));
- AddressTables.push_back(new LookupChunk(H));
+ // Create lookup and address tables. If they have external names,
+ // we need to create HintName chunks to store the names.
+ // If they don't (if they are import-by-ordinals), we store only
+ // ordinal values to the table.
+ for (DefinedImportData *S : Symbols) {
+ if (S->getExternalName().empty()) {
+ LookupTables.push_back(new OrdinalOnlyChunk(S->getOrdinal()));
+ AddressTables.push_back(new OrdinalOnlyChunk(S->getOrdinal()));
+ continue;
+ }
+ Chunk *C = new HintNameChunk(S->getExternalName(), S->getOrdinal());
+ HintNameTables.push_back(C);
+ LookupTables.push_back(new LookupChunk(C));
+ AddressTables.push_back(new LookupChunk(C));
}
-
for (int I = 0, E = Symbols.size(); I < E; ++I)
Symbols[I]->setLocation(AddressTables[I]);
-
DirTab->LookupTab = LookupTables[0];
DirTab->AddressTab = AddressTables[0];
}
};
// A chunk for the import descriptor table.
+// This chunk represent import-by-ordinal symbols.
+// See the Microsoft PE/COFF spec 7.1. Import Header for details.
+class OrdinalOnlyChunk : public Chunk {
+public:
+ explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {}
+ bool hasData() const override { return true; }
+ size_t getSize() const override { return sizeof(uint64_t); }
+ void writeTo(uint8_t *Buf) override;
+ uint16_t Ordinal;
+};
+
+// A chunk for the import descriptor table.
class DirectoryChunk : public Chunk {
public:
explicit DirectoryChunk(Chunk *N) : DLLName(N) {}
StringRef Name = StringAlloc.save(StringRef(Buf + sizeof(*Hdr)));
StringRef ImpName = StringAlloc.save(Twine("__imp_") + Name);
StringRef DLLName(Buf + sizeof(coff_import_header) + Name.size() + 1);
- auto *ImpSym = new (Alloc) DefinedImportData(DLLName, ImpName, Name, Hdr);
+ StringRef ExternalName = Name;
+ if (Hdr->getNameType() == llvm::COFF::IMPORT_ORDINAL)
+ ExternalName = "";
+ auto *ImpSym = new (Alloc) DefinedImportData(DLLName, ImpName, ExternalName,
+ Hdr);
SymbolBodies.push_back(ImpSym);
// If type is function, we need to create a thunk which jump to an
// table in an output. The former has "__imp_" prefix.
class DefinedImportData : public Defined {
public:
- DefinedImportData(StringRef D, StringRef ImportName, StringRef ExportName,
+ DefinedImportData(StringRef D, StringRef Name, StringRef E,
const coff_import_header *H)
- : Defined(DefinedImportDataKind, ImportName), DLLName(D),
- ExpName(ExportName), Hdr(H) {}
+ : Defined(DefinedImportDataKind, Name), DLLName(D),
+ ExternalName(E), Hdr(H) {}
static bool classof(const SymbolBody *S) {
return S->kind() == DefinedImportDataKind;
uint64_t getRVA() override { return Location->getRVA(); }
uint64_t getFileOff() override { return Location->getFileOff(); }
StringRef getDLLName() { return DLLName; }
- StringRef getExportName() { return ExpName; }
+ StringRef getExternalName() { return ExternalName; }
void setLocation(Chunk *AddressTable) { Location = AddressTable; }
uint16_t getOrdinal() { return Hdr->OrdinalHint; }
private:
StringRef DLLName;
- StringRef ExpName;
+ StringRef ExternalName;
const coff_import_header *Hdr;
Chunk *Location = nullptr;
};
extern ExitProcess : PROC
extern MessageBoxA : PROC
+extern ImportByOrdinal: PROC
.data
caption db 'Hello', 0
call MessageBoxA
mov ecx, 0
call ExitProcess
+ call ImportByOrdinal
main ENDP
END
TEXT-NEXT: leaq -4108(%rip), %rdx
TEXT-NEXT: leaq -4121(%rip), %r8
TEXT-NEXT: movl $0, %r9d
-TEXT-NEXT: callq 16
+TEXT-NEXT: callq 27
TEXT-NEXT: movl $0, %ecx
-TEXT-NEXT: callq 0
-TEXT-NEXT: jmpq *4108(%rip)
-TEXT-NEXT: jmpq *4110(%rip)
+TEXT-NEXT: callq 5
+TEXT-NEXT: callq 6
+TEXT-NEXT: jmpq *4111(%rip)
+TEXT-NEXT: jmpq *4113(%rip)
+TEXT-NEXT: jmpq *4115(%rip)
IMPORT: Import {
IMPORT-NEXT: Name: std64.dll
IMPORT-NEXT: ImportLookupTableRVA: 0x3028
-IMPORT-NEXT: ImportAddressTableRVA: 0x3040
+IMPORT-NEXT: ImportAddressTableRVA: 0x3048
IMPORT-NEXT: Symbol: ExitProcess (0)
+IMPORT-NEXT: Symbol: (50)
IMPORT-NEXT: Symbol: MessageBoxA (1)
IMPORT-NEXT: }