mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
MachO: fix dynamic lookup of undefined symbols at runtime
Ensures `MH_NOUNDEFS` is not set when dynamic lookup is enabled for undefined symbols via `linker_allow_shlib_undefined`.
This commit is contained in:
parent
53e615b920
commit
8710c5f2f7
2 changed files with 31 additions and 1 deletions
|
|
@ -2937,7 +2937,13 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {
|
||||||
|
|
||||||
fn writeHeader(self: *MachO, ncmds: usize, sizeofcmds: usize) !void {
|
fn writeHeader(self: *MachO, ncmds: usize, sizeofcmds: usize) !void {
|
||||||
var header: macho.mach_header_64 = .{};
|
var header: macho.mach_header_64 = .{};
|
||||||
header.flags = macho.MH_NOUNDEFS | macho.MH_DYLDLINK;
|
header.flags = macho.MH_DYLDLINK;
|
||||||
|
|
||||||
|
// Only set MH_NOUNDEFS if we're not allowing undefined symbols via dynamic lookup.
|
||||||
|
// When dynamic_lookup is enabled, undefined symbols are resolved at runtime by dyld.
|
||||||
|
if (self.undefined_treatment != .dynamic_lookup) {
|
||||||
|
header.flags |= macho.MH_NOUNDEFS;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: if (self.options.namespace == .two_level) {
|
// TODO: if (self.options.namespace == .two_level) {
|
||||||
header.flags |= macho.MH_TWOLEVEL;
|
header.flags |= macho.MH_TWOLEVEL;
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
|
||||||
macho_step.dependOn(testTlsLargeTbss(b, .{ .target = default_target }));
|
macho_step.dependOn(testTlsLargeTbss(b, .{ .target = default_target }));
|
||||||
macho_step.dependOn(testTlsZig(b, .{ .target = default_target }));
|
macho_step.dependOn(testTlsZig(b, .{ .target = default_target }));
|
||||||
macho_step.dependOn(testUndefinedFlag(b, .{ .target = default_target }));
|
macho_step.dependOn(testUndefinedFlag(b, .{ .target = default_target }));
|
||||||
|
macho_step.dependOn(testUndefinedDynamicLookup(b, .{ .target = default_target }));
|
||||||
macho_step.dependOn(testDiscardLocalSymbols(b, .{ .target = default_target }));
|
macho_step.dependOn(testDiscardLocalSymbols(b, .{ .target = default_target }));
|
||||||
macho_step.dependOn(testUnresolvedError(b, .{ .target = default_target }));
|
macho_step.dependOn(testUnresolvedError(b, .{ .target = default_target }));
|
||||||
macho_step.dependOn(testUnresolvedError2(b, .{ .target = default_target }));
|
macho_step.dependOn(testUnresolvedError2(b, .{ .target = default_target }));
|
||||||
|
|
@ -2632,6 +2633,29 @@ fn testUndefinedFlag(b: *Build, opts: Options) *Step {
|
||||||
return test_step;
|
return test_step;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn testUndefinedDynamicLookup(b: *Build, opts: Options) *Step {
|
||||||
|
const test_step = addTestStep(b, "undefined-dynamic-lookup", opts);
|
||||||
|
|
||||||
|
// Create a dylib with an undefined external symbol reference
|
||||||
|
const dylib = addSharedLibrary(b, opts, .{ .name = "a" });
|
||||||
|
addCSourceBytes(dylib,
|
||||||
|
\\extern int undefined_symbol(void);
|
||||||
|
\\int call_undefined(void) {
|
||||||
|
\\ return undefined_symbol();
|
||||||
|
\\}
|
||||||
|
, &.{});
|
||||||
|
dylib.linker_allow_shlib_undefined = true;
|
||||||
|
|
||||||
|
// Verify the Mach-O header does NOT contain NOUNDEFS flag
|
||||||
|
const check = dylib.checkObject();
|
||||||
|
check.checkInHeaders();
|
||||||
|
check.checkExact("header");
|
||||||
|
check.checkNotPresent("NOUNDEFS");
|
||||||
|
test_step.dependOn(&check.step);
|
||||||
|
|
||||||
|
return test_step;
|
||||||
|
}
|
||||||
|
|
||||||
fn testUnresolvedError(b: *Build, opts: Options) *Step {
|
fn testUnresolvedError(b: *Build, opts: Options) *Step {
|
||||||
const test_step = addTestStep(b, "unresolved-error", opts);
|
const test_step = addTestStep(b, "unresolved-error", opts);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue