summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h103
-rw-r--r--lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp5
-rw-r--r--lld/test/pecoff/localyimported.test7
-rw-r--r--lld/test/pecoff/reloc.test10
4 files changed, 100 insertions, 25 deletions
diff --git a/lld/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h b/lld/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
index cbf7ddcde07..e6926980f18 100644
--- a/lld/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
+++ b/lld/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
@@ -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
diff --git a/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp b/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
index 474b14829b6..d9117d05a5e 100644
--- a/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
@@ -110,6 +110,11 @@ bool PECOFFLinkingContext::createImplicitFiles(
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;
}
diff --git a/lld/test/pecoff/localyimported.test b/lld/test/pecoff/localyimported.test
new file mode 100644
index 00000000000..592c0fa6507
--- /dev/null
+++ b/lld/test/pecoff/localyimported.test
@@ -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
diff --git a/lld/test/pecoff/reloc.test b/lld/test/pecoff/reloc.test
index 08f95b12eba..ba1e9353c09 100644
--- a/lld/test/pecoff/reloc.test
+++ b/lld/test/pecoff/reloc.test
@@ -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
OpenPOWER on IntegriCloud