[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