1
1
mirror of https://github.com/rui314/mold.git synced 2024-09-11 21:17:28 +03:00

[Mach-O] Handle response files correctly

This commit is contained in:
Rui Ueyama 2021-11-21 14:41:00 +09:00
parent 6087782660
commit efb6e6729a
5 changed files with 50 additions and 29 deletions

View File

@ -5,7 +5,7 @@
namespace mold {
template <typename C>
static std::vector<std::string_view>
std::vector<std::string_view>
read_response_file(C &ctx, std::string_view path) {
std::vector<std::string_view> vec;
MappedFile<C> *mf = MappedFile<C>::must_open(ctx, std::string(path));

View File

@ -1,4 +1,5 @@
#include "mold.h"
#include "../cmdline.h"
#include <sstream>
#include <sys/stat.h>
@ -78,35 +79,33 @@ static i64 parse_version(Context &ctx, std::string_view arg) {
void parse_nonpositional_args(Context &ctx,
std::vector<std::string> &remaining) {
std::span<std::string_view> args = ctx.cmdline_args;
args = args.subspan(1);
std::vector<std::string_view> &args = ctx.cmdline_args;
i64 i = 1;
bool version_shown = false;
while (!args.empty()) {
while (i < args.size()) {
std::string_view arg;
std::string_view arg2;
std::string_view arg3;
auto read_arg = [&](std::string name) {
if (args[0] == name) {
if (args.size() == 1)
if (args[i] == name) {
if (args.size() <= i + 1)
Fatal(ctx) << "option -" << name << ": argument missing";
arg = args[1];
args = args.subspan(2);
arg = args[i + 1];
i += 2;
return true;
}
return false;
};
auto read_arg3 = [&](std::string name) {
if (args[0] == name) {
if (args.size() == 3)
if (args[i] == name) {
if (args.size() <= i + 3)
Fatal(ctx) << "option -" << name << ": argument missing";
arg = args[1];
arg2 = args[2];
arg3 = args[3];
args = args.subspan(4);
arg = args[i + 1];
arg2 = args[i + 2];
arg3 = args[i + 3];
i += 4;
return true;
}
return false;
@ -115,24 +114,32 @@ void parse_nonpositional_args(Context &ctx,
auto read_joined = [&](std::string name) {
if (read_arg(name))
return true;
if (args[0].starts_with(name)) {
arg = args[0].substr(2);
args = args.subspan(1);
if (args[i].starts_with(name)) {
arg = args[i].substr(2);
i++;
return true;
}
return false;
};
auto read_flag = [&](std::string name) {
if (args[0] == name) {
args = args.subspan(1);
if (args[i] == name) {
i++;
return true;
}
return false;
};
if (args[i].starts_with('@')) {
std::vector<std::string_view> vec =
read_response_file(ctx, args[i].substr(1));
args.erase(args.begin() + i);
args.insert(args.begin() + i, vec.begin(), vec.end());
continue;
}
if (read_flag("-help") || read_flag("--help")) {
SyncOut(ctx) << "Usage: " << ctx.cmdline_args[0]
SyncOut(ctx) << "Usage: " << ctx.cmdline_args[i]
<< " [options] file...\n" << helpmsg;
exit(0);
}
@ -188,10 +195,10 @@ void parse_nonpositional_args(Context &ctx,
} else if (read_flag("-v")) {
SyncOut(ctx) << mold_version;
} else {
if (args[0][0] == '-')
Fatal(ctx) << "unknown command line option: " << args[0];
remaining.push_back(std::string(args[0]));
args = args.subspan(1);
if (args[i][i] == '-')
Fatal(ctx) << "unknown command line option: " << args[i];
remaining.push_back(std::string(args[i]));
i++;
}
}

View File

@ -283,7 +283,9 @@ int main(int argc, char **argv) {
exit(0);
}
ctx.cmdline_args = expand_response_files(ctx, argv);
for (i64 i = 0; i < argc; i++)
ctx.cmdline_args.push_back(argv[i]);
std::vector<std::string> file_args;
parse_nonpositional_args(ctx, file_args);

12
test/macho/response-file.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/bash
set -e
cd $(dirname $0)
mold=`pwd`/../../ld64.mold
echo -n "Testing $(basename -s .sh $0) ... "
t=$(pwd)/../../out/test/macho/$(basename -s .sh $0)
mkdir -p $t
echo ' -help' > $t/rsp
$mold @$t/rsp | grep -q Usage
echo OK

View File

@ -10,10 +10,10 @@ cat <<EOF | cc -o $t/a.o -c -xc -
int main() {}
EOF
clang -fuse-ld=$mold -o $t/exe $t/a.o -Wl,-rpath,foo -Wl,-rpath,bar
clang -fuse-ld=$mold -o $t/exe $t/a.o -Wl,-rpath,foo -Wl,-rpath,@bar
otool -l $t/exe > $t/log
grep -A3 'cmd LC_RPATH' $t/log | grep -q 'path foo'
grep -A3 'cmd LC_RPATH' $t/log | grep -q 'path bar'
grep -A3 'cmd LC_RPATH' $t/log | grep -q 'path @bar'
echo OK