| ... | ... | @@ -145,6 +145,8 @@ symbol_resolver: std.AutoHashMapUnmanaged(u32, SymbolWithLoc) = .{}, |
| 145 | 145 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 146 | 146 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 147 | 147 | |
| 148 | dyld_stub_binder_index: ?u32 = null, |
| 149 | |
| 148 | 150 | stub_helper_stubs_start_off: ?u64 = null, |
| 149 | 151 | |
| 150 | 152 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| ... | ... | @@ -386,10 +388,8 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 386 | 388 | try self.populateMissingMetadata(); |
| 387 | 389 | try self.writeLocalSymbol(0); |
| 388 | 390 | |
| 389 | | if (!self.strtab_dir.containsAdapted(@as([]const u8, "dyld_stub_binder"), StringSliceAdapter{ |
| 390 | | .strtab = &self.strtab, |
| 391 | | })) { |
| 392 | | const import_sym_index = @intCast(u32, self.undefs.items.len); |
| 391 | if (self.dyld_stub_binder_index == null) { |
| 392 | self.dyld_stub_binder_index = @intCast(u32, self.undefs.items.len); |
| 393 | 393 | const n_strx = try self.makeString("dyld_stub_binder"); |
| 394 | 394 | try self.undefs.append(self.base.allocator, .{ |
| 395 | 395 | .n_strx = n_strx, |
| ... | ... | @@ -400,11 +400,11 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 400 | 400 | }); |
| 401 | 401 | try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{ |
| 402 | 402 | .where = .undef, |
| 403 | | .where_index = import_sym_index, |
| 403 | .where_index = self.dyld_stub_binder_index.?, |
| 404 | 404 | }); |
| 405 | 405 | const got_key = GotIndirectionKey{ |
| 406 | 406 | .where = .undef, |
| 407 | | .where_index = import_sym_index, |
| 407 | .where_index = self.dyld_stub_binder_index.?, |
| 408 | 408 | }; |
| 409 | 409 | const got_index = @intCast(u32, self.got_entries.items.len); |
| 410 | 410 | try self.got_entries.append(self.base.allocator, got_key); |
| ... | ... | @@ -799,26 +799,11 @@ pub fn flush(self: *MachO, comp: *Compilation) !void { |
| 799 | 799 | try self.parseInputFiles(positionals.items, self.base.options.sysroot); |
| 800 | 800 | try self.parseLibs(libs.items, self.base.options.sysroot); |
| 801 | 801 | try self.resolveSymbols(); |
| 802 | try self.resolveDyldStubBinder(); |
| 802 | 803 | try self.parseTextBlocks(); |
| 803 | 804 | try self.addLoadDylibLCs(); |
| 804 | 805 | try self.addDataInCodeLC(); |
| 805 | 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 | 807 | try self.sortSections(); |
| 823 | 808 | try self.allocateTextSegment(); |
| 824 | 809 | try self.allocateDataConstSegment(); |
| ... | ... | @@ -1982,13 +1967,9 @@ fn writeStubHelperCommon(self: *MachO) !void { |
| 1982 | 1967 | code[9] = 0xff; |
| 1983 | 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 | 1970 | const got_index = self.got_entries_map.get(.{ |
| 1990 | 1971 | .where = .undef, |
| 1991 | | .where_index = resolv.where_index, |
| 1972 | .where_index = self.dyld_stub_binder_index.?, |
| 1992 | 1973 | }) orelse unreachable; |
| 1993 | 1974 | const addr = got.addr + got_index * @sizeOf(u64); |
| 1994 | 1975 | const displacement = try math.cast(u32, addr - stub_helper.addr - code_size); |
| ... | ... | @@ -2033,13 +2014,9 @@ fn writeStubHelperCommon(self: *MachO) !void { |
| 2033 | 2014 | code[10] = 0xbf; |
| 2034 | 2015 | code[11] = 0xa9; |
| 2035 | 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 | 2017 | const got_index = self.got_entries_map.get(.{ |
| 2041 | 2018 | .where = .undef, |
| 2042 | | .where_index = resolv.where_index, |
| 2019 | .where_index = self.dyld_stub_binder_index.?, |
| 2043 | 2020 | }) orelse unreachable; |
| 2044 | 2021 | const this_addr = stub_helper.addr + 3 * @sizeOf(u32); |
| 2045 | 2022 | const target_addr = got.addr + got_index * @sizeOf(u64); |
| ... | ... | @@ -2405,24 +2382,6 @@ fn resolveSymbols(self: *MachO) !void { |
| 2405 | 2382 | } |
| 2406 | 2383 | |
| 2407 | 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 | 2385 | next_sym = 0; |
| 2427 | 2386 | loop: while (next_sym < unresolved.count()) { |
| 2428 | 2387 | const sym = self.undefs.items[unresolved.keys()[next_sym]]; |
| ... | ... | @@ -2523,6 +2482,59 @@ fn resolveSymbols(self: *MachO) !void { |
| 2523 | 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 | 2538 | fn parseTextBlocks(self: *MachO) !void { |
| 2527 | 2539 | for (self.objects.items) |*object, object_id| { |
| 2528 | 2540 | try object.parseTextBlocks(self.base.allocator, @intCast(u16, object_id), self); |