[lld] r239937 - COFF: Create import library files.

Rui Ueyama ruiu at google.com
Thu Jul 16 15:21:02 PDT 2015


On Thu, Jul 16, 2015 at 3:15 PM, Sean Silva <chisophugis at gmail.com> wrote:

>
>
> 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.
>

Did it work?


> -- 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/b1f019c1/attachment.html>


More information about the llvm-commits mailing list