| ... | @@ -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 { |
| 2232 | fn makeString(self: *MachO, bytes: []const u8) !u32 { | 2232 | fn 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 | } |
| 2272 | | 2275 | |
| ... | @@ -2639,6 +2642,11 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void { | ... | @@ -2639,6 +2642,11 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void { |
| 2639 | } | 2642 | } |
| 2640 | | 2643 | |
| 2641 | fn writeIndirectSymbolTable(self: *MachO) !void { | 2644 | fn 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. | | |
| 2651 | | 2657 | |
| 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(); |
| 2654 | | 2678 | |
| 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 | } |
| 2663 | | 2684 | |
| 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 | } |
| 2673 | | 2691 | |
| 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 | } |
| 2683 | | 2701 | |
| 2684 | fn writeCodeSignaturePadding(self: *MachO) !void { | 2702 | fn 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(); |
| 2687 | | 2706 | |
| ... | @@ -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 | ); |
| 2696 | | 2715 | 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 |
| 2700 | | 2719 | linkedit_segment.inner.filesize += needed_size; |
| 2701 | // Advance size of __LINKEDIT segment | 2720 | 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 file | 2726 | 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 | } |
| 2713 | | 2729 | |
| 2714 | fn writeCodeSignature(self: *MachO) !void { | 2730 | fn writeCodeSignature(self: *MachO) !void { |