summaryrefslogtreecommitdiff
path: root/lld/MachO/Driver.cpp
diff options
context:
space:
mode:
authorDaniel Bertalan <dani@danielbertalan.dev>2024-07-06 15:41:40 +0200
committerGitHub <noreply@github.com>2024-07-06 15:41:40 +0200
commitd64efe42eb98af76ba4ba26f48d079713f513af9 (patch)
tree7350fb5d49abe2327976d2c9f163255b47d095ac /lld/MachO/Driver.cpp
parent2da0055924161d63f4ecb88371ba6ccb4552f13d (diff)
[lld-macho] Remove symbols to `__mod_init_func` with `-init_offsets` (#97156)
When `-fixup_chains`/`-init_offsets` is used, a different section, `__init_offsets` is synthesized from `__mod_init_func`. If there are any symbols defined inside `__mod_init_func`, they are added to the symbol table unconditionally while processing the input files. Later, when querying these symbols' addresses (when constructing the symtab or exports trie), we crash with a null deref, as there is no output section assigned to them. Just making the symbols point to `__init_offsets` is a bad idea, as the new section stores 32-bit integers instead of 64-bit pointers; accessing the symbols would not do what the programmer intended. We should entirely omit them from the output. This is what ld64 and ld-prime do. This patch uses the same mechanism as dead-stripping to mark these symbols as not needed in the output. There might be nicer fixes than the workaround, this is discussed in #97155. Fixes https://github.com/llvm/llvm-project/pull/79894#issuecomment-1944092892 Fixes #94716
Diffstat (limited to 'lld/MachO/Driver.cpp')
-rw-r--r--lld/MachO/Driver.cpp11
1 files changed, 11 insertions, 0 deletions
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 9dddabcf3680..83c92d214de3 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -1393,6 +1393,12 @@ static void handleExplicitExports() {
}
}
+static void eraseInitializerSymbols() {
+ for (ConcatInputSection *isec : in.initOffsets->inputs())
+ for (Defined *sym : isec->symbols)
+ sym->used = false;
+}
+
namespace lld {
namespace macho {
bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
@@ -1971,6 +1977,11 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
if (config->deadStrip)
markLive();
+ // Ensure that no symbols point inside __mod_init_func sections if they are
+ // removed due to -init_offsets. This must run after dead stripping.
+ if (config->emitInitOffsets)
+ eraseInitializerSymbols();
+
// Categories are not subject to dead-strip. The __objc_catlist section is
// marked as NO_DEAD_STRIP and that propagates into all category data.
if (args.hasArg(OPT_check_category_conflicts))