authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-17 17:30:16+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-17 17:30:16+02:00
log97914d93a9733307309d5660ee5ce044f56a98cc
tree99799b029f0ad3959832609d62d7c59bb4465094
parentd81783375c2555b2e2cb6a028ea648179031bc93

zld: fixup flush function


2 files changed, 134 insertions(+), 157 deletions(-)

src/link/MachO/TextBlock.zig+26-17
......@@ -1,11 +1,14 @@
11const TextBlock = @This();
22
33const std = @import("std");
4const aarch64 = @import("../../codegen/aarch64.zig");
45const assert = std.debug.assert;
56const commands = @import("commands.zig");
67const log = std.log.scoped(.text_block);
78const macho = std.macho;
9const math = std.math;
810const mem = std.mem;
11const meta = std.meta;
912
1013const Allocator = mem.Allocator;
1114const Arch = std.Target.Cpu.Arch;
......@@ -44,25 +47,22 @@ pub const Stab = union(enum) {
4447 defer nlists.deinit();
4548
4649 const sym = zld.locals.items[local_sym_index];
47 const reg = sym.payload.regular;
48
4950 switch (stab) {
5051 .function => |size| {
5152 try nlists.ensureUnusedCapacity(4);
52 const section_id = reg.sectionId(zld);
5353 nlists.appendAssumeCapacity(.{
5454 .n_strx = 0,
5555 .n_type = macho.N_BNSYM,
56 .n_sect = section_id,
56 .n_sect = sym.n_sect,
5757 .n_desc = 0,
58 .n_value = reg.address,
58 .n_value = sym.n_value,
5959 });
6060 nlists.appendAssumeCapacity(.{
61 .n_strx = sym.strx,
61 .n_strx = sym.n_strx,
6262 .n_type = macho.N_FUN,
63 .n_sect = section_id,
63 .n_sect = sym.n_sect,
6464 .n_desc = 0,
65 .n_value = reg.address,
65 .n_value = sym.n_value,
6666 });
6767 nlists.appendAssumeCapacity(.{
6868 .n_strx = 0,
......@@ -74,14 +74,14 @@ pub const Stab = union(enum) {
7474 nlists.appendAssumeCapacity(.{
7575 .n_strx = 0,
7676 .n_type = macho.N_ENSYM,
77 .n_sect = section_id,
77 .n_sect = sym.n_sect,
7878 .n_desc = 0,
7979 .n_value = size,
8080 });
8181 },
8282 .global => {
8383 try nlists.append(.{
84 .n_strx = sym.strx,
84 .n_strx = sym.n_strx,
8585 .n_type = macho.N_GSYM,
8686 .n_sect = 0,
8787 .n_desc = 0,
......@@ -90,11 +90,11 @@ pub const Stab = union(enum) {
9090 },
9191 .static => {
9292 try nlists.append(.{
93 .n_strx = sym.strx,
93 .n_strx = sym.n_strx,
9494 .n_type = macho.N_STSYM,
95 .n_sect = reg.sectionId(zld),
95 .n_sect = sym.n_sect,
9696 .n_desc = 0,
97 .n_value = reg.address,
97 .n_value = sym.n_value,
9898 });
9999 },
100100 }
......@@ -1006,7 +1006,10 @@ pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void {
10061006 const dc_seg = zld.load_commands.items[zld.data_const_segment_cmd_index.?].Segment;
10071007 const got = dc_seg.sections.items[zld.got_section_index.?];
10081008 const got_index = zld.got_entries.getIndex(.{
1009 .where = rel.where,
1009 .where = switch (rel.where) {
1010 .local => .local,
1011 .import => .import,
1012 },
10101013 .where_index = rel.where_index,
10111014 }) orelse {
10121015 const sym = switch (rel.where) {
......@@ -1024,8 +1027,8 @@ pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void {
10241027 .local => {
10251028 const sym = zld.locals.items[rel.where_index];
10261029 const is_tlv = is_tlv: {
1027 const sym = zld.locals.items[self.local_sym_index];
1028 const match = zld.unpackSectionId(sym.n_sect);
1030 const source_sym = zld.locals.items[self.local_sym_index];
1031 const match = zld.unpackSectionId(source_sym.n_sect);
10291032 const seg = zld.load_commands.items[match.seg].Segment;
10301033 const sect = seg.sections.items[match.sect];
10311034 break :is_tlv commands.sectionType(sect) == macho.S_THREAD_LOCAL_VARIABLES;
......@@ -1073,7 +1076,13 @@ pub fn resolveRelocs(self: *TextBlock, zld: *Zld) !void {
10731076 log.warn(" | source_addr = 0x{x}", .{source_addr});
10741077 log.warn(" | target_addr = 0x{x}", .{target_addr});
10751078
1076 try rel.resolve(self, source_addr, target_addr);
1079 try rel.resolve(.{
1080 .block = self,
1081 .offset = rel.offset,
1082 .source_addr = source_addr,
1083 .target_addr = target_addr,
1084 .zld = zld,
1085 });
10771086 }
10781087}
10791088
src/link/MachO/Zld.zig+108-140
......@@ -233,6 +233,16 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
233233 try self.parseLibs(args.libs, args.syslibroot);
234234 try self.resolveSymbols();
235235 try self.parseTextBlocks();
236
237 {
238 // Add dyld_stub_binder as the final GOT entry.
239 const resolv = self.symbol_resolver.get("dyld_stub_binder") orelse unreachable;
240 try self.got_entries.putNoClobber(self.allocator, .{
241 .where = .import,
242 .where_index = resolv.where_index,
243 }, {});
244 }
245
236246 try self.sortSections();
237247 try self.addRpaths(args.rpaths);
238248 try self.addDataInCodeLC();
......@@ -296,9 +306,7 @@ pub fn link(self: *Zld, files: []const []const u8, output: Output, args: LinkArg
296306 entry.value_ptr.*.print(self);
297307 }
298308
299 return error.TODO;
300
301 // try self.flush();
309 try self.flush();
302310}
303311
304312fn parseInputFiles(self: *Zld, files: []const []const u8, syslibroot: ?[]const u8) !void {
......@@ -1097,7 +1105,7 @@ fn writeTextBlocks(self: *Zld) !void {
10971105
10981106 const sym = self.locals.items[block.local_sym_index];
10991107 log.debug(" {s}: start=0x{x}, end=0x{x}, size={}, align={}", .{
1100 self.getString(sym.strx),
1108 self.getString(sym.n_strx),
11011109 aligned_base_off,
11021110 aligned_base_off + block.size,
11031111 block.size,
......@@ -1154,8 +1162,12 @@ fn writeStubHelperCommon(self: *Zld) !void {
11541162 code[9] = 0xff;
11551163 code[10] = 0x25;
11561164 {
1157 const dyld_stub_binder = self.globals.get("dyld_stub_binder").?;
1158 const addr = (got.addr + dyld_stub_binder.got_index.? * @sizeOf(u64));
1165 const resolv = self.symbol_resolver.get("dyld_stub_binder") orelse unreachable;
1166 const got_index = self.got_entries.getIndex(.{
1167 .where = .import,
1168 .where_index = resolv.where_index,
1169 }) orelse unreachable;
1170 const addr = got.addr + got_index * @sizeOf(u64);
11591171 const displacement = try math.cast(u32, addr - stub_helper.addr - code_size);
11601172 mem.writeIntLittle(u32, code[11..], displacement);
11611173 }
......@@ -1198,9 +1210,13 @@ fn writeStubHelperCommon(self: *Zld) !void {
11981210 code[10] = 0xbf;
11991211 code[11] = 0xa9;
12001212 binder_blk_outer: {
1201 const dyld_stub_binder = self.globals.get("dyld_stub_binder").?;
1213 const resolv = self.symbol_resolver.get("dyld_stub_binder") orelse unreachable;
1214 const got_index = self.got_entries.getIndex(.{
1215 .where = .import,
1216 .where_index = resolv.where_index,
1217 }) orelse unreachable;
12021218 const this_addr = stub_helper.addr + 3 * @sizeOf(u32);
1203 const target_addr = (got.addr + dyld_stub_binder.got_index.? * @sizeOf(u64));
1219 const target_addr = got.addr + got_index * @sizeOf(u64);
12041220 binder_blk: {
12051221 const displacement = math.divExact(u64, target_addr - this_addr, 4) catch break :binder_blk;
12061222 const literal = math.cast(u18, displacement) catch break :binder_blk;
......@@ -1251,12 +1267,11 @@ fn writeStubHelperCommon(self: *Zld) !void {
12511267 }
12521268 };
12531269
1254 for (self.stubs.items) |sym| {
1270 for (self.stubs.keys()) |key| {
12551271 // TODO weak bound pointers
1256 const index = sym.stubs_index orelse unreachable;
1257 try self.writeLazySymbolPointer(index);
1258 try self.writeStub(index);
1259 try self.writeStubInStubHelper(index);
1272 try self.writeLazySymbolPointer(key);
1273 try self.writeStub(key);
1274 try self.writeStubInStubHelper(key);
12601275 }
12611276}
12621277
......@@ -1764,7 +1779,7 @@ fn resolveSymbols(self: *Zld) !void {
17641779 .n_strx = undef.n_strx,
17651780 .n_type = macho.N_UNDF | macho.N_EXT,
17661781 .n_sect = 0,
1767 .n_desc = (dylib.ordinal.? * macho.N_SYMBOL_RESOLVER) | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY,
1782 .n_desc = packDylibOrdinal(dylib.ordinal.?),
17681783 .n_value = 0,
17691784 });
17701785 resolv.* = .{
......@@ -2218,16 +2233,16 @@ fn writeGotEntries(self: *Zld) !void {
22182233 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
22192234 const sect = seg.sections.items[self.got_section_index.?];
22202235
2221 var buffer = try self.allocator.alloc(u8, self.got_entries.items.len * @sizeOf(u64));
2236 var buffer = try self.allocator.alloc(u8, self.got_entries.count() * @sizeOf(u64));
22222237 defer self.allocator.free(buffer);
22232238
22242239 var stream = std.io.fixedBufferStream(buffer);
22252240 var writer = stream.writer();
22262241
2227 for (self.got_entries.items) |sym| {
2228 const address: u64 = switch (sym.payload) {
2229 .regular => |reg| reg.address,
2230 else => 0,
2242 for (self.got_entries.keys()) |key| {
2243 const address: u64 = switch (key.where) {
2244 .local => self.locals.items[key.where_index].n_value,
2245 .import => 0,
22312246 };
22322247 try writer.writeIntLittle(u64, address);
22332248 }
......@@ -2243,9 +2258,14 @@ fn setEntryPoint(self: *Zld) !void {
22432258 // TODO we should respect the -entry flag passed in by the user to set a custom
22442259 // entrypoint. For now, assume default of `_main`.
22452260 const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2246 const sym = self.globals.get("_main") orelse return error.MissingMainEntrypoint;
2261 const resolv = self.symbol_resolver.get("_main") orelse {
2262 log.err("'_main' export not found", .{});
2263 return error.MissingMainEntrypoint;
2264 };
2265 assert(resolv.where == .global);
2266 const sym = self.globals.items[resolv.where_index];
22472267 const ec = &self.load_commands.items[self.main_cmd_index.?].Main;
2248 ec.entryoff = @intCast(u32, sym.payload.regular.address - seg.inner.vmaddr);
2268 ec.entryoff = @intCast(u32, sym.n_value - seg.inner.vmaddr);
22492269 ec.stacksize = self.stack_size;
22502270}
22512271
......@@ -2265,8 +2285,7 @@ fn writeRebaseInfoTable(self: *Zld) !void {
22652285
22662286 while (true) {
22672287 const sym = self.locals.items[block.local_sym_index];
2268 assert(sym.payload == .regular);
2269 const base_offset = sym.payload.regular.address - seg.inner.vmaddr;
2288 const base_offset = sym.n_value - seg.inner.vmaddr;
22702289
22712290 for (block.rebases.items) |offset| {
22722291 try pointers.append(.{
......@@ -2288,11 +2307,11 @@ fn writeRebaseInfoTable(self: *Zld) !void {
22882307 const base_offset = sect.addr - seg.inner.vmaddr;
22892308 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
22902309
2291 for (self.got_entries.items) |sym| {
2292 if (sym.payload == .proxy) continue;
2310 for (self.got_entries.keys()) |key, i| {
2311 if (key.where == .import) continue;
22932312
22942313 try pointers.append(.{
2295 .offset = base_offset + sym.got_index.? * @sizeOf(u64),
2314 .offset = base_offset + i * @sizeOf(u64),
22962315 .segment_id = segment_id,
22972316 });
22982317 }
......@@ -2304,10 +2323,10 @@ fn writeRebaseInfoTable(self: *Zld) !void {
23042323 const base_offset = sect.addr - seg.inner.vmaddr;
23052324 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);
23062325
2307 try pointers.ensureCapacity(pointers.items.len + self.stubs.items.len);
2308 for (self.stubs.items) |sym| {
2326 try pointers.ensureCapacity(pointers.items.len + self.stubs.count());
2327 for (self.stubs.keys()) |_, i| {
23092328 pointers.appendAssumeCapacity(.{
2310 .offset = base_offset + sym.stubs_index.? * @sizeOf(u64),
2329 .offset = base_offset + i * @sizeOf(u64),
23112330 .segment_id = segment_id,
23122331 });
23132332 }
......@@ -2343,15 +2362,15 @@ fn writeBindInfoTable(self: *Zld) !void {
23432362 const base_offset = sect.addr - seg.inner.vmaddr;
23442363 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
23452364
2346 for (self.got_entries.items) |sym| {
2347 if (sym.payload != .proxy) continue;
2365 for (self.got_entries.keys()) |key, i| {
2366 if (key.where == .local) continue;
23482367
2349 const proxy = sym.payload.proxy;
2368 const sym = self.imports.items[key.where_index];
23502369 try pointers.append(.{
2351 .offset = base_offset + sym.got_index.? * @sizeOf(u64),
2370 .offset = base_offset + i * @sizeOf(u64),
23522371 .segment_id = segment_id,
2353 .dylib_ordinal = proxy.dylibOrdinal(),
2354 .name = self.getString(sym.strx),
2372 .dylib_ordinal = unpackDylibOrdinal(sym.n_desc),
2373 .name = self.getString(sym.n_strx),
23552374 });
23562375 }
23572376 }
......@@ -2368,18 +2387,15 @@ fn writeBindInfoTable(self: *Zld) !void {
23682387
23692388 while (true) {
23702389 const sym = self.locals.items[block.local_sym_index];
2371 assert(sym.payload == .regular);
2372 const base_offset = sym.payload.regular.address - seg.inner.vmaddr;
2390 const base_offset = sym.n_value - seg.inner.vmaddr;
23732391
23742392 for (block.bindings.items) |binding| {
23752393 const bind_sym = self.imports.items[binding.local_sym_index];
2376 const proxy = bind_sym.payload.proxy;
2377
23782394 try pointers.append(.{
23792395 .offset = binding.offset + base_offset,
23802396 .segment_id = match.seg,
2381 .dylib_ordinal = proxy.dylibOrdinal(),
2382 .name = self.getString(bind_sym.strx),
2397 .dylib_ordinal = unpackDylibOrdinal(bind_sym.n_desc),
2398 .name = self.getString(bind_sym.n_strx),
23832399 });
23842400 }
23852401
......@@ -2390,21 +2406,21 @@ fn writeBindInfoTable(self: *Zld) !void {
23902406 }
23912407 }
23922408
2393 if (self.tlv_section_index) |idx| {
2394 const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2395 const sect = seg.sections.items[idx];
2396 const base_offset = sect.addr - seg.inner.vmaddr;
2397 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);
2409 // if (self.tlv_section_index) |idx| {
2410 // const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2411 // const sect = seg.sections.items[idx];
2412 // const base_offset = sect.addr - seg.inner.vmaddr;
2413 // const segment_id = @intCast(u16, self.data_segment_cmd_index.?);
23982414
2399 const sym = self.globals.get("__tlv_bootstrap") orelse unreachable;
2400 const proxy = sym.payload.proxy;
2401 try pointers.append(.{
2402 .offset = base_offset,
2403 .segment_id = segment_id,
2404 .dylib_ordinal = proxy.dylibOrdinal(),
2405 .name = self.getString(sym.strx),
2406 });
2407 }
2415 // const sym = self.globals.get("__tlv_bootstrap") orelse unreachable;
2416 // const proxy = sym.payload.proxy;
2417 // try pointers.append(.{
2418 // .offset = base_offset,
2419 // .segment_id = segment_id,
2420 // .dylib_ordinal = proxy.dylibOrdinal(),
2421 // .name = self.getString(sym.strx),
2422 // });
2423 // }
24082424
24092425 const size = try bindInfoSize(pointers.items);
24102426 var buffer = try self.allocator.alloc(u8, @intCast(usize, size));
......@@ -2434,15 +2450,15 @@ fn writeLazyBindInfoTable(self: *Zld) !void {
24342450 const base_offset = sect.addr - seg.inner.vmaddr;
24352451 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);
24362452
2437 try pointers.ensureCapacity(self.stubs.items.len);
2453 try pointers.ensureCapacity(self.stubs.count());
24382454
2439 for (self.stubs.items) |sym| {
2440 const proxy = sym.payload.proxy;
2455 for (self.stubs.keys()) |key, i| {
2456 const sym = self.imports.items[key];
24412457 pointers.appendAssumeCapacity(.{
2442 .offset = base_offset + sym.stubs_index.? * @sizeOf(u64),
2458 .offset = base_offset + i * @sizeOf(u64),
24432459 .segment_id = segment_id,
2444 .dylib_ordinal = proxy.dylibOrdinal(),
2445 .name = self.getString(sym.strx),
2460 .dylib_ordinal = unpackDylibOrdinal(sym.n_desc),
2461 .name = self.getString(sym.n_strx),
24462462 });
24472463 }
24482464 }
......@@ -2510,7 +2526,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void {
25102526 else => {},
25112527 }
25122528 }
2513 assert(self.stubs.items.len <= offsets.items.len);
2529 assert(self.stubs.count() <= offsets.items.len);
25142530
25152531 const stub_size: u4 = switch (self.target.?.cpu.arch) {
25162532 .x86_64 => 10,
......@@ -2523,8 +2539,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void {
25232539 else => unreachable,
25242540 };
25252541 var buf: [@sizeOf(u32)]u8 = undefined;
2526 for (self.stubs.items) |sym| {
2527 const index = sym.stubs_index orelse unreachable;
2542 for (self.stubs.keys()) |_, index| {
25282543 const placeholder_off = self.stub_helper_stubs_start_off.? + index * stub_size + off;
25292544 mem.writeIntLittle(u32, &buf, offsets.items[index]);
25302545 try self.file.?.pwriteAll(&buf, placeholder_off);
......@@ -2541,33 +2556,13 @@ fn writeExportInfo(self: *Zld) !void {
25412556 // TODO handle macho.EXPORT_SYMBOL_FLAGS_REEXPORT and macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER.
25422557 log.debug("writing export trie", .{});
25432558
2544 const Sorter = struct {
2545 fn lessThan(_: void, a: []const u8, b: []const u8) bool {
2546 return mem.lessThan(u8, a, b);
2547 }
2548 };
2549
2550 var sorted_globals = std.ArrayList([]const u8).init(self.allocator);
2551 defer sorted_globals.deinit();
2552
2553 for (self.globals.values()) |sym| {
2554 if (sym.payload != .regular) continue;
2555 const reg = sym.payload.regular;
2556 if (reg.linkage != .global) continue;
2557 try sorted_globals.append(self.getString(sym.strx));
2558 }
2559
2560 std.sort.sort([]const u8, sorted_globals.items, {}, Sorter.lessThan);
2561
2562 for (sorted_globals.items) |sym_name| {
2563 const sym = self.globals.get(sym_name) orelse unreachable;
2564 const reg = sym.payload.regular;
2565
2566 log.debug(" | putting '{s}' defined at 0x{x}", .{ sym_name, reg.address });
2559 for (self.globals.items) |sym| {
2560 const sym_name = self.getString(sym.n_strx);
2561 log.debug(" | putting '{s}' defined at 0x{x}", .{ sym_name, sym.n_value });
25672562
25682563 try trie.put(.{
25692564 .name = sym_name,
2570 .vmaddr_offset = reg.address - base_address,
2565 .vmaddr_offset = sym.n_value - base_address,
25712566 .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR,
25722567 });
25732568 }
......@@ -2598,23 +2593,7 @@ fn writeSymbolTable(self: *Zld) !void {
25982593
25992594 var locals = std.ArrayList(macho.nlist_64).init(self.allocator);
26002595 defer locals.deinit();
2601
2602 var exports = std.ArrayList(macho.nlist_64).init(self.allocator);
2603 defer exports.deinit();
2604
2605 for (self.locals.items) |symbol, i| {
2606 if (i == 0) continue; // skip null symbol
2607 if (symbol.isTemp(self)) continue; // TODO when merging codepaths, this should go into freelist
2608
2609 const reg = symbol.payload.regular;
2610 const nlist = try symbol.asNlist(self);
2611
2612 if (reg.linkage == .translation_unit) {
2613 try locals.append(nlist);
2614 } else {
2615 try exports.append(nlist);
2616 }
2617 }
2596 try locals.appendSlice(self.locals.items);
26182597
26192598 if (self.has_stabs) {
26202599 for (self.objects.items) |object| {
......@@ -2671,21 +2650,9 @@ fn writeSymbolTable(self: *Zld) !void {
26712650 }
26722651 }
26732652
2674 var undefs = std.ArrayList(macho.nlist_64).init(self.allocator);
2675 defer undefs.deinit();
2676 var undef_dir = std.StringHashMap(u32).init(self.allocator);
2677 defer undef_dir.deinit();
2678
2679 for (self.imports.items) |sym| {
2680 const nlist = try sym.asNlist(self);
2681 const id = @intCast(u32, undefs.items.len);
2682 try undefs.append(nlist);
2683 try undef_dir.putNoClobber(self.getString(sym.strx), id);
2684 }
2685
26862653 const nlocals = locals.items.len;
2687 const nexports = exports.items.len;
2688 const nundefs = undefs.items.len;
2654 const nexports = self.globals.items.len;
2655 const nundefs = self.imports.items.len;
26892656
26902657 const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);
26912658 const locals_size = nlocals * @sizeOf(macho.nlist_64);
......@@ -2695,12 +2662,12 @@ fn writeSymbolTable(self: *Zld) !void {
26952662 const exports_off = locals_off + locals_size;
26962663 const exports_size = nexports * @sizeOf(macho.nlist_64);
26972664 log.debug("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off });
2698 try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off);
2665 try self.file.?.pwriteAll(mem.sliceAsBytes(self.globals.items), exports_off);
26992666
27002667 const undefs_off = exports_off + exports_size;
27012668 const undefs_size = nundefs * @sizeOf(macho.nlist_64);
27022669 log.debug("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off });
2703 try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off);
2670 try self.file.?.pwriteAll(mem.sliceAsBytes(self.imports.items), undefs_off);
27042671
27052672 symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs);
27062673 seg.inner.filesize += locals_size + exports_size + undefs_size;
......@@ -2720,8 +2687,8 @@ fn writeSymbolTable(self: *Zld) !void {
27202687 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
27212688 const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?];
27222689
2723 const nstubs = @intCast(u32, self.stubs.items.len);
2724 const ngot_entries = @intCast(u32, self.got_entries.items.len);
2690 const nstubs = @intCast(u32, self.stubs.count());
2691 const ngot_entries = @intCast(u32, self.got_entries.count());
27252692
27262693 dysymtab.indirectsymoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);
27272694 dysymtab.nindirectsyms = nstubs * 2 + ngot_entries;
......@@ -2741,31 +2708,25 @@ fn writeSymbolTable(self: *Zld) !void {
27412708 var writer = stream.writer();
27422709
27432710 stubs.reserved1 = 0;
2744 for (self.stubs.items) |sym| {
2745 const sym_name = self.getString(sym.strx);
2746 const id = undef_dir.get(sym_name) orelse unreachable;
2747 try writer.writeIntLittle(u32, dysymtab.iundefsym + id);
2711 for (self.stubs.keys()) |key| {
2712 try writer.writeIntLittle(u32, dysymtab.iundefsym + key);
27482713 }
27492714
27502715 got.reserved1 = nstubs;
2751 for (self.got_entries.items) |sym| {
2752 switch (sym.payload) {
2753 .proxy => {
2754 const sym_name = self.getString(sym.strx);
2755 const id = undef_dir.get(sym_name) orelse unreachable;
2756 try writer.writeIntLittle(u32, dysymtab.iundefsym + id);
2716 for (self.got_entries.keys()) |key| {
2717 switch (key.where) {
2718 .import => {
2719 try writer.writeIntLittle(u32, dysymtab.iundefsym + key.where_index);
27572720 },
2758 else => {
2721 .local => {
27592722 try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL);
27602723 },
27612724 }
27622725 }
27632726
27642727 la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries;
2765 for (self.stubs.items) |sym| {
2766 const sym_name = self.getString(sym.strx);
2767 const id = undef_dir.get(sym_name) orelse unreachable;
2768 try writer.writeIntLittle(u32, dysymtab.iundefsym + id);
2728 for (self.stubs.keys()) |key| {
2729 try writer.writeIntLittle(u32, dysymtab.iundefsym + key);
27692730 }
27702731
27712732 try self.file.?.pwriteAll(buf, dysymtab.indirectsymoff);
......@@ -2813,8 +2774,7 @@ fn writeDices(self: *Zld) !void {
28132774 while (true) {
28142775 if (block.dices.items.len > 0) {
28152776 const sym = self.locals.items[block.local_sym_index];
2816 const reg = sym.payload.regular;
2817 const base_off = try math.cast(u32, reg.address - text_sect.addr + text_sect.offset);
2777 const base_off = try math.cast(u32, sym.n_value - text_sect.addr + text_sect.offset);
28182778
28192779 try buf.ensureUnusedCapacity(block.dices.items.len * @sizeOf(macho.data_in_code_entry));
28202780 for (block.dices.items) |dice| {
......@@ -3052,6 +3012,14 @@ pub fn unpackSectionId(self: Zld, section_id: u8) MatchingSection {
30523012 return match;
30533013}
30543014
3015fn packDylibOrdinal(ordinal: u16) u16 {
3016 return ordinal * macho.N_SYMBOL_RESOLVER;
3017}
3018
3019fn unpackDylibOrdinal(pack: u16) u16 {
3020 return @divExact(pack, macho.N_SYMBOL_RESOLVER);
3021}
3022
30553023pub fn findFirst(comptime T: type, haystack: []T, start: usize, predicate: anytype) usize {
30563024 if (!@hasDecl(@TypeOf(predicate), "predicate"))
30573025 @compileError("Predicate is required to define fn predicate(@This(), T) bool");