[lld] r239937 - COFF: Create import library files.
Rui Ueyama
ruiu at google.com
Wed Jun 17 13:40:44 PDT 2015
Author: ruiu
Date: Wed Jun 17 15:40:43 2015
New Revision: 239937
URL: http://llvm.org/viewvc/llvm-project?rev=239937&view=rev
Log:
COFF: Create import library files.
On Windows, we have to create a .lib file for each .dll.
When linking against DLLs, the linker doesn't use the DLL files,
but instead read a list of dllexported symbols from corresponding
lib files.
A library file containing descriptors of a DLL is called an
import library file.
lib.exe has a feature to create an import library file from a
module-definition file. In this patch, we create a module-definition
file and pass that to lib.exe.
We eventually want to create an import library file by ourselves
to eliminate dependency to lib.exe. For now, we just use the MSVC
tool.
Added:
lld/trunk/test/COFF/Inputs/import.yaml
lld/trunk/test/COFF/dll.test
Modified:
lld/trunk/COFF/Driver.cpp
lld/trunk/COFF/Driver.h
lld/trunk/COFF/DriverUtils.cpp
Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=239937&r1=239936&r2=239937&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Wed Jun 17 15:40:43 2015
@@ -500,6 +500,11 @@ bool LinkerDriver::link(int Argc, const
}
}
+ // 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)
Modified: lld/trunk/COFF/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.h?rev=239937&r1=239936&r2=239937&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.h (original)
+++ lld/trunk/COFF/Driver.h Wed Jun 17 15:40:43 2015
@@ -98,6 +98,7 @@ private:
};
std::error_code parseModuleDefs(MemoryBufferRef MB);
+std::error_code writeImportLibrary();
// Functions below this line are defined in DriverUtils.cpp.
Modified: lld/trunk/COFF/DriverUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DriverUtils.cpp?rev=239937&r1=239936&r2=239937&view=diff
==============================================================================
--- lld/trunk/COFF/DriverUtils.cpp (original)
+++ lld/trunk/COFF/DriverUtils.cpp Wed Jun 17 15:40:43 2015
@@ -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<Memor
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
Added: lld/trunk/test/COFF/Inputs/import.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/Inputs/import.yaml?rev=239937&view=auto
==============================================================================
--- lld/trunk/test/COFF/Inputs/import.yaml (added)
+++ lld/trunk/test/COFF/Inputs/import.yaml Wed Jun 17 15:40:43 2015
@@ -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
+...
Added: lld/trunk/test/COFF/dll.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/dll.test?rev=239937&view=auto
==============================================================================
--- lld/trunk/test/COFF/dll.test (added)
+++ lld/trunk/test/COFF/dll.test Wed Jun 17 15:40:43 2015
@@ -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
More information about the llvm-commits
mailing list