| ... | @@ -145,6 +145,8 @@ symbol_resolver: std.AutoHashMapUnmanaged(u32, SymbolWithLoc) = .{}, | ... | @@ -145,6 +145,8 @@ symbol_resolver: std.AutoHashMapUnmanaged(u32, SymbolWithLoc) = .{}, |
| 145 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, | 145 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 146 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, | 146 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 147 | | 147 | |
| | 148 | dyld_stub_binder_index: ?u32 = null, |
| | 149 | |
| 148 | stub_helper_stubs_start_off: ?u64 = null, | 150 | stub_helper_stubs_start_off: ?u64 = null, |
| 149 | | 151 | |
| 150 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 152 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| ... | @@ -386,10 +388,8 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -386,10 +388,8 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 386 | try self.populateMissingMetadata(); | 388 | try self.populateMissingMetadata(); |
| 387 | try self.writeLocalSymbol(0); | 389 | try self.writeLocalSymbol(0); |
| 388 | | 390 | |
| 389 | if (!self.strtab_dir.containsAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{ | 391 | if (self.dyld_stub_binder_index == null) { |
| 390 | .strtab = &self.strtab, | 392 | self.dyld_stub_binder_index = @intCast(u32, self.undefs.items.len); |
| 391 | })) { | | |
| 392 | const import_sym_index = @intCast(u32, self.undefs.items.len); | | |
| 393 | const n_strx = try self.makeString("dyld_stub_binder"); | 393 | const n_strx = try self.makeString("dyld_stub_binder"); |
| 394 | try self.undefs.append(self.base.allocator, .{ | 394 | try self.undefs.append(self.base.allocator, .{ |
| 395 | .n_strx = n_strx, | 395 | .n_strx = n_strx, |
| ... | @@ -400,11 +400,11 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio | ... | @@ -400,11 +400,11 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 400 | }); | 400 | }); |
| 401 | try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{ | 401 | try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{ |
| 402 | .where = .undef, | 402 | .where = .undef, |
| 403 | .where_index = import_sym_index, | 403 | .where_index = self.dyld_stub_binder_index.?, |
| 404 | }); | 404 | }); |
| 405 | const got_key = GotIndirectionKey{ | 405 | const got_key = GotIndirectionKey{ |
| 406 | .where = .undef, | 406 | .where = .undef, |
| 407 | .where_index = import_sym_index, | 407 | .where_index = self.dyld_stub_binder_index.?, |
| 408 | }; | 408 | }; |
| 409 | const got_index = @intCast(u32, self.got_entries.items.len); | 409 | const got_index = @intCast(u32, self.got_entries.items.len); |
| 410 | try self.got_entries.append(self.base.allocator, got_key); | 410 | try self.got_entries.append(self.base.allocator, got_key); |
| ... | @@ -799,26 +799,11 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { | ... | @@ -799,26 +799,11 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 799 | try self.parseInputFiles(positionals.items, self.base.options.sysroot); | 799 | try self.parseInputFiles(positionals.items, self.base.options.sysroot); |
| 800 | try self.parseLibs(libs.items, self.base.options.sysroot); | 800 | try self.parseLibs(libs.items, self.base.options.sysroot); |
| 801 | try self.resolveSymbols(); | 801 | try self.resolveSymbols(); |
| | 802 | try self.resolveDyldStubBinder(); |
| 802 | try self.parseTextBlocks(); | 803 | try self.parseTextBlocks(); |
| 803 | try self.addLoadDylibLCs(); | 804 | try self.addLoadDylibLCs(); |
| 804 | try self.addDataInCodeLC(); | 805 | try self.addDataInCodeLC(); |
| 805 | try self.addCodeSignatureLC(); | 806 | try self.addCodeSignatureLC(); |
| 806 | | | |
| 807 | { | | |
| 808 | // Add dyld_stub_binder as the final GOT entry. | | |
| 809 | const n_strx = self.strtab_dir.getAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{ | | |
| 810 | .strtab = &self.strtab, | | |
| 811 | }) orelse unreachable; | | |
| 812 | const resolv = self.symbol_resolver.get(n_strx) orelse unreachable; | | |
| 813 | const got_index = @intCast(u32, self.got_entries.items.len); | | |
| 814 | const got_entry = GotIndirectionKey{ | | |
| 815 | .where = .undef, | | |
| 816 | .where_index = resolv.where_index, | | |
| 817 | }; | | |
| 818 | try self.got_entries.append(self.base.allocator, got_entry); | | |
| 819 | try self.got_entries_map.putNoClobber(self.base.allocator, got_entry, got_index); | | |
| 820 | } | | |
| 821 | | | |
| 822 | try self.sortSections(); | 807 | try self.sortSections(); |
| 823 | try self.allocateTextSegment(); | 808 | try self.allocateTextSegment(); |
| 824 | try self.allocateDataConstSegment(); | 809 | try self.allocateDataConstSegment(); |
| ... | @@ -1982,13 +1967,9 @@ fn writeStubHelperCommon(self: *MachO) !void { | ... | @@ -1982,13 +1967,9 @@ fn writeStubHelperCommon(self: *MachO) !void { |
| 1982 | code[9] = 0xff; | 1967 | code[9] = 0xff; |
| 1983 | code[10] = 0x25; | 1968 | code[10] = 0x25; |
| 1984 | { | 1969 | { |
| 1985 | const n_strx = self.strtab_dir.getAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{ | | |
| 1986 | .strtab = &self.strtab, | | |
| 1987 | }) orelse unreachable; | | |
| 1988 | const resolv = self.symbol_resolver.get(n_strx) orelse unreachable; | | |
| 1989 | const got_index = self.got_entries_map.get(.{ | 1970 | const got_index = self.got_entries_map.get(.{ |
| 1990 | .where = .undef, | 1971 | .where = .undef, |
| 1991 | .where_index = resolv.where_index, | 1972 | .where_index = self.dyld_stub_binder_index.?, |
| 1992 | }) orelse unreachable; | 1973 | }) orelse unreachable; |
| 1993 | const addr = got.addr + got_index * @sizeOf(u64); | 1974 | const addr = got.addr + got_index * @sizeOf(u64); |
| 1994 | const displacement = try math.cast(u32, addr - stub_helper.addr - code_size); | 1975 | const displacement = try math.cast(u32, addr - stub_helper.addr - code_size); |
| ... | @@ -2033,13 +2014,9 @@ fn writeStubHelperCommon(self: *MachO) !void { | ... | @@ -2033,13 +2014,9 @@ fn writeStubHelperCommon(self: *MachO) !void { |
| 2033 | code[10] = 0xbf; | 2014 | code[10] = 0xbf; |
| 2034 | code[11] = 0xa9; | 2015 | code[11] = 0xa9; |
| 2035 | binder_blk_outer: { | 2016 | binder_blk_outer: { |
| 2036 | const n_strx = self.strtab_dir.getAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{ | | |
| 2037 | .strtab = &self.strtab, | | |
| 2038 | }) orelse unreachable; | | |
| 2039 | const resolv = self.symbol_resolver.get(n_strx) orelse unreachable; | | |
| 2040 | const got_index = self.got_entries_map.get(.{ | 2017 | const got_index = self.got_entries_map.get(.{ |
| 2041 | .where = .undef, | 2018 | .where = .undef, |
| 2042 | .where_index = resolv.where_index, | 2019 | .where_index = self.dyld_stub_binder_index.?, |
| 2043 | }) orelse unreachable; | 2020 | }) orelse unreachable; |
| 2044 | const this_addr = stub_helper.addr + 3 * @sizeOf(u32); | 2021 | const this_addr = stub_helper.addr + 3 * @sizeOf(u32); |
| 2045 | const target_addr = got.addr + got_index * @sizeOf(u64); | 2022 | const target_addr = got.addr + got_index * @sizeOf(u64); |
| ... | @@ -2405,24 +2382,6 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2405,24 +2382,6 @@ fn resolveSymbols(self: *MachO) !void { |
| 2405 | } | 2382 | } |
| 2406 | | 2383 | |
| 2407 | // Third pass, resolve symbols in dynamic libraries. | 2384 | // Third pass, resolve symbols in dynamic libraries. |
| 2408 | { | | |
| 2409 | // Put dyld_stub_binder as an undefined special symbol. | | |
| 2410 | const n_strx = try self.makeString("dyld_stub_binder"); | | |
| 2411 | const undef_sym_index = @intCast(u32, self.undefs.items.len); | | |
| 2412 | try self.undefs.append(self.base.allocator, .{ | | |
| 2413 | .n_strx = n_strx, | | |
| 2414 | .n_type = macho.N_UNDF, | | |
| 2415 | .n_sect = 0, | | |
| 2416 | .n_desc = 0, | | |
| 2417 | .n_value = 0, | | |
| 2418 | }); | | |
| 2419 | try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{ | | |
| 2420 | .where = .undef, | | |
| 2421 | .where_index = undef_sym_index, | | |
| 2422 | }); | | |
| 2423 | _ = try unresolved.getOrPut(undef_sym_index); | | |
| 2424 | } | | |
| 2425 | | | |
| 2426 | next_sym = 0; | 2385 | next_sym = 0; |
| 2427 | loop: while (next_sym < unresolved.count()) { | 2386 | loop: while (next_sym < unresolved.count()) { |
| 2428 | const sym = self.undefs.items[unresolved.keys()[next_sym]]; | 2387 | const sym = self.undefs.items[unresolved.keys()[next_sym]]; |
| ... | @@ -2523,6 +2482,59 @@ fn resolveSymbols(self: *MachO) !void { | ... | @@ -2523,6 +2482,59 @@ fn resolveSymbols(self: *MachO) !void { |
| 2523 | return error.UndefinedSymbolReference; | 2482 | return error.UndefinedSymbolReference; |
| 2524 | } | 2483 | } |
| 2525 | | 2484 | |
| | 2485 | fn resolveDyldStubBinder(self: *MachO) !void { |
| | 2486 | if (self.dyld_stub_binder_index != null) return; |
| | 2487 | |
| | 2488 | const n_strx = try self.makeString("dyld_stub_binder"); |
| | 2489 | const sym_index = @intCast(u32, self.undefs.items.len); |
| | 2490 | try self.undefs.append(self.base.allocator, .{ |
| | 2491 | .n_strx = n_strx, |
| | 2492 | .n_type = macho.N_UNDF, |
| | 2493 | .n_sect = 0, |
| | 2494 | .n_desc = 0, |
| | 2495 | .n_value = 0, |
| | 2496 | }); |
| | 2497 | try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{ |
| | 2498 | .where = .undef, |
| | 2499 | .where_index = sym_index, |
| | 2500 | }); |
| | 2501 | const sym = &self.undefs.items[sym_index]; |
| | 2502 | const sym_name = self.getString(n_strx); |
| | 2503 | |
| | 2504 | for (self.dylibs.items) |dylib, id| { |
| | 2505 | if (!dylib.symbols.contains(sym_name)) continue; |
| | 2506 | |
| | 2507 | const dylib_id = @intCast(u16, id); |
| | 2508 | if (!self.referenced_dylibs.contains(dylib_id)) { |
| | 2509 | try self.referenced_dylibs.putNoClobber(self.base.allocator, dylib_id, {}); |
| | 2510 | } |
| | 2511 | |
| | 2512 | const ordinal = self.referenced_dylibs.getIndex(dylib_id) orelse unreachable; |
| | 2513 | sym.n_type |= macho.N_EXT; |
| | 2514 | sym.n_desc = @intCast(u16, ordinal + 1) * macho.N_SYMBOL_RESOLVER; |
| | 2515 | self.dyld_stub_binder_index = sym_index; |
| | 2516 | |
| | 2517 | break; |
| | 2518 | } |
| | 2519 | |
| | 2520 | if (self.dyld_stub_binder_index == null) { |
| | 2521 | log.err("undefined reference to symbol '{s}'", .{sym_name}); |
| | 2522 | return error.UndefinedSymbolReference; |
| | 2523 | } |
| | 2524 | |
| | 2525 | // Add dyld_stub_binder as the final GOT entry. |
| | 2526 | const got_index = @intCast(u32, self.got_entries.items.len); |
| | 2527 | const got_entry = GotIndirectionKey{ |
| | 2528 | .where = .undef, |
| | 2529 | .where_index = self.dyld_stub_binder_index.?, |
| | 2530 | }; |
| | 2531 | try self.got_entries.append(self.base.allocator, got_entry); |
| | 2532 | try self.got_entries_map.putNoClobber(self.base.allocator, got_entry, got_index); |
| | 2533 | |
| | 2534 | self.binding_info_dirty = true; |
| | 2535 | self.got_entries_count_dirty = true; |
| | 2536 | } |
| | 2537 | |
| 2526 | fn parseTextBlocks(self: *MachO) !void { | 2538 | fn parseTextBlocks(self: *MachO) !void { |
| 2527 | for (self.objects.items) |*object, object_id| { | 2539 | for (self.objects.items) |*object, object_id| { |
| 2528 | try object.parseTextBlocks(self.base.allocator, @intCast(u16, object_id), self); | 2540 | try object.parseTextBlocks(self.base.allocator, @intCast(u16, object_id), self); |