Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Mach-O] Support -flat_namespace flag #795

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
[Mach-O] Support -flat_namespace flag
This implements the minimum necessary to support the `-flat_namespace`
flag.

I have not added this flag to the `-help` text, because I'm not certain
this is faithful to ld64's behaviour under this flag. From `man ld`:

     -flat_namespace
             Alters how symbols are resolved at build time and runtime.  With -two_levelnamespace (the default), the linker only
             searches dylibs on the command line for symbols, and records in which dylib they were found.  With -flat_namespace, the
             linker searches all dylibs on the command line and all dylibs those original dylibs depend on.  The linker does not record
             which dylib an external symbol came from, so at runtime dyld again searches all images and uses the first definition it
             finds.  In addition, any undefines in loaded flat_namespace dylibs must be resolvable at build time.

However, I believe what is done here is enough to approximate what build
systems expect to happen when they pass `-flat_namespace` to the linker.

Closes #785.

Signed-off-by: Carlo Cabrera <30379873+carlocab@users.noreply.github.com>
  • Loading branch information
carlocab committed Oct 19, 2022
commit d8c64c2ea72d3cab4cd6550f6758c1d4576c1338
2 changes: 2 additions & 0 deletions macho/cmdline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,8 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &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")) {
Expand Down
1 change: 1 addition & 0 deletions macho/mold.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion macho/output-chunks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ void OutputMachHeader<E>::copy_buf(Context<E> &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;
Expand All @@ -357,6 +357,9 @@ void OutputMachHeader<E>::copy_buf(Context<E> &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));
}

Expand Down
19 changes: 19 additions & 0 deletions test/macho/flat_namespace.sh
Original file line number Diff line number Diff line change
@@ -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 <<EOF | cc -o $t/a.o -c -xc -
int main() {}
EOF

cc --ld-path=./ld64 -o $t/exe $t/a.o -Wl,-flat_namespace
otool -hv $t/exe | grep -qv TWOLEVEL

cc --ld-path=./ld64 -o $t/exe $t/a.o
otool -hv $t/exe | grep -v TWOLEVEL

echo OK