summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/COFF/Driver.cpp5
-rw-r--r--lld/COFF/Driver.h1
-rw-r--r--lld/COFF/DriverUtils.cpp71
-rw-r--r--lld/test/COFF/Inputs/import.yaml41
-rw-r--r--lld/test/COFF/dll.test19
5 files changed, 137 insertions, 0 deletions
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index be13aa971b8..af316670197 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -500,6 +500,11 @@ bool LinkerDriver::link(int Argc, const char *Argv[]) {
}
}
+ // Windows specific -- when we are creating a .dll file, we also
+ // need to create a .lib file.
+ if (!Config->Exports.empty())
+ writeImportLibrary();
+
// Windows specific -- fix up dllexported symbols.
if (!Config->Exports.empty()) {
for (Export &E : Config->Exports)
diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h
index 07b76b17b3d..8b43e36abe0 100644
--- a/lld/COFF/Driver.h
+++ b/lld/COFF/Driver.h
@@ -98,6 +98,7 @@ private:
};
std::error_code parseModuleDefs(MemoryBufferRef MB);
+std::error_code writeImportLibrary();
// Functions below this line are defined in DriverUtils.cpp.
diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp
index 662e5822335..c210834faa3 100644
--- a/lld/COFF/DriverUtils.cpp
+++ b/lld/COFF/DriverUtils.cpp
@@ -24,6 +24,8 @@
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
@@ -269,6 +271,75 @@ convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) {
return MemoryBuffer::getFile(Path);
}
+static std::string writeToTempFile(StringRef Contents) {
+ SmallString<128> Path;
+ int FD;
+ if (llvm::sys::fs::createTemporaryFile("tmp", "def", FD, Path)) {
+ llvm::errs() << "failed to create a temporary file\n";
+ return "";
+ }
+ llvm::raw_fd_ostream OS(FD, /*shouldClose*/ true);
+ OS << Contents;
+ return Path.str();
+}
+
+/// Creates a .def file containing the list of exported symbols.
+static std::string createModuleDefinitionFile() {
+ std::string S;
+ llvm::raw_string_ostream OS(S);
+ OS << "LIBRARY \"" << llvm::sys::path::filename(Config->OutputFile) << "\"\n"
+ << "EXPORTS\n";
+ for (Export &E : Config->Exports) {
+ OS << " " << E.ExtName;
+ if (E.Ordinal > 0)
+ OS << " @" << E.Ordinal;
+ if (E.Noname)
+ OS << " NONAME";
+ if (E.Data)
+ OS << " DATA";
+ if (E.Private)
+ OS << " PRIVATE";
+ OS << "\n";
+ }
+ OS.flush();
+ return S;
+}
+
+// Creates a .def file and runs lib.exe on it to create an import library.
+std::error_code writeImportLibrary() {
+ std::string Prog = "lib.exe";
+ ErrorOr<std::string> ExeOrErr = llvm::sys::findProgramByName(Prog);
+ if (auto EC = ExeOrErr.getError()) {
+ llvm::errs() << "unable to find " << Prog << " in PATH: "
+ << EC.message() << "\n";
+ return make_error_code(LLDError::InvalidOption);
+ }
+ llvm::BumpPtrAllocator Alloc;
+ llvm::BumpPtrStringSaver S(Alloc);
+ const char *Exe = S.save(ExeOrErr.get());
+
+ std::string Contents = createModuleDefinitionFile();
+ StringRef Def = S.save(StringRef(writeToTempFile(Contents)));
+ llvm::FileRemover TempFile(Def);
+
+ SmallString<128> Out = StringRef(Config->OutputFile);
+ sys::path::replace_extension(Out, ".lib");
+
+ std::vector<const char *> Args;
+ Args.push_back(Exe);
+ Args.push_back("/nologo");
+ Args.push_back("/machine:x64");
+ Args.push_back(S.save("/def:" + Def));
+ Args.push_back(S.save("/out:" + Out));
+ Args.push_back(nullptr);
+
+ if (sys::ExecuteAndWait(Exe, Args.data()) != 0) {
+ llvm::errs() << Exe << " failed\n";
+ return make_error_code(LLDError::InvalidOption);
+ }
+ return std::error_code();
+}
+
// Create OptTable
// Create prefix string literals used in Options.td
diff --git a/lld/test/COFF/Inputs/import.yaml b/lld/test/COFF/Inputs/import.yaml
new file mode 100644
index 00000000000..97ccac5b8b4
--- /dev/null
+++ b/lld/test/COFF/Inputs/import.yaml
@@ -0,0 +1,41 @@
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 0000000000000000
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 8
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: mainCRTStartup
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: exportfn1
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: exportfn2
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lld/test/COFF/dll.test b/lld/test/COFF/dll.test
new file mode 100644
index 00000000000..75ecaf5b391
--- /dev/null
+++ b/lld/test/COFF/dll.test
@@ -0,0 +1,19 @@
+# REQUIRES: winres
+
+# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj
+# RUN: lld -flavor link2 /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=EXPORT %s
+
+EXPORT: Export Table:
+EXPORT: DLL name: dll.test.tmp.dll
+EXPORT: Ordinal RVA Name
+EXPORT-NEXT: 0 0
+EXPORT-NEXT: 1 0x1008 exportfn1
+EXPORT-NEXT: 2 0x1010 exportfn2
+
+# RUN: yaml2obj < %p/Inputs/import.yaml > %t2.obj
+# RUN: lld -flavor link2 /out:%t2.exe %t2.obj %t.lib
+# RUN: llvm-readobj -coff-imports %t2.exe | FileCheck -check-prefix=IMPORT %s
+
+IMPORT: Symbol: exportfn1
+IMPORT: Symbol: exportfn2
OpenPOWER on IntegriCloud