From ffff62112942631d5a4a91c416fea640ee25abac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 24 Aug 2016 23:35:07 +0300 Subject: [PATCH] Add patches for llvm-dlltool --- patches/llvm-0004.patch | 1446 +++++++++++++++++++++++++++++++++++++++ patches/llvm-0005.patch | 96 +++ patches/llvm-0006.patch | 36 + 3 files changed, 1578 insertions(+) create mode 100644 patches/llvm-0004.patch create mode 100644 patches/llvm-0005.patch create mode 100644 patches/llvm-0006.patch diff --git a/patches/llvm-0004.patch b/patches/llvm-0004.patch new file mode 100644 index 0000000..8282d5a --- /dev/null +++ b/patches/llvm-0004.patch @@ -0,0 +1,1446 @@ +From e809b3e41dd5d4ba55c1b941f2b4f72b408b4c2e Mon Sep 17 00:00:00 2001 +From: Martell Malone +Date: Tue, 9 Aug 2016 17:52:46 -0700 +Subject: [PATCH 4/6] genlib: named as llvm-dlltool + +A PE COFF spec compliant import library generator. +Intended to be used with mingw-w64. + +Supports: +PE COFF spec (section 8, Import Library Format) +PE COFF spec (Aux Format 3: Weak Externals) +--- + include/llvm/DllDriver/DllDriver.h | 24 ++ + lib/CMakeLists.txt | 1 + + lib/DLLDriver/CMakeLists.txt | 11 + + lib/DLLDriver/Config.h | 119 ++++++++ + lib/DLLDriver/DllDriver.cpp | 185 ++++++++++++ + lib/DLLDriver/LLVMBuild.txt | 22 ++ + lib/DLLDriver/Librarian.cpp | 603 +++++++++++++++++++++++++++++++++++++ + lib/DLLDriver/ModuleDef.cpp | 321 ++++++++++++++++++++ + lib/DLLDriver/Options.td | 5 + + lib/Object/ArchiveWriter.cpp | 3 +- + tools/llvm-ar/CMakeLists.txt | 2 + + tools/llvm-ar/llvm-ar.cpp | 6 +- + 12 files changed, 1300 insertions(+), 2 deletions(-) + create mode 100644 include/llvm/DllDriver/DllDriver.h + create mode 100644 lib/DLLDriver/CMakeLists.txt + create mode 100644 lib/DLLDriver/Config.h + create mode 100644 lib/DLLDriver/DllDriver.cpp + create mode 100644 lib/DLLDriver/LLVMBuild.txt + create mode 100644 lib/DLLDriver/Librarian.cpp + create mode 100644 lib/DLLDriver/ModuleDef.cpp + create mode 100644 lib/DLLDriver/Options.td + +diff --git a/include/llvm/DllDriver/DllDriver.h b/include/llvm/DllDriver/DllDriver.h +new file mode 100644 +index 0000000..79fb7b7 +--- /dev/null ++++ b/include/llvm/DllDriver/DllDriver.h +@@ -0,0 +1,24 @@ ++//===- llvm/DLLDriver/DLLDriver.h - dlltool.exe-compatible driver ---*- C++ -*-===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// Defines an interface to a dlltool.exe-compatible driver that also understands ++// bitcode files. Used by llvm-dlltool and lld. ++// ++//===----------------------------------------------------------------------===// ++ ++#ifndef LLVM_DLLDRIVER_DLLDRIVER_H ++#define LLVM_DLLDRIVER_DLLDRIVER_H ++ ++namespace llvm { ++template class ArrayRef; ++ ++int dllToolDriverMain(ArrayRef ARgs); ++} ++ ++#endif +diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt +index 9449421..03988a6 100644 +--- a/lib/CMakeLists.txt ++++ b/lib/CMakeLists.txt +@@ -20,4 +20,5 @@ add_subdirectory(LineEditor) + add_subdirectory(ProfileData) + add_subdirectory(Fuzzer) + add_subdirectory(Passes) ++add_subdirectory(DLLDriver) + add_subdirectory(LibDriver) +diff --git a/lib/DLLDriver/CMakeLists.txt b/lib/DLLDriver/CMakeLists.txt +new file mode 100644 +index 0000000..91fb2f0 +--- /dev/null ++++ b/lib/DLLDriver/CMakeLists.txt +@@ -0,0 +1,11 @@ ++set(LLVM_TARGET_DEFINITIONS Options.td) ++tablegen(LLVM Options.inc -gen-opt-parser-defs) ++add_public_tablegen_target(DllOptionsTableGen) ++ ++add_llvm_library(LLVMDllDriver ++ DllDriver.cpp ++ ModuleDef.cpp ++ Librarian.cpp ++ ) ++ ++add_dependencies(LLVMDllDriver DllOptionsTableGen) +diff --git a/lib/DLLDriver/Config.h b/lib/DLLDriver/Config.h +new file mode 100644 +index 0000000..d5a3d26 +--- /dev/null ++++ b/lib/DLLDriver/Config.h +@@ -0,0 +1,119 @@ ++#ifndef LLVM_COFF_CONFIG_H ++#define LLVM_COFF_CONFIG_H ++ ++#include "llvm/ADT/StringRef.h" ++#include "llvm/Object/COFF.h" ++#include ++#include ++#include ++#include ++ ++namespace llvm { ++ ++using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN; ++using llvm::COFF::WindowsSubsystem; ++using llvm::StringRef; ++ ++// Short aliases. ++static const auto AMD64 = llvm::COFF::IMAGE_FILE_MACHINE_AMD64; ++static const auto ARMNT = llvm::COFF::IMAGE_FILE_MACHINE_ARMNT; ++static const auto I386 = llvm::COFF::IMAGE_FILE_MACHINE_I386; ++ ++struct Export { ++ StringRef Name; // N in N or E=N ++ StringRef ExtName; // E in E=N ++ ++ uint16_t Ordinal = 0; ++ bool Noname = false; ++ bool Data = false; ++ bool Private = false; ++ ++ // True if this /export option was in .drectves section. ++ bool Directives = false; ++ StringRef SymbolName; ++ StringRef ExportName; // Name in DLL ++ ++ bool isWeak() { ++ if(ExtName.size() && Name != ExtName) ++ return true; ++ return false; ++ } ++}; ++ ++// Global configuration. ++struct Configuration { ++ enum ManifestKind { SideBySide, Embed, No }; ++ bool is64() { return Machine == AMD64; } ++ std::vector Exports; ++ ++ llvm::COFF::MachineTypes Machine = IMAGE_FILE_MACHINE_UNKNOWN; ++ bool Verbose = false; ++ WindowsSubsystem Subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN; ++ bool NoEntry = false; ++ std::string OutputFile; ++ bool DoGC = true; ++ bool DoICF = true; ++ bool Relocatable = true; ++ bool Force = false; ++ bool Debug = false; ++ bool WriteSymtab = true; ++ ++ std::set NoDefaultLibs; ++ bool NoDefaultLibAll = false; ++ ++ // True if we are creating a DLL. ++ bool DLL = false; ++ StringRef Implib; ++ std::set DelayLoads; ++ std::map DLLOrder; ++ ++ // Used for /opt:lldlto=N ++ unsigned LTOOptLevel = 2; ++ ++ // Used for /opt:lldltojobs=N ++ unsigned LTOJobs = 1; ++ ++ // Used for /merge:from=to (e.g. /merge:.rdata=.text) ++ std::map Merge; ++ ++ // Used for /section=.name,{DEKPRSW} to set section attributes. ++ std::map Section; ++ ++ // Options for manifest files. ++ ManifestKind Manifest = SideBySide; ++ int ManifestID = 1; ++ StringRef ManifestDependency; ++ bool ManifestUAC = true; ++ std::vector ManifestInput; ++ StringRef ManifestLevel = "'asInvoker'"; ++ StringRef ManifestUIAccess = "'false'"; ++ StringRef ManifestFile; ++ ++ // Used for /failifmismatch. ++ std::map MustMatch; ++ ++ // Used for /alternatename. ++ std::map AlternateNames; ++ ++ uint64_t ImageBase = -1; ++ uint64_t StackReserve = 1024 * 1024; ++ uint64_t StackCommit = 4096; ++ uint64_t HeapReserve = 1024 * 1024; ++ uint64_t HeapCommit = 4096; ++ uint32_t MajorImageVersion = 0; ++ uint32_t MinorImageVersion = 0; ++ uint32_t MajorOSVersion = 6; ++ uint32_t MinorOSVersion = 0; ++ bool DynamicBase = true; ++ bool AllowBind = true; ++ bool NxCompat = true; ++ bool AllowIsolation = true; ++ bool TerminalServerAware = true; ++ bool LargeAddressAware = false; ++ bool HighEntropyVA = false; ++}; ++ ++extern Configuration *Config; ++} // namespace llvm ++ ++#endif +\ No newline at end of file +diff --git a/lib/DLLDriver/DllDriver.cpp b/lib/DLLDriver/DllDriver.cpp +new file mode 100644 +index 0000000..aa9adc8 +--- /dev/null ++++ b/lib/DLLDriver/DllDriver.cpp +@@ -0,0 +1,185 @@ ++//===- DllDriver.cpp - dlltool.exe-compatible driver --------------------------===// ++// ++// The LLVM Compiler Infrastructure ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// Defines an interface to a dlltool.exe-compatible driver that also understands ++// bitcode files. ++// ++//===----------------------------------------------------------------------===// ++ ++#include "llvm/DllDriver/DllDriver.h" ++#include "llvm/ADT/STLExtras.h" ++#include "llvm/Object/ArchiveWriter.h" ++#include "llvm/Option/Arg.h" ++#include "llvm/Option/ArgList.h" ++#include "llvm/Object/COFF.h" ++#include "llvm/Option/Option.h" ++#include "llvm/Support/CommandLine.h" ++#include "llvm/Support/StringSaver.h" ++#include "llvm/Support/Path.h" ++#include "llvm/Support/Process.h" ++#include "llvm/Support/raw_ostream.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "Config.h" ++ ++using namespace llvm; ++ ++namespace llvm{ ++Configuration *Config; ++void parseModuleDefs(MemoryBufferRef MB, StringSaver *Alloc); ++} ++ ++namespace { ++ ++enum { ++ OPT_INVALID = 0, ++#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID, ++#include "Options.inc" ++#undef OPTION ++}; ++ ++#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; ++#include "Options.inc" ++#undef PREFIX ++ ++static const llvm::opt::OptTable::Info infoTable[] = { ++#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \ ++ { \ ++ X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \ ++ OPT_##GROUP, OPT_##ALIAS, X6 \ ++ }, ++#include "Options.inc" ++#undef OPTION ++}; ++ ++class DllOptTable : public llvm::opt::OptTable { ++public: ++ DllOptTable() : OptTable(infoTable, false) {} ++}; ++ ++} ++ ++std::vector> OwningMBs; ++ ++// Opens a file. Path has to be resolved already. ++// Newly created memory buffers are owned by this driver. ++MemoryBufferRef openFile(StringRef Path) { ++ llvm::ErrorOr> MB = ++ MemoryBuffer::getFile(Path); ++ ++ if (std::error_code EC = MB.getError()) ++ llvm::errs() << "fail openFile: " << EC.message() << "\n"; ++ ++ MemoryBufferRef MBRef = MB.get()->getMemBufferRef(); ++ OwningMBs.push_back(std::move(MB.get())); // take ownership ++ return MBRef; ++} ++ ++#include "llvm/Support/raw_ostream.h" ++ ++#include "llvm/ADT/StringSwitch.h" ++#include "llvm/Option/Arg.h" ++#include "llvm/Option/ArgList.h" ++#include "llvm/Support/StringSaver.h" ++ ++static llvm::COFF::MachineTypes getEmulation(StringRef S) { ++ return StringSwitch(S) ++ .Case("x86", llvm::COFF::IMAGE_FILE_MACHINE_I386) ++ .Case("x86_64", llvm::COFF::IMAGE_FILE_MACHINE_AMD64) ++ .Case("arm", llvm::COFF::IMAGE_FILE_MACHINE_ARMNT) ++ .Default(llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN); ++} ++ ++static std::string getImplibPath() { ++ if (!Config->Implib.empty()) ++ return Config->Implib; ++ SmallString<128> Out = StringRef(Config->OutputFile); ++ sys::path::replace_extension(Out, ".lib"); ++ return Out.str(); ++} ++ ++int writeImportLibrary(std::string &Path); ++ ++int llvm::dllToolDriverMain(llvm::ArrayRef ArgsArr) { ++ SmallVector NewArgs(ArgsArr.begin(), ArgsArr.end()); ++ BumpPtrAllocator Alloc; ++ StringSaver Saver(Alloc); ++ cl::ExpandResponseFiles(Saver, cl::TokenizeWindowsCommandLine, NewArgs); ++ ArgsArr = NewArgs; ++ ++ Configuration C; ++ Config = &C; ++ ++ DllOptTable Table; ++ unsigned MissingIndex; ++ unsigned MissingCount; ++ llvm::opt::InputArgList Args = ++ Table.ParseArgs(ArgsArr.slice(1), MissingIndex, MissingCount); ++ if (MissingCount) { ++ llvm::errs() << "missing arg value for \"" ++ << Args.getArgString(MissingIndex) << "\", expected " ++ << MissingCount ++ << (MissingCount == 1 ? " argument.\n" : " arguments.\n"); ++ return 1; ++ } ++ for (auto *Arg : Args.filtered(OPT_UNKNOWN)) ++ llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n"; ++ ++ if (Args.filtered_begin(OPT_INPUT) == Args.filtered_end()) { ++ llvm::outs() << "NO ARGS" << "\n"; ++ return 0; ++ } ++ ++ if (Args.filtered_begin(OPT_emu) == Args.filtered_end()) { ++ llvm::outs() << "Need to set an emulation mode" << "\n"; ++ return -1; ++ } ++ ++ std::string Path; ++ MemoryBufferRef MB; ++ int i=0; ++ for (auto *Arg : Args.filtered(OPT_INPUT)) { ++ if(i==0) ++ MB = openFile(Arg->getValue()); ++ if(i==1) ++ Path = Arg->getValue(); ++ i++; ++ } ++ ++ if (auto *Arg = Args.getLastArg(OPT_out)) ++ Path = Arg->getValue(); ++ ++ if(!Path.length()) ++ Path = getImplibPath(); ++ ++ llvm::outs() << Path << "\n"; ++ ++ Config->Machine = IMAGE_FILE_MACHINE_UNKNOWN; ++ if (auto *Arg = Args.getLastArg(OPT_emu)) ++ Config->Machine = getEmulation(Arg->getValue()); ++ ++ if(Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) { ++ llvm::outs() << "Need to set a valid emulation mode" << "\n"; ++ return -2; ++ } ++ ++ llvm::parseModuleDefs(MB, &Saver); ++ ++ // has to happen after the parser ++ if (auto *Arg = Args.getLastArg(OPT_dll)) ++ Config->OutputFile = Arg->getValue(); ++ ++ return writeImportLibrary(Path); ++ ++} +diff --git a/lib/DLLDriver/LLVMBuild.txt b/lib/DLLDriver/LLVMBuild.txt +new file mode 100644 +index 0000000..8e2b1d65 +--- /dev/null ++++ b/lib/DLLDriver/LLVMBuild.txt +@@ -0,0 +1,22 @@ ++;===- ./lib/LibDriver/LLVMBuild.txt ----------------------------*- Conf -*--===; ++; ++; The LLVM Compiler Infrastructure ++; ++; This file is distributed under the University of Illinois Open Source ++; License. See LICENSE.TXT for details. ++; ++;===------------------------------------------------------------------------===; ++; ++; This is an LLVMBuild description file for the components in this subdirectory. ++; ++; For more information on the LLVMBuild system, please see: ++; ++; http://llvm.org/docs/LLVMBuild.html ++; ++;===------------------------------------------------------------------------===; ++ ++[component_0] ++type = Library ++name = DllDriver ++parent = Libraries ++required_libraries = Object Option Support +diff --git a/lib/DLLDriver/Librarian.cpp b/lib/DLLDriver/Librarian.cpp +new file mode 100644 +index 0000000..486733e +--- /dev/null ++++ b/lib/DLLDriver/Librarian.cpp +@@ -0,0 +1,603 @@ ++//===- Librarian.cpp ------------------------------------------------------===// ++// ++// The LLVM Linker ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// This file contains functions for the Librarian. The librarian creates and ++// manages libraries of the Common Object File Format (COFF) object files. It ++// primarily is used for creating static libraries and import libraries. ++// ++//===----------------------------------------------------------------------===// ++ ++#include "llvm/Object/Archive.h" ++#include "llvm/Object/ArchiveWriter.h" ++#include "llvm/Object/COFF.h" ++#include "llvm/Support/Error.h" ++#include "llvm/Support/Path.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "Config.h" ++ ++using namespace llvm; ++using namespace llvm::COFF; ++using namespace llvm::object; ++ ++static bool is32bit() { ++ switch (Config->Machine) { ++ default: ++ llvm_unreachable("unsupported machine"); ++ case IMAGE_FILE_MACHINE_AMD64: ++ return false; ++ case IMAGE_FILE_MACHINE_ARMNT: ++ case IMAGE_FILE_MACHINE_I386: ++ return true; ++ } ++} ++ ++static uint16_t getImgRelRelocation() { ++ switch (Config->Machine) { ++ default: ++ llvm_unreachable("unsupported machine"); ++ case IMAGE_FILE_MACHINE_AMD64: ++ return IMAGE_REL_AMD64_ADDR32NB; ++ case IMAGE_FILE_MACHINE_ARMNT: ++ return IMAGE_REL_ARM_ADDR32NB; ++ case IMAGE_FILE_MACHINE_I386: ++ return IMAGE_REL_I386_DIR32NB; ++ } ++} ++ ++template static void append(std::vector &B, const T &Data) { ++ size_t S = B.size(); ++ B.resize(S + sizeof(T)); ++ memcpy(&B[S], &Data, sizeof(T)); ++} ++ ++static void writeStringTable(std::vector &B, ++ ArrayRef Strings) { ++ // The COFF string table consists of a 4-byte value which is the size of the ++ // table, including the length field itself. This value is followed by the ++ // string content itself, which is an array of null-terminated C-style ++ // strings. The termination is important as they are referenced to by offset ++ // by the symbol entity in the file format. ++ ++ std::vector::size_type Pos = B.size(); ++ std::vector::size_type Offset = B.size(); ++ ++ // Skip over the length field, we will fill it in later as we will have ++ // computed the length while emitting the string content itself. ++ Pos += sizeof(uint32_t); ++ ++ for (const auto &S : Strings) { ++ B.resize(Pos + S.length() + 1); ++ strcpy(reinterpret_cast(&B[Pos]), S.c_str()); ++ Pos += S.length() + 1; ++ } ++ ++ // Backfill the length of the table now that it has been computed. ++ support::ulittle32_t Length(B.size() - Offset); ++ memcpy(&B[Offset], &Length, sizeof(Length)); ++} ++ ++static ImportNameType getNameType(StringRef Sym, StringRef ExtName) { ++ if (Sym != ExtName) ++ return IMPORT_NAME_UNDECORATE; ++ if (Config->Machine == I386 && Sym.startswith("_")) ++ return IMPORT_NAME_NOPREFIX; ++ return IMPORT_NAME; ++} ++ ++static const std::string NullImportDescriptorSymbolName = ++ "__NULL_IMPORT_DESCRIPTOR"; ++ ++namespace { ++// This class constructs various small object files necessary to support linking ++// symbols imported from a DLL. The contents are pretty strictly defined and ++// nearly entirely static. The details of the structures files are defined in ++// WINNT.h and the PE/COFF specification. ++class ObjectFactory { ++ using u16 = support::ulittle16_t; ++ using u32 = support::ulittle32_t; ++ ++ BumpPtrAllocator Alloc; ++ StringRef DLLName; ++ StringRef Library; ++ std::string ImportDescriptorSymbolName; ++ std::string NullThunkSymbolName; ++ ++public: ++ ObjectFactory(StringRef S) ++ : DLLName(S), Library(S.drop_back(4)), ++ ImportDescriptorSymbolName(("__IMPORT_DESCRIPTOR_" + Library).str()), ++ NullThunkSymbolName(("\x7f" + Library + "_NULL_THUNK_DATA").str()) {} ++ ++ // Creates an Import Descriptor. This is a small object file which contains a ++ // reference to the terminators and contains the library name (entry) for the ++ // import name table. It will force the linker to construct the necessary ++ // structure to import symbols from the DLL. ++ NewArchiveMember createImportDescriptor(std::vector &Buffer); ++ ++ // Creates a NULL import descriptor. This is a small object file whcih ++ // contains a NULL import descriptor. It is used to terminate the imports ++ // from a specific DLL. ++ NewArchiveMember createNullImportDescriptor(std::vector &Buffer); ++ ++ // Create a NULL Thunk Entry. This is a small object file which contains a ++ // NULL Import Address Table entry and a NULL Import Lookup Table Entry. It ++ // is used to terminate the IAT and ILT. ++ NewArchiveMember createNullThunk(std::vector &Buffer); ++ ++ // Create a short import file which is described in PE/COFF spec 7. Import ++ // Library Format. ++ NewArchiveMember createShortImport(StringRef Sym, uint16_t Ordinal, ++ ImportNameType NameType, bool isData); ++ ++ // Create a weak external file which is described in PE/COFF Aux Format 3. ++ NewArchiveMember createWeakExternal(std::vector &Buffer, StringRef Sym, StringRef Weak, bool imp); ++}; ++} ++ ++NewArchiveMember ++ObjectFactory::createImportDescriptor(std::vector &Buffer) { ++ static const uint32_t NumberOfSections = 2; ++ static const uint32_t NumberOfSymbols = 8; ++ static const uint32_t NumberOfRelocations = 3; ++ ++ // COFF Header ++ coff_file_header Header{ ++ u16(Config->Machine), u16(NumberOfSections), u32(0), ++ u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) + ++ // .idata$2 ++ sizeof(coff_import_directory_table_entry) + ++ NumberOfRelocations * sizeof(coff_relocation) + ++ // .idata$6 ++ (DLLName.size() + 1)), ++ u32(NumberOfSymbols), u16(0), ++ u16(is32bit() ? IMAGE_FILE_32BIT_MACHINE : 0), ++ }; ++ append(Buffer, Header); ++ ++ // Section Header Table ++ static const coff_section SectionTable[NumberOfSections] = { ++ {{'.', 'i', 'd', 'a', 't', 'a', '$', '2'}, ++ u32(0), ++ u32(0), ++ u32(sizeof(coff_import_directory_table_entry)), ++ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)), ++ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) + ++ sizeof(coff_import_directory_table_entry)), ++ u32(0), ++ u16(NumberOfRelocations), ++ u16(0), ++ u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA | ++ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)}, ++ {{'.', 'i', 'd', 'a', 't', 'a', '$', '6'}, ++ u32(0), ++ u32(0), ++ u32(DLLName.size() + 1), ++ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) + ++ sizeof(coff_import_directory_table_entry) + ++ NumberOfRelocations * sizeof(coff_relocation)), ++ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) + ++ sizeof(coff_import_directory_table_entry)), ++ u32(0), ++ u16(0), ++ u16(0), ++ u32(IMAGE_SCN_ALIGN_2BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA | ++ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)}, ++ }; ++ append(Buffer, SectionTable); ++ ++ // .idata$2 ++ static const coff_import_directory_table_entry ImportDescriptor{ ++ u32(0), u32(0), u32(0), u32(0), u32(0), ++ }; ++ append(Buffer, ImportDescriptor); ++ ++ static const coff_relocation RelocationTable[NumberOfRelocations] = { ++ {u32(offsetof(coff_import_directory_table_entry, NameRVA)), u32(3), ++ u16(getImgRelRelocation())}, ++ {u32(offsetof(coff_import_directory_table_entry, ImportLookupTableRVA)), ++ u32(4), u16(getImgRelRelocation())}, ++ {u32(offsetof(coff_import_directory_table_entry, ImportAddressTableRVA)), ++ u32(5), u16(getImgRelRelocation())}, ++ }; ++ append(Buffer, RelocationTable); ++ ++ // .idata$6 ++ auto S = Buffer.size(); ++ Buffer.resize(S + DLLName.size() + 1); ++ memcpy(&Buffer[S], DLLName.data(), DLLName.size()); ++ Buffer[S + DLLName.size()] = '\0'; ++ ++ // Symbol Table ++ coff_symbol16 SymbolTable[NumberOfSymbols] = { ++ {{{'@', 'c', 'o', 'm', 'p', '.', 'i', 'd'}}, ++ u32(0), ++ u16(0xFFFF), ++ u16(0), ++ IMAGE_SYM_CLASS_STATIC, ++ 0}, ++ {{{0, 0, 0, 0, 0, 0, 0, 0}}, ++ u32(0), ++ u16(2), ++ u16(0), ++ IMAGE_SYM_CLASS_EXTERNAL, ++ 0}, ++ {{{'.', 'i', 'd', 'a', 't', 'a', '$', '2'}}, ++ u32(0), ++ u16(2), ++ u16(0), ++ IMAGE_SYM_CLASS_SECTION, ++ 0}, ++ {{{'.', 'i', 'd', 'a', 't', 'a', '$', '6'}}, ++ u32(0), ++ u16(3), ++ u16(0), ++ IMAGE_SYM_CLASS_STATIC, ++ 0}, ++ {{{'.', 'i', 'd', 'a', 't', 'a', '$', '4'}}, ++ u32(0), ++ u16(0), ++ u16(0), ++ IMAGE_SYM_CLASS_SECTION, ++ 0}, ++ {{{'.', 'i', 'd', 'a', 't', 'a', '$', '5'}}, ++ u32(0), ++ u16(0), ++ u16(0), ++ IMAGE_SYM_CLASS_SECTION, ++ 0}, ++ {{{0, 0, 0, 0, 0, 0, 0, 0}}, ++ u32(0), ++ u16(2), ++ u16(0), ++ IMAGE_SYM_CLASS_NULL, ++ 0}, ++ {{{0, 0, 0, 0, 0, 0, 0, 0}}, ++ u32(0), ++ u16(2), ++ u16(0), ++ IMAGE_SYM_CLASS_NULL, ++ 0}, ++ }; ++ reinterpret_cast(SymbolTable[1].Name).Offset = ++ sizeof(uint32_t); ++ reinterpret_cast(SymbolTable[6].Name).Offset = ++ sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1; ++ reinterpret_cast(SymbolTable[7].Name).Offset = ++ sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1 + ++ NullImportDescriptorSymbolName.length() + 1; ++ append(Buffer, SymbolTable); ++ ++ // String Table ++ writeStringTable(Buffer, ++ {ImportDescriptorSymbolName, NullImportDescriptorSymbolName, ++ NullThunkSymbolName}); ++ ++ StringRef F{reinterpret_cast(Buffer.data()), Buffer.size()}; ++ return {MemoryBufferRef(F, DLLName)}; ++} ++ ++NewArchiveMember ++ObjectFactory::createNullImportDescriptor(std::vector &Buffer) { ++ static const uint32_t NumberOfSections = 1; ++ static const uint32_t NumberOfSymbols = 2; ++ ++ // COFF Header ++ coff_file_header Header{ ++ u16(Config->Machine), u16(NumberOfSections), u32(0), ++ u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) + ++ // .idata$3 ++ sizeof(coff_import_directory_table_entry)), ++ u32(NumberOfSymbols), u16(0), ++ u16(is32bit() ? IMAGE_FILE_32BIT_MACHINE : 0), ++ }; ++ append(Buffer, Header); ++ ++ // Section Header Table ++ static const coff_section SectionTable[NumberOfSections] = { ++ {{'.', 'i', 'd', 'a', 't', 'a', '$', '3'}, ++ u32(0), ++ u32(0), ++ u32(sizeof(coff_import_directory_table_entry)), ++ u32(sizeof(coff_file_header) + ++ (NumberOfSections * sizeof(coff_section))), ++ u32(0), ++ u32(0), ++ u16(0), ++ u16(0), ++ u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA | ++ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)}, ++ }; ++ append(Buffer, SectionTable); ++ ++ // .idata$3 ++ static const coff_import_directory_table_entry ImportDescriptor{ ++ u32(0), u32(0), u32(0), u32(0), u32(0), ++ }; ++ append(Buffer, ImportDescriptor); ++ ++ // Symbol Table ++ coff_symbol16 SymbolTable[NumberOfSymbols] = { ++ {{{'@', 'c', 'o', 'm', 'p', '.', 'i', 'd'}}, ++ u32(0), ++ u16(0xFFFF), ++ u16(0), ++ IMAGE_SYM_CLASS_STATIC, ++ 0}, ++ {{{0, 0, 0, 0, 0, 0, 0, 0}}, ++ u32(0), ++ u16(2), ++ u16(0), ++ IMAGE_SYM_CLASS_EXTERNAL, ++ 0}, ++ }; ++ reinterpret_cast(SymbolTable[1].Name).Offset = ++ sizeof(uint32_t); ++ append(Buffer, SymbolTable); ++ ++ // String Table ++ writeStringTable(Buffer, {NullImportDescriptorSymbolName}); ++ ++ StringRef F{reinterpret_cast(Buffer.data()), Buffer.size()}; ++ return {MemoryBufferRef(F, DLLName)}; ++} ++ ++NewArchiveMember ObjectFactory::createNullThunk(std::vector &Buffer) { ++ static const uint32_t NumberOfSections = 2; ++ static const uint32_t NumberOfSymbols = 2; ++ ++ // COFF Header ++ coff_file_header Header{ ++ u16(Config->Machine), u16(NumberOfSections), u32(0), ++ u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) + ++ // .idata$5 ++ sizeof(export_address_table_entry) + ++ // .idata$4 ++ sizeof(export_address_table_entry)), ++ u32(NumberOfSymbols), u16(0), ++ u16(is32bit() ? IMAGE_FILE_32BIT_MACHINE : 0), ++ }; ++ append(Buffer, Header); ++ ++ // Section Header Table ++ static const coff_section SectionTable[NumberOfSections] = { ++ {{'.', 'i', 'd', 'a', 't', 'a', '$', '5'}, ++ u32(0), ++ u32(0), ++ u32(sizeof(export_address_table_entry)), ++ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)), ++ u32(0), ++ u32(0), ++ u16(0), ++ u16(0), ++ u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA | ++ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)}, ++ {{'.', 'i', 'd', 'a', 't', 'a', '$', '4'}, ++ u32(0), ++ u32(0), ++ u32(sizeof(export_address_table_entry)), ++ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) + ++ sizeof(export_address_table_entry)), ++ u32(0), ++ u32(0), ++ u16(0), ++ u16(0), ++ u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA | ++ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)}, ++ }; ++ append(Buffer, SectionTable); ++ ++ // .idata$5 ++ static const export_address_table_entry ILT{u32(0)}; ++ append(Buffer, ILT); ++ ++ // .idata$4 ++ static const export_address_table_entry IAT{u32(0)}; ++ append(Buffer, IAT); ++ ++ // Symbol Table ++ coff_symbol16 SymbolTable[NumberOfSymbols] = { ++ {{{'@', 'c', 'o', 'm', 'p', '.', 'i', 'd'}}, ++ u32(0), ++ u16(0xFFFF), ++ u16(0), ++ IMAGE_SYM_CLASS_STATIC, ++ 0}, ++ {{{0, 0, 0, 0, 0, 0, 0, 0}}, ++ u32(0), ++ u16(2), ++ u16(0), ++ IMAGE_SYM_CLASS_EXTERNAL, ++ 0}, ++ }; ++ reinterpret_cast(SymbolTable[1].Name).Offset = ++ sizeof(uint32_t); ++ append(Buffer, SymbolTable); ++ ++ // String Table ++ writeStringTable(Buffer, {NullThunkSymbolName}); ++ ++ StringRef F{reinterpret_cast(Buffer.data()), Buffer.size()}; ++ return {MemoryBufferRef{F, DLLName}}; ++} ++ ++NewArchiveMember ObjectFactory::createShortImport(StringRef Sym, ++ uint16_t Ordinal, ++ ImportNameType NameType, ++ bool isData) { ++ size_t ImpSize = DLLName.size() + Sym.size() + 2; // +2 for NULs ++ size_t Size = sizeof(coff_import_header) + ImpSize; ++ char *Buf = Alloc.Allocate(Size); ++ memset(Buf, 0, Size); ++ char *P = Buf; ++ ++ // Write short import library. ++ auto *Imp = reinterpret_cast(P); ++ P += sizeof(*Imp); ++ Imp->Sig2 = 0xFFFF; ++ Imp->Machine = Config->Machine; ++ Imp->SizeOfData = ImpSize; ++ if (Ordinal > 0) ++ Imp->OrdinalHint = Ordinal; ++ Imp->TypeInfo = (isData ? IMPORT_DATA : IMPORT_CODE); ++ ++ if(Config->Machine == IMAGE_FILE_MACHINE_I386) { ++ if(Sym.find('@') != StringRef::npos) ++ Imp->TypeInfo |= IMPORT_NAME_UNDECORATE << 2; ++ else ++ Imp->TypeInfo |= IMPORT_NAME_NOPREFIX << 2; ++ } ++ else ++ Imp->TypeInfo |= IMPORT_NAME << 2; ++ ++ // Write symbol name and DLL name. ++ memcpy(P, Sym.data(), Sym.size()); ++ P += Sym.size() + 1; ++ memcpy(P, DLLName.data(), DLLName.size()); ++ ++ return {MemoryBufferRef(StringRef(Buf, Size), DLLName)}; ++} ++ ++NewArchiveMember ObjectFactory::createWeakExternal(std::vector &Buffer, ++ StringRef Sym, StringRef Weak, bool imp) { ++ static const uint32_t NumberOfSections = 1; ++ static const uint32_t NumberOfSymbols = 5; ++ ++ // COFF Header ++ coff_file_header Header{ ++ u16(0), u16(NumberOfSections), u32(0), ++ u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section))), ++ u32(NumberOfSymbols), u16(0), ++ u16(0), ++ }; ++ append(Buffer, Header); ++ ++ // Section Header Table ++ static const coff_section SectionTable[NumberOfSections] = { ++ {{'.', 'd', 'r', 'e', 'c', 't', 'v', 'e'}, ++ u32(0), ++ u32(0), ++ u32(0), ++ u32(0), ++ u32(0), ++ u32(0), ++ u16(0), ++ u16(0), ++ u32(IMAGE_SCN_LNK_INFO | IMAGE_SCN_LNK_REMOVE)} ++ }; ++ append(Buffer, SectionTable); ++ ++ // Symbol Table ++ coff_symbol16 SymbolTable[NumberOfSymbols] = { ++ {{{'@', 'c', 'o', 'm', 'p', '.', 'i', 'd'}}, ++ u32(0), ++ u16(0xFFFF), ++ u16(0), ++ IMAGE_SYM_CLASS_STATIC, ++ 0}, ++ {{{'@', 'f', 'e', 'a', 't', '.', '0', '0'}}, ++ u32(0), ++ u16(0xFFFF), ++ u16(0), ++ IMAGE_SYM_CLASS_STATIC, ++ 0}, ++ {{{0, 0, 0, 0, 0, 0, 0, 0}}, ++ u32(0), ++ u16(0), ++ u16(0), ++ IMAGE_SYM_CLASS_EXTERNAL, ++ 0}, ++ {{{0, 0, 0, 0, 0, 0, 0, 0}}, ++ u32(0), ++ u16(0), ++ u16(0), ++ IMAGE_SYM_CLASS_WEAK_EXTERNAL, ++ 1}, ++ {{{2, 0, 0, 0, 3, 0, 0, 0}}, ++ u32(0), ++ u16(0), ++ u16(0), ++ uint8_t(0), ++ 0}, ++ }; ++ reinterpret_cast(SymbolTable[2].Name).Offset = ++ sizeof(uint32_t); ++ ++ if(imp) ++ reinterpret_cast(SymbolTable[3].Name).Offset = ++ sizeof(uint32_t) + Sym.size() + 1 + 6; //__imp_ ++ else ++ reinterpret_cast(SymbolTable[3].Name).Offset = ++ sizeof(uint32_t) + Sym.size() + 1;// + 6; //__imp_ ++ ++ append(Buffer, SymbolTable); ++ ++ // String Table ++ if(imp) ++ writeStringTable(Buffer, {std::string("__imp_").append(Sym), std::string("__imp_").append(Weak)}); ++ else ++ writeStringTable(Buffer, {Sym, Weak}); ++ ++ StringRef F{reinterpret_cast(Buffer.data()), Buffer.size()}; ++ return {MemoryBufferRef{F, DLLName}}; ++ ++} ++ ++// Creates an import library for a DLL. In this function, we first ++// create an empty import library using lib.exe and then adds short ++// import files to that file. ++int writeImportLibrary(std::string &Path) { ++ ++ std::vector Members; ++ ++ ObjectFactory OF(llvm::sys::path::filename(Config->OutputFile)); ++ ++ std::vector ImportDescriptor; ++ Members.push_back(OF.createImportDescriptor(ImportDescriptor)); ++ ++ std::vector NullImportDescriptor; ++ Members.push_back(OF.createNullImportDescriptor(NullImportDescriptor)); ++ ++ std::vector NullThunk; ++ Members.push_back(OF.createNullThunk(NullThunk)); ++ ++ for (Export &E : Config->Exports) { ++ if (E.Private) ++ continue; ++ ++ if (E.isWeak()) { ++ std::vector *WeakBuffer1 = new std::vector(); ++ std::vector *WeakBuffer2 = new std::vector(); ++ Members.push_back(OF.createWeakExternal(*WeakBuffer1, E.Name, E.ExtName, false)); ++ Members.push_back(OF.createWeakExternal(*WeakBuffer2, E.Name, E.ExtName, true)); ++ continue; ++ } ++ ++ if(E.ExtName.size() == 0) { ++ E.ExtName = E.Name; ++ } ++ ++ ImportNameType Type = getNameType(E.SymbolName, E.Name); ++ Members.push_back(OF.createShortImport(E.Name, E.Ordinal, Type, E.Data)); ++ } ++ ++ std::pair Result = ++ writeArchive(Path, Members, /*WriteSymtab*/ true, object::Archive::K_GNU, ++ /*Deterministic*/ true, /*Thin*/ false); ++ ++ if (Result.second) ++ return -1; ++ ++ return 0; ++} +diff --git a/lib/DLLDriver/ModuleDef.cpp b/lib/DLLDriver/ModuleDef.cpp +new file mode 100644 +index 0000000..428049a +--- /dev/null ++++ b/lib/DLLDriver/ModuleDef.cpp +@@ -0,0 +1,321 @@ ++//===- COFF/ModuleDef.cpp -------------------------------------------------===// ++// ++// The LLVM Linker ++// ++// This file is distributed under the University of Illinois Open Source ++// License. See LICENSE.TXT for details. ++// ++//===----------------------------------------------------------------------===// ++// ++// Windows-specific. ++// A parser for the module-definition file (.def file). ++// Parsed results are directly written to Config global variable. ++// ++// The format of module-definition files are described in this document: ++// https://msdn.microsoft.com/en-us/library/28d6s79h.aspx ++// ++//===----------------------------------------------------------------------===// ++ ++#include "Config.h" ++//#include "Error.h" ++#include "llvm/ADT/StringRef.h" ++#include "llvm/ADT/StringSwitch.h" ++#include "llvm/Object/COFF.h" ++#include "llvm/Support/StringSaver.h" ++#include "llvm/Support/raw_ostream.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN; ++using llvm::COFF::WindowsSubsystem; ++using llvm::StringRef; ++ ++using namespace llvm::COFF; ++using namespace llvm::object; ++using namespace llvm; ++ ++#include "llvm/Support/Error.h" ++ ++void fatal(const Twine &Msg) { ++ llvm::errs() << Msg << "\n"; ++ exit(1); ++} ++ ++void fatal(std::error_code EC, const Twine &Msg) { ++ fatal(Msg + ": " + EC.message()); ++} ++ ++void fatal(llvm::Error &Err, const Twine &Msg) { ++ fatal(errorToErrorCode(std::move(Err)), Msg); ++} ++ ++namespace llvm { ++namespace { ++ ++enum Kind { ++ Unknown, ++ Eof, ++ Identifier, ++ Comma, ++ Equal, ++ KwBase, ++ KwData, ++ KwExports, ++ KwHeapsize, ++ KwLibrary, ++ KwName, ++ KwNoname, ++ KwPrivate, ++ KwStacksize, ++ KwVersion, ++}; ++ ++struct Token { ++ explicit Token(Kind T = Unknown, StringRef S = "") : K(T), Value(S) {} ++ Kind K; ++ StringRef Value; ++}; ++ ++static bool isDecorated(StringRef Sym) { ++ // Disable Sym.startswith("_") because mingw-w64 is weird about this ++ return Sym.startswith("@") || Sym.startswith("?"); ++} ++ ++class Lexer { ++public: ++ explicit Lexer(StringRef S) : Buf(S) {} ++ ++ Token lex() { ++ Buf = Buf.trim(); ++ if (Buf.empty()) ++ return Token(Eof); ++ ++ switch (Buf[0]) { ++ case '\0': ++ return Token(Eof); ++ case ';': { ++ size_t End = Buf.find('\n'); ++ Buf = (End == Buf.npos) ? "" : Buf.drop_front(End); ++ return lex(); ++ } ++ case '=': ++ // TODO: Fix HACK TO WORK AROUND "==" in mingw-w64 ++ if(Buf[1] == '=') ++ Buf = Buf.drop_front(); ++ Buf = Buf.drop_front(); ++ return Token(Equal, "="); ++ case ',': ++ Buf = Buf.drop_front(); ++ return Token(Comma, ","); ++ case '"': { ++ StringRef S; ++ std::tie(S, Buf) = Buf.substr(1).split('"'); ++ return Token(Identifier, S); ++ } ++ default: { ++ size_t End = Buf.find_first_of("=,\r\n \t\v"); ++ StringRef Word = Buf.substr(0, End); ++ Kind K = llvm::StringSwitch(Word) ++ .Case("BASE", KwBase) ++ .Case("DATA", KwData) ++ .Case("EXPORTS", KwExports) ++ .Case("HEAPSIZE", KwHeapsize) ++ .Case("LIBRARY", KwLibrary) ++ .Case("NAME", KwName) ++ .Case("NONAME", KwNoname) ++ .Case("PRIVATE", KwPrivate) ++ .Case("STACKSIZE", KwStacksize) ++ .Case("VERSION", KwVersion) ++ .Default(Identifier); ++ Buf = (End == Buf.npos) ? "" : Buf.drop_front(End); ++ return Token(K, Word); ++ } ++ } ++ } ++ ++private: ++ StringRef Buf; ++}; ++ ++class Parser { ++public: ++ explicit Parser(StringRef S, StringSaver *A) : Lex(S), Alloc(A) {} ++ ++ void parse() { ++ do { ++ parseOne(); ++ } while (Tok.K != Eof); ++ } ++ ++private: ++ void read() { ++ if (Stack.empty()) { ++ Tok = Lex.lex(); ++ return; ++ } ++ Tok = Stack.back(); ++ Stack.pop_back(); ++ } ++ ++ void readAsInt(uint64_t *I) { ++ read(); ++ if (Tok.K != Identifier || Tok.Value.getAsInteger(10, *I)) ++ fatal("integer expected"); ++ } ++ ++ void expect(Kind Expected, StringRef Msg) { ++ read(); ++ if (Tok.K != Expected) ++ fatal(Msg); ++ } ++ ++ void unget() { Stack.push_back(Tok); } ++ ++ void parseOne() { ++ read(); ++ switch (Tok.K) { ++ case Eof: ++ return; ++ case KwExports: ++ for (;;) { ++ read(); ++ if (Tok.K != Identifier) { ++ unget(); ++ return; ++ } ++ parseExport(); ++ } ++ case KwHeapsize: ++ parseNumbers(&Config->HeapReserve, &Config->HeapCommit); ++ return; ++ case KwLibrary: ++ parseName(&Config->OutputFile, &Config->ImageBase); ++ if (!StringRef(Config->OutputFile).endswith_lower(".dll")) ++ Config->OutputFile += ".dll"; ++ return; ++ case KwStacksize: ++ parseNumbers(&Config->StackReserve, &Config->StackCommit); ++ return; ++ case KwName: ++ parseName(&Config->OutputFile, &Config->ImageBase); ++ return; ++ case KwVersion: ++ parseVersion(&Config->MajorImageVersion, &Config->MinorImageVersion); ++ return; ++ default: ++ fatal("unknown directive: " + Tok.Value); ++ } ++ } ++ ++ void parseExport() { ++ Export E; ++ E.Name = Tok.Value; ++ read(); ++ if (Tok.K == Equal) { ++ read(); ++ if (Tok.K != Identifier) ++ fatal("identifier expected, but got " + Tok.Value); ++ E.ExtName = E.Name; ++ E.Name = Tok.Value; ++ } else { ++ unget(); ++ } ++ ++ if (Config->Machine == I386) { ++ if (!isDecorated(E.Name)) ++ E.Name = Alloc->save("_" + E.Name); ++ if (!E.ExtName.empty() && !isDecorated(E.ExtName)) ++ E.ExtName = Alloc->save("_" + E.ExtName); ++ } ++ ++ for (;;) { ++ read(); ++ if (Tok.K == Identifier && Tok.Value[0] == '@') { ++ Tok.Value.drop_front().getAsInteger(10, E.Ordinal); ++ read(); ++ if (Tok.K == KwNoname) { ++ E.Noname = true; ++ } else { ++ unget(); ++ } ++ continue; ++ } ++ if (Tok.K == KwData) { ++ E.Data = true; ++ continue; ++ } ++ if (Tok.K == KwPrivate) { ++ E.Private = true; ++ continue; ++ } ++ unget(); ++ Config->Exports.push_back(E); ++ return; ++ } ++ } ++ ++ // HEAPSIZE/STACKSIZE reserve[,commit] ++ void parseNumbers(uint64_t *Reserve, uint64_t *Commit) { ++ readAsInt(Reserve); ++ read(); ++ if (Tok.K != Comma) { ++ unget(); ++ Commit = nullptr; ++ return; ++ } ++ readAsInt(Commit); ++ } ++ ++ // NAME outputPath [BASE=address] ++ void parseName(std::string *Out, uint64_t *Baseaddr) { ++ read(); ++ if (Tok.K == Identifier) { ++ *Out = Tok.Value; ++ } else { ++ *Out = ""; ++ unget(); ++ return; ++ } ++ read(); ++ if (Tok.K == KwBase) { ++ expect(Equal, "'=' expected"); ++ readAsInt(Baseaddr); ++ } else { ++ unget(); ++ *Baseaddr = 0; ++ } ++ } ++ ++ // VERSION major[.minor] ++ void parseVersion(uint32_t *Major, uint32_t *Minor) { ++ read(); ++ if (Tok.K != Identifier) ++ fatal("identifier expected, but got " + Tok.Value); ++ StringRef V1, V2; ++ std::tie(V1, V2) = Tok.Value.split('.'); ++ if (V1.getAsInteger(10, *Major)) ++ fatal("integer expected, but got " + Tok.Value); ++ if (V2.empty()) ++ *Minor = 0; ++ else if (V2.getAsInteger(10, *Minor)) ++ fatal("integer expected, but got " + Tok.Value); ++ } ++ ++ Lexer Lex; ++ Token Tok; ++ std::vector Stack; ++ StringSaver *Alloc; ++}; ++ ++} // anonymous namespace ++ ++void parseModuleDefs(MemoryBufferRef MB, StringSaver *Alloc) { ++ Parser(MB.getBuffer(), Alloc).parse(); ++} ++ ++} // namespace llvm +diff --git a/lib/DLLDriver/Options.td b/lib/DLLDriver/Options.td +new file mode 100644 +index 0000000..62f33f3 +--- /dev/null ++++ b/lib/DLLDriver/Options.td +@@ -0,0 +1,5 @@ ++include "llvm/Option/OptParser.td" ++ ++def emu: JoinedOrSeparate<["-"], "a">, HelpText<"Set target arch">; ++def out: JoinedOrSeparate<["-"], "o">, HelpText<"Set output file">; ++def dll: JoinedOrSeparate<["-"], "d">, HelpText<"Set dll name">; +diff --git a/lib/Object/ArchiveWriter.cpp b/lib/Object/ArchiveWriter.cpp +index 5357326..46b9d97 100644 +--- a/lib/Object/ArchiveWriter.cpp ++++ b/lib/Object/ArchiveWriter.cpp +@@ -273,7 +273,8 @@ writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind, + continue; + if (!(Symflags & object::SymbolRef::SF_Global)) + continue; +- if (Symflags & object::SymbolRef::SF_Undefined) ++ if (Symflags & object::SymbolRef::SF_Undefined && ++ !(Symflags & object::SymbolRef::SF_Weak)) + continue; + + unsigned NameOffset = NameOS.tell(); +diff --git a/tools/llvm-ar/CMakeLists.txt b/tools/llvm-ar/CMakeLists.txt +index 86233df..94cc205 100644 +--- a/tools/llvm-ar/CMakeLists.txt ++++ b/tools/llvm-ar/CMakeLists.txt +@@ -1,6 +1,7 @@ + set(LLVM_LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} + Core ++ DllDriver + LibDriver + Object + Support +@@ -12,3 +13,4 @@ add_llvm_tool(llvm-ar + + add_llvm_tool_symlink(llvm-ranlib llvm-ar) + add_llvm_tool_symlink(llvm-lib llvm-ar) ++add_llvm_tool_symlink(llvm-dlltool llvm-ar) +diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp +index 865152b..936c417 100644 +--- a/tools/llvm-ar/llvm-ar.cpp ++++ b/tools/llvm-ar/llvm-ar.cpp +@@ -16,6 +16,7 @@ + #include "llvm/ADT/Triple.h" + #include "llvm/IR/LLVMContext.h" + #include "llvm/IR/Module.h" ++#include "llvm/DllDriver/DllDriver.h" + #include "llvm/LibDriver/LibDriver.h" + #include "llvm/Object/Archive.h" + #include "llvm/Object/ArchiveWriter.h" +@@ -827,6 +828,9 @@ int main(int argc, char **argv) { + llvm::InitializeAllAsmParsers(); + + StringRef Stem = sys::path::stem(ToolName); ++ if (Stem.find("dlltool") != StringRef::npos) ++ return dllToolDriverMain(makeArrayRef(argv, argc)); ++ + if (Stem.find("ranlib") == StringRef::npos && + Stem.find("lib") != StringRef::npos) + return libDriverMain(makeArrayRef(argv, argc)); +@@ -842,5 +846,5 @@ int main(int argc, char **argv) { + return ranlib_main(); + if (Stem.find("ar") != StringRef::npos) + return ar_main(); +- fail("Not ranlib, ar or lib!"); ++ fail("Not ranlib, ar, lib or dlltool!"); + } +-- +2.7.4 + diff --git a/patches/llvm-0005.patch b/patches/llvm-0005.patch new file mode 100644 index 0000000..5d60037 --- /dev/null +++ b/patches/llvm-0005.patch @@ -0,0 +1,96 @@ +From 3de4f391131ab56e03622bf3bbb152c29bdc293e Mon Sep 17 00:00:00 2001 +From: Martell Malone +Date: Tue, 16 Aug 2016 13:05:23 -0700 +Subject: [PATCH 5/6] COFF: Fix short import lib import name type bitshift + +llvm-readobj: Support short import objects from within an archive +The import magic was previous just checked against the archive as a whole + +As per the PE COFF spec (section 8.3, Import Name Type) +Offset: 18 Size 2 bits Name: Type +Offset: 20 Size 3 bits Name: Name Type + +Offset: 20 added based on 18+2 +--- + include/llvm/Support/COFF.h | 2 +- + .../llvm-readobj/Inputs/imports.mangle.coff-x86_64 | Bin 0 -> 2108 bytes + test/tools/llvm-readobj/imports-mangle.test | 17 +++++++++++++++++ + tools/llvm-readobj/llvm-readobj.cpp | 2 ++ + 4 files changed, 20 insertions(+), 1 deletion(-) + create mode 100644 test/tools/llvm-readobj/Inputs/imports.mangle.coff-x86_64 + create mode 100644 test/tools/llvm-readobj/imports-mangle.test + +diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h +index 7dad3e8..1ca781b9 100644 +--- a/include/llvm/Support/COFF.h ++++ b/include/llvm/Support/COFF.h +@@ -657,7 +657,7 @@ namespace COFF { + } + + ImportNameType getNameType() const { +- return static_cast((TypeInfo & 0x1C) >> 3); ++ return static_cast((TypeInfo & 0x1C) >> 2); + } + }; + +diff --git a/test/tools/llvm-readobj/Inputs/imports.mangle.coff-x86_64 b/test/tools/llvm-readobj/Inputs/imports.mangle.coff-x86_64 +new file mode 100644 +index 0000000000000000000000000000000000000000..af6e583a31b953d1c9451266b09bee50093b8d54 +GIT binary patch +literal 2108 +zcmb_d&2JJ>5dX1!Db|LlF)`5wn@hpnzkM|G&UYM +z`7e0zkMPE!S8sYU9@>AzL!H_8-m)OpZqrTX&6^Kq-uu0o;qIg6PHW>y;$dp^%bG^c +zDC9Dk{HQ)7MLna--C6>`6+oK-A_XA23B(U19TR7o6%-o)v4L%umsXZ*b$j8(>hoH8 +zrM_IV*SlTVcC}Hd{B6VsvI<+h)Tl1n3&nboyxW~^d$-rg!d*OBXIYnab}%5;r?fXM +z>s7H-vR+I3s4g%H*&zyXf?-Aj3K3v43LKE)m}r)05OX0y93g15#t=bNu3?OxAuu}P +z;^RRW99vv|2$T;aVIv0@K7BIAgnQcA+VWueUsafSRW54@rys`8kDnXi5O9gG;VEigrVzjtk^-P-BycGve(_iGPQm2!1a+D8~W^C6h1?A=|G +zR(f~R$qcYs-Oe_haldzjlM}x;xlti7sjFImd&~``aW5ruNFS4Z=tuB;=7$>A-{wVr +z937aK5;F}iX$@Rn6Pqs)v@&!v=gkYJuep`+)jbp+ZE|He!sM;K$}p6YE8~k2B(&*ChildOrErr.get())) + dumpObject(Obj); ++ else if (COFFImportFile *Import = dyn_cast(&*ChildOrErr.get())) ++ dumpCOFFImportFile(Import); + else + reportError(Arc->getFileName(), readobj_error::unrecognized_file_format); + } +-- +2.7.4 + diff --git a/patches/llvm-0006.patch b/patches/llvm-0006.patch new file mode 100644 index 0000000..88838d6 --- /dev/null +++ b/patches/llvm-0006.patch @@ -0,0 +1,36 @@ +From 2743b4757dcb3ef66dc9e7b64034b0f8b94ff66a Mon Sep 17 00:00:00 2001 +From: Martell Malone +Date: Tue, 16 Aug 2016 12:55:01 -0700 +Subject: [PATCH 6/6] mingw-w64: use MSVC style ByteAlignment + +We can do alignment without -aligncomm derectives in PE COFF +Until we support GNU style in lld we should use this +--- + lib/MC/WinCOFFStreamer.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp +index 5c6407e..f86cbc5 100644 +--- a/lib/MC/WinCOFFStreamer.cpp ++++ b/lib/MC/WinCOFFStreamer.cpp +@@ -208,7 +208,7 @@ void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size, + auto *Symbol = cast(S); + + const Triple &T = getContext().getObjectFileInfo()->getTargetTriple(); +- if (T.isKnownWindowsMSVCEnvironment()) { ++ if (T.getEnvironment() != Triple::Cygnus) { + if (ByteAlignment > 32) + report_fatal_error("alignment is limited to 32-bytes"); + +@@ -220,7 +220,7 @@ void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size, + Symbol->setExternal(true); + Symbol->setCommon(Size, ByteAlignment); + +- if (!T.isKnownWindowsMSVCEnvironment() && ByteAlignment > 1) { ++ if (T.getEnvironment() == Triple::Cygnus && ByteAlignment > 1) { + SmallString<128> Directive; + raw_svector_ostream OS(Directive); + const MCObjectFileInfo *MFI = getContext().getObjectFileInfo(); +-- +2.7.4 +