diff --git a/lld/COFF/Chunks.cpp b/lld/COFF/Chunks.cpp index 3a64a78bf559..5a151ea4d0ad 100644 --- a/lld/COFF/Chunks.cpp +++ b/lld/COFF/Chunks.cpp @@ -186,6 +186,12 @@ void LookupChunk::applyRelocations(uint8_t *Buf) { 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(); @@ -195,20 +201,27 @@ void DirectoryChunk::applyRelocations(uint8_t *Buf) { ImportTable::ImportTable(StringRef N, std::vector &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]; } diff --git a/lld/COFF/Chunks.h b/lld/COFF/Chunks.h index c4dc7282aada..967f94277209 100644 --- a/lld/COFF/Chunks.h +++ b/lld/COFF/Chunks.h @@ -213,6 +213,18 @@ public: Chunk *HintName; }; +// 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: diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp index e2a597a168fa..0205328495ed 100644 --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -229,7 +229,11 @@ std::error_code ImportFile::parse() { 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 diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h index 4641ecea185a..f866718e3b76 100644 --- a/lld/COFF/Symbols.h +++ b/lld/COFF/Symbols.h @@ -207,10 +207,10 @@ private: // 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; @@ -219,13 +219,13 @@ public: 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; }; diff --git a/lld/test/COFF/Inputs/hello64.asm b/lld/test/COFF/Inputs/hello64.asm index 1aa5629e26d8..6605213224bc 100644 --- a/lld/test/COFF/Inputs/hello64.asm +++ b/lld/test/COFF/Inputs/hello64.asm @@ -3,6 +3,7 @@ extern ExitProcess : PROC extern MessageBoxA : PROC +extern ImportByOrdinal: PROC .data caption db 'Hello', 0 @@ -18,5 +19,6 @@ main PROC call MessageBoxA mov ecx, 0 call ExitProcess + call ImportByOrdinal main ENDP END diff --git a/lld/test/COFF/Inputs/hello64.obj b/lld/test/COFF/Inputs/hello64.obj index 0ae241e2013e..90c1ce4aa4cf 100644 Binary files a/lld/test/COFF/Inputs/hello64.obj and b/lld/test/COFF/Inputs/hello64.obj differ diff --git a/lld/test/COFF/Inputs/std64.lib b/lld/test/COFF/Inputs/std64.lib index 9c47d4f6accc..bbd223c59f40 100644 Binary files a/lld/test/COFF/Inputs/std64.lib and b/lld/test/COFF/Inputs/std64.lib differ diff --git a/lld/test/COFF/imports.test b/lld/test/COFF/imports.test index 1bc358ef4880..a336217b8fdf 100644 --- a/lld/test/COFF/imports.test +++ b/lld/test/COFF/imports.test @@ -12,16 +12,19 @@ TEXT-NEXT: movq $0, %rcx 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: }