parent
2772b1d36d
commit
115d7c1036
|
@ -77,31 +77,12 @@ ErrorOr<std::unique_ptr<InputFile>> LinkerDriver::openFile(StringRef Path) {
|
||||||
return std::unique_ptr<InputFile>(new ObjectFile(MBRef));
|
return std::unique_ptr<InputFile>(new ObjectFile(MBRef));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
|
||||||
class BumpPtrStringSaver : public llvm::cl::StringSaver {
|
|
||||||
public:
|
|
||||||
BumpPtrStringSaver(lld::coff::StringAllocator *A) : Alloc(A) {}
|
|
||||||
const char *SaveString(const char *S) override {
|
|
||||||
return Alloc->save(S).data();
|
|
||||||
}
|
|
||||||
lld::coff::StringAllocator *Alloc;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parses .drectve section contents and returns a list of files
|
// Parses .drectve section contents and returns a list of files
|
||||||
// specified by /defaultlib.
|
// specified by /defaultlib.
|
||||||
std::error_code
|
std::error_code
|
||||||
LinkerDriver::parseDirectives(StringRef S,
|
LinkerDriver::parseDirectives(StringRef S,
|
||||||
std::vector<std::unique_ptr<InputFile>> *Res) {
|
std::vector<std::unique_ptr<InputFile>> *Res) {
|
||||||
SmallVector<const char *, 16> Tokens;
|
auto ArgsOrErr = Parser.parse(S);
|
||||||
Tokens.push_back("link"); // argv[0] value. Will be ignored.
|
|
||||||
BumpPtrStringSaver Saver(&Alloc);
|
|
||||||
llvm::cl::TokenizeWindowsCommandLine(S, Saver, Tokens);
|
|
||||||
Tokens.push_back(nullptr);
|
|
||||||
int Argc = Tokens.size() - 1;
|
|
||||||
const char **Argv = &Tokens[0];
|
|
||||||
|
|
||||||
auto ArgsOrErr = parseArgs(Argc, Argv);
|
|
||||||
if (auto EC = ArgsOrErr.getError())
|
if (auto EC = ArgsOrErr.getError())
|
||||||
return EC;
|
return EC;
|
||||||
std::unique_ptr<llvm::opt::InputArgList> Args = std::move(ArgsOrErr.get());
|
std::unique_ptr<llvm::opt::InputArgList> Args = std::move(ArgsOrErr.get());
|
||||||
|
@ -204,7 +185,7 @@ bool LinkerDriver::link(int Argc, const char *Argv[]) {
|
||||||
llvm::InitializeAllDisassemblers();
|
llvm::InitializeAllDisassemblers();
|
||||||
|
|
||||||
// Parse command line options.
|
// Parse command line options.
|
||||||
auto ArgsOrErr = parseArgs(Argc, Argv);
|
auto ArgsOrErr = Parser.parse(Argc, Argv);
|
||||||
if (auto EC = ArgsOrErr.getError()) {
|
if (auto EC = ArgsOrErr.getError()) {
|
||||||
llvm::errs() << EC.message() << "\n";
|
llvm::errs() << EC.message() << "\n";
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -35,6 +35,29 @@ class InputFile;
|
||||||
// Entry point of the COFF linker.
|
// Entry point of the COFF linker.
|
||||||
bool link(int Argc, const char *Argv[]);
|
bool link(int Argc, const char *Argv[]);
|
||||||
|
|
||||||
|
class ArgParser {
|
||||||
|
public:
|
||||||
|
// Parses command line options.
|
||||||
|
ErrorOr<std::unique_ptr<llvm::opt::InputArgList>> parse(int Argc,
|
||||||
|
const char *Argv[]);
|
||||||
|
|
||||||
|
// Tokenizes a given string and then parses as command line options.
|
||||||
|
ErrorOr<std::unique_ptr<llvm::opt::InputArgList>> parse(StringRef S) {
|
||||||
|
return parse(tokenize(S));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ErrorOr<std::unique_ptr<llvm::opt::InputArgList>>
|
||||||
|
parse(std::vector<const char *> Argv);
|
||||||
|
|
||||||
|
std::vector<const char *> tokenize(StringRef S);
|
||||||
|
|
||||||
|
ErrorOr<std::vector<const char *>>
|
||||||
|
replaceResponseFiles(std::vector<const char *>);
|
||||||
|
|
||||||
|
StringAllocator Alloc;
|
||||||
|
};
|
||||||
|
|
||||||
class LinkerDriver {
|
class LinkerDriver {
|
||||||
public:
|
public:
|
||||||
LinkerDriver() : SearchPaths(getSearchPaths()) {}
|
LinkerDriver() : SearchPaths(getSearchPaths()) {}
|
||||||
|
@ -46,6 +69,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StringAllocator Alloc;
|
StringAllocator Alloc;
|
||||||
|
ArgParser Parser;
|
||||||
|
|
||||||
// Opens a file. Path has to be resolved already.
|
// Opens a file. Path has to be resolved already.
|
||||||
ErrorOr<std::unique_ptr<InputFile>> openFile(StringRef Path);
|
ErrorOr<std::unique_ptr<InputFile>> openFile(StringRef Path);
|
||||||
|
@ -68,9 +92,6 @@ private:
|
||||||
std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
|
std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
|
||||||
};
|
};
|
||||||
|
|
||||||
ErrorOr<std::unique_ptr<llvm::opt::InputArgList>>
|
|
||||||
parseArgs(int Argc, const char *Argv[]);
|
|
||||||
|
|
||||||
// Functions below this line are defined in DriverUtils.cpp.
|
// Functions below this line are defined in DriverUtils.cpp.
|
||||||
|
|
||||||
void printHelp(const char *Argv0);
|
void printHelp(const char *Argv0);
|
||||||
|
|
|
@ -159,13 +159,24 @@ public:
|
||||||
COFFOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable), true) {}
|
COFFOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable), true) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Parses a given list of options.
|
||||||
ErrorOr<std::unique_ptr<llvm::opt::InputArgList>>
|
ErrorOr<std::unique_ptr<llvm::opt::InputArgList>>
|
||||||
parseArgs(int Argc, const char *Argv[]) {
|
ArgParser::parse(std::vector<const char *> Argv) {
|
||||||
|
// First, replace respnose files (@<file>-style options).
|
||||||
|
auto ArgvOrErr = replaceResponseFiles(Argv);
|
||||||
|
if (auto EC = ArgvOrErr.getError()) {
|
||||||
|
llvm::errs() << "error while reading response file: " << EC.message()
|
||||||
|
<< "\n";
|
||||||
|
return EC;
|
||||||
|
}
|
||||||
|
Argv = std::move(ArgvOrErr.get());
|
||||||
|
|
||||||
|
// Make InputArgList from string vectors.
|
||||||
COFFOptTable Table;
|
COFFOptTable Table;
|
||||||
unsigned MissingIndex;
|
unsigned MissingIndex;
|
||||||
unsigned MissingCount;
|
unsigned MissingCount;
|
||||||
std::unique_ptr<llvm::opt::InputArgList> Args(
|
std::unique_ptr<llvm::opt::InputArgList> Args(Table.ParseArgs(
|
||||||
Table.ParseArgs(&Argv[1], &Argv[Argc], MissingIndex, MissingCount));
|
&Argv[0], &Argv[0] + Argv.size(), MissingIndex, MissingCount));
|
||||||
if (MissingCount) {
|
if (MissingCount) {
|
||||||
llvm::errs() << "missing arg value for \""
|
llvm::errs() << "missing arg value for \""
|
||||||
<< Args->getArgString(MissingIndex)
|
<< Args->getArgString(MissingIndex)
|
||||||
|
@ -178,6 +189,55 @@ parseArgs(int Argc, const char *Argv[]) {
|
||||||
return std::move(Args);
|
return std::move(Args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<std::unique_ptr<llvm::opt::InputArgList>>
|
||||||
|
ArgParser::parse(int Argc, const char *Argv[]) {
|
||||||
|
std::vector<const char *> V;
|
||||||
|
V.insert(V.end(), Argv + 1, Argv + Argc);
|
||||||
|
return parse(V);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class BumpPtrStringSaver : public llvm::cl::StringSaver {
|
||||||
|
public:
|
||||||
|
BumpPtrStringSaver(lld::coff::StringAllocator *A) : Alloc(A) {}
|
||||||
|
const char *SaveString(const char *S) override {
|
||||||
|
return Alloc->save(S).data();
|
||||||
|
}
|
||||||
|
lld::coff::StringAllocator *Alloc;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<const char *> ArgParser::tokenize(StringRef S) {
|
||||||
|
SmallVector<const char *, 16> Tokens;
|
||||||
|
BumpPtrStringSaver Saver(&Alloc);
|
||||||
|
llvm::cl::TokenizeWindowsCommandLine(S, Saver, Tokens);
|
||||||
|
std::vector<const char *> V;
|
||||||
|
V.insert(V.end(), &Tokens[0], &Tokens[0] + Tokens.size());
|
||||||
|
return V;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new command line by replaceing options starting with '@'
|
||||||
|
// character. '@<filename>' is replaced by the file's contents.
|
||||||
|
ErrorOr<std::vector<const char *>>
|
||||||
|
ArgParser::replaceResponseFiles(std::vector<const char *> Argv) {
|
||||||
|
std::vector<const char *> V;
|
||||||
|
for (const char *S : Argv) {
|
||||||
|
if (S[0] != '@') {
|
||||||
|
V.push_back(S);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
StringRef Path = S + 1;
|
||||||
|
auto BufOrErr = MemoryBuffer::getFile(Path);
|
||||||
|
if (auto EC = BufOrErr.getError())
|
||||||
|
return EC;
|
||||||
|
std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get());
|
||||||
|
StringRef Str = Alloc.save(Buf->getBuffer());
|
||||||
|
std::vector<const char *> Tokens = tokenize(Str);
|
||||||
|
V.insert(V.end(), Tokens.begin(), Tokens.end());
|
||||||
|
}
|
||||||
|
return V;
|
||||||
|
}
|
||||||
|
|
||||||
void printHelp(const char *Argv0) {
|
void printHelp(const char *Argv0) {
|
||||||
COFFOptTable Table;
|
COFFOptTable Table;
|
||||||
Table.PrintHelp(llvm::outs(), Argv0, "LLVM Linker", false);
|
Table.PrintHelp(llvm::outs(), Argv0, "LLVM Linker", false);
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
|
||||||
|
|
||||||
|
# RUN: echo /out:%t.exe %t.obj > %t.rsp
|
||||||
|
# RUN: lld -flavor link2 @%t.rsp /heap:0x3000
|
||||||
|
# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
|
||||||
|
|
||||||
|
CHECK: SizeOfHeapReserve: 12288
|
Loading…
Reference in New Issue