authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-17 18:33:41+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-17 18:33:41+02:00
log69f42817745a13fc3cc69896cb628a7028696a88
tree2db265ec8dd270631a281f3358fd5e487c02cd40
parentc6ea181e75cc6822edbaceccb11bc3a39484d116

macho: memorize if dyld_stub_binder was already resolved


1 files changed, 62 insertions(+), 50 deletions(-)

src/link/MachO.zig+62-50
......@@ -145,6 +145,8 @@ symbol_resolver: std.AutoHashMapUnmanaged(u32, SymbolWithLoc) = .{},
145145locals_free_list: std.ArrayListUnmanaged(u32) = .{},
146146globals_free_list: std.ArrayListUnmanaged(u32) = .{},
147147
148dyld_stub_binder_index: ?u32 = null,
149
148150stub_helper_stubs_start_off: ?u64 = null,
149151
150152strtab: std.ArrayListUnmanaged(u8) = .{},
......@@ -386,10 +388,8 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
386388 try self.populateMissingMetadata();
387389 try self.writeLocalSymbol(0);
388390
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);
393393 const n_strx = try self.makeString("dyld_stub_binder");
394394 try self.undefs.append(self.base.allocator, .{
395395 .n_strx = n_strx,
......@@ -400,11 +400,11 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
400400 });
401401 try self.symbol_resolver.putNoClobber(self.base.allocator, n_strx, .{
402402 .where = .undef,
403 .where_index = import_sym_index,
403 .where_index = self.dyld_stub_binder_index.?,
404404 });
405405 const got_key = GotIndirectionKey{
406406 .where = .undef,
407 .where_index = import_sym_index,
407 .where_index = self.dyld_stub_binder_index.?,
408408 };
409409 const got_index = @intCast(u32, self.got_entries.items.len);
410410 try self.got_entries.append(self.base.allocator, got_key);
......@@ -799,26 +799,11 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
799799 try self.parseInputFiles(positionals.items, self.base.options.sysroot);
800800 try self.parseLibs(libs.items, self.base.options.sysroot);
801801 try self.resolveSymbols();
802 try self.resolveDyldStubBinder();
802803 try self.parseTextBlocks();
803804 try self.addLoadDylibLCs();
804805 try self.addDataInCodeLC();
805806 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
822807 try self.sortSections();
823808 try self.allocateTextSegment();
824809 try self.allocateDataConstSegment();
......@@ -1982,13 +1967,9 @@ fn writeStubHelperCommon(self: *MachO) !void {
19821967 code[9] = 0xff;
19831968 code[10] = 0x25;
19841969 {
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;
19891970 const got_index = self.got_entries_map.get(.{
19901971 .where = .undef,
1991 .where_index = resolv.where_index,
1972 .where_index = self.dyld_stub_binder_index.?,
19921973 }) orelse unreachable;
19931974 const addr = got.addr + got_index * @sizeOf(u64);
19941975 const displacement = try math.cast(u32, addr - stub_helper.addr - code_size);
......@@ -2033,13 +2014,9 @@ fn writeStubHelperCommon(self: *MachO) !void {
20332014 code[10] = 0xbf;
20342015 code[11] = 0xa9;
20352016 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;
20402017 const got_index = self.got_entries_map.get(.{
20412018 .where = .undef,
2042 .where_index = resolv.where_index,
2019 .where_index = self.dyld_stub_binder_index.?,
20432020 }) orelse unreachable;
20442021 const this_addr = stub_helper.addr + 3 * @sizeOf(u32);
20452022 const target_addr = got.addr + got_index * @sizeOf(u64);
......@@ -2405,24 +2382,6 @@ fn resolveSymbols(self: *MachO) !void {
24052382 }
24062383
24072384 // 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
24262385 next_sym = 0;
24272386 loop: while (next_sym < unresolved.count()) {
24282387 const sym = self.undefs.items[unresolved.keys()[next_sym]];
......@@ -2523,6 +2482,59 @@ fn resolveSymbols(self: *MachO) !void {
25232482 return error.UndefinedSymbolReference;
25242483}
25252484
2485fn 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
25262538fn parseTextBlocks(self: *MachO) !void {
25272539 for (self.objects.items) |*object, object_id| {
25282540 try object.parseTextBlocks(self.base.allocator, @intCast(u16, object_id), self);