[lld] r238780 - COFF: Support import-by-ordinal DLL imports.

Rui Ueyama ruiu at google.com
Mon Jun 1 14:05:28 PDT 2015


Author: ruiu
Date: Mon Jun  1 16:05:27 2015
New Revision: 238780

URL: http://llvm.org/viewvc/llvm-project?rev=238780&view=rev
Log:
COFF: Support import-by-ordinal DLL imports.

Symbols exported by DLLs can be imported not by name but by
small number or ordinal. Usually, symbols have both ordinals
and names, and in that case ordinals are called "hints" and
used by the loader as hints.

However, symbols can have only ordinals. They are called
import-by-ordinal symbols. You need to manage ordinals by hand
so that they will never change if you choose to use the feature.
But it's supposed to make dynamic linking faster because
it needs no string comparison. Not sure if that claim still
stands in year 2015, though. Anyways, the feature exists,
and this patch implements that.

Modified:
    lld/trunk/COFF/Chunks.cpp
    lld/trunk/COFF/Chunks.h
    lld/trunk/COFF/InputFiles.cpp
    lld/trunk/COFF/Symbols.h
    lld/trunk/test/COFF/Inputs/hello64.asm
    lld/trunk/test/COFF/Inputs/hello64.obj
    lld/trunk/test/COFF/Inputs/std64.lib
    lld/trunk/test/COFF/imports.test

Modified: lld/trunk/COFF/Chunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.cpp?rev=238780&r1=238779&r2=238780&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.cpp (original)
+++ lld/trunk/COFF/Chunks.cpp Mon Jun  1 16:05:27 2015
@@ -186,6 +186,12 @@ void LookupChunk::applyRelocations(uint8
   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(ui
 
 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];
 }

Modified: lld/trunk/COFF/Chunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.h?rev=238780&r1=238779&r2=238780&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.h (original)
+++ lld/trunk/COFF/Chunks.h Mon Jun  1 16:05:27 2015
@@ -214,6 +214,18 @@ public:
 };
 
 // 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) {}

Modified: lld/trunk/COFF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.cpp?rev=238780&r1=238779&r2=238780&view=diff
==============================================================================
--- lld/trunk/COFF/InputFiles.cpp (original)
+++ lld/trunk/COFF/InputFiles.cpp Mon Jun  1 16:05:27 2015
@@ -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

Modified: lld/trunk/COFF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Symbols.h?rev=238780&r1=238779&r2=238780&view=diff
==============================================================================
--- lld/trunk/COFF/Symbols.h (original)
+++ lld/trunk/COFF/Symbols.h Mon Jun  1 16:05:27 2015
@@ -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;
 };

Modified: lld/trunk/test/COFF/Inputs/hello64.asm
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/Inputs/hello64.asm?rev=238780&r1=238779&r2=238780&view=diff
==============================================================================
--- lld/trunk/test/COFF/Inputs/hello64.asm (original)
+++ lld/trunk/test/COFF/Inputs/hello64.asm Mon Jun  1 16:05:27 2015
@@ -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

Modified: lld/trunk/test/COFF/Inputs/hello64.obj
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/Inputs/hello64.obj?rev=238780&r1=238779&r2=238780&view=diff
==============================================================================
Binary files lld/trunk/test/COFF/Inputs/hello64.obj (original) and lld/trunk/test/COFF/Inputs/hello64.obj Mon Jun  1 16:05:27 2015 differ

Modified: lld/trunk/test/COFF/Inputs/std64.lib
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/Inputs/std64.lib?rev=238780&r1=238779&r2=238780&view=diff
==============================================================================
Binary files lld/trunk/test/COFF/Inputs/std64.lib (original) and lld/trunk/test/COFF/Inputs/std64.lib Mon Jun  1 16:05:27 2015 differ

Modified: lld/trunk/test/COFF/imports.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/imports.test?rev=238780&r1=238779&r2=238780&view=diff
==============================================================================
--- lld/trunk/test/COFF/imports.test (original)
+++ lld/trunk/test/COFF/imports.test Mon Jun  1 16:05:27 2015
@@ -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: }





More information about the llvm-commits mailing list