Skip to content

[lld][MachO] Support for -interposable #131813

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

Merged
merged 1 commit into from
Mar 28, 2025
Merged
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
1 change: 1 addition & 0 deletions lld/MachO/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ struct Configuration {
bool deadStripDylibs = false;
bool demangle = false;
bool deadStrip = false;
bool interposable = false;
bool errorForArchMismatch = false;
bool ignoreAutoLink = false;
// ld64 allows invalid auto link options as long as the link succeeds. LLD
Expand Down
1 change: 1 addition & 0 deletions lld/MachO/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1676,6 +1676,7 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,

// Must be set before any InputSections and Symbols are created.
config->deadStrip = args.hasArg(OPT_dead_strip);
config->interposable = args.hasArg(OPT_interposable);

config->systemLibraryRoots = getSystemLibraryRoots(args);
if (const char *path = getReproduceOption(args)) {
Expand Down
7 changes: 3 additions & 4 deletions lld/MachO/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,9 @@ def grp_opts : OptionGroup<"opts">, HelpText<"OPTIMIZATIONS">;
def dead_strip : Flag<["-"], "dead_strip">,
HelpText<"Remove unreachable functions and data">,
Group<grp_opts>;
def interposable : Flag<["-"], "interposable">,
HelpText<"Indirects access to all exported symbols in an image">,
Group<grp_opts>;
def order_file : Separate<["-"], "order_file">,
MetaVarName<"<file>">,
HelpText<"Layout functions and data according to specification in <file>">,
Expand Down Expand Up @@ -873,10 +876,6 @@ def setuid_safe : Flag<["-"], "setuid_safe">,
HelpText<"Set the MH_SETUID_SAFE bit in the mach-o header">,
Flags<[HelpHidden]>,
Group<grp_rare>;
def interposable : Flag<["-"], "interposable">,
HelpText<"Indirects access to all to exported symbols in a dylib">,
Flags<[HelpHidden]>,
Group<grp_rare>;
def multi_module : Flag<["-"], "multi_module">,
Alias<interposable>,
HelpText<"Alias for -interposable">,
Expand Down
6 changes: 3 additions & 3 deletions lld/MachO/SymbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,9 @@ Defined *SymbolTable::addDefined(StringRef name, InputFile *file,
}

// With -flat_namespace, all extern symbols in dylibs are interposable.
// FIXME: Add support for `-interposable` (PR53680).
bool interposable = config->namespaceKind == NamespaceKind::flat &&
config->outputType != MachO::MH_EXECUTE &&
bool interposable = ((config->namespaceKind == NamespaceKind::flat &&
config->outputType != MachO::MH_EXECUTE) ||
config->interposable) &&
!isPrivateExtern;
Defined *defined = replaceSymbol<Defined>(
s, name, file, isec, value, size, isWeakDef, /*isExternal=*/true,
Expand Down
34 changes: 34 additions & 0 deletions lld/test/MachO/interposable.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# REQUIRES: x86

# RUN: rm -rf %t; split-file %s %t
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/2.s -o %t/2.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/3.s -o %t/3.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/main.s -o %t/main.o

# RUN: %lld -arch x86_64 -interposable -lSystem -o %t/main %t/main.o %t/2.o %t/3.o
# RUN: llvm-objdump --macho -d %t/main | FileCheck %s --check-prefix BUNDLE-OBJ
BUNDLE-OBJ-LABEL: _my_user:
BUNDLE-OBJ-NEXT: callq [[#%#x,]] ## symbol stub for: _my_friend

#--- 2.s
# my_lib: This contains the exported function
.globl _my_friend
_my_friend:
retq

#--- 3.s
# _my_user.s: This is the user/caller of the
# exported function
.text
_my_user:
callq _my_friend()
retq

#--- main.s
# main.s: dummy exec/main loads the exported function.
# This is basically a way to say `my_user` should get
# `my_func` from this executable.
.globl _main
.text
_main:
retq
Loading