lld-link: Add --rsp-quoting= flag.

This ports https://reviews.llvm.org/D19425 from clang /
https://reviews.llvm.org/D22015 from the ELF port to COFF lld. This can be
useful when linking COFF files on a posix host.

https://reviews.llvm.org/D37452

llvm-svn: 312594
This commit is contained in:
Nico Weber 2017-09-05 23:46:45 +00:00
parent 79cdf36a2c
commit a05cbb8b95
5 changed files with 57 additions and 28 deletions

View File

@ -202,6 +202,7 @@ static bool isDecorated(StringRef Sym) {
// specified by /defaultlib.
void LinkerDriver::parseDirectives(StringRef S) {
ArgParser Parser;
// .drectve is always tokenized using Windows shell rules.
opt::InputArgList Args = Parser.parse(S);
for (auto *Arg : Args) {

View File

@ -48,18 +48,17 @@ public:
class ArgParser {
public:
// Parses command line options.
llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> Args);
// Concatenate LINK environment varirable and given arguments and parse them.
// Concatenate LINK environment variable and given arguments and parse them.
llvm::opt::InputArgList parseLINK(std::vector<const char *> Args);
// Tokenizes a given string and then parses as command line options.
llvm::opt::InputArgList parse(StringRef S) { return parse(tokenize(S)); }
private:
// Parses command line options.
llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> Args);
std::vector<const char *> tokenize(StringRef S);
std::vector<const char *> replaceResponseFiles(std::vector<const char *>);
COFFOptTable Table;
};

View File

@ -38,8 +38,6 @@
using namespace llvm::COFF;
using namespace llvm;
using llvm::cl::ExpandResponseFiles;
using llvm::cl::TokenizeWindowsCommandLine;
using llvm::sys::Process;
namespace lld {
@ -718,20 +716,40 @@ static const llvm::opt::OptTable::Info InfoTable[] = {
COFFOptTable::COFFOptTable() : OptTable(InfoTable, true) {}
// Parses a given list of options.
opt::InputArgList ArgParser::parse(ArrayRef<const char *> ArgsArr) {
// First, replace respnose files (@<file>-style options).
std::vector<const char *> Argv = replaceResponseFiles(ArgsArr);
static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) {
if (auto *Arg = Args.getLastArg(OPT_rsp_quoting)) {
StringRef S = Arg->getValue();
if (S != "windows" && S != "posix")
error("invalid response file quoting: " + S);
if (S == "windows")
return cl::TokenizeWindowsCommandLine;
return cl::TokenizeGNUCommandLine;
}
// The COFF linker always defaults to Windows quoting.
return cl::TokenizeWindowsCommandLine;
}
// Parses a given list of options.
opt::InputArgList ArgParser::parse(ArrayRef<const char *> Argv) {
// Make InputArgList from string vectors.
unsigned MissingIndex;
unsigned MissingCount;
opt::InputArgList Args = Table.ParseArgs(Argv, MissingIndex, MissingCount);
SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
// We need to get the quoting style for response files before parsing all
// options so we parse here before and ignore all the options but
// --rsp-quoting.
opt::InputArgList Args = Table.ParseArgs(Vec, MissingIndex, MissingCount);
// Expand response files (arguments in the form of @<filename>)
// and then parse the argument again.
cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), Vec);
Args = Table.ParseArgs(Vec, MissingIndex, MissingCount);
// Print the real command line if response files are expanded.
if (Args.hasArg(OPT_verbose) && ArgsArr.size() != Argv.size()) {
if (Args.hasArg(OPT_verbose) && Argv.size() != Vec.size()) {
std::string Msg = "Command line:";
for (const char *S : Argv)
for (const char *S : Vec)
Msg += " " + std::string(S);
message(Msg);
}
@ -746,17 +764,17 @@ opt::InputArgList ArgParser::parse(ArrayRef<const char *> ArgsArr) {
// link.exe has an interesting feature. If LINK or _LINK_ environment
// variables exist, their contents are handled as command line strings.
// So you can pass extra arguments using them.
opt::InputArgList ArgParser::parseLINK(std::vector<const char *> Args) {
opt::InputArgList ArgParser::parseLINK(std::vector<const char *> Argv) {
// Concatenate LINK env and command line arguments, and then parse them.
if (Optional<std::string> S = Process::GetEnv("LINK")) {
std::vector<const char *> V = tokenize(*S);
Args.insert(Args.begin(), V.begin(), V.end());
Argv.insert(Argv.begin(), V.begin(), V.end());
}
if (Optional<std::string> S = Process::GetEnv("_LINK_")) {
std::vector<const char *> V = tokenize(*S);
Args.insert(Args.begin(), V.begin(), V.end());
Argv.insert(Argv.begin(), V.begin(), V.end());
}
return parse(Args);
return parse(Argv);
}
std::vector<const char *> ArgParser::tokenize(StringRef S) {
@ -765,15 +783,6 @@ std::vector<const char *> ArgParser::tokenize(StringRef S) {
return std::vector<const char *>(Tokens.begin(), Tokens.end());
}
// Creates a new command line by replacing options starting with '@'
// character. '@<filename>' is replaced by the file's contents.
std::vector<const char *>
ArgParser::replaceResponseFiles(std::vector<const char *> Argv) {
SmallVector<const char *, 256> Tokens(Argv.data(), Argv.data() + Argv.size());
ExpandResponseFiles(Saver, TokenizeWindowsCommandLine, Tokens);
return std::vector<const char *>(Tokens.begin(), Tokens.end());
}
void printHelp(const char *Argv0) {
COFFOptTable Table;
Table.PrintHelp(outs(), Argv0, "LLVM Linker", false);

View File

@ -101,6 +101,8 @@ def help_q : Flag<["/?", "-?"], "">, Alias<help>;
def nopdb : F<"nopdb">, HelpText<"Disable PDB generation for DWARF users">;
def nosymtab : F<"nosymtab">;
def msvclto : F<"msvclto">;
def rsp_quoting : Joined<["--"], "rsp-quoting=">,
HelpText<"Quoting style for response files, 'windows' (default) or 'posix'">;
// Flags for debugging
def lldmap : F<"lldmap">;

View File

@ -3,5 +3,23 @@
# RUN: echo /out:%t.exe /entry:main %t.obj > %t.rsp
# RUN: lld-link @%t.rsp /heap:0x3000
# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
CHECK: SizeOfHeapReserve: 12288
# RUN: not lld-link --rsp-quoting=foobar @%t.rsp 2>&1 | \
# RUN: FileCheck --check-prefix=INVRSP %s
INVRSP: invalid response file quoting: foobar
# RUN: echo "blah\foo" > %t.rsp
# RUN: not lld-link @%t.rsp 2>&1 | \
# RUN: FileCheck --check-prefix=DEFRSP %s
DEFRSP: error: could not open blah\foo
# RUN: echo "blah\foo" > %t.rsp
# RUN: not lld-link --rsp-quoting=windows @%t.rsp 2>&1 | \
# RUN: FileCheck --check-prefix=WINRSP %s
WINRSP: error: could not open blah\foo
# RUN: echo "blah\foo" > %t.rsp
# RUN: not lld-link --rsp-quoting=posix @%t.rsp 2>&1 | \
# RUN: FileCheck --check-prefix=POSRSP %s
POSRSP: error: could not open blahfoo