mirror of
https://github.com/rui314/mold.git
synced 2024-11-10 10:57:55 +03:00
[Mach-O] Support -dylib
This commit is contained in:
parent
39fbd5b29c
commit
4998a130e5
@ -23,8 +23,10 @@ Options:
|
||||
-arch <ARCH_NAME> Specify target architecture
|
||||
-dead_strip Remove unreachable functions and data
|
||||
-demangle Demangle C++ symbols in log messages (default)
|
||||
-dylib Produce a dynamic library
|
||||
-dynamic Link against dylibs (default)
|
||||
-e <SYMBOL> Specify the entry point of a main executable
|
||||
-execute Produce an executable (default)
|
||||
-filelist <FILE>[,<DIR>] Specify the list of input file names
|
||||
-framework <NAME>,[,<SUFFIX>]
|
||||
Search for a given framework
|
||||
@ -176,6 +178,8 @@ void parse_nonpositional_args(Context &ctx,
|
||||
ctx.arg.dead_strip = true;
|
||||
} else if (read_flag("-demangle")) {
|
||||
ctx.arg.demangle = true;
|
||||
} else if (read_flag("-dylib")) {
|
||||
ctx.output_type = MH_DYLIB;
|
||||
} else if (read_arg("-headerpad")) {
|
||||
size_t pos;
|
||||
ctx.arg.headerpad = std::stoi(std::string(arg), &pos, 16);
|
||||
@ -185,6 +189,8 @@ void parse_nonpositional_args(Context &ctx,
|
||||
ctx.arg.dynamic = true;
|
||||
} else if (read_arg("-e")) {
|
||||
ctx.arg.entry = arg;
|
||||
} else if (read_flag("-execute")) {
|
||||
ctx.output_type = MH_EXECUTE;
|
||||
} else if (read_arg("-fatal_warnings")) {
|
||||
} else if (read_arg("-filelist")) {
|
||||
remaining.push_back("-filelist");
|
||||
|
@ -5,9 +5,19 @@ namespace mold::macho {
|
||||
static std::vector<Subsection *> collect_root_set(Context &ctx) {
|
||||
std::vector<Subsection *> rootset;
|
||||
|
||||
if (Symbol *sym = intern(ctx, ctx.arg.entry))
|
||||
if (sym->subsec)
|
||||
auto mark = [&](Symbol *sym) {
|
||||
if (sym && sym->subsec)
|
||||
rootset.push_back(sym->subsec);
|
||||
};
|
||||
|
||||
mark(intern(ctx, ctx.arg.entry));
|
||||
|
||||
if (ctx.output_type == MH_DYLIB)
|
||||
for (ObjectFile *file : ctx.objs)
|
||||
for (Symbol *sym : file->syms)
|
||||
if (sym->file == file && sym->is_extern)
|
||||
mark(sym);
|
||||
|
||||
return rootset;
|
||||
}
|
||||
|
||||
|
@ -34,10 +34,20 @@ static void create_internal_file(Context &ctx) {
|
||||
|
||||
add("__dyld_private");
|
||||
|
||||
Symbol *sym = add("__mh_execute_header");
|
||||
sym->is_extern = true;
|
||||
sym->referenced_dynamically = true;
|
||||
sym->value = ctx.arg.pagezero_size;
|
||||
switch (ctx.output_type) {
|
||||
case MH_EXECUTE: {
|
||||
Symbol *sym = add("__mh_execute_header");
|
||||
sym->is_extern = true;
|
||||
sym->referenced_dynamically = true;
|
||||
sym->value = ctx.arg.pagezero_size;
|
||||
break;
|
||||
}
|
||||
case MH_DYLIB:
|
||||
add("__mh_dylib_header");
|
||||
break;
|
||||
default:
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
static bool compare_segments(const std::unique_ptr<OutputSegment> &a,
|
||||
@ -193,6 +203,7 @@ static i64 assign_offsets(Context &ctx) {
|
||||
|
||||
static void fix_synthetic_symbol_values(Context &ctx) {
|
||||
intern(ctx, "__dyld_private")->value = ctx.data->hdr.addr;
|
||||
intern(ctx, "__mh_dylib_header")->value = ctx.data->hdr.addr;
|
||||
}
|
||||
|
||||
MappedFile<Context> *find_framework(Context &ctx, std::string name) {
|
||||
@ -366,7 +377,7 @@ int main(int argc, char **argv) {
|
||||
for (DylibFile *dylib : ctx.dylibs)
|
||||
dylib->resolve_symbols(ctx);
|
||||
|
||||
if (!intern(ctx, ctx.arg.entry)->file)
|
||||
if (ctx.output_type == MH_EXECUTE && !intern(ctx, ctx.arg.entry)->file)
|
||||
Error(ctx) << "undefined entry point symbol: " << ctx.arg.entry;
|
||||
|
||||
create_internal_file(ctx);
|
||||
|
@ -723,14 +723,15 @@ struct Context {
|
||||
bool dead_strip = true;
|
||||
bool deduplicate = true;
|
||||
bool demangle = false;
|
||||
bool dylib = false;
|
||||
bool dynamic = true;
|
||||
bool fatal_warnings = false;
|
||||
bool trace = false;
|
||||
i64 headerpad = 256;
|
||||
i64 pagezero_size = 0x100000000;
|
||||
i64 platform = PLATFORM_MACOS;
|
||||
i64 platform_min_version = 0;
|
||||
i64 platform_sdk_version = 0;
|
||||
i64 headerpad = 256;
|
||||
i64 pagezero_size = 0x100000000;
|
||||
std::string chroot;
|
||||
std::string entry = "_main";
|
||||
std::string map;
|
||||
@ -742,6 +743,7 @@ struct Context {
|
||||
} arg;
|
||||
|
||||
std::vector<std::string_view> cmdline_args;
|
||||
u32 output_type = MH_EXECUTE;
|
||||
|
||||
bool has_error = false;
|
||||
|
||||
|
@ -193,6 +193,17 @@ static std::vector<u8> create_data_in_code_cmd(Context &ctx) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
static std::vector<u8> create_id_dylib_cmd(Context &ctx) {
|
||||
std::vector<u8> buf(sizeof(DylibCommand) + ctx.arg.output.size() + 1);
|
||||
DylibCommand &cmd = *(DylibCommand *)buf.data();
|
||||
|
||||
cmd.cmd = LC_ID_DYLIB;
|
||||
cmd.cmdsize = buf.size();
|
||||
cmd.nameoff = sizeof(cmd);
|
||||
write_string(buf.data() + sizeof(cmd), ctx.arg.output);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static std::vector<u8> create_code_signature_cmd(Context &ctx) {
|
||||
std::vector<u8> buf(sizeof(LinkEditDataCommand));
|
||||
LinkEditDataCommand &cmd = *(LinkEditDataCommand *)buf.data();
|
||||
@ -239,11 +250,9 @@ static std::pair<i64, std::vector<u8>> create_load_commands(Context &ctx) {
|
||||
vec.push_back(create_dyld_info_only_cmd(ctx));
|
||||
vec.push_back(create_symtab_cmd(ctx));
|
||||
vec.push_back(create_dysymtab_cmd(ctx));
|
||||
vec.push_back(create_dylinker_cmd(ctx));
|
||||
vec.push_back(create_uuid_cmd(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)
|
||||
@ -255,6 +264,18 @@ static std::pair<i64, std::vector<u8>> create_load_commands(Context &ctx) {
|
||||
if (!ctx.data_in_code.contents.empty())
|
||||
vec.push_back(create_data_in_code_cmd(ctx));
|
||||
|
||||
switch (ctx.output_type) {
|
||||
case MH_EXECUTE:
|
||||
vec.push_back(create_dylinker_cmd(ctx));
|
||||
vec.push_back(create_main_cmd(ctx));
|
||||
break;
|
||||
case MH_DYLIB:
|
||||
vec.push_back(create_id_dylib_cmd(ctx));
|
||||
break;
|
||||
default:
|
||||
unreachable();
|
||||
}
|
||||
|
||||
if (ctx.arg.adhoc_codesign)
|
||||
vec.push_back(create_code_signature_cmd(ctx));
|
||||
|
||||
@ -286,7 +307,7 @@ void OutputMachHeader::copy_buf(Context &ctx) {
|
||||
mhdr.magic = 0xfeedfacf;
|
||||
mhdr.cputype = CPU_TYPE_X86_64;
|
||||
mhdr.cpusubtype = CPU_SUBTYPE_X86_64_ALL;
|
||||
mhdr.filetype = MH_EXECUTE;
|
||||
mhdr.filetype = ctx.output_type;
|
||||
mhdr.ncmds = ncmds;
|
||||
mhdr.sizeofcmds = cmds.size();
|
||||
mhdr.flags = MH_TWOLEVEL | MH_NOUNDEFS | MH_DYLDLINK | MH_PIE;
|
||||
@ -294,6 +315,9 @@ void OutputMachHeader::copy_buf(Context &ctx) {
|
||||
if (has_tlv(ctx))
|
||||
mhdr.flags |= MH_HAS_TLV_DESCRIPTORS;
|
||||
|
||||
if (ctx.output_type == MH_DYLIB)
|
||||
mhdr.flags |= MH_NO_REEXPORTED_DYLIBS;
|
||||
|
||||
write_vector(buf + sizeof(mhdr), cmds);
|
||||
}
|
||||
|
||||
@ -659,7 +683,12 @@ i64 ExportEncoder::finish() {
|
||||
return a.name < b.name;
|
||||
});
|
||||
|
||||
root = construct_trie(entries, 0);
|
||||
TrieNode trie = construct_trie(entries, 0);
|
||||
|
||||
if (trie.prefix.empty())
|
||||
root = std::move(trie);
|
||||
else
|
||||
root.children.push_back(std::move(trie));
|
||||
|
||||
i64 size = set_offset(root, 0);
|
||||
for (;;) {
|
||||
|
@ -6,7 +6,7 @@ echo -n "Testing $(basename -s .sh $0) ... "
|
||||
t=$(pwd)/../../out/test/macho/$(basename -s .sh $0)
|
||||
mkdir -p $t
|
||||
|
||||
cat <<EOF | cc -shared -o $t/a.dylib -xc -
|
||||
cat <<EOF | cc -c -o $t/a.o -xc -
|
||||
#include <stdio.h>
|
||||
char world[] = "world";
|
||||
|
||||
@ -15,7 +15,9 @@ char *hello() {
|
||||
}
|
||||
EOF
|
||||
|
||||
cat <<EOF | cc -o $t/b.o -c -xc -
|
||||
clang -fuse-ld=$mold -o $t/b.dylib -shared $t/a.o
|
||||
|
||||
cat <<EOF | cc -o $t/c.o -c -xc -
|
||||
#include <stdio.h>
|
||||
|
||||
char *hello();
|
||||
@ -26,7 +28,7 @@ int main() {
|
||||
}
|
||||
EOF
|
||||
|
||||
clang -fuse-ld=$mold -o $t/exe $t/b.o $t/a.dylib
|
||||
clang -fuse-ld=$mold -o $t/exe $t/c.o $t/b.dylib
|
||||
$t/exe | grep -q 'Hello world'
|
||||
|
||||
echo OK
|
||||
|
Loading…
Reference in New Issue
Block a user