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 {
6666 linkage_unit,
6767 global,
6868 };
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 }
6976};
7077
7178pub 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 {
209209 try self.allocateDataSegment();
210210 self.allocateLinkeditSegment();
211211 try self.allocateSymbols();
212 return error.Unfinished;
213 // try self.writeStubHelperCommon();
214 // try self.resolveRelocsAndWriteSections();
215 // try self.flush();
212 try self.writeStubHelperCommon();
213 try self.resolveRelocsAndWriteSections();
214 try self.flush();
216215}
217216
218217fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
......@@ -268,7 +267,7 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
268267 continue;
269268 }
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});
272271 }
273272
274273 // Based on our classification, proceed with parsing.
......@@ -326,7 +325,7 @@ fn mapAndUpdateSections(
326325 .target_sect_id = target_sect_id,
327326 .offset = @intCast(u32, offset),
328327 });
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}", .{
330329 object.name,
331330 parseName(&source_sect.segname),
332331 parseName(&source_sect.sectname),
......@@ -556,7 +555,7 @@ fn updateMetadata(self: *Zld) !void {
556555 });
557556 },
558557 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 });
560559 },
561560 }
562561 }
......@@ -581,7 +580,7 @@ fn updateMetadata(self: *Zld) !void {
581580 const segname = parseName(&source_sect.segname);
582581 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
586585 try self.unhandled_sections.putNoClobber(self.allocator, .{
587586 .object_id = object_id,
......@@ -978,8 +977,8 @@ fn writeStubHelperCommon(self: *Zld) !void {
978977 code[9] = 0xff;
979978 code[10] = 0x25;
980979 {
981 const dyld_stub_binder = self.got_entries.get("dyld_stub_binder").?;
982 const addr = (got.addr + dyld_stub_binder.index * @sizeOf(u64));
980 const dyld_stub_binder = self.imports.get("dyld_stub_binder").?;
981 const addr = (got.addr + dyld_stub_binder.got_index.? * @sizeOf(u64));
983982 const displacement = try math.cast(u32, addr - stub_helper.addr - code_size);
984983 mem.writeIntLittle(u32, code[11..], displacement);
985984 }
......@@ -1022,9 +1021,9 @@ fn writeStubHelperCommon(self: *Zld) !void {
10221021 code[10] = 0xbf;
10231022 code[11] = 0xa9;
10241023 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").?;
10261025 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));
10281027 binder_blk: {
10291028 const displacement = math.divExact(u64, target_addr - this_addr, 4) catch |_| break :binder_blk;
10301029 const literal = math.cast(u18, displacement) catch |_| break :binder_blk;
......@@ -1075,8 +1074,9 @@ fn writeStubHelperCommon(self: *Zld) !void {
10751074 }
10761075 };
10771076
1078 for (self.stubs.items()) |entry| {
1079 const index = entry.value;
1077 for (self.stubs.items) |sym| {
1078 // TODO weak bound pointers
1079 const index = sym.stubs_index orelse unreachable;
10801080 try self.writeLazySymbolPointer(index);
10811081 try self.writeStub(index);
10821082 try self.writeStubInStubHelper(index);
......@@ -1099,7 +1099,7 @@ fn writeLazySymbolPointer(self: *Zld, index: u32) !void {
10991099 var buf: [@sizeOf(u64)]u8 = undefined;
11001100 mem.writeIntLittle(u64, &buf, end);
11011101 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 });
11031103 try self.file.?.pwriteAll(&buf, off);
11041104}
11051105
......@@ -1112,7 +1112,7 @@ fn writeStub(self: *Zld, index: u32) !void {
11121112 const stub_off = stubs.offset + index * stubs.reserved2;
11131113 const stub_addr = stubs.addr + index * stubs.reserved2;
11141114 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});
11161116 var code = try self.allocator.alloc(u8, stubs.reserved2);
11171117 defer self.allocator.free(code);
11181118 switch (self.arch.?) {
......@@ -1413,7 +1413,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
14131413
14141414fn resolveRelocsAndWriteSections(self: *Zld) !void {
14151415 for (self.objects.items) |object, object_id| {
1416 log.debug("relocating object {s}", .{object.name});
1416 log.warn("relocating object {s}", .{object.name});
14171417
14181418 for (object.sections.items) |sect, source_sect_id| {
14191419 if (sect.inner.flags == macho.S_MOD_INIT_FUNC_POINTERS or
......@@ -1422,14 +1422,14 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
14221422 const segname = parseName(&sect.inner.segname);
14231423 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
14271427 // Get mapping
14281428 const target_mapping = self.mappings.get(.{
14291429 .object_id = @intCast(u16, object_id),
14301430 .source_sect_id = @intCast(u16, source_sect_id),
14311431 }) orelse {
1432 log.debug("no mapping for {s},{s}; skipping", .{ segname, sectname });
1432 log.warn("no mapping for {s},{s}; skipping", .{ segname, sectname });
14331433 continue;
14341434 };
14351435 const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment;
......@@ -1482,11 +1482,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
14821482 // TLV is handled via a separate offset mechanism.
14831483 // Calculate the offset to the initializer.
14841484 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
14881485 // 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
14911488 const base_addr = blk: {
14921489 if (self.tlv_data_section_index) |index| {
......@@ -1505,10 +1502,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
15051502 .got_page, .got_page_off, .got_load, .got => {
15061503 const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
15071504 const got = dc_seg.sections.items[self.got_section_index.?];
1508 const sym = object.symtab.items[rel.target.symbol];
1509 const sym_name = object.getString(sym.n_strx);
1510 const entry = self.got_entries.get(sym_name) orelse unreachable;
1511 args.target_addr = got.addr + entry.index * @sizeOf(u64);
1505 const final = rel.target.symbol.getTopmostAlias();
1506 args.target_addr = got.addr + final.got_index.? * @sizeOf(u64);
15121507 },
15131508 else => |tt| {
15141509 if (tt == .signed and rel.target == .section) {
......@@ -1523,7 +1518,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
15231518 }
15241519 }
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}", .{
15271522 segname,
15281523 sectname,
15291524 object.name,
......@@ -1535,7 +1530,7 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
15351530 target_sect.flags == macho.S_THREAD_LOCAL_ZEROFILL or
15361531 target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES)
15371532 {
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}", .{
15391534 parseName(&target_sect.segname),
15401535 parseName(&target_sect.sectname),
15411536 target_sect_off,
......@@ -1555,58 +1550,27 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
15551550}
15561551
15571552fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target) !u64 {
1558 const object = self.objects.items[object_id];
15591553 const target_addr = blk: {
15601554 switch (target) {
1561 .symbol => |sym_id| {
1562 const sym = object.symtab.items[sym_id];
1563 const sym_name = object.getString(sym.n_strx);
1564
1565 if (Symbol.isSect(sym)) {
1566 log.debug(" | local symbol '{s}'", .{sym_name});
1567 if (object.locals.get(sym_name)) |local| {
1568 break :blk local.address;
1569 }
1570 // For temp locals, i.e., symbols prefixed with l... we relocate
1571 // based on section addressing.
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,
1555 .symbol => |sym| {
1556 const final = sym.getTopmostAlias();
1557 if (final.cast(Symbol.Regular)) |reg| {
1558 log.warn(" | regular '{s}'", .{sym.name});
1559 break :blk reg.address;
1560 } else if (final.cast(Symbol.Proxy)) |proxy| {
1561 if (mem.eql(u8, sym.name, "__tlv_bootstrap")) {
1562 log.warn(" | symbol '__tlv_bootstrap'", .{});
1563 const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1564 const tlv = segment.sections.items[self.tlv_section_index.?];
1565 break :blk tlv.addr;
16071566 }
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;
16081572 } 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});
16101574 return error.FailedToResolveRelocationTarget;
16111575 }
16121576 },
......@@ -2071,10 +2035,10 @@ fn flush(self: *Zld) !void {
20712035 var initializers = std.ArrayList(u64).init(self.allocator);
20722036 defer initializers.deinit();
20732037
2074 // TODO sort the initializers globally
20752038 for (self.objects.items) |object| {
20762039 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);
20782042 }
20792043 }
20802044
......@@ -2128,17 +2092,18 @@ fn writeGotEntries(self: *Zld) !void {
21282092 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
21292093 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));
21322096 defer self.allocator.free(buffer);
21332097
21342098 var stream = std.io.fixedBufferStream(buffer);
21352099 var writer = stream.writer();
21362100
2137 for (self.got_entries.items()) |entry| {
2138 try writer.writeIntLittle(u64, entry.value.target_addr);
2101 for (self.got_entries.items) |sym| {
2102 const address: u64 = if (sym.cast(Symbol.Regular)) |reg| reg.address else 0;
2103 try writer.writeIntLittle(u64, address);
21392104 }
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
21432108 try self.file.?.pwriteAll(buffer, sect.offset);
21442109}
......@@ -2148,7 +2113,8 @@ fn setEntryPoint(self: *Zld) !void {
21482113 // entrypoint. For now, assume default of `_main`.
21492114 const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
21502115 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;
21522118 const ec = &self.load_commands.items[self.main_cmd_index.?].Main;
21532119 ec.entryoff = @intCast(u32, entry_sym.address - seg.inner.vmaddr);
21542120}
......@@ -2161,24 +2127,21 @@ fn writeRebaseInfoTable(self: *Zld) !void {
21612127 pointers.appendSliceAssumeCapacity(self.local_rebases.items);
21622128
21632129 if (self.got_section_index) |idx| {
2164 // TODO this should be cleaned up!
21652130 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
21662131 const sect = seg.sections.items[idx];
21672132 const base_offset = sect.addr - seg.inner.vmaddr;
21682133 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
21692134
2170 for (self.got_entries.items()) |entry| {
2171 if (entry.value.tag == .import) continue;
2172
2135 for (self.got_entries.items) |sym| {
2136 if (sym.@"type" == .proxy) continue;
21732137 try pointers.append(.{
2174 .offset = base_offset + entry.value.index * @sizeOf(u64),
2138 .offset = base_offset + sym.got_index.? * @sizeOf(u64),
21752139 .segment_id = segment_id,
21762140 });
21772141 }
21782142 }
21792143
21802144 if (self.mod_init_func_section_index) |idx| {
2181 // TODO audit and investigate this.
21822145 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
21832146 const sect = seg.sections.items[idx];
21842147 const base_offset = sect.addr - seg.inner.vmaddr;
......@@ -2202,10 +2165,10 @@ fn writeRebaseInfoTable(self: *Zld) !void {
22022165 const base_offset = sect.addr - seg.inner.vmaddr;
22032166 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);
22042167
2205 try pointers.ensureCapacity(pointers.items.len + self.stubs.items().len);
2206 for (self.stubs.items()) |entry| {
2168 try pointers.ensureCapacity(pointers.items.len + self.stubs.items.len);
2169 for (self.stubs.items) |sym| {
22072170 pointers.appendAssumeCapacity(.{
2208 .offset = base_offset + entry.value * @sizeOf(u64),
2171 .offset = base_offset + sym.stubs_index.? * @sizeOf(u64),
22092172 .segment_id = segment_id,
22102173 });
22112174 }
......@@ -2226,7 +2189,7 @@ fn writeRebaseInfoTable(self: *Zld) !void {
22262189 dyld_info.rebase_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @sizeOf(u64)));
22272190 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
22312194 try self.file.?.pwriteAll(buffer, dyld_info.rebase_off);
22322195}
......@@ -2241,21 +2204,16 @@ fn writeBindInfoTable(self: *Zld) !void {
22412204 const base_offset = sect.addr - seg.inner.vmaddr;
22422205 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
22432206
2244 for (self.got_entries.items()) |entry| {
2245 if (entry.value.tag == .local) continue;
2246
2247 const dylib_ordinal = dylib_ordinal: {
2248 const sym = self.symtab.get(entry.key) orelse continue; // local indirection
2249 if (sym.tag != .import) continue; // local indirection
2250 break :dylib_ordinal sym.file.? + 1;
2251 };
2252
2253 try pointers.append(.{
2254 .offset = base_offset + entry.value.index * @sizeOf(u64),
2255 .segment_id = segment_id,
2256 .dylib_ordinal = dylib_ordinal,
2257 .name = entry.key,
2258 });
2207 for (self.got_entries.items) |sym| {
2208 if (sym.cast(Symbol.Proxy)) |proxy| {
2209 const dylib_ordinal = proxy.dylib + 1;
2210 try pointers.append(.{
2211 .offset = base_offset + proxy.base.got_index.? * @sizeOf(u64),
2212 .segment_id = segment_id,
2213 .dylib_ordinal = dylib_ordinal,
2214 .name = proxy.base.name,
2215 });
2216 }
22592217 }
22602218 }
22612219
......@@ -2265,14 +2223,15 @@ fn writeBindInfoTable(self: *Zld) !void {
22652223 const base_offset = sect.addr - seg.inner.vmaddr;
22662224 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);
22672225
2268 const sym = self.symtab.get("__tlv_bootstrap") orelse unreachable;
2269 const dylib_ordinal = sym.file.? + 1;
2226 const sym = self.imports.get("__tlv_bootstrap") orelse unreachable;
2227 const proxy = sym.cast(Symbol.Proxy) orelse unreachable;
2228 const dylib_ordinal = proxy.dylib + 1;
22702229
22712230 try pointers.append(.{
22722231 .offset = base_offset,
22732232 .segment_id = segment_id,
22742233 .dylib_ordinal = dylib_ordinal,
2275 .name = "__tlv_bootstrap",
2234 .name = proxy.base.name,
22762235 });
22772236 }
22782237
......@@ -2289,7 +2248,7 @@ fn writeBindInfoTable(self: *Zld) !void {
22892248 dyld_info.bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
22902249 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
22942253 try self.file.?.pwriteAll(buffer, dyld_info.bind_off);
22952254}
......@@ -2304,20 +2263,16 @@ fn writeLazyBindInfoTable(self: *Zld) !void {
23042263 const base_offset = sect.addr - seg.inner.vmaddr;
23052264 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);
23062265
2307 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 };
2266 try pointers.ensureCapacity(self.stubs.items.len);
23152267
2268 for (self.stubs.items) |sym| {
2269 const proxy = sym.cast(Symbol.Proxy) orelse unreachable;
2270 const dylib_ordinal = proxy.dylib + 1;
23162271 pointers.appendAssumeCapacity(.{
2317 .offset = base_offset + entry.value * @sizeOf(u64),
2272 .offset = base_offset + sym.stubs_index.? * @sizeOf(u64),
23182273 .segment_id = segment_id,
23192274 .dylib_ordinal = dylib_ordinal,
2320 .name = entry.key,
2275 .name = sym.name,
23212276 });
23222277 }
23232278 }
......@@ -2335,7 +2290,7 @@ fn writeLazyBindInfoTable(self: *Zld) !void {
23352290 dyld_info.lazy_bind_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
23362291 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
23402295 try self.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);
23412296 try self.populateLazyBindOffsetsInStubHelper(buffer);
......@@ -2386,7 +2341,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void {
23862341 else => {},
23872342 }
23882343 }
2389 assert(self.stubs.items().len <= offsets.items.len);
2344 assert(self.stubs.items.len <= offsets.items.len);
23902345
23912346 const stub_size: u4 = switch (self.arch.?) {
23922347 .x86_64 => 10,
......@@ -2399,9 +2354,10 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void {
23992354 else => unreachable,
24002355 };
24012356 var buf: [@sizeOf(u32)]u8 = undefined;
2402 for (self.stubs.items()) |entry| {
2403 const placeholder_off = self.stub_helper_stubs_start_off.? + entry.value * stub_size + off;
2404 mem.writeIntLittle(u32, &buf, offsets.items[entry.value]);
2357 for (self.stubs.items) |sym| {
2358 const index = sym.stubs_index orelse unreachable;
2359 const placeholder_off = self.stub_helper_stubs_start_off.? + index * stub_size + off;
2360 mem.writeIntLittle(u32, &buf, offsets.items[index]);
24052361 try self.file.?.pwriteAll(&buf, placeholder_off);
24062362 }
24072363}
......@@ -2413,12 +2369,13 @@ fn writeExportInfo(self: *Zld) !void {
24132369 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
24142370
24152371 // TODO export items for dylibs
2416 const sym = self.symtab.get("_main") orelse return error.MissingMainEntrypoint;
2417 assert(sym.address >= text_segment.inner.vmaddr);
2372 const sym = self.globals.get("_main") orelse return error.MissingMainEntrypoint;
2373 const reg = sym.cast(Symbol.Regular) orelse unreachable;
2374 assert(reg.address >= text_segment.inner.vmaddr);
24182375
24192376 try trie.put(.{
2420 .name = "_main",
2421 .vmaddr_offset = sym.address - text_segment.inner.vmaddr,
2377 .name = sym.name,
2378 .vmaddr_offset = reg.address - text_segment.inner.vmaddr,
24222379 .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR,
24232380 });
24242381
......@@ -2437,7 +2394,7 @@ fn writeExportInfo(self: *Zld) !void {
24372394 dyld_info.export_size = @intCast(u32, mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64)));
24382395 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
24422399 try self.file.?.pwriteAll(buffer, dyld_info.export_off);
24432400}
......@@ -2446,7 +2403,7 @@ fn writeDebugInfo(self: *Zld) !void {
24462403 var stabs = std.ArrayList(macho.nlist_64).init(self.allocator);
24472404 defer stabs.deinit();
24482405
2449 for (self.objects.items) |object, object_id| {
2406 for (self.objects.items) |object| {
24502407 const tu_path = object.tu_path orelse continue;
24512408 const tu_mtime = object.tu_mtime orelse continue;
24522409 const dirname = std.fs.path.dirname(tu_path) orelse "./";
......@@ -2475,39 +2432,42 @@ fn writeDebugInfo(self: *Zld) !void {
24752432 .n_value = 0, //tu_mtime, TODO figure out why precalculated mtime value doesn't work
24762433 });
24772434
2478 for (object.stabs.items) |stab| {
2479 const entry = object.locals.items()[stab.symbol];
2480 const sym = entry.value;
2435 for (object.symbols.items) |sym| {
2436 if (sym.@"type" != .regular) continue;
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) {
24832443 .function => {
24842444 try stabs.append(.{
24852445 .n_strx = 0,
24862446 .n_type = macho.N_BNSYM,
2487 .n_sect = sym.section,
2447 .n_sect = reg.section,
24882448 .n_desc = 0,
2489 .n_value = sym.address,
2449 .n_value = reg.address,
24902450 });
24912451 try stabs.append(.{
24922452 .n_strx = try self.makeString(sym.name),
24932453 .n_type = macho.N_FUN,
2494 .n_sect = sym.section,
2454 .n_sect = reg.section,
24952455 .n_desc = 0,
2496 .n_value = sym.address,
2456 .n_value = reg.address,
24972457 });
24982458 try stabs.append(.{
24992459 .n_strx = 0,
25002460 .n_type = macho.N_FUN,
25012461 .n_sect = 0,
25022462 .n_desc = 0,
2503 .n_value = stab.size.?,
2463 .n_value = stab.size,
25042464 });
25052465 try stabs.append(.{
25062466 .n_strx = 0,
25072467 .n_type = macho.N_ENSYM,
2508 .n_sect = sym.section,
2468 .n_sect = reg.section,
25092469 .n_desc = 0,
2510 .n_value = stab.size.?,
2470 .n_value = stab.size,
25112471 });
25122472 },
25132473 .global => {
......@@ -2523,9 +2483,9 @@ fn writeDebugInfo(self: *Zld) !void {
25232483 try stabs.append(.{
25242484 .n_strx = try self.makeString(sym.name),
25252485 .n_type = macho.N_STSYM,
2526 .n_sect = sym.section,
2486 .n_sect = reg.section,
25272487 .n_desc = 0,
2528 .n_value = sym.address,
2488 .n_value = reg.address,
25292489 });
25302490 },
25312491 }
......@@ -2551,7 +2511,7 @@ fn writeDebugInfo(self: *Zld) !void {
25512511
25522512 const stabs_off = symtab.symoff;
25532513 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 });
25552515 try self.file.?.pwriteAll(mem.sliceAsBytes(stabs.items), stabs_off);
25562516
25572517 linkedit.inner.filesize += stabs_size;
......@@ -2561,27 +2521,6 @@ fn writeDebugInfo(self: *Zld) !void {
25612521 dysymtab.nlocalsym = symtab.nsyms;
25622522}
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
25852524fn writeSymbolTable(self: *Zld) !void {
25862525 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
25872526 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
......@@ -2589,56 +2528,52 @@ fn writeSymbolTable(self: *Zld) !void {
25892528 var locals = std.ArrayList(macho.nlist_64).init(self.allocator);
25902529 defer locals.deinit();
25912530
2531 var exports = std.ArrayList(macho.nlist_64).init(self.allocator);
2532 defer exports.deinit();
2533
25922534 for (self.objects.items) |object| {
2593 for (object.locals.items()) |entry| {
2594 const sym = entry.value;
2595 if (sym.tag != .local) continue;
2596
2597 try locals.append(.{
2598 .n_strx = try self.makeString(sym.name),
2599 .n_type = macho.N_SECT,
2600 .n_sect = sym.section,
2601 .n_desc = 0,
2602 .n_value = sym.address,
2603 });
2535 for (object.symbols.items) |sym| {
2536 const final = sym.getTopmostAlias();
2537 if (final.@"type" != .regular) continue;
2538
2539 const reg = final.cast(Symbol.Regular) orelse unreachable;
2540 if (reg.isTemp()) continue;
2541
2542 switch (reg.linkage) {
2543 .translation_unit => {
2544 try locals.append(.{
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 }
26042562 }
26052563 }
26062564
2607 var exports = std.ArrayList(macho.nlist_64).init(self.allocator);
2608 defer exports.deinit();
2609
26102565 var undefs = std.ArrayList(macho.nlist_64).init(self.allocator);
26112566 defer undefs.deinit();
26122567
2613 var undefs_ids = std.StringHashMap(u32).init(self.allocator);
2614 defer undefs_ids.deinit();
2615
2616 var undef_id: u32 = 0;
2617 for (self.symtab.items()) |entry| {
2568 for (self.imports.items()) |entry| {
26182569 const sym = entry.value;
2619 switch (sym.tag) {
2620 .weak, .strong => {
2621 try exports.append(.{
2622 .n_strx = try self.makeString(sym.name),
2623 .n_type = macho.N_SECT | macho.N_EXT,
2624 .n_sect = sym.section,
2625 .n_desc = 0,
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 }
2570 try undefs.append(.{
2571 .n_strx = try self.makeString(sym.name),
2572 .n_type = macho.N_UNDF | macho.N_EXT,
2573 .n_sect = 0,
2574 .n_desc = macho.N_SYMBOL_RESOLVER | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY,
2575 .n_value = 0,
2576 });
26422577 }
26432578
26442579 const nlocals = locals.items.len;
......@@ -2647,17 +2582,17 @@ fn writeSymbolTable(self: *Zld) !void {
26472582
26482583 const locals_off = symtab.symoff + symtab.nsyms * @sizeOf(macho.nlist_64);
26492584 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 });
26512586 try self.file.?.pwriteAll(mem.sliceAsBytes(locals.items), locals_off);
26522587
26532588 const exports_off = locals_off + locals_size;
26542589 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 });
26562591 try self.file.?.pwriteAll(mem.sliceAsBytes(exports.items), exports_off);
26572592
26582593 const undefs_off = exports_off + exports_size;
26592594 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 });
26612596 try self.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off);
26622597
26632598 symtab.nsyms += @intCast(u32, nlocals + nexports + nundefs);
......@@ -2678,8 +2613,8 @@ fn writeSymbolTable(self: *Zld) !void {
26782613 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
26792614 const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?];
26802615
2681 const nstubs = @intCast(u32, self.stubs.items().len);
2682 const ngot_entries = @intCast(u32, self.got_entries.items().len);
2616 const nstubs = @intCast(u32, self.stubs.items.len);
2617 const ngot_entries = @intCast(u32, self.got_entries.items.len);
26832618
26842619 dysymtab.indirectsymoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);
26852620 dysymtab.nindirectsyms = nstubs * 2 + ngot_entries;
......@@ -2687,7 +2622,7 @@ fn writeSymbolTable(self: *Zld) !void {
26872622 const needed_size = dysymtab.nindirectsyms * @sizeOf(u32);
26882623 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}", .{
26912626 dysymtab.indirectsymoff,
26922627 dysymtab.indirectsymoff + needed_size,
26932628 });
......@@ -2699,25 +2634,25 @@ fn writeSymbolTable(self: *Zld) !void {
26992634 var writer = stream.writer();
27002635
27012636 stubs.reserved1 = 0;
2702 for (self.stubs.items()) |entry| {
2703 const id = undefs_ids.get(entry.key) orelse unreachable;
2704 try writer.writeIntLittle(u32, dysymtab.iundefsym + id);
2637 for (self.stubs.items) |sym| {
2638 const id = self.imports.getIndex(sym.name) orelse unreachable;
2639 try writer.writeIntLittle(u32, dysymtab.iundefsym + @intCast(u32, id));
27052640 }
27062641
27072642 got.reserved1 = nstubs;
2708 for (self.got_entries.items()) |entry| {
2709 if (entry.value.tag == .import) {
2710 const id = undefs_ids.get(entry.key) orelse unreachable;
2711 try writer.writeIntLittle(u32, dysymtab.iundefsym + id);
2643 for (self.got_entries.items) |sym| {
2644 if (sym.@"type" == .proxy) {
2645 const id = self.imports.getIndex(sym.name) orelse unreachable;
2646 try writer.writeIntLittle(u32, dysymtab.iundefsym + @intCast(u32, id));
27122647 } else {
27132648 try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL);
27142649 }
27152650 }
27162651
27172652 la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries;
2718 for (self.stubs.items()) |entry| {
2719 const id = undefs_ids.get(entry.key) orelse unreachable;
2720 try writer.writeIntLittle(u32, dysymtab.iundefsym + id);
2653 for (self.stubs.items) |sym| {
2654 const id = self.imports.getIndex(sym.name) orelse unreachable;
2655 try writer.writeIntLittle(u32, dysymtab.iundefsym + @intCast(u32, id));
27212656 }
27222657
27232658 try self.file.?.pwriteAll(buf, dysymtab.indirectsymoff);
......@@ -2730,7 +2665,7 @@ fn writeStringTable(self: *Zld) !void {
27302665 symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64)));
27312666 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
27352670 try self.file.?.pwriteAll(self.strtab.items, symtab.stroff);
27362671
......@@ -2776,7 +2711,7 @@ fn writeDataInCode(self: *Zld) !void {
27762711 dice_cmd.datasize = datasize;
27772712 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
27812716 try self.file.?.pwriteAll(buf.items, fileoff);
27822717}
......@@ -2797,7 +2732,7 @@ fn writeCodeSignaturePadding(self: *Zld) !void {
27972732 seg.inner.filesize += needed_size;
27982733 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
28022737 // Pad out the space. We need to do this to calculate valid hashes for everything in the file
28032738 // except for code signature data.
......@@ -2823,7 +2758,7 @@ fn writeCodeSignature(self: *Zld) !void {
28232758 var stream = std.io.fixedBufferStream(buffer);
28242759 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 });
28272762 try self.file.?.pwriteAll(buffer, code_sig_cmd.dataoff);
28282763}
28292764
......@@ -2841,7 +2776,7 @@ fn writeLoadCommands(self: *Zld) !void {
28412776 }
28422777
28432778 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 });
28452780 try self.file.?.pwriteAll(buffer, off);
28462781}
28472782
......@@ -2879,7 +2814,7 @@ fn writeHeader(self: *Zld) !void {
28792814 for (self.load_commands.items) |cmd| {
28802815 header.sizeofcmds += cmd.cmdsize();
28812816 }
2882 log.debug("writing Mach-O header {}", .{header});
2817 log.warn("writing Mach-O header {}", .{header});
28832818 try self.file.?.pwriteAll(mem.asBytes(&header), 0);
28842819}
28852820
......@@ -2892,13 +2827,13 @@ pub fn makeStaticString(bytes: []const u8) [16]u8 {
28922827
28932828fn makeString(self: *Zld, bytes: []const u8) !u32 {
28942829 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 });
28962831 return offset;
28972832 }
28982833
28992834 try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1);
29002835 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 });
29022837 self.strtab.appendSliceAssumeCapacity(bytes);
29032838 self.strtab.appendAssumeCapacity(0);
29042839 try self.strtab_dir.putNoClobber(self.allocator, try self.allocator.dupe(u8, bytes), offset);