authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-01-19 08:58:51+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-01-19 08:58:51+01:00
logd5b0a963d1bf3399e3d8b63b03ea61f7d771adbd
tree4ae07939bc49274fb769cf91416ee002c8b66ebf
parent30a824cb9e148adb0799a0a81721160c0d474b50
parenta2ebe3c82c89084a3672593cb34f259fca5a5e30
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #7818 from kubkon/macho-more-cleanup

Macho more cleanup

3 files changed, 59 insertions(+), 39 deletions(-)

src/Module.zig+4-2
...@@ -1617,8 +1617,10 @@ pub fn analyzeContainer(self: *Module, container_scope: *Scope.Container) !void...@@ -1617,8 +1617,10 @@ pub fn analyzeContainer(self: *Module, container_scope: *Scope.Container) !void
1617 // in `Decl` to notice that the line number did not change.1617 // in `Decl` to notice that the line number did not change.
1618 self.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });1618 self.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });
1619 },1619 },
1620 .macho => {1620 .macho => if (decl.fn_link.macho.len != 0) {
1621 // TODO Implement for MachO1621 // TODO Look into detecting when this would be unnecessary by storing enough state
1622 // in `Decl` to notice that the line number did not change.
1623 self.comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl });
1622 },1624 },
1623 .c, .wasm => {},1625 .c, .wasm => {},
1624 }1626 }
src/link/MachO.zig+51-35
...@@ -2232,6 +2232,7 @@ pub fn makeStaticString(comptime bytes: []const u8) [16]u8 {...@@ -2232,6 +2232,7 @@ pub fn makeStaticString(comptime bytes: []const u8) [16]u8 {
2232fn makeString(self: *MachO, bytes: []const u8) !u32 {2232fn makeString(self: *MachO, bytes: []const u8) !u32 {
2233 try self.string_table.ensureCapacity(self.base.allocator, self.string_table.items.len + bytes.len + 1);2233 try self.string_table.ensureCapacity(self.base.allocator, self.string_table.items.len + bytes.len + 1);
2234 const offset = @intCast(u32, self.string_table.items.len);2234 const offset = @intCast(u32, self.string_table.items.len);
2235 log.debug("writing '{s}' into the string table at offset 0x{x}", .{ bytes, offset });
2235 self.string_table.appendSliceAssumeCapacity(bytes);2236 self.string_table.appendSliceAssumeCapacity(bytes);
2236 self.string_table.appendAssumeCapacity(0);2237 self.string_table.appendAssumeCapacity(0);
2237 self.string_table_dirty = true;2238 self.string_table_dirty = true;
...@@ -2257,6 +2258,7 @@ pub fn addExternSymbol(self: *MachO, name: []const u8) !u32 {...@@ -2257,6 +2258,7 @@ pub fn addExternSymbol(self: *MachO, name: []const u8) !u32 {
2257 const index = @intCast(u32, self.extern_lazy_symbols.items().len);2258 const index = @intCast(u32, self.extern_lazy_symbols.items().len);
2258 const offset = try self.makeString(name);2259 const offset = try self.makeString(name);
2259 const sym_name = try self.base.allocator.dupe(u8, name);2260 const sym_name = try self.base.allocator.dupe(u8, name);
2261 const dylib_ordinal = 1; // TODO this is now hardcoded, since we only support libSystem.
2260 try self.extern_lazy_symbols.putNoClobber(self.base.allocator, sym_name, .{2262 try self.extern_lazy_symbols.putNoClobber(self.base.allocator, sym_name, .{
2261 .inner = .{2263 .inner = .{
2262 .n_strx = offset,2264 .n_strx = offset,
...@@ -2265,8 +2267,9 @@ pub fn addExternSymbol(self: *MachO, name: []const u8) !u32 {...@@ -2265,8 +2267,9 @@ pub fn addExternSymbol(self: *MachO, name: []const u8) !u32 {
2265 .n_desc = macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | macho.N_SYMBOL_RESOLVER,2267 .n_desc = macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | macho.N_SYMBOL_RESOLVER,
2266 .n_value = 0,2268 .n_value = 0,
2267 },2269 },
2268 .dylib_ordinal = 1, // TODO this is now hardcoded, since we only support libSystem.2270 .dylib_ordinal = dylib_ordinal,
2269 });2271 });
2272 log.debug("adding new extern symbol '{s}' with dylib ordinal '{}'", .{ name, dylib_ordinal });
2270 return index;2273 return index;
2271}2274}
22722275
...@@ -2639,6 +2642,11 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void {...@@ -2639,6 +2642,11 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void {
2639}2642}
26402643
2641fn writeIndirectSymbolTable(self: *MachO) !void {2644fn writeIndirectSymbolTable(self: *MachO) !void {
2645 // TODO figure out a way not to rewrite the table every time if
2646 // no new undefs are not added.
2647 const tracy = trace(@src());
2648 defer tracy.end();
2649
2642 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;2650 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2643 const stubs = &text_segment.sections.items[self.stubs_section_index.?];2651 const stubs = &text_segment.sections.items[self.stubs_section_index.?];
2644 const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;2652 const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
...@@ -2646,42 +2654,53 @@ fn writeIndirectSymbolTable(self: *MachO) !void {...@@ -2646,42 +2654,53 @@ fn writeIndirectSymbolTable(self: *MachO) !void {
2646 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;2654 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2647 const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?];2655 const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?];
2648 const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;2656 const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
2649 dysymtab.nindirectsyms = 0;
2650 // TODO check if we have allocated enough size.
26512657
2652 var buf: [@sizeOf(u32)]u8 = undefined;2658 const lazy = self.extern_lazy_symbols.items();
2653 var off = dysymtab.indirectsymoff;2659 const nonlazy = self.extern_nonlazy_symbols.items();
2660 const allocated_size = self.allocatedSizeLinkedit(dysymtab.indirectsymoff);
2661 const nindirectsyms = @intCast(u32, lazy.len * 2 + nonlazy.len);
2662 const needed_size = @intCast(u32, nindirectsyms * @sizeOf(u32));
2663
2664 if (needed_size > allocated_size) {
2665 dysymtab.nindirectsyms = 0;
2666 dysymtab.indirectsymoff = @intCast(u32, self.findFreeSpaceLinkedit(needed_size, @sizeOf(u32), null));
2667 }
2668 dysymtab.nindirectsyms = nindirectsyms;
2669 log.debug("writing indirect symbol table from 0x{x} to 0x{x}", .{
2670 dysymtab.indirectsymoff,
2671 dysymtab.indirectsymoff + needed_size,
2672 });
2673
2674 var buf = try self.base.allocator.alloc(u8, needed_size);
2675 defer self.base.allocator.free(buf);
2676 var stream = std.io.fixedBufferStream(buf);
2677 var writer = stream.writer();
26542678
2655 stubs.reserved1 = 0;2679 stubs.reserved1 = 0;
2656 for (self.extern_lazy_symbols.items()) |_, i| {2680 for (self.extern_lazy_symbols.items()) |_, i| {
2657 const symtab_idx = @intCast(u32, dysymtab.iundefsym + i);2681 const symtab_idx = @intCast(u32, dysymtab.iundefsym + i);
2658 mem.writeIntLittle(u32, &buf, symtab_idx);2682 try writer.writeIntLittle(u32, symtab_idx);
2659 try self.base.file.?.pwriteAll(&buf, off);
2660 off += @sizeOf(u32);
2661 dysymtab.nindirectsyms += 1;
2662 }2683 }
26632684
2664 const base_id = @intCast(u32, self.extern_lazy_symbols.items().len);2685 const base_id = @intCast(u32, lazy.len);
2665 got.reserved1 = base_id;2686 got.reserved1 = base_id;
2666 for (self.extern_nonlazy_symbols.items()) |_, i| {2687 for (self.extern_nonlazy_symbols.items()) |_, i| {
2667 const symtab_idx = @intCast(u32, dysymtab.iundefsym + i + base_id);2688 const symtab_idx = @intCast(u32, dysymtab.iundefsym + i + base_id);
2668 mem.writeIntLittle(u32, &buf, symtab_idx);2689 try writer.writeIntLittle(u32, symtab_idx);
2669 try self.base.file.?.pwriteAll(&buf, off);
2670 off += @sizeOf(u32);
2671 dysymtab.nindirectsyms += 1;
2672 }2690 }
26732691
2674 la_symbol_ptr.reserved1 = got.reserved1 + @intCast(u32, self.extern_nonlazy_symbols.items().len);2692 la_symbol_ptr.reserved1 = got.reserved1 + @intCast(u32, nonlazy.len);
2675 for (self.extern_lazy_symbols.items()) |_, i| {2693 for (self.extern_lazy_symbols.items()) |_, i| {
2676 const symtab_idx = @intCast(u32, dysymtab.iundefsym + i);2694 const symtab_idx = @intCast(u32, dysymtab.iundefsym + i);
2677 mem.writeIntLittle(u32, &buf, symtab_idx);2695 try writer.writeIntLittle(u32, symtab_idx);
2678 try self.base.file.?.pwriteAll(&buf, off);
2679 off += @sizeOf(u32);
2680 dysymtab.nindirectsyms += 1;
2681 }2696 }
2697
2698 try self.base.file.?.pwriteAll(buf, dysymtab.indirectsymoff);
2699 self.load_commands_dirty = true;
2682}2700}
26832701
2684fn writeCodeSignaturePadding(self: *MachO) !void {2702fn writeCodeSignaturePadding(self: *MachO) !void {
2703 // TODO figure out how not to rewrite padding every single time.
2685 const tracy = trace(@src());2704 const tracy = trace(@src());
2686 defer tracy.end();2705 defer tracy.end();
26872706
...@@ -2693,22 +2712,19 @@ fn writeCodeSignaturePadding(self: *MachO) !void {...@@ -2693,22 +2712,19 @@ fn writeCodeSignaturePadding(self: *MachO) !void {
2693 fileoff,2712 fileoff,
2694 self.page_size,2713 self.page_size,
2695 );2714 );
26962715 code_sig_cmd.dataoff = @intCast(u32, fileoff);
2697 if (code_sig_cmd.datasize < needed_size) {2716 code_sig_cmd.datasize = needed_size;
2698 code_sig_cmd.dataoff = @intCast(u32, fileoff);2717
2699 code_sig_cmd.datasize = needed_size;2718 // Advance size of __LINKEDIT segment
27002719 linkedit_segment.inner.filesize += needed_size;
2701 // Advance size of __LINKEDIT segment2720 if (linkedit_segment.inner.vmsize < linkedit_segment.inner.filesize) {
2702 linkedit_segment.inner.filesize += needed_size;2721 linkedit_segment.inner.vmsize = mem.alignForwardGeneric(u64, linkedit_segment.inner.filesize, self.page_size);
2703 if (linkedit_segment.inner.vmsize < linkedit_segment.inner.filesize) {2722 }
2704 linkedit_segment.inner.vmsize = mem.alignForwardGeneric(u64, linkedit_segment.inner.filesize, self.page_size);2723 log.debug("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size });
2705 }2724 // Pad out the space. We need to do this to calculate valid hashes for everything in the file
2706 log.debug("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size });2725 // except for code signature data.
2707 // Pad out the space. We need to do this to calculate valid hashes for everything in the file2726 try self.base.file.?.pwriteAll(&[_]u8{0}, fileoff + needed_size - 1);
2708 // except for code signature data.2727 self.load_commands_dirty = true;
2709 try self.base.file.?.pwriteAll(&[_]u8{0}, fileoff + needed_size - 1);
2710 self.load_commands_dirty = true;
2711 }
2712}2728}
27132729
2714fn writeCodeSignature(self: *MachO) !void {2730fn writeCodeSignature(self: *MachO) !void {
src/link/MachO/DebugSymbols.zig+4-2
...@@ -1079,7 +1079,8 @@ pub fn commitDeclDebugInfo(...@@ -1079,7 +1079,8 @@ pub fn commitDeclDebugInfo(
1079 const debug_line_sect = &dwarf_segment.sections.items[self.debug_line_section_index.?];1079 const debug_line_sect = &dwarf_segment.sections.items[self.debug_line_section_index.?];
1080 const src_fn = &decl.fn_link.macho;1080 const src_fn = &decl.fn_link.macho;
1081 src_fn.len = @intCast(u32, dbg_line_buffer.items.len);1081 src_fn.len = @intCast(u32, dbg_line_buffer.items.len);
1082 if (self.dbg_line_fn_last) |last| {1082 if (self.dbg_line_fn_last) |last| blk: {
1083 if (src_fn == last) break :blk;
1083 if (src_fn.next) |next| {1084 if (src_fn.next) |next| {
1084 // Update existing function - non-last item.1085 // Update existing function - non-last item.
1085 if (src_fn.off + src_fn.len + min_nop_size > next.off) {1086 if (src_fn.off + src_fn.len + min_nop_size > next.off) {
...@@ -1238,7 +1239,8 @@ fn updateDeclDebugInfoAllocation(...@@ -1238,7 +1239,8 @@ fn updateDeclDebugInfoAllocation(
1238 const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;1239 const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
1239 const debug_info_sect = &dwarf_segment.sections.items[self.debug_info_section_index.?];1240 const debug_info_sect = &dwarf_segment.sections.items[self.debug_info_section_index.?];
1240 text_block.dbg_info_len = len;1241 text_block.dbg_info_len = len;
1241 if (self.dbg_info_decl_last) |last| {1242 if (self.dbg_info_decl_last) |last| blk: {
1243 if (text_block == last) break :blk;
1242 if (text_block.dbg_info_next) |next| {1244 if (text_block.dbg_info_next) |next| {
1243 // Update existing Decl - non-last item.1245 // Update existing Decl - non-last item.
1244 if (text_block.dbg_info_off + text_block.dbg_info_len + min_nop_size > next.dbg_info_off) {1246 if (text_block.dbg_info_off + text_block.dbg_info_len + min_nop_size > next.dbg_info_off) {