| ... | @@ -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(); |
| 239 | | 239 | |
| 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 | // } |
| 244 | | 244 | |
| 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 | // } |
| 251 | | 251 | |
| 252 | return error.TODO; | 252 | try self.flush(); |
| 253 | // try self.flush(); | | |
| 254 | } | 253 | } |
| 255 | | 254 | |
| 256 | fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u8) !void { | 255 | fn 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(); |
| 2321 | | 2322 | |
| 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(); |
| 2382 | | 2383 | |
| 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 | } |
| 2387 | | 2391 | |
| ... | @@ -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 | } |
| 2405 | | 2408 | |
| ... | @@ -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.?); |
| 2418 | | 2421 | |
| 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.?); |
| 2490 | | 2494 | |
| 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 | } |
| 2502 | | 2507 | |
| 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 | } |
| 2516 | | 2522 | |
| ... | @@ -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.?); |
| 2522 | | 2528 | |
| 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 | } |
| 2533 | | 2538 | |
| ... | @@ -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); |
| 2563 | | 2568 | |
| 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(); |
| 2677 | | 2682 | |
| 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 { |
| 2685 | | 2691 | |
| 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; |
| 2689 | | 2695 | |
| 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 }); |
| 2691 | | 2697 | |
| 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 { |
| 2722 | | 2728 | |
| 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 | } |
| 2725 | | 2738 | |
| 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(); |
| 2728 | | 2741 | |
| 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(); |
| 2764 | | 2746 | |
| 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 | } |
| 2770 | | 2759 | |
| 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 { |
| 2827 | | 2816 | |
| 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 | } |
| 2833 | | 2822 | |
| 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 | } |
| 2843 | | 2835 | |
| 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 | } |
| 2849 | | 2841 | |
| 2850 | try self.file.?.pwriteAll(buf, dysymtab.indirectsymoff); | 2842 | try self.file.?.pwriteAll(buf, dysymtab.indirectsymoff); |