authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-05-03 16:00:50+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-05-04 13:09:32+02:00
log9e11f27c4134b885786f703f0c340392644a39db
tree7cf87d0d9a99e33539021a4a038b7504ca6867c2
parent00c3d57a51d963e078e8f4dfc090bd2a0d0d6a30

zld: build updated macho backend


2 files changed, 177 insertions(+), 235 deletions(-)

src/link/MachO/Symbol.zig+7
...@@ -66,6 +66,13 @@ pub const Regular = struct {...@@ -66,6 +66,13 @@ pub const Regular = struct {
66 linkage_unit,66 linkage_unit,
67 global,67 global,
68 };68 };
69
70 pub fn isTemp(regular: *Regular) bool {
71 if (regular.linkage == .translation_unit) {
72 return mem.startsWith(u8, regular.base.name, "l") or mem.startsWith(u8, regular.base.name, "L");
73 }
74 return false;
75 }
69};76};
7077
71pub const Proxy = struct {78pub const Proxy = struct {
src/link/MachO/Zld.zig+170-235
...@@ -209,10 +209,9 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void {...@@ -209,10 +209,9 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void {
209 try self.allocateDataSegment();209 try self.allocateDataSegment();
210 self.allocateLinkeditSegment();210 self.allocateLinkeditSegment();
211 try self.allocateSymbols();211 try self.allocateSymbols();
212 return error.Unfinished;212 try self.writeStubHelperCommon();
213 // try self.writeStubHelperCommon();213 try self.resolveRelocsAndWriteSections();
214 // try self.resolveRelocsAndWriteSections();214 try self.flush();
215 // try self.flush();
216}215}
217216
218fn parseInputFiles(self: *Zld, files: []const []const u8) !void {217fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
...@@ -268,7 +267,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {...@@ -268,7 +267,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
268 continue;267 continue;
269 }268 }
270269
271 log.debug("unexpected input file of unknown type '{s}'", .{file_name});270 log.warn("unexpected input file of unknown type '{s}'", .{file_name});
272 }271 }
273272
274 // Based on our classification, proceed with parsing.273 // Based on our classification, proceed with parsing.
...@@ -326,7 +325,7 @@ fn mapAndUpdateSections(...@@ -326,7 +325,7 @@ fn mapAndUpdateSections(
326 .target_sect_id = target_sect_id,325 .target_sect_id = target_sect_id,
327 .offset = @intCast(u32, offset),326 .offset = @intCast(u32, offset),
328 });327 });
329 log.debug("{s}: {s},{s} mapped to {s},{s} from 0x{x} to 0x{x}", .{328 log.warn("{s}: {s},{s} mapped to {s},{s} from 0x{x} to 0x{x}", .{
330 object.name,329 object.name,
331 parseName(&source_sect.segname),330 parseName(&source_sect.segname),
332 parseName(&source_sect.sectname),331 parseName(&source_sect.sectname),
...@@ -556,7 +555,7 @@ fn updateMetadata(self: *Zld) !void {...@@ -556,7 +555,7 @@ fn updateMetadata(self: *Zld) !void {
556 });555 });
557 },556 },
558 else => {557 else => {
559 log.debug("unhandled section type 0x{x} for '{s}/{s}'", .{ flags, segname, sectname });558 log.warn("unhandled section type 0x{x} for '{s}/{s}'", .{ flags, segname, sectname });
560 },559 },
561 }560 }
562 }561 }
...@@ -581,7 +580,7 @@ fn updateMetadata(self: *Zld) !void {...@@ -581,7 +580,7 @@ fn updateMetadata(self: *Zld) !void {
581 const segname = parseName(&source_sect.segname);580 const segname = parseName(&source_sect.segname);
582 const sectname = parseName(&source_sect.sectname);581 const sectname = parseName(&source_sect.sectname);
583582
584 log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname });583 log.warn("section '{s}/{s}' will be unmapped", .{ segname, sectname });
585584
586 try self.unhandled_sections.putNoClobber(self.allocator, .{585 try self.unhandled_sections.putNoClobber(self.allocator, .{
587 .object_id = object_id,586 .object_id = object_id,
...@@ -978,8 +977,8 @@ fn writeStubHelperCommon(self: *Zld) !void {...@@ -978,8 +977,8 @@ fn writeStubHelperCommon(self: *Zld) !void {
978 code[9] = 0xff;977 code[9] = 0xff;
979 code[10] = 0x25;978 code[10] = 0x25;
980 {979 {
981 const dyld_stub_binder = self.got_entries.get("dyld_stub_binder").?;980 const dyld_stub_binder = self.imports.get("dyld_stub_binder").?;
982 const addr = (got.addr + dyld_stub_binder.index * @sizeOf(u64));981 const addr = (got.addr + dyld_stub_binder.got_index.? * @sizeOf(u64));
983 const displacement = try math.cast(u32, addr - stub_helper.addr - code_size);982 const displacement = try math.cast(u32, addr - stub_helper.addr - code_size);
984 mem.writeIntLittle(u32, code[11..], displacement);983 mem.writeIntLittle(u32, code[11..], displacement);
985 }984 }
...@@ -1022,9 +1021,9 @@ fn writeStubHelperCommon(self: *Zld) !void {...@@ -1022,9 +1021,9 @@ fn writeStubHelperCommon(self: *Zld) !void {
1022 code[10] = 0xbf;1021 code[10] = 0xbf;
1023 code[11] = 0xa9;1022 code[11] = 0xa9;
1024 binder_blk_outer: {1023 binder_blk_outer: {
1025 const dyld_stub_binder = self.got_entries.get("dyld_stub_binder").?;1024 const dyld_stub_binder = self.imports.get("dyld_stub_binder").?;
1026 const this_addr = stub_helper.addr + 3 * @sizeOf(u32);1025 const this_addr = stub_helper.addr + 3 * @sizeOf(u32);
1027 const target_addr = (got.addr + dyld_stub_binder.index * @sizeOf(u64));1026 const target_addr = (got.addr + dyld_stub_binder.got_index.? * @sizeOf(u64));
1028 binder_blk: {1027 binder_blk: {
1029 const displacement = math.divExact(u64, target_addr - this_addr, 4) catch |_| break :binder_blk;1028 const displacement = math.divExact(u64, target_addr - this_addr, 4) catch |_| break :binder_blk;
1030 const literal = math.cast(u18, displacement) catch |_| break :binder_blk;1029 const literal = math.cast(u18, displacement) catch |_| break :binder_blk;
...@@ -1075,8 +1074,9 @@ fn writeStubHelperCommon(self: *Zld) !void {...@@ -1075,8 +1074,9 @@ fn writeStubHelperCommon(self: *Zld) !void {
1075 }1074 }
1076 };1075 };
10771076
1078 for (self.stubs.items()) |entry| {1077 for (self.stubs.items) |sym| {
1079 const index = entry.value;1078 // TODO weak bound pointers
1079 const index = sym.stubs_index orelse unreachable;
1080 try self.writeLazySymbolPointer(index);1080 try self.writeLazySymbolPointer(index);
1081 try self.writeStub(index);1081 try self.writeStub(index);
1082 try self.writeStubInStubHelper(index);1082 try self.writeStubInStubHelper(index);
...@@ -1099,7 +1099,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void {...@@ -1099,7 +1099,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void {
1099 var buf: [@sizeOf(u64)]u8 = undefined;1099 var buf: [@sizeOf(u64)]u8 = undefined;
1100 mem.writeIntLittle(u64, &buf, end);1100 mem.writeIntLittle(u64, &buf, end);
1101 const off = la_symbol_ptr.offset + index * @sizeOf(u64);1101 const off = la_symbol_ptr.offset + index * @sizeOf(u64);
1102 log.debug("writing lazy symbol pointer entry 0x{x} at 0x{x}", .{ end, off });1102 log.warn("writing lazy symbol pointer entry 0x{x} at 0x{x}", .{ end, off });
1103 try self.file.?.pwriteAll(&buf, off);1103 try self.file.?.pwriteAll(&buf, off);
1104}1104}
11051105
...@@ -1112,7 +1112,7 @@ fn writeStub(self: *Zld, index: u32) !void {...@@ -1112,7 +1112,7 @@ fn writeStub(self: *Zld, index: u32) !void {
1112 const stub_off = stubs.offset + index * stubs.reserved2;1112 const stub_off = stubs.offset + index * stubs.reserved2;
1113 const stub_addr = stubs.addr + index * stubs.reserved2;1113 const stub_addr = stubs.addr + index * stubs.reserved2;
1114 const la_ptr_addr = la_symbol_ptr.addr + index * @sizeOf(u64);1114 const la_ptr_addr = la_symbol_ptr.addr + index * @sizeOf(u64);
1115 log.debug("writing stub at 0x{x}", .{stub_off});1115 log.warn("writing stub at 0x{x}", .{stub_off});
1116 var code = try self.allocator.alloc(u8, stubs.reserved2);1116 var code = try self.allocator.alloc(u8, stubs.reserved2);
1117 defer self.allocator.free(code);1117 defer self.allocator.free(code);
1118 switch (self.arch.?) {1118 switch (self.arch.?) {
...@@ -1413,7 +1413,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1413,7 +1413,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
14131413
1414fn resolveRelocsAndWriteSections(self: *Zld) !void {1414fn resolveRelocsAndWriteSections(self: *Zld) !void {
1415 for (self.objects.items) |object, object_id| {1415 for (self.objects.items) |object, object_id| {
1416 log.debug("relocating object {s}", .{object.name});1416 log.warn("relocating object {s}", .{object.name});
14171417
1418 for (object.sections.items) |sect, source_sect_id| {1418 for (object.sections.items) |sect, source_sect_id| {
1419 if (sect.inner.flags == macho.S_MOD_INIT_FUNC_POINTERS or1419 if (sect.inner.flags == macho.S_MOD_INIT_FUNC_POINTERS or
...@@ -1422,14 +1422,14 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1422,14 +1422,14 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1422 const segname = parseName(&sect.inner.segname);1422 const segname = parseName(&sect.inner.segname);
1423 const sectname = parseName(&sect.inner.sectname);1423 const sectname = parseName(&sect.inner.sectname);
14241424
1425 log.debug("relocating section '{s},{s}'", .{ segname, sectname });1425 log.warn("relocating section '{s},{s}'", .{ segname, sectname });
14261426
1427 // Get mapping1427 // Get mapping
1428 const target_mapping = self.mappings.get(.{1428 const target_mapping = self.mappings.get(.{
1429 .object_id = @intCast(u16, object_id),1429 .object_id = @intCast(u16, object_id),
1430 .source_sect_id = @intCast(u16, source_sect_id),1430 .source_sect_id = @intCast(u16, source_sect_id),
1431 }) orelse {1431 }) orelse {
1432 log.debug("no mapping for {s},{s}; skipping", .{ segname, sectname });1432 log.warn("no mapping for {s},{s}; skipping", .{ segname, sectname });
1433 continue;1433 continue;
1434 };1434 };
1435 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;1435 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
...@@ -1482,11 +1482,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1482,11 +1482,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1482 // TLV is handled via a separate offset mechanism.1482 // TLV is handled via a separate offset mechanism.
1483 // Calculate the offset to the initializer.1483 // Calculate the offset to the initializer.
1484 if (target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: {1484 if (target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: {
1485 const sym = object.symtab.items[rel.target.symbol];
1486 const sym_name = object.getString(sym.n_strx);
1487
1488 // TODO we don't want to save offset to tlv_bootstrap1485 // TODO we don't want to save offset to tlv_bootstrap
1489 if (mem.eql(u8, sym_name, "__tlv_bootstrap")) break :tlv;1486 if (mem.eql(u8, rel.target.symbol.name, "__tlv_bootstrap")) break :tlv;
14901487
1491 const base_addr = blk: {1488 const base_addr = blk: {
1492 if (self.tlv_data_section_index) |index| {1489 if (self.tlv_data_section_index) |index| {
...@@ -1505,10 +1502,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1505,10 +1502,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1505 .got_page, .got_page_off, .got_load, .got => {1502 .got_page, .got_page_off, .got_load, .got => {
1506 const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;1503 const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
1507 const got = dc_seg.sections.items[self.got_section_index.?];1504 const got = dc_seg.sections.items[self.got_section_index.?];
1508 const sym = object.symtab.items[rel.target.symbol];1505 const final = rel.target.symbol.getTopmostAlias();
1509 const sym_name = object.getString(sym.n_strx);1506 args.target_addr = got.addr + final.got_index.? * @sizeOf(u64);
1510 const entry = self.got_entries.get(sym_name) orelse unreachable;
1511 args.target_addr = got.addr + entry.index * @sizeOf(u64);
1512 },1507 },
1513 else => |tt| {1508 else => |tt| {
1514 if (tt == .signed and rel.target == .section) {1509 if (tt == .signed and rel.target == .section) {
...@@ -1523,7 +1518,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1523,7 +1518,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1523 }1518 }
1524 }1519 }
15251520
1526 log.debug("writing contents of '{s},{s}' section from '{s}' from 0x{x} to 0x{x}", .{1521 log.warn("writing contents of '{s},{s}' section from '{s}' from 0x{x} to 0x{x}", .{
1527 segname,1522 segname,
1528 sectname,1523 sectname,
1529 object.name,1524 object.name,
...@@ -1535,7 +1530,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1535,7 +1530,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1535 target_sect.flags == macho.S_THREAD_LOCAL_ZEROFILL or1530 target_sect.flags == macho.S_THREAD_LOCAL_ZEROFILL or
1536 target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES)1531 target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES)
1537 {1532 {
1538 log.debug("zeroing out '{s},{s}' from 0x{x} to 0x{x}", .{1533 log.warn("zeroing out '{s},{s}' from 0x{x} to 0x{x}", .{
1539 parseName(&target_sect.segname),1534 parseName(&target_sect.segname),
1540 parseName(&target_sect.sectname),1535 parseName(&target_sect.sectname),
1541 target_sect_off,1536 target_sect_off,
...@@ -1555,58 +1550,27 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1555,58 +1550,27 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1555}1550}
15561551
1557fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target) !u64 {1552fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target) !u64 {
1558 const object = self.objects.items[object_id];
1559 const target_addr = blk: {1553 const target_addr = blk: {
1560 switch (target) {1554 switch (target) {
1561 .symbol => |sym_id| {1555 .symbol => |sym| {
1562 const sym = object.symtab.items[sym_id];1556 const final = sym.getTopmostAlias();
1563 const sym_name = object.getString(sym.n_strx);1557 if (final.cast(Symbol.Regular)) |reg| {
15641558 log.warn(" | regular '{s}'", .{sym.name});
1565 if (Symbol.isSect(sym)) {1559 break :blk reg.address;
1566 log.debug(" | local symbol '{s}'", .{sym_name});1560 } else if (final.cast(Symbol.Proxy)) |proxy| {
1567 if (object.locals.get(sym_name)) |local| {1561 if (mem.eql(u8, sym.name, "__tlv_bootstrap")) {
1568 break :blk local.address;1562 log.warn(" | symbol '__tlv_bootstrap'", .{});
1569 }1563 const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1570 // For temp locals, i.e., symbols prefixed with l... we relocate1564 const tlv = segment.sections.items[self.tlv_section_index.?];
1571 // based on section addressing.1565 break :blk tlv.addr;
1572 const source_sect_id = sym.n_sect - 1;
1573 const target_mapping = self.mappings.get(.{
1574 .object_id = object_id,
1575 .source_sect_id = source_sect_id,
1576 }) orelse unreachable;
1577
1578 const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
1579 const source_sect = source_seg.sections.items[source_sect_id];
1580 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
1581 const target_sect = target_seg.sections.items[target_mapping.target_sect_id];
1582 const target_addr = target_sect.addr + target_mapping.offset;
1583 break :blk sym.n_value - source_sect.addr + target_addr;
1584 } else if (self.symtab.get(sym_name)) |global| {
1585 switch (global.tag) {
1586 .weak, .strong => {
1587 log.debug(" | global symbol '{s}'", .{sym_name});
1588 break :blk global.address;
1589 },
1590 .import => {
1591 if (self.stubs.get(sym_name)) |index| {
1592 log.debug(" | symbol stub '{s}'", .{sym_name});
1593 const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1594 const stubs = segment.sections.items[self.stubs_section_index.?];
1595 break :blk stubs.addr + index * stubs.reserved2;
1596 } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) {
1597 log.debug(" | symbol '__tlv_bootstrap'", .{});
1598 const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1599 const tlv = segment.sections.items[self.tlv_section_index.?];
1600 break :blk tlv.addr;
1601 } else {
1602 log.err("failed to resolve symbol '{s}' as a relocation target", .{sym_name});
1603 return error.FailedToResolveRelocationTarget;
1604 }
1605 },
1606 else => unreachable,
1607 }1566 }
1567
1568 log.warn(" | symbol stub '{s}'", .{sym.name});
1569 const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1570 const stubs = segment.sections.items[self.stubs_section_index.?];
1571 break :blk stubs.addr + proxy.base.stubs_index.? * stubs.reserved2;
1608 } else {1572 } else {
1609 log.err("failed to resolve symbol '{s}' as a relocation target", .{sym_name});1573 log.err("failed to resolve symbol '{s}' as a relocation target", .{sym.name});
1610 return error.FailedToResolveRelocationTarget;1574 return error.FailedToResolveRelocationTarget;
1611 }1575 }
1612 },1576 },
...@@ -2071,10 +2035,10 @@ fn flush(self: *Zld) !void {...@@ -2071,10 +2035,10 @@ fn flush(self: *Zld) !void {
2071 var initializers = std.ArrayList(u64).init(self.allocator);2035 var initializers = std.ArrayList(u64).init(self.allocator);
2072 defer initializers.deinit();2036 defer initializers.deinit();
20732037
2074 // TODO sort the initializers globally
2075 for (self.objects.items) |object| {2038 for (self.objects.items) |object| {
2076 for (object.initializers.items) |initializer| {2039 for (object.initializers.items) |initializer| {
2077 try initializers.append(initializer.target_addr);2040 const address = initializer.cast(Symbol.Regular).?.address;
2041 try initializers.append(address);
2078 }2042 }
2079 }2043 }
20802044
...@@ -2128,17 +2092,18 @@ fn writeGotEntries(self: *Zld) !void {...@@ -2128,17 +2092,18 @@ fn writeGotEntries(self: *Zld) !void {
2128 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;2092 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
2129 const sect = seg.sections.items[self.got_section_index.?];2093 const sect = seg.sections.items[self.got_section_index.?];
21302094
2131 var buffer = try self.allocator.alloc(u8, self.got_entries.items().len * @sizeOf(u64));2095 var buffer = try self.allocator.alloc(u8, self.got_entries.items.len * @sizeOf(u64));
2132 defer self.allocator.free(buffer);2096 defer self.allocator.free(buffer);
21332097
2134 var stream = std.io.fixedBufferStream(buffer);2098 var stream = std.io.fixedBufferStream(buffer);
2135 var writer = stream.writer();2099 var writer = stream.writer();
21362100
2137 for (self.got_entries.items()) |entry| {2101 for (self.got_entries.items) |sym| {
2138 try writer.writeIntLittle(u64, entry.value.target_addr);2102 const address: u64 = if (sym.cast(Symbol.Regular)) |reg| reg.address else 0;
2103 try writer.writeIntLittle(u64, address);
2139 }2104 }
21402105
2141 log.debug("writing GOT pointers at 0x{x} to 0x{x}", .{ sect.offset, sect.offset + buffer.len });2106 log.warn("writing GOT pointers at 0x{x} to 0x{x}", .{ sect.offset, sect.offset + buffer.len });
21422107
2143 try self.file.?.pwriteAll(buffer, sect.offset);2108 try self.file.?.pwriteAll(buffer, sect.offset);
2144}2109}
...@@ -2148,7 +2113,8 @@ fn setEntryPoint(self: *Zld) !void {...@@ -2148,7 +2113,8 @@ fn setEntryPoint(self: *Zld) !void {
2148 // entrypoint. For now, assume default of `_main`.2113 // entrypoint. For now, assume default of `_main`.
2149 const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;2114 const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2150 const text = seg.sections.items[self.text_section_index.?];2115 const text = seg.sections.items[self.text_section_index.?];
2151 const entry_sym = self.symtab.get("_main") orelse return error.MissingMainEntrypoint;2116 const sym = self.globals.get("_main") orelse return error.MissingMainEntrypoint;
2117 const entry_sym = sym.cast(Symbol.Regular) orelse unreachable;
2152 const ec = &self.load_commands.items[self.main_cmd_index.?].Main;2118 const ec = &self.load_commands.items[self.main_cmd_index.?].Main;
2153 ec.entryoff = @intCast(u32, entry_sym.address - seg.inner.vmaddr);2119 ec.entryoff = @intCast(u32, entry_sym.address - seg.inner.vmaddr);
2154}2120}
...@@ -2161,24 +2127,21 @@ fn writeRebaseInfoTable(self: *Zld) !void {...@@ -2161,24 +2127,21 @@ fn writeRebaseInfoTable(self: *Zld) !void {
2161 pointers.appendSliceAssumeCapacity(self.local_rebases.items);2127 pointers.appendSliceAssumeCapacity(self.local_rebases.items);
21622128
2163 if (self.got_section_index) |idx| {2129 if (self.got_section_index) |idx| {
2164 // TODO this should be cleaned up!
2165 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;2130 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
2166 const sect = seg.sections.items[idx];2131 const sect = seg.sections.items[idx];
2167 const base_offset = sect.addr - seg.inner.vmaddr;2132 const base_offset = sect.addr - seg.inner.vmaddr;
2168 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);2133 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
21692134
2170 for (self.got_entries.items()) |entry| {2135 for (self.got_entries.items) |sym| {
2171 if (entry.value.tag == .import) continue;2136 if (sym.@"type" == .proxy) continue;
2172
2173 try pointers.append(.{2137 try pointers.append(.{
2174 .offset = base_offset + entry.value.index * @sizeOf(u64),2138 .offset = base_offset + sym.got_index.? * @sizeOf(u64),
2175 .segment_id = segment_id,2139 .segment_id = segment_id,
2176 });2140 });
2177 }2141 }
2178 }2142 }
21792143
2180 if (self.mod_init_func_section_index) |idx| {2144 if (self.mod_init_func_section_index) |idx| {
2181 // TODO audit and investigate this.
2182 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;2145 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
2183 const sect = seg.sections.items[idx];2146 const sect = seg.sections.items[idx];
2184 const base_offset = sect.addr - seg.inner.vmaddr;2147 const base_offset = sect.addr - seg.inner.vmaddr;
...@@ -2202,10 +2165,10 @@ fn writeRebaseInfoTable(self: *Zld) !void {...@@ -2202,10 +2165,10 @@ fn writeRebaseInfoTable(self: *Zld) !void {
2202 const base_offset = sect.addr - seg.inner.vmaddr;2165 const base_offset = sect.addr - seg.inner.vmaddr;
2203 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);2166 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);
22042167
2205 try pointers.ensureCapacity(pointers.items.len + self.stubs.items().len);2168 try pointers.ensureCapacity(pointers.items.len + self.stubs.items.len);
2206 for (self.stubs.items()) |entry| {2169 for (self.stubs.items) |sym| {
2207 pointers.appendAssumeCapacity(.{2170 pointers.appendAssumeCapacity(.{
2208 .offset = base_offset + entry.value * @sizeOf(u64),2171 .offset = base_offset + sym.stubs_index.? * @sizeOf(u64),
2209 .segment_id = segment_id,2172 .segment_id = segment_id,
2210 });2173 });
2211 }2174 }
...@@ -2226,7 +2189,7 @@ fn writeRebaseInfoTable(self: *Zld) !void {...@@ -2226,7 +2189,7 @@ fn writeRebaseInfoTable(self: *Zld) !void {
2226 dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @sizeOf(u64)));2189 dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @sizeOf(u64)));
2227 seg.inner.filesize += dyld_info.rebase_size;2190 seg.inner.filesize += dyld_info.rebase_size;
22282191
2229 log.debug("writing rebase info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + dyld_info.rebase_size });2192 log.warn("writing rebase info from 0x{x} to 0x{x}", .{ dyld_info.rebase_off, dyld_info.rebase_off + dyld_info.rebase_size });
22302193
2231 try self.file.?.pwriteAll(buffer, dyld_info.rebase_off);2194 try self.file.?.pwriteAll(buffer, dyld_info.rebase_off);
2232}2195}
...@@ -2241,21 +2204,16 @@ fn writeBindInfoTable(self: *Zld) !void {...@@ -2241,21 +2204,16 @@ fn writeBindInfoTable(self: *Zld) !void {
2241 const base_offset = sect.addr - seg.inner.vmaddr;2204 const base_offset = sect.addr - seg.inner.vmaddr;
2242 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);2205 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
22432206
2244 for (self.got_entries.items()) |entry| {2207 for (self.got_entries.items) |sym| {
2245 if (entry.value.tag == .local) continue;2208 if (sym.cast(Symbol.Proxy)) |proxy| {
22462209 const dylib_ordinal = proxy.dylib + 1;
2247 const dylib_ordinal = dylib_ordinal: {2210 try pointers.append(.{
2248 const sym = self.symtab.get(entry.key) orelse continue; // local indirection2211 .offset = base_offset + proxy.base.got_index.? * @sizeOf(u64),
2249 if (sym.tag != .import) continue; // local indirection2212 .segment_id = segment_id,
2250 break :dylib_ordinal sym.file.? + 1;2213 .dylib_ordinal = dylib_ordinal,
2251 };2214 .name = proxy.base.name,
22522215 });
2253 try pointers.append(.{2216 }
2254 .offset = base_offset + entry.value.index * @sizeOf(u64),
2255 .segment_id = segment_id,
2256 .dylib_ordinal = dylib_ordinal,
2257 .name = entry.key,
2258 });
2259 }2217 }
2260 }2218 }
22612219
...@@ -2265,14 +2223,15 @@ fn writeBindInfoTable(self: *Zld) !void {...@@ -2265,14 +2223,15 @@ fn writeBindInfoTable(self: *Zld) !void {
2265 const base_offset = sect.addr - seg.inner.vmaddr;2223 const base_offset = sect.addr - seg.inner.vmaddr;
2266 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);2224 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);
22672225
2268 const sym = self.symtab.get("__tlv_bootstrap") orelse unreachable;2226 const sym = self.imports.get("__tlv_bootstrap") orelse unreachable;
2269 const dylib_ordinal = sym.file.? + 1;2227 const proxy = sym.cast(Symbol.Proxy) orelse unreachable;
2228 const dylib_ordinal = proxy.dylib + 1;
22702229
2271 try pointers.append(.{2230 try pointers.append(.{
2272 .offset = base_offset,2231 .offset = base_offset,
2273 .segment_id = segment_id,2232 .segment_id = segment_id,
2274 .dylib_ordinal = dylib_ordinal,2233 .dylib_ordinal = dylib_ordinal,
2275 .name = "__tlv_bootstrap",2234 .name = proxy.base.name,
2276 });2235 });
2277 }2236 }
22782237
...@@ -2289,7 +2248,7 @@ fn writeBindInfoTable(self: *Zld) !void {...@@ -2289,7 +2248,7 @@ fn writeBindInfoTable(self: *Zld) !void {
2289 dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));2248 dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
2290 seg.inner.filesize += dyld_info.bind_size;2249 seg.inner.filesize += dyld_info.bind_size;
22912250
2292 log.debug("writing binding info from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + dyld_info.bind_size });2251 log.warn("writing binding info from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + dyld_info.bind_size });
22932252
2294 try self.file.?.pwriteAll(buffer, dyld_info.bind_off);2253 try self.file.?.pwriteAll(buffer, dyld_info.bind_off);
2295}2254}
...@@ -2304,20 +2263,16 @@ fn writeLazyBindInfoTable(self: *Zld) !void {...@@ -2304,20 +2263,16 @@ fn writeLazyBindInfoTable(self: *Zld) !void {
2304 const base_offset = sect.addr - seg.inner.vmaddr;2263 const base_offset = sect.addr - seg.inner.vmaddr;
2305 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);2264 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);
23062265
2307 try pointers.ensureCapacity(self.stubs.items().len);2266 try pointers.ensureCapacity(self.stubs.items.len);
2308
2309 for (self.stubs.items()) |entry| {
2310 const dylib_ordinal = dylib_ordinal: {
2311 const sym = self.symtab.get(entry.key) orelse unreachable;
2312 assert(sym.tag == .import);
2313 break :dylib_ordinal sym.file.? + 1;
2314 };
23152267
2268 for (self.stubs.items) |sym| {
2269 const proxy = sym.cast(Symbol.Proxy) orelse unreachable;
2270 const dylib_ordinal = proxy.dylib + 1;
2316 pointers.appendAssumeCapacity(.{2271 pointers.appendAssumeCapacity(.{
2317 .offset = base_offset + entry.value * @sizeOf(u64),2272 .offset = base_offset + sym.stubs_index.? * @sizeOf(u64),
2318 .segment_id = segment_id,2273 .segment_id = segment_id,
2319 .dylib_ordinal = dylib_ordinal,2274 .dylib_ordinal = dylib_ordinal,
2320 .name = entry.key,2275 .name = sym.name,
2321 });2276 });
2322 }2277 }
2323 }2278 }
...@@ -2335,7 +2290,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void {...@@ -2335,7 +2290,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void {
2335 dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));2290 dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
2336 seg.inner.filesize += dyld_info.lazy_bind_size;2291 seg.inner.filesize += dyld_info.lazy_bind_size;
23372292
2338 log.debug("writing lazy binding info from 0x{x} to 0x{x}", .{ dyld_info.lazy_bind_off, dyld_info.lazy_bind_off + dyld_info.lazy_bind_size });2293 log.warn("writing lazy binding info from 0x{x} to 0x{x}", .{ dyld_info.lazy_bind_off, dyld_info.lazy_bind_off + dyld_info.lazy_bind_size });
23392294
2340 try self.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);2295 try self.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);
2341 try self.populateLazyBindOffsetsInStubHelper(buffer);2296 try self.populateLazyBindOffsetsInStubHelper(buffer);
...@@ -2386,7 +2341,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void {...@@ -2386,7 +2341,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void {
2386 else => {},2341 else => {},
2387 }2342 }
2388 }2343 }
2389 assert(self.stubs.items().len <= offsets.items.len);2344 assert(self.stubs.items.len <= offsets.items.len);
23902345
2391 const stub_size: u4 = switch (self.arch.?) {2346 const stub_size: u4 = switch (self.arch.?) {
2392 .x86_64 => 10,2347 .x86_64 => 10,
...@@ -2399,9 +2354,10 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void {...@@ -2399,9 +2354,10 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void {
2399 else => unreachable,2354 else => unreachable,
2400 };2355 };
2401 var buf: [@sizeOf(u32)]u8 = undefined;2356 var buf: [@sizeOf(u32)]u8 = undefined;
2402 for (self.stubs.items()) |entry| {2357 for (self.stubs.items) |sym| {
2403 const placeholder_off = self.stub_helper_stubs_start_off.? + entry.value * stub_size + off;2358 const index = sym.stubs_index orelse unreachable;
2404 mem.writeIntLittle(u32, &buf, offsets.items[entry.value]);2359 const placeholder_off = self.stub_helper_stubs_start_off.? + index * stub_size + off;
2360 mem.writeIntLittle(u32, &buf, offsets.items[index]);
2405 try self.file.?.pwriteAll(&buf, placeholder_off);2361 try self.file.?.pwriteAll(&buf, placeholder_off);
2406 }2362 }
2407}2363}
...@@ -2413,12 +2369,13 @@ fn writeExportInfo(self: *Zld) !void {...@@ -2413,12 +2369,13 @@ fn writeExportInfo(self: *Zld) !void {
2413 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;2369 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
24142370
2415 // TODO export items for dylibs2371 // TODO export items for dylibs
2416 const sym = self.symtab.get("_main") orelse return error.MissingMainEntrypoint;2372 const sym = self.globals.get("_main") orelse return error.MissingMainEntrypoint;
2417 assert(sym.address >= text_segment.inner.vmaddr);2373 const reg = sym.cast(Symbol.Regular) orelse unreachable;
2374 assert(reg.address >= text_segment.inner.vmaddr);
24182375
2419 try trie.put(.{2376 try trie.put(.{
2420 .name = "_main",2377 .name = sym.name,
2421 .vmaddr_offset = sym.address - text_segment.inner.vmaddr,2378 .vmaddr_offset = reg.address - text_segment.inner.vmaddr,
2422 .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR,2379 .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR,
2423 });2380 });
24242381
...@@ -2437,7 +2394,7 @@ fn writeExportInfo(self: *Zld) !void {...@@ -2437,7 +2394,7 @@ fn writeExportInfo(self: *Zld) !void {
2437 dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));2394 dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
2438 seg.inner.filesize += dyld_info.export_size;2395 seg.inner.filesize += dyld_info.export_size;
24392396
2440 log.debug("writing export info from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size });2397 log.warn("writing export info from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size });
24412398
2442 try self.file.?.pwriteAll(buffer, dyld_info.export_off);2399 try self.file.?.pwriteAll(buffer, dyld_info.export_off);
2443}2400}
...@@ -2446,7 +2403,7 @@ fn writeDebugInfo(self: *Zld) !void {...@@ -2446,7 +2403,7 @@ fn writeDebugInfo(self: *Zld) !void {
2446 var stabs = std.ArrayList(macho.nlist_64).init(self.allocator);2403 var stabs = std.ArrayList(macho.nlist_64).init(self.allocator);
2447 defer stabs.deinit();2404 defer stabs.deinit();
24482405
2449 for (self.objects.items) |object, object_id| {2406 for (self.objects.items) |object| {
2450 const tu_path = object.tu_path orelse continue;2407 const tu_path = object.tu_path orelse continue;
2451 const tu_mtime = object.tu_mtime orelse continue;2408 const tu_mtime = object.tu_mtime orelse continue;
2452 const dirname = std.fs.path.dirname(tu_path) orelse "./";2409 const dirname = std.fs.path.dirname(tu_path) orelse "./";
...@@ -2475,39 +2432,42 @@ fn writeDebugInfo(self: *Zld) !void {...@@ -2475,39 +2432,42 @@ fn writeDebugInfo(self: *Zld) !void {
2475 .n_value = 0, //tu_mtime, TODO figure out why precalculated mtime value doesn't work2432 .n_value = 0, //tu_mtime, TODO figure out why precalculated mtime value doesn't work
2476 });2433 });
24772434
2478 for (object.stabs.items) |stab| {2435 for (object.symbols.items) |sym| {
2479 const entry = object.locals.items()[stab.symbol];2436 if (sym.@"type" != .regular) continue;
2480 const sym = entry.value;2437 const reg = sym.cast(Symbol.Regular) orelse unreachable;
2438
2439 if (reg.isTemp() or reg.stab == null) continue;
2440 const stab = reg.stab orelse unreachable;
24812441
2482 switch (stab.tag) {2442 switch (stab.kind) {
2483 .function => {2443 .function => {
2484 try stabs.append(.{2444 try stabs.append(.{
2485 .n_strx = 0,2445 .n_strx = 0,
2486 .n_type = macho.N_BNSYM,2446 .n_type = macho.N_BNSYM,
2487 .n_sect = sym.section,2447 .n_sect = reg.section,
2488 .n_desc = 0,2448 .n_desc = 0,
2489 .n_value = sym.address,2449 .n_value = reg.address,
2490 });2450 });
2491 try stabs.append(.{2451 try stabs.append(.{
2492 .n_strx = try self.makeString(sym.name),2452 .n_strx = try self.makeString(sym.name),
2493 .n_type = macho.N_FUN,2453 .n_type = macho.N_FUN,
2494 .n_sect = sym.section,2454 .n_sect = reg.section,
2495 .n_desc = 0,2455 .n_desc = 0,
2496 .n_value = sym.address,2456 .n_value = reg.address,
2497 });2457 });
2498 try stabs.append(.{2458 try stabs.append(.{
2499 .n_strx = 0,2459 .n_strx = 0,
2500 .n_type = macho.N_FUN,2460 .n_type = macho.N_FUN,
2501 .n_sect = 0,2461 .n_sect = 0,
2502 .n_desc = 0,2462 .n_desc = 0,
2503 .n_value = stab.size.?,2463 .n_value = stab.size,
2504 });2464 });
2505 try stabs.append(.{2465 try stabs.append(.{
2506 .n_strx = 0,2466 .n_strx = 0,
2507 .n_type = macho.N_ENSYM,2467 .n_type = macho.N_ENSYM,
2508 .n_sect = sym.section,2468 .n_sect = reg.section,
2509 .n_desc = 0,2469 .n_desc = 0,
2510 .n_value = stab.size.?,2470 .n_value = stab.size,
2511 });2471 });
2512 },2472 },
2513 .global => {2473 .global => {
...@@ -2523,9 +2483,9 @@ fn writeDebugInfo(self: *Zld) !void {...@@ -2523,9 +2483,9 @@ fn writeDebugInfo(self: *Zld) !void {
2523 try stabs.append(.{2483 try stabs.append(.{
2524 .n_strx = try self.makeString(sym.name),2484 .n_strx = try self.makeString(sym.name),
2525 .n_type = macho.N_STSYM,2485 .n_type = macho.N_STSYM,
2526 .n_sect = sym.section,2486 .n_sect = reg.section,
2527 .n_desc = 0,2487 .n_desc = 0,
2528 .n_value = sym.address,2488 .n_value = reg.address,
2529 });2489 });
2530 },2490 },
2531 }2491 }
...@@ -2551,7 +2511,7 @@ fn writeDebugInfo(self: *Zld) !void {...@@ -2551,7 +2511,7 @@ fn writeDebugInfo(self: *Zld) !void {
25512511
2552 const stabs_off = symtab.symoff;2512 const stabs_off = symtab.symoff;
2553 const stabs_size = symtab.nsyms * @sizeOf(macho.nlist_64);2513 const stabs_size = symtab.nsyms * @sizeOf(macho.nlist_64);
2554 log.debug("writing symbol stabs from 0x{x} to 0x{x}", .{ stabs_off, stabs_size + stabs_off });2514 log.warn("writing symbol stabs from 0x{x} to 0x{x}", .{ stabs_off, stabs_size + stabs_off });
2555 try self.file.?.pwriteAll(mem.sliceAsBytes(stabs.items), stabs_off);2515 try self.file.?.pwriteAll(mem.sliceAsBytes(stabs.items), stabs_off);
25562516
2557 linkedit.inner.filesize += stabs_size;2517 linkedit.inner.filesize += stabs_size;
...@@ -2561,27 +2521,6 @@ fn writeDebugInfo(self: *Zld) !void {...@@ -2561,27 +2521,6 @@ fn writeDebugInfo(self: *Zld) !void {
2561 dysymtab.nlocalsym = symtab.nsyms;2521 dysymtab.nlocalsym = symtab.nsyms;
2562}2522}
25632523
2564fn populateStringTable(self: *Zld) !void {
2565 for (self.objects.items) |*object| {
2566 for (object.symtab.items) |*sym| {
2567 switch (sym.tag) {
2568 .undef, .import => continue,
2569 else => {},
2570 }
2571 const sym_name = object.getString(sym.inner.n_strx);
2572 const n_strx = try self.makeString(sym_name);
2573 sym.inner.n_strx = n_strx;
2574 }
2575 }
2576
2577 for (self.symtab.items()) |*entry| {
2578 if (entry.value.tag != .import) continue;
2579
2580 const n_strx = try self.makeString(entry.key);
2581 entry.value.inner.n_strx = n_strx;
2582 }
2583}
2584
2585fn writeSymbolTable(self: *Zld) !void {2524fn writeSymbolTable(self: *Zld) !void {
2586 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;2525 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
2587 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;2526 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
...@@ -2589,56 +2528,52 @@ fn writeSymbolTable(self: *Zld) !void {...@@ -2589,56 +2528,52 @@ fn writeSymbolTable(self: *Zld) !void {
2589 var locals = std.ArrayList(macho.nlist_64).init(self.allocator);2528 var locals = std.ArrayList(macho.nlist_64).init(self.allocator);
2590 defer locals.deinit();2529 defer locals.deinit();
25912530
2531 var exports = std.ArrayList(macho.nlist_64).init(self.allocator);
2532 defer exports.deinit();
2533
2592 for (self.objects.items) |object| {2534 for (self.objects.items) |object| {
2593 for (object.locals.items()) |entry| {2535 for (object.symbols.items) |sym| {
2594 const sym = entry.value;2536 const final = sym.getTopmostAlias();
2595 if (sym.tag != .local) continue;2537 if (final.@"type" != .regular) continue;
25962538
2597 try locals.append(.{2539 const reg = final.cast(Symbol.Regular) orelse unreachable;
2598 .n_strx = try self.makeString(sym.name),2540 if (reg.isTemp()) continue;
2599 .n_type = macho.N_SECT,2541
2600 .n_sect = sym.section,2542 switch (reg.linkage) {
2601 .n_desc = 0,2543 .translation_unit => {
2602 .n_value = sym.address,2544 try locals.append(.{
2603 });2545 .n_strx = try self.makeString(sym.name),
2546 .n_type = macho.N_SECT,
2547 .n_sect = reg.section,
2548 .n_desc = 0,
2549 .n_value = reg.address,
2550 });
2551 },
2552 else => {
2553 try exports.append(.{
2554 .n_strx = try self.makeString(sym.name),
2555 .n_type = macho.N_SECT | macho.N_EXT,
2556 .n_sect = reg.section,
2557 .n_desc = 0,
2558 .n_value = reg.address,
2559 });
2560 },
2561 }
2604 }2562 }
2605 }2563 }
26062564
2607 var exports = std.ArrayList(macho.nlist_64).init(self.allocator);
2608 defer exports.deinit();
2609
2610 var undefs = std.ArrayList(macho.nlist_64).init(self.allocator);2565 var undefs = std.ArrayList(macho.nlist_64).init(self.allocator);
2611 defer undefs.deinit();2566 defer undefs.deinit();
26122567
2613 var undefs_ids = std.StringHashMap(u32).init(self.allocator);2568 for (self.imports.items()) |entry| {
2614 defer undefs_ids.deinit();
2615
2616 var undef_id: u32 = 0;
2617 for (self.symtab.items()) |entry| {
2618 const sym = entry.value;2569 const sym = entry.value;
2619 switch (sym.tag) {2570 try undefs.append(.{
2620 .weak, .strong => {2571 .n_strx = try self.makeString(sym.name),
2621 try exports.append(.{2572 .n_type = macho.N_UNDF | macho.N_EXT,
2622 .n_strx = try self.makeString(sym.name),2573 .n_sect = 0,
2623 .n_type = macho.N_SECT | macho.N_EXT,2574 .n_desc = macho.N_SYMBOL_RESOLVER | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY,
2624 .n_sect = sym.section,2575 .n_value = 0,
2625 .n_desc = 0,2576 });
2626 .n_value = sym.address,
2627 });
2628 },
2629 .import => {
2630 try undefs.append(.{
2631 .n_strx = try self.makeString(sym.name),
2632 .n_type = macho.N_UNDF | macho.N_EXT,
2633 .n_sect = 0,
2634 .n_desc = macho.N_SYMBOL_RESOLVER | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY,
2635 .n_value = 0,
2636 });
2637 try undefs_ids.putNoClobber(sym.name, undef_id);
2638 undef_id += 1;
2639 },
2640 else => unreachable,
2641 }
2642 }2577 }
26432578
2644 const nlocals = locals.items.len;2579 const nlocals = locals.items.len;
...@@ -2647,17 +2582,17 @@ fn writeSymbolTable(self: *Zld) !void {...@@ -2647,17 +2582,17 @@ fn writeSymbolTable(self: *Zld) !void {
26472582
2648 const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);2583 const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);
2649 const locals_size = nlocals * @sizeOf(macho.nlist_64);2584 const locals_size = nlocals * @sizeOf(macho.nlist_64);
2650 log.debug("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off });2585 log.warn("writing local symbols from 0x{x} to 0x{x}", .{ locals_off, locals_size + locals_off });
2651 try self.file.?.pwriteAll(mem.sliceAsBytes(locals.items), locals_off);2586 try self.file.?.pwriteAll(mem.sliceAsBytes(locals.items), locals_off);
26522587
2653 const exports_off = locals_off + locals_size;2588 const exports_off = locals_off + locals_size;
2654 const exports_size = nexports * @sizeOf(macho.nlist_64);2589 const exports_size = nexports * @sizeOf(macho.nlist_64);
2655 log.debug("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off });2590 log.warn("writing exported symbols from 0x{x} to 0x{x}", .{ exports_off, exports_size + exports_off });
2656 try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off);2591 try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off);
26572592
2658 const undefs_off = exports_off + exports_size;2593 const undefs_off = exports_off + exports_size;
2659 const undefs_size = nundefs * @sizeOf(macho.nlist_64);2594 const undefs_size = nundefs * @sizeOf(macho.nlist_64);
2660 log.debug("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off });2595 log.warn("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off });
2661 try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off);2596 try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off);
26622597
2663 symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs);2598 symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs);
...@@ -2678,8 +2613,8 @@ fn writeSymbolTable(self: *Zld) !void {...@@ -2678,8 +2613,8 @@ fn writeSymbolTable(self: *Zld) !void {
2678 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;2613 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2679 const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?];2614 const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?];
26802615
2681 const nstubs = @intCast(u32, self.stubs.items().len);2616 const nstubs = @intCast(u32, self.stubs.items.len);
2682 const ngot_entries = @intCast(u32, self.got_entries.items().len);2617 const ngot_entries = @intCast(u32, self.got_entries.items.len);
26832618
2684 dysymtab.indirectsymoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);2619 dysymtab.indirectsymoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);
2685 dysymtab.nindirectsyms = nstubs * 2 + ngot_entries;2620 dysymtab.nindirectsyms = nstubs * 2 + ngot_entries;
...@@ -2687,7 +2622,7 @@ fn writeSymbolTable(self: *Zld) !void {...@@ -2687,7 +2622,7 @@ fn writeSymbolTable(self: *Zld) !void {
2687 const needed_size = dysymtab.nindirectsyms * @sizeOf(u32);2622 const needed_size = dysymtab.nindirectsyms * @sizeOf(u32);
2688 seg.inner.filesize += needed_size;2623 seg.inner.filesize += needed_size;
26892624
2690 log.debug("writing indirect symbol table from 0x{x} to 0x{x}", .{2625 log.warn("writing indirect symbol table from 0x{x} to 0x{x}", .{
2691 dysymtab.indirectsymoff,2626 dysymtab.indirectsymoff,
2692 dysymtab.indirectsymoff + needed_size,2627 dysymtab.indirectsymoff + needed_size,
2693 });2628 });
...@@ -2699,25 +2634,25 @@ fn writeSymbolTable(self: *Zld) !void {...@@ -2699,25 +2634,25 @@ fn writeSymbolTable(self: *Zld) !void {
2699 var writer = stream.writer();2634 var writer = stream.writer();
27002635
2701 stubs.reserved1 = 0;2636 stubs.reserved1 = 0;
2702 for (self.stubs.items()) |entry| {2637 for (self.stubs.items) |sym| {
2703 const id = undefs_ids.get(entry.key) orelse unreachable;2638 const id = self.imports.getIndex(sym.name) orelse unreachable;
2704 try writer.writeIntLittle(u32, dysymtab.iundefsym + id);2639 try writer.writeIntLittle(u32, dysymtab.iundefsym + @intCast(u32, id));
2705 }2640 }
27062641
2707 got.reserved1 = nstubs;2642 got.reserved1 = nstubs;
2708 for (self.got_entries.items()) |entry| {2643 for (self.got_entries.items) |sym| {
2709 if (entry.value.tag == .import) {2644 if (sym.@"type" == .proxy) {
2710 const id = undefs_ids.get(entry.key) orelse unreachable;2645 const id = self.imports.getIndex(sym.name) orelse unreachable;
2711 try writer.writeIntLittle(u32, dysymtab.iundefsym + id);2646 try writer.writeIntLittle(u32, dysymtab.iundefsym + @intCast(u32, id));
2712 } else {2647 } else {
2713 try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL);2648 try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL);
2714 }2649 }
2715 }2650 }
27162651
2717 la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries;2652 la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries;
2718 for (self.stubs.items()) |entry| {2653 for (self.stubs.items) |sym| {
2719 const id = undefs_ids.get(entry.key) orelse unreachable;2654 const id = self.imports.getIndex(sym.name) orelse unreachable;
2720 try writer.writeIntLittle(u32, dysymtab.iundefsym + id);2655 try writer.writeIntLittle(u32, dysymtab.iundefsym + @intCast(u32, id));
2721 }2656 }
27222657
2723 try self.file.?.pwriteAll(buf, dysymtab.indirectsymoff);2658 try self.file.?.pwriteAll(buf, dysymtab.indirectsymoff);
...@@ -2730,7 +2665,7 @@ fn writeStringTable(self: *Zld) !void {...@@ -2730,7 +2665,7 @@ fn writeStringTable(self: *Zld) !void {
2730 symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64)));2665 symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64)));
2731 seg.inner.filesize += symtab.strsize;2666 seg.inner.filesize += symtab.strsize;
27322667
2733 log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize });2668 log.warn("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize });
27342669
2735 try self.file.?.pwriteAll(self.strtab.items, symtab.stroff);2670 try self.file.?.pwriteAll(self.strtab.items, symtab.stroff);
27362671
...@@ -2776,7 +2711,7 @@ fn writeDataInCode(self: *Zld) !void {...@@ -2776,7 +2711,7 @@ fn writeDataInCode(self: *Zld) !void {
2776 dice_cmd.datasize = datasize;2711 dice_cmd.datasize = datasize;
2777 seg.inner.filesize += datasize;2712 seg.inner.filesize += datasize;
27782713
2779 log.debug("writing data-in-code from 0x{x} to 0x{x}", .{ fileoff, fileoff + datasize });2714 log.warn("writing data-in-code from 0x{x} to 0x{x}", .{ fileoff, fileoff + datasize });
27802715
2781 try self.file.?.pwriteAll(buf.items, fileoff);2716 try self.file.?.pwriteAll(buf.items, fileoff);
2782}2717}
...@@ -2797,7 +2732,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void {...@@ -2797,7 +2732,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void {
2797 seg.inner.filesize += needed_size;2732 seg.inner.filesize += needed_size;
2798 seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);2733 seg.inner.vmsize = mem.alignForwardGeneric(u64, seg.inner.filesize, self.page_size.?);
27992734
2800 log.debug("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size });2735 log.warn("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size });
28012736
2802 // Pad out the space. We need to do this to calculate valid hashes for everything in the file2737 // Pad out the space. We need to do this to calculate valid hashes for everything in the file
2803 // except for code signature data.2738 // except for code signature data.
...@@ -2823,7 +2758,7 @@ fn writeCodeSignature(self: *Zld) !void {...@@ -2823,7 +2758,7 @@ fn writeCodeSignature(self: *Zld) !void {
2823 var stream = std.io.fixedBufferStream(buffer);2758 var stream = std.io.fixedBufferStream(buffer);
2824 try code_sig.write(stream.writer());2759 try code_sig.write(stream.writer());
28252760
2826 log.debug("writing code signature from 0x{x} to 0x{x}", .{ code_sig_cmd.dataoff, code_sig_cmd.dataoff + buffer.len });2761 log.warn("writing code signature from 0x{x} to 0x{x}", .{ code_sig_cmd.dataoff, code_sig_cmd.dataoff + buffer.len });
2827 try self.file.?.pwriteAll(buffer, code_sig_cmd.dataoff);2762 try self.file.?.pwriteAll(buffer, code_sig_cmd.dataoff);
2828}2763}
28292764
...@@ -2841,7 +2776,7 @@ fn writeLoadCommands(self: *Zld) !void {...@@ -2841,7 +2776,7 @@ fn writeLoadCommands(self: *Zld) !void {
2841 }2776 }
28422777
2843 const off = @sizeOf(macho.mach_header_64);2778 const off = @sizeOf(macho.mach_header_64);
2844 log.debug("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds });2779 log.warn("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds });
2845 try self.file.?.pwriteAll(buffer, off);2780 try self.file.?.pwriteAll(buffer, off);
2846}2781}
28472782
...@@ -2879,7 +2814,7 @@ fn writeHeader(self: *Zld) !void {...@@ -2879,7 +2814,7 @@ fn writeHeader(self: *Zld) !void {
2879 for (self.load_commands.items) |cmd| {2814 for (self.load_commands.items) |cmd| {
2880 header.sizeofcmds += cmd.cmdsize();2815 header.sizeofcmds += cmd.cmdsize();
2881 }2816 }
2882 log.debug("writing Mach-O header {}", .{header});2817 log.warn("writing Mach-O header {}", .{header});
2883 try self.file.?.pwriteAll(mem.asBytes(&header), 0);2818 try self.file.?.pwriteAll(mem.asBytes(&header), 0);
2884}2819}
28852820
...@@ -2892,13 +2827,13 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 {...@@ -2892,13 +2827,13 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 {
28922827
2893fn makeString(self: *Zld, bytes: []const u8) !u32 {2828fn makeString(self: *Zld, bytes: []const u8) !u32 {
2894 if (self.strtab_dir.get(bytes)) |offset| {2829 if (self.strtab_dir.get(bytes)) |offset| {
2895 log.debug("reusing '{s}' from string table at offset 0x{x}", .{ bytes, offset });2830 log.warn("reusing '{s}' from string table at offset 0x{x}", .{ bytes, offset });
2896 return offset;2831 return offset;
2897 }2832 }
28982833
2899 try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1);2834 try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1);
2900 const offset = @intCast(u32, self.strtab.items.len);2835 const offset = @intCast(u32, self.strtab.items.len);
2901 log.debug("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset });2836 log.warn("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset });
2902 self.strtab.appendSliceAssumeCapacity(bytes);2837 self.strtab.appendSliceAssumeCapacity(bytes);
2903 self.strtab.appendAssumeCapacity(0);2838 self.strtab.appendAssumeCapacity(0);
2904 try self.strtab_dir.putNoClobber(self.allocator, try self.allocator.dupe(u8, bytes), offset);2839 try self.strtab_dir.putNoClobber(self.allocator, try self.allocator.dupe(u8, bytes), offset);