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

Rafael EspĂ­ndola rafael.espindola at gmail.com
Thu Jul 16 15:55:05 PDT 2015


On 16 July 2015 at 15:21, Rui Ueyama <ruiu at google.com> wrote:
> 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
>>>>> 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
>>>>
>>>>
>>>> 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?

Yes, thanks!

Cheers,
Rafael



More information about the llvm-commits mailing list