1
1
mirror of https://github.com/rui314/mold.git synced 2024-09-20 09:27:45 +03:00

[Mach-O] Add -rpath

This commit is contained in:
Rui Ueyama 2021-11-20 19:01:18 +09:00
parent 1e4262753a
commit cee6412e3d
5 changed files with 50 additions and 2 deletions

View File

@ -29,6 +29,7 @@ Options:
-pagezero_size <SIZE> Specify the size of the __PAGEZERO segment
-platform_version <PLATFORM> <MIN_VERSION> <SDK_VERSION>
Set platform, platform version and SDK version
-rpath <PATH> Add PATH to the runpath search path list
-syslibroot <DIR> Prepend DIR to library search paths
-t Print out each file the linker loads
-v Report version information)";
@ -174,6 +175,8 @@ void parse_nonpositional_args(Context &ctx,
ctx.arg.platform = parse_platform(ctx, arg);
ctx.arg.platform_min_version = parse_version(ctx, arg2);
ctx.arg.platform_sdk_version = parse_version(ctx, arg3);
} else if (read_arg("-rpath")) {
ctx.arg.rpath.push_back(std::string(arg));
} else if (read_arg("-syslibroot")) {
ctx.arg.syslibroot.push_back(std::string(arg));
} else if (read_flag("-t")) {

View File

@ -475,6 +475,12 @@ struct UUIDCommand {
u8 uuid[16];
};
struct RpathCommand {
u32 cmd;
u32 cmdsize;
u32 path_off;
};
struct LinkEditDataCommand {
u32 cmd;
u32 cmdsize;

View File

@ -733,8 +733,9 @@ struct Context {
std::string entry = "_main";
std::string map;
std::string output;
std::vector<std::string> syslibroot;
std::vector<std::string> library_paths;
std::vector<std::string> rpath;
std::vector<std::string> syslibroot;
} arg;
std::vector<std::string_view> cmdline_args;

View File

@ -159,6 +159,18 @@ static std::vector<u8> create_load_dylib_cmd(Context &ctx, std::string_view name
return buf;
}
static std::vector<u8> create_rpath_cmd(Context &ctx, std::string_view name) {
i64 size = sizeof(RpathCommand) + name.size() + 1; // +1 for NUL
std::vector<u8> buf(align_to(size, 8));
RpathCommand &cmd = *(RpathCommand *)buf.data();
cmd.cmd = LC_RPATH;
cmd.cmdsize = buf.size();
cmd.path_off = sizeof(cmd);
write_string(buf.data() + sizeof(cmd), name);
return buf;
}
static std::vector<u8> create_function_starts_cmd(Context &ctx) {
std::vector<u8> buf(sizeof(LinkEditDataCommand));
LinkEditDataCommand &cmd = *(LinkEditDataCommand *)buf.data();
@ -232,13 +244,20 @@ static std::pair<i64, std::vector<u8>> create_load_commands(Context &ctx) {
vec.push_back(create_build_version_cmd(ctx));
vec.push_back(create_source_version_cmd(ctx));
vec.push_back(create_main_cmd(ctx));
vec.push_back(create_function_starts_cmd(ctx));
for (DylibFile *dylib : ctx.dylibs)
vec.push_back(create_load_dylib_cmd(ctx, dylib->install_name));
vec.push_back(create_function_starts_cmd(ctx));
for (std::string_view rpath : ctx.arg.rpath)
vec.push_back(create_rpath_cmd(ctx, rpath));
if (!ctx.data_in_code.contents.empty())
vec.push_back(create_data_in_code_cmd(ctx));
if (ctx.arg.adhoc_codesign)
vec.push_back(create_code_signature_cmd(ctx));
return {vec.size(), flatten(vec)};
}

19
test/macho/rpath.sh Executable file
View File

@ -0,0 +1,19 @@
#!/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
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
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'
echo OK