forked from swiftlang/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
LLD: Introduce a GNU LD style driver for COFF
When building COFF programs many targets such as mingw prefer to have a gnu ld frontend. Rather then having a fully fledged standalone driver we wrap a shim around the LINK driver. Extra tests were provided by mstorsjo Reviewers: mstorsjo, ruiu Differential Revision: https://reviews.llvm.org/D33880 llvm-svn: 312926
- Loading branch information
Showing
13 changed files
with
519 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -221,4 +221,5 @@ endif() | |
add_subdirectory(docs) | ||
add_subdirectory(COFF) | ||
add_subdirectory(ELF) | ||
add_subdirectory(MinGW) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
set(LLVM_TARGET_DEFINITIONS Options.td) | ||
tablegen(LLVM Options.inc -gen-opt-parser-defs) | ||
add_public_tablegen_target(ShimOptionsTableGen) | ||
|
||
if(NOT LLD_BUILT_STANDALONE) | ||
set(tablegen_deps intrinsics_gen) | ||
endif() | ||
|
||
add_lld_library(lldMinGW | ||
Driver.cpp | ||
|
||
LINK_LIBS | ||
lldConfig | ||
lldCore | ||
${LLVM_PTHREAD_LIB} | ||
|
||
DEPENDS | ||
ShimOptionsTableGen | ||
${tablegen_deps} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
//===- MinGW/Driver.cpp ---------------------------------------------------===// | ||
// | ||
// The LLVM Linker | ||
// | ||
// This file is distributed under the University of Illinois Open Source | ||
// License. See LICENSE.TXT for details. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
/// | ||
/// GNU ld style linker driver for COFF currently supporting mingw-w64. | ||
/// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "lld/Driver/Driver.h" | ||
#include "llvm/ADT/ArrayRef.h" | ||
#include "llvm/ADT/Optional.h" | ||
#include "llvm/ADT/StringRef.h" | ||
#include "llvm/ADT/StringSwitch.h" | ||
#include "llvm/ADT/Triple.h" | ||
#include "llvm/Option/Arg.h" | ||
#include "llvm/Option/ArgList.h" | ||
#include "llvm/Option/Option.h" | ||
#include "llvm/Support/CommandLine.h" | ||
#include "llvm/Support/FileSystem.h" | ||
#include "llvm/Support/Path.h" | ||
|
||
#if !defined(_MSC_VER) && !defined(__MINGW32__) | ||
#include <unistd.h> | ||
#endif | ||
|
||
using namespace lld; | ||
using namespace llvm; | ||
|
||
namespace lld { | ||
namespace mingw { | ||
namespace { | ||
|
||
// Create OptTable | ||
enum { | ||
OPT_INVALID = 0, | ||
#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID, | ||
#include "Options.inc" | ||
#undef OPTION | ||
}; | ||
|
||
// Create prefix string literals used in Options.td | ||
#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; | ||
#include "Options.inc" | ||
#undef PREFIX | ||
|
||
// Create table mapping all options defined in Options.td | ||
static const opt::OptTable::Info InfoTable[] = { | ||
#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ | ||
{X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ | ||
X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, | ||
#include "Options.inc" | ||
#undef OPTION | ||
}; | ||
|
||
class COFFLdOptTable : public opt::OptTable { | ||
public: | ||
COFFLdOptTable() : OptTable(InfoTable, false) {} | ||
opt::InputArgList parse(ArrayRef<const char *> Argv); | ||
}; | ||
|
||
} // namespace | ||
|
||
static std::vector<std::string> LinkArgs; | ||
static std::vector<StringRef> SearchPaths; | ||
|
||
static void error(const Twine &Msg) { | ||
errs() << Msg << "\n"; | ||
llvm_shutdown(); | ||
exit(1); | ||
} | ||
|
||
// Find a file by concatenating given paths. | ||
static Optional<std::string> findFile(StringRef Path1, const Twine &Path2) { | ||
SmallString<128> S; | ||
sys::path::append(S, Path1, Path2); | ||
if (sys::fs::exists(S)) | ||
return S.str().str(); | ||
return None; | ||
} | ||
|
||
static Optional<std::string> findFromSearchPaths(StringRef Path) { | ||
for (StringRef Dir : SearchPaths) | ||
if (Optional<std::string> S = findFile(Dir, Path)) | ||
return S; | ||
return None; | ||
} | ||
|
||
// This is for -lfoo. We'll look for libfoo.dll.a or libfoo.a from search paths. | ||
static Optional<std::string> searchLibrary(StringRef Name, bool StaticOnly) { | ||
if (Name.startswith(":")) | ||
return findFromSearchPaths(Name.substr(1)); | ||
for (StringRef Dir : SearchPaths) { | ||
if (!StaticOnly) | ||
if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".dll.a")) | ||
return S; | ||
if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a")) | ||
return S; | ||
} | ||
return None; | ||
} | ||
|
||
// Add a given library by searching it from input search paths. | ||
static void addLibrary(StringRef Name, bool StaticOnly) { | ||
if (Optional<std::string> Path = searchLibrary(Name, StaticOnly)) | ||
LinkArgs.push_back(*Path); | ||
else | ||
error("unable to find library -l" + Name); | ||
} | ||
|
||
static void createFiles(opt::InputArgList &Args) { | ||
for (auto *Arg : Args) { | ||
switch (Arg->getOption().getUnaliasedOption().getID()) { | ||
case OPT_l: | ||
addLibrary(Arg->getValue(), Args.hasArg(OPT_Bstatic)); | ||
break; | ||
case OPT_INPUT: | ||
LinkArgs.push_back(Arg->getValue()); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
static void forward(opt::InputArgList &Args, unsigned Key, | ||
const std::string &OutArg, std::string Default = "") { | ||
StringRef S = Args.getLastArgValue(Key); | ||
if (!S.empty()) | ||
LinkArgs.push_back(std::string("-").append(OutArg).append(":").append(S)); | ||
else if (!Default.empty()) | ||
LinkArgs.push_back( | ||
std::string("-").append(OutArg).append(":").append(Default)); | ||
} | ||
|
||
static void forwardValue(opt::InputArgList &Args, unsigned Key, | ||
const std::string &CmpArg, const std::string &OutArg) { | ||
StringRef S = Args.getLastArgValue(Key); | ||
if (S == CmpArg) | ||
LinkArgs.push_back(std::string("-").append(OutArg)); | ||
} | ||
|
||
static bool convertValue(opt::InputArgList &Args, unsigned Key, | ||
StringRef OutArg) { | ||
if (Args.hasArg(Key)) { | ||
LinkArgs.push_back(std::string("-").append(OutArg)); | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
opt::InputArgList COFFLdOptTable::parse(ArrayRef<const char *> Argv) { | ||
unsigned MissingIndex; | ||
unsigned MissingCount; | ||
SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size()); | ||
opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount); | ||
if (MissingCount) | ||
error(Twine(Args.getArgString(MissingIndex)) + ": missing argument"); | ||
if (!Args.hasArgNoClaim(OPT_INPUT) && !Args.hasArgNoClaim(OPT_l)) | ||
error("no input files"); | ||
for (auto *Arg : Args.filtered(OPT_UNKNOWN)) | ||
error("unknown argument: " + Arg->getSpelling()); | ||
return Args; | ||
} | ||
|
||
bool link(ArrayRef<const char *> ArgsArr, raw_ostream &Diag) { | ||
COFFLdOptTable Parser; | ||
opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); | ||
LinkArgs.push_back(ArgsArr[0]); | ||
|
||
forwardValue(Args, OPT_m, "i386pe", "machine:x86"); | ||
forwardValue(Args, OPT_m, "i386pep", "machine:x64"); | ||
forwardValue(Args, OPT_m, "thumb2pe", "machine:arm"); | ||
forwardValue(Args, OPT_m, "arm64pe", "machine:arm64"); | ||
|
||
forward(Args, OPT_o, "out", | ||
convertValue(Args, OPT_shared, "dll") ? "a.dll" : "a.exe"); | ||
forward(Args, OPT_entry, "entry"); | ||
forward(Args, OPT_subs, "subsystem"); | ||
forward(Args, OPT_outlib, "implib"); | ||
forward(Args, OPT_stack, "stack"); | ||
|
||
for (auto *Arg : Args.filtered(OPT_L)) | ||
SearchPaths.push_back(Arg->getValue()); | ||
|
||
createFiles(Args); | ||
|
||
// handle __image_base__ | ||
if (Args.getLastArgValue(OPT_m) == "i386pe") | ||
LinkArgs.push_back("/alternatename:__image_base__=___ImageBase"); | ||
else | ||
LinkArgs.push_back("/alternatename:__image_base__=__ImageBase"); | ||
|
||
// repack vector of strings to vector of const char pointers for coff::link | ||
std::vector<const char *> Vec; | ||
for (const std::string &S : LinkArgs) | ||
Vec.push_back(S.c_str()); | ||
return coff::link(Vec); | ||
} | ||
|
||
} // namespace mingw | ||
} // namespace lld |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
include "llvm/Option/OptParser.td" | ||
|
||
class F<string name>: Flag<["--", "-"], name>; | ||
class J<string name>: Joined<["--", "-"], name>; | ||
class S<string name>: Separate<["--", "-"], name>; | ||
|
||
def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">, | ||
HelpText<"Add a directory to the library search path">; | ||
def entry: S<"entry">, MetaVarName<"<entry>">, | ||
HelpText<"Name of entry point symbol">; | ||
def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target emulation">; | ||
def o: JoinedOrSeparate<["-"], "o">, MetaVarName<"<path>">, | ||
HelpText<"Path to file to write output">; | ||
def l: JoinedOrSeparate<["-"], "l">, MetaVarName<"<libName>">, | ||
HelpText<"Root name of library to use">; | ||
def shared: F<"shared">, HelpText<"Build a shared object">; | ||
def subs: Separate<["--"], "subsystem">, HelpText<"Specify subsystem">; | ||
def stack: Separate<["--"], "stack">; | ||
def outlib: Separate<["--"], "out-implib">, HelpText<"Import library name">; | ||
|
||
// Currently stubs to avoid errors | ||
def Bdynamic: F<"Bdynamic">, HelpText<"Link against shared libraries">; | ||
def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries">; | ||
def major_image_version: Separate<["--"], "major-image-version">; | ||
def minor_image_version: Separate<["--"], "minor-image-version">; | ||
def enable_auto_image_base: Flag<["--"], "enable-auto-image-base">; | ||
def full_shutdown: Flag<["--"], "full-shutdown">; | ||
def O: Joined<["-"], "O">, HelpText<"Optimize output file size">; | ||
def v: Flag<["-"], "v">, HelpText<"Display the version number">; | ||
def verbose: F<"verbose">, HelpText<"Verbose mode">; | ||
def version: F<"version">, HelpText<"Display the version number and exit">; | ||
|
||
// Alias | ||
def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
--- !COFF | ||
header: | ||
Machine: IMAGE_FILE_MACHINE_ARM64 | ||
Characteristics: [ ] | ||
sections: | ||
- Name: .text | ||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
Alignment: 16 | ||
SectionData: 31C0C3666666662E0F1F84000000000031C0C3666666662E0F1F840000000000488D0500000000C3 | ||
symbols: | ||
- Name: .text | ||
Value: 0 | ||
SectionNumber: 1 | ||
SimpleType: IMAGE_SYM_TYPE_NULL | ||
ComplexType: IMAGE_SYM_DTYPE_NULL | ||
StorageClass: IMAGE_SYM_CLASS_STATIC | ||
SectionDefinition: | ||
Length: 40 | ||
NumberOfRelocations: 1 | ||
NumberOfLinenumbers: 0 | ||
CheckSum: 3930888477 | ||
Number: 1 | ||
- Name: mainCRTStartup | ||
Value: 0 | ||
SectionNumber: 1 | ||
SimpleType: IMAGE_SYM_TYPE_NULL | ||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
- Name: main | ||
Value: 16 | ||
SectionNumber: 1 | ||
SimpleType: IMAGE_SYM_TYPE_NULL | ||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
- Name: func | ||
Value: 32 | ||
SectionNumber: 1 | ||
SimpleType: IMAGE_SYM_TYPE_NULL | ||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
- Name: __ImageBase | ||
Value: 0 | ||
SectionNumber: 0 | ||
SimpleType: IMAGE_SYM_TYPE_NULL | ||
ComplexType: IMAGE_SYM_DTYPE_NULL | ||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
--- !COFF | ||
header: | ||
Machine: IMAGE_FILE_MACHINE_ARMNT | ||
Characteristics: [ ] | ||
sections: | ||
- Name: .text | ||
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | ||
Alignment: 16 | ||
SectionData: 31C0C3666666662E0F1F84000000000031C0C3666666662E0F1F840000000000B800000000C3 | ||
symbols: | ||
- Name: .text | ||
Value: 0 | ||
SectionNumber: 1 | ||
SimpleType: IMAGE_SYM_TYPE_NULL | ||
ComplexType: IMAGE_SYM_DTYPE_NULL | ||
StorageClass: IMAGE_SYM_CLASS_STATIC | ||
SectionDefinition: | ||
Length: 38 | ||
NumberOfRelocations: 1 | ||
NumberOfLinenumbers: 0 | ||
CheckSum: 3189961473 | ||
Number: 1 | ||
- Name: mainCRTStartup | ||
Value: 0 | ||
SectionNumber: 1 | ||
SimpleType: IMAGE_SYM_TYPE_NULL | ||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
- Name: main | ||
Value: 16 | ||
SectionNumber: 1 | ||
SimpleType: IMAGE_SYM_TYPE_NULL | ||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
- Name: func | ||
Value: 32 | ||
SectionNumber: 1 | ||
SimpleType: IMAGE_SYM_TYPE_NULL | ||
ComplexType: IMAGE_SYM_DTYPE_FUNCTION | ||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
- Name: __ImageBase | ||
Value: 0 | ||
SectionNumber: 0 | ||
SimpleType: IMAGE_SYM_TYPE_NULL | ||
ComplexType: IMAGE_SYM_DTYPE_NULL | ||
StorageClass: IMAGE_SYM_CLASS_EXTERNAL | ||
... |
Oops, something went wrong.