[lld] r207141 - [PECOFF] Define implicit symbols for exported ones.

Rui Ueyama ruiu at google.com
Thu Apr 24 13:12:01 PDT 2014


Author: ruiu
Date: Thu Apr 24 15:12:01 2014
New Revision: 207141

URL: http://llvm.org/viewvc/llvm-project?rev=207141&view=rev
Log:
[PECOFF] Define implicit symbols for exported ones.

This patch is to fix a compatibility issue with MSVC link.exe as to
use of dllexported symbols inside DLL.

A DLL exports two symbols for a function. One is non-decorated one,
and the other is with __imp_ prefix. The former is a function that
you can directly call, and the latter is a pointer to the function.
These dllexported symbols are created by linker for programs that
link against the DLL. So, I naturally believed that __imp_ symbols
become available when you once create a DLL and link against it, but
they don't exist until then. And that's not true.

MSVC link.exe is smart enough to allow users to use __imp_ symbols
locally. That is, if a symbol is specified with /export option, it
implicitly creates a new symbol with __imp_ prefix as a pointer to
the exported symbol. This feature allows the following program to
be linked and run, although _imp__hello is not defined in this code.

  #include <stdio.h>

  __declspec(dllexport)
  void hello(void) { printf("Hello\n"); }

  extern void (*_imp__hello)(void);

  int main() {
    _imp__hello();
    return 0;
  }

MSVC link.exe prints out the following warning when linking it.

  LNK4217: locally defined symbol _hello imported in function _main

Using __imp_ symbols locally is I think not a good coding style. One
should just take an address using "&" operator rather than appending
__imp_ prefix. However, there are programs in the wild that depends
on this link.exe's behavior, so we need this feature.

Modified:
    lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h

Modified: lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h?rev=207141&r1=207140&r2=207141&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h Thu Apr 24 15:12:01 2014
@@ -11,10 +11,25 @@
 
 #include "lld/ReaderWriter/PECOFFLinkingContext.h"
 #include "lld/ReaderWriter/Simple.h"
+#include "llvm/Support/Allocator.h"
 
 namespace lld {
 namespace pecoff {
 
+/// The defined atom for dllexported symbols with __imp_ prefix.
+class ImpPointerAtom : public COFFLinkerInternalAtom {
+public:
+  ImpPointerAtom(const File &file, StringRef symbolName)
+      : COFFLinkerInternalAtom(file, /*oridnal*/ 0, std::vector<uint8_t>(4),
+                               symbolName) {}
+
+  uint64_t ordinal() const override { return 0; }
+  Scope scope() const override { return scopeGlobal; }
+  ContentType contentType() const override { return typeData; }
+  Alignment alignment() const override { return Alignment(4); }
+  ContentPermissions permissions() const override { return permR__; }
+};
+
 // 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.
@@ -25,10 +40,29 @@ public:
         _imageBaseAtom(*this, ctx.decorateSymbol("__ImageBase"),
                        Atom::scopeGlobal, ctx.getBaseAddress()) {
     addAtom(_imageBaseAtom);
+
+    // 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));
+  }
+
   COFFAbsoluteAtom _imageBaseAtom;
+  llvm::BumpPtrAllocator _alloc;
 };
 
 } // end namespace pecoff





More information about the llvm-commits mailing list