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

Filipe Cabecinhas filcab at gmail.com
Thu Jul 16 14:53:44 PDT 2015


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.

Are we going to be able to remove the lib.exe dependency in the future?

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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150716/4220e5b1/attachment.html>


More information about the llvm-commits mailing list