authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-03 15:30:42+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:47+02:00
log3bd9f3801771189ad1aa9d9b41786026add38075
treec15bd0d54a436a38013644816710cdd2bcbc0860
parent7c82079d2cfb2f8c299707aa4c79455a73601914

zld: reenable entire linker in the new scheme

without the stabs... They are tricky and need a bit more work.

2 files changed, 133 insertions(+), 136 deletions(-)

src/link/MachO/Symbol.zig+13-8
...@@ -58,13 +58,6 @@ pub const Regular = struct {...@@ -58,13 +58,6 @@ pub const Regular = struct {
58 global,58 global,
59 };59 };
6060
61 pub fn isTemp(regular: Regular) bool {
62 if (regular.linkage == .translation_unit) {
63 return mem.startsWith(u8, regular.base.name, "l") or mem.startsWith(u8, regular.base.name, "L");
64 }
65 return false;
66 }
67
68 pub fn format(self: Regular, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {61 pub fn format(self: Regular, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
69 try std.fmt.format(writer, "Regular {{ ", .{});62 try std.fmt.format(writer, "Regular {{ ", .{});
70 try std.fmt.format(writer, ".linkage = {s}, ", .{self.linkage});63 try std.fmt.format(writer, ".linkage = {s}, ", .{self.linkage});
...@@ -164,7 +157,19 @@ pub fn new(allocator: *Allocator, name: []const u8) !*Symbol {...@@ -164,7 +157,19 @@ pub fn new(allocator: *Allocator, name: []const u8) !*Symbol {
164 return new_sym;157 return new_sym;
165}158}
166159
167pub fn asNlist(symbol: *Symbol, strtab: *StringTable) macho.nlist_64 {160pub fn isTemp(symbol: Symbol) bool {
161 switch (symbol.payload) {
162 .regular => |regular| {
163 if (regular.linkage == .translation_unit) {
164 return mem.startsWith(u8, symbol.name, "l") or mem.startsWith(u8, symbol.name, "L");
165 }
166 },
167 else => {},
168 }
169 return false;
170}
171
172pub fn asNlist(symbol: *Symbol, strtab: *StringTable) !macho.nlist_64 {
168 const n_strx = try strtab.getOrPut(symbol.name);173 const n_strx = try strtab.getOrPut(symbol.name);
169 const nlist = nlist: {174 const nlist = nlist: {
170 switch (symbol.payload) {175 switch (symbol.payload) {
src/link/MachO/Zld.zig+120-128
...@@ -237,20 +237,19 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg...@@ -237,20 +237,19 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
237 try self.allocateTentativeSymbols();237 try self.allocateTentativeSymbols();
238 try self.allocateProxyBindAddresses();238 try self.allocateProxyBindAddresses();
239239
240 log.warn("globals", .{});240 // log.warn("globals", .{});
241 for (self.globals.values()) |value| {241 // for (self.globals.values()) |value| {
242 log.warn(" | {s}: {}", .{ value.name, value.payload });242 // log.warn(" | {s}: {}", .{ value.name, value.payload });
243 }243 // }
244244
245 for (self.objects.items) |object| {245 // for (self.objects.items) |object| {
246 log.warn("object {s}", .{object.name.?});246 // log.warn("object {s}", .{object.name.?});
247 for (object.symbols.items) |sym| {247 // for (object.symbols.items) |sym| {
248 log.warn(" | {s}: {}", .{ sym.name, sym.payload });248 // log.warn(" | {s}: {}", .{ sym.name, sym.payload });
249 }249 // }
250 }250 // }
251251
252 return error.TODO;252 try self.flush();
253 // try self.flush();
254}253}
255254
256fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u8) !void {255fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u8) !void {
...@@ -1226,7 +1225,7 @@ fn writeStubHelperCommon(self: *Zld) !void {...@@ -1226,7 +1225,7 @@ fn writeStubHelperCommon(self: *Zld) !void {
1226 code[9] = 0xff;1225 code[9] = 0xff;
1227 code[10] = 0x25;1226 code[10] = 0x25;
1228 {1227 {
1229 const dyld_stub_binder = self.imports.get("dyld_stub_binder").?;1228 const dyld_stub_binder = self.globals.get("dyld_stub_binder").?;
1230 const addr = (got.addr + dyld_stub_binder.got_index.? * @sizeOf(u64));1229 const addr = (got.addr + dyld_stub_binder.got_index.? * @sizeOf(u64));
1231 const displacement = try math.cast(u32, addr - stub_helper.addr - code_size);1230 const displacement = try math.cast(u32, addr - stub_helper.addr - code_size);
1232 mem.writeIntLittle(u32, code[11..], displacement);1231 mem.writeIntLittle(u32, code[11..], displacement);
...@@ -1270,7 +1269,7 @@ fn writeStubHelperCommon(self: *Zld) !void {...@@ -1270,7 +1269,7 @@ fn writeStubHelperCommon(self: *Zld) !void {
1270 code[10] = 0xbf;1269 code[10] = 0xbf;
1271 code[11] = 0xa9;1270 code[11] = 0xa9;
1272 binder_blk_outer: {1271 binder_blk_outer: {
1273 const dyld_stub_binder = self.imports.get("dyld_stub_binder").?;1272 const dyld_stub_binder = self.globals.get("dyld_stub_binder").?;
1274 const this_addr = stub_helper.addr + 3 * @sizeOf(u32);1273 const this_addr = stub_helper.addr + 3 * @sizeOf(u32);
1275 const target_addr = (got.addr + dyld_stub_binder.got_index.? * @sizeOf(u64));1274 const target_addr = (got.addr + dyld_stub_binder.got_index.? * @sizeOf(u64));
1276 binder_blk: {1275 binder_blk: {
...@@ -1789,8 +1788,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1789,8 +1788,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1789 break :rebase false;1788 break :rebase false;
1790 }1789 }
1791 if (rel.target == .symbol) {1790 if (rel.target == .symbol) {
1792 const final = object.symbols.items[rel.target.symbol].getTopmostAlias();1791 const sym = object.symbols.items[rel.target.symbol];
1793 if (final.cast(Symbol.Proxy)) |_| {1792 if (sym.payload == .proxy) {
1794 break :rebase false;1793 break :rebase false;
1795 }1794 }
1796 }1795 }
...@@ -1832,9 +1831,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1832,9 +1831,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1832 const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;1831 const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
1833 const got = dc_seg.sections.items[self.got_section_index.?];1832 const got = dc_seg.sections.items[self.got_section_index.?];
1834 const sym = object.symbols.items[rel.target.symbol];1833 const sym = object.symbols.items[rel.target.symbol];
1835 const final = sym.getTopmostAlias();1834 const got_index = sym.got_index orelse {
1836 const got_index = final.got_index orelse {1835 log.err("expected GOT index relocating symbol '{s}'", .{sym.name});
1837 log.err("expected GOT index relocating symbol '{s}'", .{final.name});
1838 log.err("this is an internal linker error", .{});1836 log.err("this is an internal linker error", .{});
1839 return error.FailedToResolveRelocationTarget;1837 return error.FailedToResolveRelocationTarget;
1840 };1838 };
...@@ -1890,37 +1888,40 @@ fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.T...@@ -1890,37 +1888,40 @@ fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.T
1890 switch (target) {1888 switch (target) {
1891 .symbol => |sym_id| {1889 .symbol => |sym_id| {
1892 const sym = object.symbols.items[sym_id];1890 const sym = object.symbols.items[sym_id];
1893 const final = sym.getTopmostAlias();1891 switch (sym.payload) {
1894 if (final.cast(Symbol.Regular)) |reg| {1892 .regular => |reg| {
1895 log.debug(" | regular '{s}'", .{sym.name});1893 log.debug(" | regular '{s}'", .{sym.name});
1896 break :blk reg.address;1894 break :blk reg.address;
1897 } else if (final.cast(Symbol.Proxy)) |proxy| {1895 },
1898 if (mem.eql(u8, sym.name, "__tlv_bootstrap")) {1896 .proxy => |proxy| {
1899 log.debug(" | symbol '__tlv_bootstrap'", .{});1897 if (mem.eql(u8, sym.name, "__tlv_bootstrap")) {
1900 const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;1898 log.debug(" | symbol '__tlv_bootstrap'", .{});
1901 const tlv = segment.sections.items[self.tlv_section_index.?];1899 const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1902 break :blk tlv.addr;1900 const tlv = segment.sections.items[self.tlv_section_index.?];
1903 }1901 break :blk tlv.addr;
1904
1905 log.debug(" | symbol stub '{s}'", .{sym.name});
1906 const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1907 const stubs = segment.sections.items[self.stubs_section_index.?];
1908 const stubs_index = proxy.base.stubs_index orelse {
1909 if (proxy.bind_info.items.len > 0) {
1910 break :blk 0; // Dynamically bound by dyld.
1911 }1902 }
1912 log.err(1903
1913 "expected stubs index or dynamic bind address when relocating symbol '{s}'",1904 log.debug(" | symbol stub '{s}'", .{sym.name});
1914 .{final.name},1905 const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1915 );1906 const stubs = segment.sections.items[self.stubs_section_index.?];
1907 const stubs_index = sym.stubs_index orelse {
1908 if (proxy.bind_info.items.len > 0) {
1909 break :blk 0; // Dynamically bound by dyld.
1910 }
1911 log.err(
1912 "expected stubs index or dynamic bind address when relocating symbol '{s}'",
1913 .{sym.name},
1914 );
1915 log.err("this is an internal linker error", .{});
1916 return error.FailedToResolveRelocationTarget;
1917 };
1918 break :blk stubs.addr + stubs_index * stubs.reserved2;
1919 },
1920 else => {
1921 log.err("failed to resolve symbol '{s}' as a relocation target", .{sym.name});
1916 log.err("this is an internal linker error", .{});1922 log.err("this is an internal linker error", .{});
1917 return error.FailedToResolveRelocationTarget;1923 return error.FailedToResolveRelocationTarget;
1918 };1924 },
1919 break :blk stubs.addr + stubs_index * stubs.reserved2;
1920 } else {
1921 log.err("failed to resolve symbol '{s}' as a relocation target", .{sym.name});
1922 log.err("this is an internal linker error", .{});
1923 return error.FailedToResolveRelocationTarget;
1924 }1925 }
1925 },1926 },
1926 .section => |sect_id| {1927 .section => |sect_id| {
...@@ -2320,8 +2321,8 @@ fn flush(self: *Zld) !void {...@@ -2320,8 +2321,8 @@ fn flush(self: *Zld) !void {
2320 defer initializers.deinit();2321 defer initializers.deinit();
23212322
2322 for (self.objects.items) |object| {2323 for (self.objects.items) |object| {
2323 for (object.initializers.items) |initializer| {2324 for (object.initializers.items) |sym_id| {
2324 const address = initializer.cast(Symbol.Regular).?.address;2325 const address = object.symbols.items[sym_id].payload.regular.address;
2325 try initializers.append(address);2326 try initializers.append(address);
2326 }2327 }
2327 }2328 }
...@@ -2381,7 +2382,10 @@ fn writeGotEntries(self: *Zld) !void {...@@ -2381,7 +2382,10 @@ fn writeGotEntries(self: *Zld) !void {
2381 var writer = stream.writer();2382 var writer = stream.writer();
23822383
2383 for (self.got_entries.items) |sym| {2384 for (self.got_entries.items) |sym| {
2384 const address: u64 = if (sym.cast(Symbol.Regular)) |reg| reg.address else 0;2385 const address: u64 = switch (sym.payload) {
2386 .regular => |reg| reg.address,
2387 else => 0,
2388 };
2385 try writer.writeIntLittle(u64, address);2389 try writer.writeIntLittle(u64, address);
2386 }2390 }
23872391
...@@ -2397,9 +2401,8 @@ fn setEntryPoint(self: *Zld) !void {...@@ -2397,9 +2401,8 @@ fn setEntryPoint(self: *Zld) !void {
2397 // entrypoint. For now, assume default of `_main`.2401 // entrypoint. For now, assume default of `_main`.
2398 const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;2402 const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2399 const sym = self.globals.get("_main") orelse return error.MissingMainEntrypoint;2403 const sym = self.globals.get("_main") orelse return error.MissingMainEntrypoint;
2400 const entry_sym = sym.cast(Symbol.Regular) orelse unreachable;
2401 const ec = &self.load_commands.items[self.main_cmd_index.?].Main;2404 const ec = &self.load_commands.items[self.main_cmd_index.?].Main;
2402 ec.entryoff = @intCast(u32, entry_sym.address - seg.inner.vmaddr);2405 ec.entryoff = @intCast(u32, sym.payload.regular.address - seg.inner.vmaddr);
2403 ec.stacksize = self.stack_size;2406 ec.stacksize = self.stack_size;
2404}2407}
24052408
...@@ -2417,7 +2420,8 @@ fn writeRebaseInfoTable(self: *Zld) !void {...@@ -2417,7 +2420,8 @@ fn writeRebaseInfoTable(self: *Zld) !void {
2417 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);2420 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
24182421
2419 for (self.got_entries.items) |sym| {2422 for (self.got_entries.items) |sym| {
2420 if (sym.@"type" == .proxy) continue;2423 if (sym.payload == .proxy) continue;
2424
2421 try pointers.append(.{2425 try pointers.append(.{
2422 .offset = base_offset + sym.got_index.? * @sizeOf(u64),2426 .offset = base_offset + sym.got_index.? * @sizeOf(u64),
2423 .segment_id = segment_id,2427 .segment_id = segment_id,
...@@ -2489,28 +2493,30 @@ fn writeBindInfoTable(self: *Zld) !void {...@@ -2489,28 +2493,30 @@ fn writeBindInfoTable(self: *Zld) !void {
2489 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);2493 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
24902494
2491 for (self.got_entries.items) |sym| {2495 for (self.got_entries.items) |sym| {
2492 if (sym.cast(Symbol.Proxy)) |proxy| {2496 if (sym.payload != .proxy) continue;
2493 try pointers.append(.{2497
2494 .offset = base_offset + proxy.base.got_index.? * @sizeOf(u64),2498 const proxy = sym.payload.proxy;
2495 .segment_id = segment_id,2499 try pointers.append(.{
2496 .dylib_ordinal = proxy.dylibOrdinal(),2500 .offset = base_offset + sym.got_index.? * @sizeOf(u64),
2497 .name = proxy.base.name,2501 .segment_id = segment_id,
2498 });2502 .dylib_ordinal = proxy.dylibOrdinal(),
2499 }2503 .name = sym.name,
2504 });
2500 }2505 }
2501 }2506 }
25022507
2503 for (self.imports.values()) |sym| {2508 for (self.globals.values()) |sym| {
2504 if (sym.cast(Symbol.Proxy)) |proxy| {2509 if (sym.payload != .proxy) continue;
2505 for (proxy.bind_info.items) |info| {2510
2506 const seg = self.load_commands.items[info.segment_id].Segment;2511 const proxy = sym.payload.proxy;
2507 try pointers.append(.{2512 for (proxy.bind_info.items) |info| {
2508 .offset = info.address - seg.inner.vmaddr,2513 const seg = self.load_commands.items[info.segment_id].Segment;
2509 .segment_id = info.segment_id,2514 try pointers.append(.{
2510 .dylib_ordinal = proxy.dylibOrdinal(),2515 .offset = info.address - seg.inner.vmaddr,
2511 .name = proxy.base.name,2516 .segment_id = info.segment_id,
2512 });2517 .dylib_ordinal = proxy.dylibOrdinal(),
2513 }2518 .name = sym.name,
2519 });
2514 }2520 }
2515 }2521 }
25162522
...@@ -2520,14 +2526,13 @@ fn writeBindInfoTable(self: *Zld) !void {...@@ -2520,14 +2526,13 @@ fn writeBindInfoTable(self: *Zld) !void {
2520 const base_offset = sect.addr - seg.inner.vmaddr;2526 const base_offset = sect.addr - seg.inner.vmaddr;
2521 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);2527 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);
25222528
2523 const sym = self.imports.get("__tlv_bootstrap") orelse unreachable;2529 const sym = self.globals.get("__tlv_bootstrap") orelse unreachable;
2524 const proxy = sym.cast(Symbol.Proxy) orelse unreachable;2530 const proxy = sym.payload.proxy;
2525
2526 try pointers.append(.{2531 try pointers.append(.{
2527 .offset = base_offset,2532 .offset = base_offset,
2528 .segment_id = segment_id,2533 .segment_id = segment_id,
2529 .dylib_ordinal = proxy.dylibOrdinal(),2534 .dylib_ordinal = proxy.dylibOrdinal(),
2530 .name = proxy.base.name,2535 .name = sym.name,
2531 });2536 });
2532 }2537 }
25332538
...@@ -2562,7 +2567,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void {...@@ -2562,7 +2567,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void {
2562 try pointers.ensureCapacity(self.stubs.items.len);2567 try pointers.ensureCapacity(self.stubs.items.len);
25632568
2564 for (self.stubs.items) |sym| {2569 for (self.stubs.items) |sym| {
2565 const proxy = sym.cast(Symbol.Proxy) orelse unreachable;2570 const proxy = sym.payload.proxy;
2566 pointers.appendAssumeCapacity(.{2571 pointers.appendAssumeCapacity(.{
2567 .offset = base_offset + sym.stubs_index.? * @sizeOf(u64),2572 .offset = base_offset + sym.stubs_index.? * @sizeOf(u64),
2568 .segment_id = segment_id,2573 .segment_id = segment_id,
...@@ -2676,7 +2681,8 @@ fn writeExportInfo(self: *Zld) !void {...@@ -2676,7 +2681,8 @@ fn writeExportInfo(self: *Zld) !void {
2676 defer sorted_globals.deinit();2681 defer sorted_globals.deinit();
26772682
2678 for (self.globals.values()) |sym| {2683 for (self.globals.values()) |sym| {
2679 const reg = sym.cast(Symbol.Regular) orelse continue;2684 if (sym.payload != .regular) continue;
2685 const reg = sym.payload.regular;
2680 if (reg.linkage != .global) continue;2686 if (reg.linkage != .global) continue;
2681 try sorted_globals.append(sym.name);2687 try sorted_globals.append(sym.name);
2682 }2688 }
...@@ -2685,9 +2691,9 @@ fn writeExportInfo(self: *Zld) !void {...@@ -2685,9 +2691,9 @@ fn writeExportInfo(self: *Zld) !void {
26852691
2686 for (sorted_globals.items) |sym_name| {2692 for (sorted_globals.items) |sym_name| {
2687 const sym = self.globals.get(sym_name) orelse unreachable;2693 const sym = self.globals.get(sym_name) orelse unreachable;
2688 const reg = sym.cast(Symbol.Regular) orelse unreachable;2694 const reg = sym.payload.regular;
26892695
2690 log.debug(" | putting '{s}' defined at 0x{x}", .{ reg.base.name, reg.address });2696 log.debug(" | putting '{s}' defined at 0x{x}", .{ sym.name, reg.address });
26912697
2692 try trie.put(.{2698 try trie.put(.{
2693 .name = sym.name,2699 .name = sym.name,
...@@ -2722,50 +2728,33 @@ fn writeSymbolTable(self: *Zld) !void {...@@ -2722,50 +2728,33 @@ fn writeSymbolTable(self: *Zld) !void {
27222728
2723 var locals = std.ArrayList(macho.nlist_64).init(self.allocator);2729 var locals = std.ArrayList(macho.nlist_64).init(self.allocator);
2724 defer locals.deinit();2730 defer locals.deinit();
2731 try locals.ensureTotalCapacity(self.locals.items.len);
2732
2733 for (self.locals.items) |symbol| {
2734 if (symbol.isTemp()) continue; // TODO when merging codepaths, this should go into freelist
2735 const nlist = try symbol.asNlist(&self.strtab);
2736 locals.appendAssumeCapacity(nlist);
2737 }
27252738
2726 var exports = std.ArrayList(macho.nlist_64).init(self.allocator);2739 var exports = std.ArrayList(macho.nlist_64).init(self.allocator);
2727 defer exports.deinit();2740 defer exports.deinit();
27282741
2729 for (self.objects.items) |object| {
2730 for (object.stabs.items) |sym| {
2731 const stab = sym.cast(Symbol.Stab) orelse unreachable;
2732
2733 const nlists = try stab.asNlists(self.allocator, &self.strtab);
2734 defer self.allocator.free(nlists);
2735
2736 try locals.appendSlice(nlists);
2737 }
2738
2739 for (object.symbols.items) |sym| {
2740 const final = sym.getTopmostAlias();
2741 if (final.@"type" != .regular) continue;
2742
2743 const reg = final.cast(Symbol.Regular) orelse unreachable;
2744 if (reg.isTemp()) continue;
2745 if (reg.visited) continue;
2746
2747 const nlist = try reg.asNlist(&self.strtab);
2748
2749 switch (reg.linkage) {
2750 .translation_unit => {
2751 try locals.append(nlist);
2752 },
2753 else => {
2754 try exports.append(nlist);
2755 },
2756 }
2757
2758 reg.visited = true;
2759 }
2760 }
2761
2762 var undefs = std.ArrayList(macho.nlist_64).init(self.allocator);2742 var undefs = std.ArrayList(macho.nlist_64).init(self.allocator);
2763 defer undefs.deinit();2743 defer undefs.deinit();
2744 var undef_dir = std.StringHashMap(u32).init(self.allocator);
2745 defer undef_dir.deinit();
27642746
2765 for (self.imports.values()) |sym| {2747 for (self.globals.values()) |sym| {
2766 const proxy = sym.cast(Symbol.Proxy) orelse unreachable;2748 const nlist = try sym.asNlist(&self.strtab);
2767 const nlist = try proxy.asNlist(&self.strtab);2749 switch (sym.payload) {
2768 try undefs.append(nlist);2750 .regular => try exports.append(nlist),
2751 .proxy => {
2752 const id = @intCast(u32, undefs.items.len);
2753 try undefs.append(nlist);
2754 try undef_dir.putNoClobber(sym.name, id);
2755 },
2756 else => unreachable,
2757 }
2769 }2758 }
27702759
2771 const nlocals = locals.items.len;2760 const nlocals = locals.items.len;
...@@ -2827,24 +2816,27 @@ fn writeSymbolTable(self: *Zld) !void {...@@ -2827,24 +2816,27 @@ fn writeSymbolTable(self: *Zld) !void {
28272816
2828 stubs.reserved1 = 0;2817 stubs.reserved1 = 0;
2829 for (self.stubs.items) |sym| {2818 for (self.stubs.items) |sym| {
2830 const id = self.imports.getIndex(sym.name) orelse unreachable;2819 const id = undef_dir.get(sym.name) orelse unreachable;
2831 try writer.writeIntLittle(u32, dysymtab.iundefsym + @intCast(u32, id));2820 try writer.writeIntLittle(u32, dysymtab.iundefsym + id);
2832 }2821 }
28332822
2834 got.reserved1 = nstubs;2823 got.reserved1 = nstubs;
2835 for (self.got_entries.items) |sym| {2824 for (self.got_entries.items) |sym| {
2836 if (sym.@"type" == .proxy) {2825 switch (sym.payload) {
2837 const id = self.imports.getIndex(sym.name) orelse unreachable;2826 .proxy => {
2838 try writer.writeIntLittle(u32, dysymtab.iundefsym + @intCast(u32, id));2827 const id = undef_dir.get(sym.name) orelse unreachable;
2839 } else {2828 try writer.writeIntLittle(u32, dysymtab.iundefsym + id);
2840 try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL);2829 },
2830 else => {
2831 try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL);
2832 },
2841 }2833 }
2842 }2834 }
28432835
2844 la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries;2836 la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries;
2845 for (self.stubs.items) |sym| {2837 for (self.stubs.items) |sym| {
2846 const id = self.imports.getIndex(sym.name) orelse unreachable;2838 const id = undef_dir.get(sym.name) orelse unreachable;
2847 try writer.writeIntLittle(u32, dysymtab.iundefsym + @intCast(u32, id));2839 try writer.writeIntLittle(u32, dysymtab.iundefsym + id);
2848 }2840 }
28492841
2850 try self.file.?.pwriteAll(buf, dysymtab.indirectsymoff);2842 try self.file.?.pwriteAll(buf, dysymtab.indirectsymoff);