diff --git a/macho/cmdline.cc b/macho/cmdline.cc index 835bbdddbe..688f231781 100644 --- a/macho/cmdline.cc +++ b/macho/cmdline.cc @@ -354,6 +354,8 @@ std::vector parse_nonpositional_args(Context &ctx) { ctx.arg.dependency_info = arg; } else if (read_flag("-dylib")) { ctx.output_type = MH_DYLIB; + } else if (read_flag("-flat_namespace")) { + ctx.arg.flat_namespace = true; } else if (read_hex("-headerpad")) { ctx.arg.headerpad = hex_arg; } else if (read_flag("-headerpad_max_install_names")) { diff --git a/macho/mold.h b/macho/mold.h index ce97683593..6e535555aa 100644 --- a/macho/mold.h +++ b/macho/mold.h @@ -869,6 +869,7 @@ struct Context { bool dynamic = true; bool export_dynamic = false; bool fatal_warnings = false; + bool flat_namespace = false; bool function_starts = true; bool ignore_optimization_hints = true; bool mark_dead_strippable_dylib = false; diff --git a/macho/output-chunks.cc b/macho/output-chunks.cc index 2f0b685de8..61b2e5bd37 100644 --- a/macho/output-chunks.cc +++ b/macho/output-chunks.cc @@ -346,7 +346,7 @@ void OutputMachHeader::copy_buf(Context &ctx) { mhdr.filetype = ctx.output_type; mhdr.ncmds = cmds.size(); mhdr.sizeofcmds = flatten(cmds).size(); - mhdr.flags = MH_TWOLEVEL | MH_NOUNDEFS | MH_DYLDLINK | MH_PIE; + mhdr.flags = MH_NOUNDEFS | MH_DYLDLINK | MH_PIE; if (has_tlv(ctx)) mhdr.flags |= MH_HAS_TLV_DESCRIPTORS; @@ -357,6 +357,9 @@ void OutputMachHeader::copy_buf(Context &ctx) { if (ctx.arg.mark_dead_strippable_dylib) mhdr.flags |= MH_DEAD_STRIPPABLE_DYLIB; + if (!ctx.arg.flat_namespace) + mhdr.flags |= MH_TWOLEVEL; + write_vector(buf + sizeof(mhdr), flatten(cmds)); } diff --git a/test/macho/flat_namespace.sh b/test/macho/flat_namespace.sh new file mode 100755 index 0000000000..ae4c72eb18 --- /dev/null +++ b/test/macho/flat_namespace.sh @@ -0,0 +1,19 @@ +#!/bin/bash +export LC_ALL=C +set -e +testname=$(basename "$0" .sh) +echo -n "Testing $testname ... " +t=out/test/macho/$(uname -m)/$testname +mkdir -p $t + +cat <