[lld] r239937 - COFF: Create import library files.
Sean Silva
chisophugis at gmail.com
Thu Jul 16 15:15:54 PDT 2015
On Thu, Jul 16, 2015 at 2:57 PM, Rui Ueyama <ruiu at google.com> wrote:
> On Thu, Jul 16, 2015 at 2:53 PM, Filipe Cabecinhas <filcab at gmail.com>
> wrote:
>
>> Hi Rui,
>>
>> On Wed, Jun 17, 2015 at 1:40 PM, Rui Ueyama <ruiu at google.com> wrote:
>>
>>> Author: ruiu
>>> Date: Wed Jun 17 15:40:43 2015
>>> New Revision: 239937
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=239937&view=rev
>>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject-3Frev-3D239937-26view-3Drev&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=HotEHX2Iaf4Itp0QWStZq6bAh5NFroMvhCLFt64IWzw&s=rFgSuKRaIFB7IwNuaXxNuJpriqeG1fpXho1oshJZzrA&e=>
>>> 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
>>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_COFF_Driver.cpp-3Frev-3D239937-26r1-3D239936-26r2-3D239937-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=HotEHX2Iaf4Itp0QWStZq6bAh5NFroMvhCLFt64IWzw&s=INZG3GoafMTwC4FFB-qSulbFyNpEPJPEWKqfNdsVKho&e=>
>>>
>>> ==============================================================================
>>> --- 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
>>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_COFF_Driver.h-3Frev-3D239937-26r1-3D239936-26r2-3D239937-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=HotEHX2Iaf4Itp0QWStZq6bAh5NFroMvhCLFt64IWzw&s=BMZbPr-ruVc6h40qEwZypPZjh7k0eckpTrq1nfC3xlE&e=>
>>>
>>> ==============================================================================
>>> --- 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
>>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_COFF_DriverUtils.cpp-3Frev-3D239937-26r1-3D239936-26r2-3D239937-26view-3Ddiff&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=HotEHX2Iaf4Itp0QWStZq6bAh5NFroMvhCLFt64IWzw&s=T2ileZ1F9GHIWlr-hzNFoeed4SghyDnruyRi783s4OE&e=>
>>>
>>>
>>> ==============================================================================
>>> --- 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
>>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_test_COFF_Inputs_import.yaml-3Frev-3D239937-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=HotEHX2Iaf4Itp0QWStZq6bAh5NFroMvhCLFt64IWzw&s=zGc5n60h8jXHKnatOwxVpNYZWzHfN-sE0aW41MeNeME&e=>
>>>
>>>
>>> ==============================================================================
>>> --- 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
>>> <https://urldefense.proofpoint.com/v2/url?u=http-3A__llvm.org_viewvc_llvm-2Dproject_lld_trunk_test_COFF_dll.test-3Frev-3D239937-26view-3Dauto&d=AwMFaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=mQ4LZ2PUj9hpadE3cDHZnIdEwhEBrbAstXeMaFoB9tg&m=HotEHX2Iaf4Itp0QWStZq6bAh5NFroMvhCLFt64IWzw&s=FVspeG05-fGr8wcJOvocRPUmnlowGc0ax3XEJHiV3yo&e=>
>>>
>>> ==============================================================================
>>> --- 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
>>>
>>
>> Shouldn't it REQUIRE winlib, too?
>> We have a builder that's failing because it tries to execute lib.exe, but
>> that can't be found.
>> I think what's happening is that CMake finds all the utilities due to
>> having some env var defined pointing at Visual Studio, but then we don't
>> have those in the path.
>>
>
> Yes, I think we need to add REQUIRES: winlib too. I'm sorry about that, I
> should have done that when I submit this patch. In most cases, lib.exe is
> available as long as res.exe is available, so I didn't notice that.
>
Thanks for the info. I've added REQUIRES: winlib in r242452.
-- Sean Silva
>
> Are we going to be able to remove the lib.exe dependency in the future?
>>
>
> That's the plan. We already have a lib.exe-compatible command in LLVM, so
> it might be as easy as calling it instead of MSVC's lib.exe.
>
>
>> Thank you,
>>
>> Filipe
>>
>>
>>
>>> +
>>> +# 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
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>>
>>
>>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150716/42f45f72/attachment.html>
More information about the llvm-commits
mailing list