From 4854c96bc55d73797abe042c02d1f714945d1c25 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Sat, 19 Jun 2021 22:03:29 +0200 Subject: [PATCH] zld: create a synthetic ___dso_handle symbol self-referenced --- src/link/MachO/Symbol.zig | 3 ++- src/link/MachO/Zld.zig | 27 +++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/link/MachO/Symbol.zig b/src/link/MachO/Symbol.zig index 3fc64febe0..35656852ea 100644 --- a/src/link/MachO/Symbol.zig +++ b/src/link/MachO/Symbol.zig @@ -85,7 +85,8 @@ pub const Proxy = struct { base: Symbol, /// Dylib where to locate this symbol. - dylib: *Dylib, + /// null means self-reference. + dylib: ?*Dylib = null, pub const base_type: Symbol.Type = .proxy; }; diff --git a/src/link/MachO/Zld.zig b/src/link/MachO/Zld.zig index 4226943353..5218c2e821 100644 --- a/src/link/MachO/Zld.zig +++ b/src/link/MachO/Zld.zig @@ -1919,6 +1919,24 @@ fn resolveSymbols(self: *Zld) !void { } if (!found) { + if (mem.eql(u8, undef.name, "___dso_handle")) { + const proxy = self.imports.get(undef.name) orelse blk: { + const name = try self.allocator.dupe(u8, undef.name); + const proxy = try self.allocator.create(Symbol.Proxy); + errdefer self.allocator.destroy(proxy); + proxy.* = .{ + .base = .{ + .@"type" = .proxy, + .name = name, + }, + }; + try self.imports.putNoClobber(self.allocator, name, &proxy.base); + break :blk &proxy.base; + }; + undef.alias = proxy; + continue; + } + log.err("undefined reference to symbol '{s}'", .{undef.name}); log.err(" | referenced in {s}", .{ undef.cast(Symbol.Unresolved).?.file.name.?, @@ -2796,7 +2814,7 @@ fn writeBindInfoTable(self: *Zld) !void { try pointers.append(.{ .offset = base_offset + proxy.base.got_index.? * @sizeOf(u64), .segment_id = segment_id, - .dylib_ordinal = proxy.dylib.ordinal.?, + .dylib_ordinal = if (proxy.dylib) |dylib| dylib.ordinal.? else 0, .name = proxy.base.name, }); } @@ -2815,7 +2833,7 @@ fn writeBindInfoTable(self: *Zld) !void { try pointers.append(.{ .offset = base_offset, .segment_id = segment_id, - .dylib_ordinal = proxy.dylib.ordinal.?, + .dylib_ordinal = if (proxy.dylib) |dylib| dylib.ordinal.? else 0, .name = proxy.base.name, }); } @@ -2855,7 +2873,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void { pointers.appendAssumeCapacity(.{ .offset = base_offset + sym.stubs_index.? * @sizeOf(u64), .segment_id = segment_id, - .dylib_ordinal = proxy.dylib.ordinal.?, + .dylib_ordinal = if (proxy.dylib) |dylib| dylib.ordinal.? else 0, .name = sym.name, }); } @@ -3163,11 +3181,12 @@ fn writeSymbolTable(self: *Zld) !void { for (self.imports.values()) |sym| { const proxy = sym.cast(Symbol.Proxy) orelse unreachable; + const dylib_ordinal = if (proxy.dylib) |dylib| dylib.ordinal.? else 0; try undefs.append(.{ .n_strx = try self.makeString(sym.name), .n_type = macho.N_UNDF | macho.N_EXT, .n_sect = 0, - .n_desc = (proxy.dylib.ordinal.? * macho.N_SYMBOL_RESOLVER) | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY, + .n_desc = (dylib_ordinal * macho.N_SYMBOL_RESOLVER) | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY, .n_value = 0, }); }