[lld] r207476 - [PECOFF] Fix _imp_ implicit symbols.

Rui Ueyama ruiu at google.com
Mon Apr 28 17:32:00 PDT 2014


Author: ruiu
Date: Mon Apr 28 19:32:00 2014
New Revision: 207476

URL: http://llvm.org/viewvc/llvm-project?rev=207476&view=rev
Log:
[PECOFF] Fix _imp_ implicit symbols.

Implicit symbol for local use implemented in r207141 was not fully
compatible with MSVC link.exe. In r207141, I implemented the feature
in such way that implicit symbols are defined only when they are
exported with /EXPORT option.

After that I found that implicit symbols are defined not only for
dllexported symbols but for all defined symbols. Actually _imp_
implicit symbols have no relationship with the dllexport feature. You
could add _imp_ to any symbol to get a pointer to the symbol, whether
the symbol is dllexported or not.  It looks pretty weird to me but
that's what we want if link.exe behaves that way.

Here is a bit about the implementation: Creating all implicit symbols
beforehand is going to be a huge waste of resource. This feature is
rarely used, and MSVC link.exe even prints out a warning message when
it finds this feature is being used. So we create implicit symbols
on demand. There is an archive file that creates implicit symbols when
they are needed.

Added:
    lld/trunk/test/pecoff/localyimported.test
Modified:
    lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
    lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
    lld/trunk/test/pecoff/reloc.test

Modified: lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h?rev=207476&r1=207475&r2=207476&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h Mon Apr 28 19:32:00 2014
@@ -9,6 +9,7 @@
 
 #include "Atoms.h"
 
+#include "lld/Core/ArchiveLibraryFile.h"
 #include "lld/ReaderWriter/PECOFFLinkingContext.h"
 #include "lld/ReaderWriter/Simple.h"
 #include "llvm/Support/Allocator.h"
@@ -16,6 +17,8 @@
 namespace lld {
 namespace pecoff {
 
+namespace {
+
 /// The defined atom for dllexported symbols with __imp_ prefix.
 class ImpPointerAtom : public COFFLinkerInternalAtom {
 public:
@@ -34,6 +37,24 @@ private:
   uint64_t _ordinal;
 };
 
+class ImpSymbolFile : public SimpleFile {
+public:
+  ImpSymbolFile(StringRef defsym, StringRef undefsym, uint64_t ordinal)
+      : SimpleFile(defsym), _undefined(*this, undefsym),
+        _defined(*this, defsym, ordinal) {
+    _defined.addReference(std::unique_ptr<COFFReference>(
+        new COFFReference(&_undefined, 0, llvm::COFF::IMAGE_REL_I386_DIR32)));
+    addAtom(_defined);
+    addAtom(_undefined);
+  };
+
+private:
+  SimpleUndefinedAtom _undefined;
+  ImpPointerAtom _defined;
+};
+
+} // anonymous namespace
+
 // A virtual file containing absolute symbol __ImageBase. __ImageBase (or
 // ___ImageBase on x86) is a linker-generated symbol whose address is the same
 // as the image base address.
@@ -44,31 +65,73 @@ public:
         _imageBaseAtom(*this, ctx.decorateSymbol("__ImageBase"),
                        Atom::scopeGlobal, ctx.getBaseAddress()) {
     addAtom(_imageBaseAtom);
-    _ordinal = 1;
-
-    // Create implciit symbols for exported symbols.
-    for (const PECOFFLinkingContext::ExportDesc &exp : ctx.getDllExports()) {
-      UndefinedAtom *target = new (_alloc) SimpleUndefinedAtom(*this, exp.name);
-      COFFLinkerInternalAtom *imp = createImpPointerAtom(ctx, exp.name);
-      imp->addReference(std::unique_ptr<COFFReference>(
-          new COFFReference(target, 0, llvm::COFF::IMAGE_REL_I386_DIR32)));
-      addAtom(*target);
-      addAtom(*imp);
-    }
   };
 
 private:
-  COFFLinkerInternalAtom *createImpPointerAtom(const PECOFFLinkingContext &ctx,
-                                               StringRef name) {
-    std::string sym = "_imp_";
-    sym.append(name);
-    sym = ctx.decorateSymbol(sym);
-    return new (_alloc) ImpPointerAtom(*this, ctx.allocate(sym), _ordinal++);
+  COFFAbsoluteAtom _imageBaseAtom;
+};
+
+// A LocallyImporteSymbolFile is an archive file containing _imp_
+// symbols for local use.
+//
+// For each defined symbol, linker creates an implicit defined symbol
+// by appending "_imp_" prefix to the original name. The content of
+// the implicit symbol is a pointer to the original symbol
+// content. This feature allows one to compile and link the following
+// code without error, although _imp__hello is not defined in the
+// code.
+//
+//   void hello() { printf("Hello\n"); }
+//   extern void (*_imp__hello)();
+//   int main() {
+//      _imp__hello();
+//      return 0;
+//   }
+//
+// This odd feature is for the compatibility with MSVC link.exe.
+class LocallyImportedSymbolFile : public ArchiveLibraryFile {
+public:
+  LocallyImportedSymbolFile(const PECOFFLinkingContext &ctx)
+      : ArchiveLibraryFile("__imp_"), _prefix(ctx.decorateSymbol("_imp_")),
+        _ordinal(0) {}
+
+  const File *find(StringRef sym, bool dataSymbolOnly) const override {
+    if (!sym.startswith(_prefix))
+      return nullptr;
+    StringRef undef = sym.substr(_prefix.size());
+    return new (_alloc) ImpSymbolFile(sym, undef, _ordinal++);
   }
 
-  COFFAbsoluteAtom _imageBaseAtom;
-  uint64_t _ordinal;
-  llvm::BumpPtrAllocator _alloc;
+  const atom_collection<DefinedAtom> &defined() const override {
+    return _definedAtoms;
+  }
+
+  const atom_collection<UndefinedAtom> &undefined() const override {
+    return _undefinedAtoms;
+  }
+
+  const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
+    return _sharedLibraryAtoms;
+  }
+
+  const atom_collection<AbsoluteAtom> &absolute() const override {
+    return _absoluteAtoms;
+  }
+
+  error_code
+  parseAllMembers(std::vector<std::unique_ptr<File>> &result) const override {
+    return error_code::success();
+  }
+
+private:
+  std::string _prefix;
+  mutable uint64_t _ordinal;
+  mutable llvm::BumpPtrAllocator _alloc;
+
+  atom_collection_vector<DefinedAtom> _definedAtoms;
+  atom_collection_vector<UndefinedAtom> _undefinedAtoms;
+  atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
+  atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
 };
 
 } // end namespace pecoff

Modified: lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=207476&r1=207475&r2=207476&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp Mon Apr 28 19:32:00 2014
@@ -110,6 +110,11 @@ bool PECOFFLinkingContext::createImplici
   fileNode->appendInputFile(std::move(linkerGeneratedSymFile));
   getInputGraph().insertElementAt(std::move(fileNode),
                                   InputGraph::Position::END);
+
+  std::unique_ptr<SimpleFileNode> impFileNode(new SimpleFileNode("imp"));
+  impFileNode->appendInputFile(
+      std::unique_ptr<File>(new pecoff::LocallyImportedSymbolFile(*this)));
+  getLibraryGroup()->addFile(std::move(impFileNode));
   return true;
 }
 

Added: lld/trunk/test/pecoff/localyimported.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/localyimported.test?rev=207476&view=auto
==============================================================================
--- lld/trunk/test/pecoff/localyimported.test (added)
+++ lld/trunk/test/pecoff/localyimported.test Mon Apr 28 19:32:00 2014
@@ -0,0 +1,7 @@
+# RUN: yaml2obj %p/Inputs/hello.obj.yaml > %t.obj
+#
+# RUN: not lld -flavor link /out:%t2.exe /include:__imp__nosuchsym %t.obj \
+# RUN:   >& %t2.log
+# RUN: FileCheck %s < %t2.log
+
+CHECK: Undefined symbol: __imp__nosuchsym: _nosuchsym

Modified: lld/trunk/test/pecoff/reloc.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/reloc.test?rev=207476&r1=207475&r2=207476&view=diff
==============================================================================
--- lld/trunk/test/pecoff/reloc.test (original)
+++ lld/trunk/test/pecoff/reloc.test Mon Apr 28 19:32:00 2014
@@ -5,8 +5,8 @@
 # RUN: llvm-objdump -d %t.exe | FileCheck %s
 
 CHECK: .text:
-CHECK:    2000: 68 02 00 00 00
-CHECK:    2005: 68 05 00 00 00
-CHECK:    200a: 68 00 10 40 00
-CHECK:    200f: 68 00 10 40 00
-CHECK:    2014: 68 00 00 40 00
+CHECK:    3000: 68 02 00 00 00
+CHECK:    3005: 68 05 00 00 00
+CHECK:    300a: 68 00 10 40 00
+CHECK:    300f: 68 00 10 40 00
+CHECK:    3014: 68 00 20 40 00





More information about the llvm-commits mailing list