| ... | ... | @@ -2232,6 +2232,7 @@ pub fn makeStaticString(comptime bytes: []const u8) [16]u8 { |
| 2232 | 2232 | fn makeString(self: *MachO, bytes: []const u8) !u32 { |
| 2233 | 2233 | try self.string_table.ensureCapacity(self.base.allocator, self.string_table.items.len + bytes.len + 1); |
| 2234 | 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 | 2236 | self.string_table.appendSliceAssumeCapacity(bytes); |
| 2236 | 2237 | self.string_table.appendAssumeCapacity(0); |
| 2237 | 2238 | self.string_table_dirty = true; |
| ... | ... | @@ -2257,6 +2258,7 @@ pub fn addExternSymbol(self: *MachO, name: []const u8) !u32 { |
| 2257 | 2258 | const index = @intCast(u32, self.extern_lazy_symbols.items().len); |
| 2258 | 2259 | const offset = try self.makeString(name); |
| 2259 | 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 | 2262 | try self.extern_lazy_symbols.putNoClobber(self.base.allocator, sym_name, .{ |
| 2261 | 2263 | .inner = .{ |
| 2262 | 2264 | .n_strx = offset, |
| ... | ... | @@ -2265,8 +2267,9 @@ pub fn addExternSymbol(self: *MachO, name: []const u8) !u32 { |
| 2265 | 2267 | .n_desc = macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY | macho.N_SYMBOL_RESOLVER, |
| 2266 | 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 | 2273 | return index; |
| 2271 | 2274 | } |
| 2272 | 2275 | |
| ... | ... | @@ -2639,6 +2642,11 @@ fn writeAllGlobalAndUndefSymbols(self: *MachO) !void { |
| 2639 | 2642 | } |
| 2640 | 2643 | |
| 2641 | 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 | 2650 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 2643 | 2651 | const stubs = &text_segment.sections.items[self.stubs_section_index.?]; |
| 2644 | 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 | 2654 | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 2647 | 2655 | const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?]; |
| 2648 | 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; |
| 2653 | | var off = dysymtab.indirectsymoff; |
| 2658 | const lazy = self.extern_lazy_symbols.items(); |
| 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 | 2679 | stubs.reserved1 = 0; |
| 2656 | 2680 | for (self.extern_lazy_symbols.items()) |_, i| { |
| 2657 | 2681 | const symtab_idx = @intCast(u32, dysymtab.iundefsym + i); |
| 2658 | | mem.writeIntLittle(u32, &buf, symtab_idx); |
| 2659 | | try self.base.file.?.pwriteAll(&buf, off); |
| 2660 | | off += @sizeOf(u32); |
| 2661 | | dysymtab.nindirectsyms += 1; |
| 2682 | try writer.writeIntLittle(u32, symtab_idx); |
| 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 | 2686 | got.reserved1 = base_id; |
| 2666 | 2687 | for (self.extern_nonlazy_symbols.items()) |_, i| { |
| 2667 | 2688 | const symtab_idx = @intCast(u32, dysymtab.iundefsym + i + base_id); |
| 2668 | | mem.writeIntLittle(u32, &buf, symtab_idx); |
| 2669 | | try self.base.file.?.pwriteAll(&buf, off); |
| 2670 | | off += @sizeOf(u32); |
| 2671 | | dysymtab.nindirectsyms += 1; |
| 2689 | try writer.writeIntLittle(u32, symtab_idx); |
| 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 | 2693 | for (self.extern_lazy_symbols.items()) |_, i| { |
| 2676 | 2694 | const symtab_idx = @intCast(u32, dysymtab.iundefsym + i); |
| 2677 | | mem.writeIntLittle(u32, &buf, symtab_idx); |
| 2678 | | try self.base.file.?.pwriteAll(&buf, off); |
| 2679 | | off += @sizeOf(u32); |
| 2680 | | dysymtab.nindirectsyms += 1; |
| 2695 | try writer.writeIntLittle(u32, symtab_idx); |
| 2681 | 2696 | } |
| 2697 | |
| 2698 | try self.base.file.?.pwriteAll(buf, dysymtab.indirectsymoff); |
| 2699 | self.load_commands_dirty = true; |
| 2682 | 2700 | } |
| 2683 | 2701 | |
| 2684 | 2702 | fn writeCodeSignaturePadding(self: *MachO) !void { |
| 2703 | // TODO figure out how not to rewrite padding every single time. |
| 2685 | 2704 | const tracy = trace(@src()); |
| 2686 | 2705 | defer tracy.end(); |
| 2687 | 2706 | |
| ... | ... | @@ -2693,22 +2712,19 @@ fn writeCodeSignaturePadding(self: *MachO) !void { |
| 2693 | 2712 | fileoff, |
| 2694 | 2713 | self.page_size, |
| 2695 | 2714 | ); |
| 2696 | | |
| 2697 | | if (code_sig_cmd.datasize < needed_size) { |
| 2698 | | code_sig_cmd.dataoff = @intCast(u32, fileoff); |
| 2699 | | code_sig_cmd.datasize = needed_size; |
| 2700 | | |
| 2701 | | // Advance size of __LINKEDIT segment |
| 2702 | | linkedit_segment.inner.filesize += needed_size; |
| 2703 | | if (linkedit_segment.inner.vmsize < linkedit_segment.inner.filesize) { |
| 2704 | | linkedit_segment.inner.vmsize = mem.alignForwardGeneric(u64, linkedit_segment.inner.filesize, self.page_size); |
| 2705 | | } |
| 2706 | | log.debug("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size }); |
| 2707 | | // Pad out the space. We need to do this to calculate valid hashes for everything in the file |
| 2708 | | // except for code signature data. |
| 2709 | | try self.base.file.?.pwriteAll(&[_]u8{0}, fileoff + needed_size - 1); |
| 2710 | | self.load_commands_dirty = true; |
| 2711 | | } |
| 2715 | code_sig_cmd.dataoff = @intCast(u32, fileoff); |
| 2716 | code_sig_cmd.datasize = needed_size; |
| 2717 | |
| 2718 | // Advance size of __LINKEDIT segment |
| 2719 | linkedit_segment.inner.filesize += needed_size; |
| 2720 | if (linkedit_segment.inner.vmsize < linkedit_segment.inner.filesize) { |
| 2721 | linkedit_segment.inner.vmsize = mem.alignForwardGeneric(u64, linkedit_segment.inner.filesize, self.page_size); |
| 2722 | } |
| 2723 | log.debug("writing code signature padding from 0x{x} to 0x{x}", .{ fileoff, fileoff + needed_size }); |
| 2724 | // Pad out the space. We need to do this to calculate valid hashes for everything in the file |
| 2725 | // except for code signature data. |
| 2726 | try self.base.file.?.pwriteAll(&[_]u8{0}, fileoff + needed_size - 1); |
| 2727 | self.load_commands_dirty = true; |
| 2712 | 2728 | } |
| 2713 | 2729 | |
| 2714 | 2730 | fn writeCodeSignature(self: *MachO) !void { |