| author | |
| committer | |
| log | cc931660eb3e5b7251944c727808aa36e72c1e52 |
| tree | c6564aff1d2e77163cfce1cd8e599a187ce9274a |
| parent | 2dc6ddd7e8cfb83f5ffd57b8b40f33dde9de892d |
15 files changed, 236 insertions(+), 250 deletions(-)
lib/std/Io/Writer.zig+1| ... | @@ -2381,6 +2381,7 @@ pub fn fromArrayList(array_list: *ArrayList(u8)) Writer { | ... | @@ -2381,6 +2381,7 @@ pub fn fromArrayList(array_list: *ArrayList(u8)) Writer { |
| 2381 | .vtable = &.{ | 2381 | .vtable = &.{ |
| 2382 | .drain = fixedDrain, | 2382 | .drain = fixedDrain, |
| 2383 | .flush = noopFlush, | 2383 | .flush = noopFlush, |
| 2384 | .rebase = failingRebase, | ||
| 2384 | }, | 2385 | }, |
| 2385 | .buffer = array_list.allocatedSlice(), | 2386 | .buffer = array_list.allocatedSlice(), |
| 2386 | .end = array_list.items.len, | 2387 | .end = array_list.items.len, |
lib/std/macho.zig-2| ... | @@ -1883,10 +1883,8 @@ pub const GenericBlob = extern struct { | ... | @@ -1883,10 +1883,8 @@ pub const GenericBlob = extern struct { |
| 1883 | pub const data_in_code_entry = extern struct { | 1883 | pub const data_in_code_entry = extern struct { |
| 1884 | /// From mach_header to start of data range. | 1884 | /// From mach_header to start of data range. |
| 1885 | offset: u32, | 1885 | offset: u32, |
| 1886 | |||
| 1887 | /// Number of bytes in data range. | 1886 | /// Number of bytes in data range. |
| 1888 | length: u16, | 1887 | length: u16, |
| 1889 | |||
| 1890 | /// A DICE_KIND value. | 1888 | /// A DICE_KIND value. |
| 1891 | kind: u16, | 1889 | kind: u16, |
| 1892 | }; | 1890 | }; |
src/link/MachO.zig+65-65| ... | @@ -589,7 +589,7 @@ pub fn flush( | ... | @@ -589,7 +589,7 @@ pub fn flush( |
| 589 | ); | 589 | ); |
| 590 | 590 | ||
| 591 | const ncmds, const sizeofcmds, const uuid_cmd_offset = self.writeLoadCommands() catch |err| switch (err) { | 591 | const ncmds, const sizeofcmds, const uuid_cmd_offset = self.writeLoadCommands() catch |err| switch (err) { |
| 592 | error.NoSpaceLeft => unreachable, | 592 | error.WriteFailed => unreachable, |
| 593 | error.OutOfMemory => return error.OutOfMemory, | 593 | error.OutOfMemory => return error.OutOfMemory, |
| 594 | error.LinkFailure => return error.LinkFailure, | 594 | error.LinkFailure => return error.LinkFailure, |
| 595 | }; | 595 | }; |
| ... | @@ -1074,7 +1074,7 @@ fn accessLibPath( | ... | @@ -1074,7 +1074,7 @@ fn accessLibPath( |
| 1074 | 1074 | ||
| 1075 | for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { | 1075 | for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { |
| 1076 | test_path.clearRetainingCapacity(); | 1076 | test_path.clearRetainingCapacity(); |
| 1077 | try test_path.writer().print("{s}" ++ sep ++ "lib{s}{s}", .{ search_dir, name, ext }); | 1077 | try test_path.print("{s}" ++ sep ++ "lib{s}{s}", .{ search_dir, name, ext }); |
| 1078 | try checked_paths.append(try arena.dupe(u8, test_path.items)); | 1078 | try checked_paths.append(try arena.dupe(u8, test_path.items)); |
| 1079 | fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { | 1079 | fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { |
| 1080 | error.FileNotFound => continue, | 1080 | error.FileNotFound => continue, |
| ... | @@ -1097,7 +1097,7 @@ fn accessFrameworkPath( | ... | @@ -1097,7 +1097,7 @@ fn accessFrameworkPath( |
| 1097 | 1097 | ||
| 1098 | for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { | 1098 | for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { |
| 1099 | test_path.clearRetainingCapacity(); | 1099 | test_path.clearRetainingCapacity(); |
| 1100 | try test_path.writer().print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{ | 1100 | try test_path.print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{ |
| 1101 | search_dir, | 1101 | search_dir, |
| 1102 | name, | 1102 | name, |
| 1103 | name, | 1103 | name, |
| ... | @@ -1178,9 +1178,9 @@ fn parseDependentDylibs(self: *MachO) !void { | ... | @@ -1178,9 +1178,9 @@ fn parseDependentDylibs(self: *MachO) !void { |
| 1178 | for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { | 1178 | for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { |
| 1179 | test_path.clearRetainingCapacity(); | 1179 | test_path.clearRetainingCapacity(); |
| 1180 | if (self.base.comp.sysroot) |root| { | 1180 | if (self.base.comp.sysroot) |root| { |
| 1181 | try test_path.writer().print("{s}" ++ fs.path.sep_str ++ "{s}{s}", .{ root, path, ext }); | 1181 | try test_path.print("{s}" ++ fs.path.sep_str ++ "{s}{s}", .{ root, path, ext }); |
| 1182 | } else { | 1182 | } else { |
| 1183 | try test_path.writer().print("{s}{s}", .{ path, ext }); | 1183 | try test_path.print("{s}{s}", .{ path, ext }); |
| 1184 | } | 1184 | } |
| 1185 | try checked_paths.append(try arena.dupe(u8, test_path.items)); | 1185 | try checked_paths.append(try arena.dupe(u8, test_path.items)); |
| 1186 | fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { | 1186 | fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { |
| ... | @@ -2528,8 +2528,8 @@ fn writeThunkWorker(self: *MachO, thunk: Thunk) void { | ... | @@ -2528,8 +2528,8 @@ fn writeThunkWorker(self: *MachO, thunk: Thunk) void { |
| 2528 | fn doWork(th: Thunk, buffer: []u8, macho_file: *MachO) !void { | 2528 | fn doWork(th: Thunk, buffer: []u8, macho_file: *MachO) !void { |
| 2529 | const off = try macho_file.cast(usize, th.value); | 2529 | const off = try macho_file.cast(usize, th.value); |
| 2530 | const size = th.size(); | 2530 | const size = th.size(); |
| 2531 | var stream = std.io.fixedBufferStream(buffer[off..][0..size]); | 2531 | var stream: Writer = .fixed(buffer[off..][0..size]); |
| 2532 | try th.write(macho_file, stream.writer()); | 2532 | try th.write(macho_file, &stream); |
| 2533 | } | 2533 | } |
| 2534 | }.doWork; | 2534 | }.doWork; |
| 2535 | const out = self.sections.items(.out)[thunk.out_n_sect].items; | 2535 | const out = self.sections.items(.out)[thunk.out_n_sect].items; |
| ... | @@ -2556,15 +2556,15 @@ fn writeSyntheticSectionWorker(self: *MachO, sect_id: u8, out: []u8) void { | ... | @@ -2556,15 +2556,15 @@ fn writeSyntheticSectionWorker(self: *MachO, sect_id: u8, out: []u8) void { |
| 2556 | 2556 | ||
| 2557 | const doWork = struct { | 2557 | const doWork = struct { |
| 2558 | fn doWork(macho_file: *MachO, tag: Tag, buffer: []u8) !void { | 2558 | fn doWork(macho_file: *MachO, tag: Tag, buffer: []u8) !void { |
| 2559 | var stream = std.io.fixedBufferStream(buffer); | 2559 | var stream: Writer = .fixed(buffer); |
| 2560 | switch (tag) { | 2560 | switch (tag) { |
| 2561 | .eh_frame => eh_frame.write(macho_file, buffer), | 2561 | .eh_frame => eh_frame.write(macho_file, buffer), |
| 2562 | .unwind_info => try macho_file.unwind_info.write(macho_file, buffer), | 2562 | .unwind_info => try macho_file.unwind_info.write(macho_file, buffer), |
| 2563 | .got => try macho_file.got.write(macho_file, stream.writer()), | 2563 | .got => try macho_file.got.write(macho_file, &stream), |
| 2564 | .stubs => try macho_file.stubs.write(macho_file, stream.writer()), | 2564 | .stubs => try macho_file.stubs.write(macho_file, &stream), |
| 2565 | .la_symbol_ptr => try macho_file.la_symbol_ptr.write(macho_file, stream.writer()), | 2565 | .la_symbol_ptr => try macho_file.la_symbol_ptr.write(macho_file, &stream), |
| 2566 | .tlv_ptr => try macho_file.tlv_ptr.write(macho_file, stream.writer()), | 2566 | .tlv_ptr => try macho_file.tlv_ptr.write(macho_file, &stream), |
| 2567 | .objc_stubs => try macho_file.objc_stubs.write(macho_file, stream.writer()), | 2567 | .objc_stubs => try macho_file.objc_stubs.write(macho_file, &stream), |
| 2568 | } | 2568 | } |
| 2569 | } | 2569 | } |
| 2570 | }.doWork; | 2570 | }.doWork; |
| ... | @@ -2605,8 +2605,8 @@ fn updateLazyBindSizeWorker(self: *MachO) void { | ... | @@ -2605,8 +2605,8 @@ fn updateLazyBindSizeWorker(self: *MachO) void { |
| 2605 | try macho_file.lazy_bind_section.updateSize(macho_file); | 2605 | try macho_file.lazy_bind_section.updateSize(macho_file); |
| 2606 | const sect_id = macho_file.stubs_helper_sect_index.?; | 2606 | const sect_id = macho_file.stubs_helper_sect_index.?; |
| 2607 | const out = &macho_file.sections.items(.out)[sect_id]; | 2607 | const out = &macho_file.sections.items(.out)[sect_id]; |
| 2608 | var stream = std.io.fixedBufferStream(out.items); | 2608 | var stream: Writer = .fixed(out.items); |
| 2609 | try macho_file.stubs_helper.write(macho_file, stream.writer()); | 2609 | try macho_file.stubs_helper.write(macho_file, &stream); |
| 2610 | } | 2610 | } |
| 2611 | }.doWork; | 2611 | }.doWork; |
| 2612 | doWork(self) catch |err| | 2612 | doWork(self) catch |err| |
| ... | @@ -2669,18 +2669,17 @@ fn writeDyldInfo(self: *MachO) !void { | ... | @@ -2669,18 +2669,17 @@ fn writeDyldInfo(self: *MachO) !void { |
| 2669 | defer gpa.free(buffer); | 2669 | defer gpa.free(buffer); |
| 2670 | @memset(buffer, 0); | 2670 | @memset(buffer, 0); |
| 2671 | 2671 | ||
| 2672 | var stream = std.io.fixedBufferStream(buffer); | 2672 | var writer: Writer = .fixed(buffer); |
| 2673 | const writer = stream.writer(); | 2673 | |
| 2674 | 2674 | try self.rebase_section.write(&writer); | |
| 2675 | try self.rebase_section.write(writer); | 2675 | writer.end = cmd.bind_off - base_off; |
| 2676 | try stream.seekTo(cmd.bind_off - base_off); | 2676 | try self.bind_section.write(&writer); |
| 2677 | try self.bind_section.write(writer); | 2677 | writer.end = cmd.weak_bind_off - base_off; |
| 2678 | try stream.seekTo(cmd.weak_bind_off - base_off); | 2678 | try self.weak_bind_section.write(&writer); |
| 2679 | try self.weak_bind_section.write(writer); | 2679 | writer.end = cmd.lazy_bind_off - base_off; |
| 2680 | try stream.seekTo(cmd.lazy_bind_off - base_off); | 2680 | try self.lazy_bind_section.write(&writer); |
| 2681 | try self.lazy_bind_section.write(writer); | 2681 | writer.end = cmd.export_off - base_off; |
| 2682 | try stream.seekTo(cmd.export_off - base_off); | 2682 | try self.export_trie.write(&writer); |
| 2683 | try self.export_trie.write(writer); | ||
| 2684 | try self.pwriteAll(buffer, cmd.rebase_off); | 2683 | try self.pwriteAll(buffer, cmd.rebase_off); |
| 2685 | } | 2684 | } |
| 2686 | 2685 | ||
| ... | @@ -2689,10 +2688,10 @@ pub fn writeDataInCode(self: *MachO) !void { | ... | @@ -2689,10 +2688,10 @@ pub fn writeDataInCode(self: *MachO) !void { |
| 2689 | defer tracy.end(); | 2688 | defer tracy.end(); |
| 2690 | const gpa = self.base.comp.gpa; | 2689 | const gpa = self.base.comp.gpa; |
| 2691 | const cmd = self.data_in_code_cmd; | 2690 | const cmd = self.data_in_code_cmd; |
| 2692 | var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.data_in_code.size()); | 2691 | var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.data_in_code.size()); |
| 2693 | defer buffer.deinit(); | 2692 | defer buffer.deinit(); |
| 2694 | try self.data_in_code.write(self, buffer.writer()); | 2693 | self.data_in_code.write(self, &buffer.writer) catch return error.OutOfMemory; |
| 2695 | try self.pwriteAll(buffer.items, cmd.dataoff); | 2694 | try self.pwriteAll(buffer.written(), cmd.dataoff); |
| 2696 | } | 2695 | } |
| 2697 | 2696 | ||
| 2698 | fn writeIndsymtab(self: *MachO) !void { | 2697 | fn writeIndsymtab(self: *MachO) !void { |
| ... | @@ -2701,10 +2700,11 @@ fn writeIndsymtab(self: *MachO) !void { | ... | @@ -2701,10 +2700,11 @@ fn writeIndsymtab(self: *MachO) !void { |
| 2701 | const gpa = self.base.comp.gpa; | 2700 | const gpa = self.base.comp.gpa; |
| 2702 | const cmd = self.dysymtab_cmd; | 2701 | const cmd = self.dysymtab_cmd; |
| 2703 | const needed_size = cmd.nindirectsyms * @sizeOf(u32); | 2702 | const needed_size = cmd.nindirectsyms * @sizeOf(u32); |
| 2704 | var buffer = try std.array_list.Managed(u8).initCapacity(gpa, needed_size); | 2703 | const buffer = try gpa.alloc(u8, needed_size); |
| 2705 | defer buffer.deinit(); | 2704 | defer gpa.free(buffer); |
| 2706 | try self.indsymtab.write(self, buffer.writer()); | 2705 | var writer: Writer = .fixed(buffer); |
| 2707 | try self.pwriteAll(buffer.items, cmd.indirectsymoff); | 2706 | try self.indsymtab.write(self, &writer); |
| 2707 | try self.pwriteAll(buffer, cmd.indirectsymoff); | ||
| 2708 | } | 2708 | } |
| 2709 | 2709 | ||
| 2710 | pub fn writeSymtabToFile(self: *MachO) !void { | 2710 | pub fn writeSymtabToFile(self: *MachO) !void { |
| ... | @@ -2821,8 +2821,7 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { | ... | @@ -2821,8 +2821,7 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { |
| 2821 | const buffer = try gpa.alloc(u8, needed_size); | 2821 | const buffer = try gpa.alloc(u8, needed_size); |
| 2822 | defer gpa.free(buffer); | 2822 | defer gpa.free(buffer); |
| 2823 | 2823 | ||
| 2824 | var stream = std.io.fixedBufferStream(buffer); | 2824 | var writer: Writer = .fixed(buffer); |
| 2825 | const writer = stream.writer(); | ||
| 2826 | 2825 | ||
| 2827 | var ncmds: usize = 0; | 2826 | var ncmds: usize = 0; |
| 2828 | 2827 | ||
| ... | @@ -2831,26 +2830,26 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { | ... | @@ -2831,26 +2830,26 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { |
| 2831 | const slice = self.sections.slice(); | 2830 | const slice = self.sections.slice(); |
| 2832 | var sect_id: usize = 0; | 2831 | var sect_id: usize = 0; |
| 2833 | for (self.segments.items) |seg| { | 2832 | for (self.segments.items) |seg| { |
| 2834 | try writer.writeStruct(seg); | 2833 | try writer.writeStruct(seg, .little); |
| 2835 | for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| { | 2834 | for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| { |
| 2836 | try writer.writeStruct(header); | 2835 | try writer.writeStruct(header, .little); |
| 2837 | } | 2836 | } |
| 2838 | sect_id += seg.nsects; | 2837 | sect_id += seg.nsects; |
| 2839 | } | 2838 | } |
| 2840 | ncmds += self.segments.items.len; | 2839 | ncmds += self.segments.items.len; |
| 2841 | } | 2840 | } |
| 2842 | 2841 | ||
| 2843 | try writer.writeStruct(self.dyld_info_cmd); | 2842 | try writer.writeStruct(self.dyld_info_cmd, .little); |
| 2844 | ncmds += 1; | 2843 | ncmds += 1; |
| 2845 | try writer.writeStruct(self.function_starts_cmd); | 2844 | try writer.writeStruct(self.function_starts_cmd, .little); |
| 2846 | ncmds += 1; | 2845 | ncmds += 1; |
| 2847 | try writer.writeStruct(self.data_in_code_cmd); | 2846 | try writer.writeStruct(self.data_in_code_cmd, .little); |
| 2848 | ncmds += 1; | 2847 | ncmds += 1; |
| 2849 | try writer.writeStruct(self.symtab_cmd); | 2848 | try writer.writeStruct(self.symtab_cmd, .little); |
| 2850 | ncmds += 1; | 2849 | ncmds += 1; |
| 2851 | try writer.writeStruct(self.dysymtab_cmd); | 2850 | try writer.writeStruct(self.dysymtab_cmd, .little); |
| 2852 | ncmds += 1; | 2851 | ncmds += 1; |
| 2853 | try load_commands.writeDylinkerLC(writer); | 2852 | try load_commands.writeDylinkerLC(&writer); |
| 2854 | ncmds += 1; | 2853 | ncmds += 1; |
| 2855 | 2854 | ||
| 2856 | if (self.getInternalObject()) |obj| { | 2855 | if (self.getInternalObject()) |obj| { |
| ... | @@ -2861,44 +2860,44 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { | ... | @@ -2861,44 +2860,44 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { |
| 2861 | 0 | 2860 | 0 |
| 2862 | else | 2861 | else |
| 2863 | @as(u32, @intCast(sym.getAddress(.{ .stubs = true }, self) - seg.vmaddr)); | 2862 | @as(u32, @intCast(sym.getAddress(.{ .stubs = true }, self) - seg.vmaddr)); |
| 2864 | try writer.writeStruct(macho.entry_point_command{ | 2863 | try writer.writeStruct(@as(macho.entry_point_command, .{ |
| 2865 | .entryoff = entryoff, | 2864 | .entryoff = entryoff, |
| 2866 | .stacksize = self.base.stack_size, | 2865 | .stacksize = self.base.stack_size, |
| 2867 | }); | 2866 | }), .little); |
| 2868 | ncmds += 1; | 2867 | ncmds += 1; |
| 2869 | } | 2868 | } |
| 2870 | } | 2869 | } |
| 2871 | 2870 | ||
| 2872 | if (self.base.isDynLib()) { | 2871 | if (self.base.isDynLib()) { |
| 2873 | try load_commands.writeDylibIdLC(self, writer); | 2872 | try load_commands.writeDylibIdLC(self, &writer); |
| 2874 | ncmds += 1; | 2873 | ncmds += 1; |
| 2875 | } | 2874 | } |
| 2876 | 2875 | ||
| 2877 | for (self.rpath_list) |rpath| { | 2876 | for (self.rpath_list) |rpath| { |
| 2878 | try load_commands.writeRpathLC(rpath, writer); | 2877 | try load_commands.writeRpathLC(rpath, &writer); |
| 2879 | ncmds += 1; | 2878 | ncmds += 1; |
| 2880 | } | 2879 | } |
| 2881 | if (comp.config.any_sanitize_thread) { | 2880 | if (comp.config.any_sanitize_thread) { |
| 2882 | const path = try comp.tsan_lib.?.full_object_path.toString(gpa); | 2881 | const path = try comp.tsan_lib.?.full_object_path.toString(gpa); |
| 2883 | defer gpa.free(path); | 2882 | defer gpa.free(path); |
| 2884 | const rpath = std.fs.path.dirname(path) orelse "."; | 2883 | const rpath = std.fs.path.dirname(path) orelse "."; |
| 2885 | try load_commands.writeRpathLC(rpath, writer); | 2884 | try load_commands.writeRpathLC(rpath, &writer); |
| 2886 | ncmds += 1; | 2885 | ncmds += 1; |
| 2887 | } | 2886 | } |
| 2888 | 2887 | ||
| 2889 | try writer.writeStruct(macho.source_version_command{ .version = 0 }); | 2888 | try writer.writeStruct(@as(macho.source_version_command, .{ .version = 0 }), .little); |
| 2890 | ncmds += 1; | 2889 | ncmds += 1; |
| 2891 | 2890 | ||
| 2892 | if (self.platform.isBuildVersionCompatible()) { | 2891 | if (self.platform.isBuildVersionCompatible()) { |
| 2893 | try load_commands.writeBuildVersionLC(self.platform, self.sdk_version, writer); | 2892 | try load_commands.writeBuildVersionLC(self.platform, self.sdk_version, &writer); |
| 2894 | ncmds += 1; | 2893 | ncmds += 1; |
| 2895 | } else { | 2894 | } else { |
| 2896 | try load_commands.writeVersionMinLC(self.platform, self.sdk_version, writer); | 2895 | try load_commands.writeVersionMinLC(self.platform, self.sdk_version, &writer); |
| 2897 | ncmds += 1; | 2896 | ncmds += 1; |
| 2898 | } | 2897 | } |
| 2899 | 2898 | ||
| 2900 | const uuid_cmd_offset = @sizeOf(macho.mach_header_64) + stream.pos; | 2899 | const uuid_cmd_offset = @sizeOf(macho.mach_header_64) + writer.end; |
| 2901 | try writer.writeStruct(self.uuid_cmd); | 2900 | try writer.writeStruct(self.uuid_cmd, .little); |
| 2902 | ncmds += 1; | 2901 | ncmds += 1; |
| 2903 | 2902 | ||
| 2904 | for (self.dylibs.items) |index| { | 2903 | for (self.dylibs.items) |index| { |
| ... | @@ -2916,16 +2915,16 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { | ... | @@ -2916,16 +2915,16 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { |
| 2916 | .timestamp = dylib_id.timestamp, | 2915 | .timestamp = dylib_id.timestamp, |
| 2917 | .current_version = dylib_id.current_version, | 2916 | .current_version = dylib_id.current_version, |
| 2918 | .compatibility_version = dylib_id.compatibility_version, | 2917 | .compatibility_version = dylib_id.compatibility_version, |
| 2919 | }, writer); | 2918 | }, &writer); |
| 2920 | ncmds += 1; | 2919 | ncmds += 1; |
| 2921 | } | 2920 | } |
| 2922 | 2921 | ||
| 2923 | if (self.requiresCodeSig()) { | 2922 | if (self.requiresCodeSig()) { |
| 2924 | try writer.writeStruct(self.codesig_cmd); | 2923 | try writer.writeStruct(self.codesig_cmd, .little); |
| 2925 | ncmds += 1; | 2924 | ncmds += 1; |
| 2926 | } | 2925 | } |
| 2927 | 2926 | ||
| 2928 | assert(stream.pos == needed_size); | 2927 | assert(writer.end == needed_size); |
| 2929 | 2928 | ||
| 2930 | try self.pwriteAll(buffer, @sizeOf(macho.mach_header_64)); | 2929 | try self.pwriteAll(buffer, @sizeOf(macho.mach_header_64)); |
| 2931 | 2930 | ||
| ... | @@ -3014,25 +3013,26 @@ pub fn writeCodeSignaturePadding(self: *MachO, code_sig: *CodeSignature) !void { | ... | @@ -3014,25 +3013,26 @@ pub fn writeCodeSignaturePadding(self: *MachO, code_sig: *CodeSignature) !void { |
| 3014 | pub fn writeCodeSignature(self: *MachO, code_sig: *CodeSignature) !void { | 3013 | pub fn writeCodeSignature(self: *MachO, code_sig: *CodeSignature) !void { |
| 3015 | const seg = self.getTextSegment(); | 3014 | const seg = self.getTextSegment(); |
| 3016 | const offset = self.codesig_cmd.dataoff; | 3015 | const offset = self.codesig_cmd.dataoff; |
| 3016 | const gpa = self.base.comp.gpa; | ||
| 3017 | 3017 | ||
| 3018 | var buffer = std.array_list.Managed(u8).init(self.base.comp.gpa); | 3018 | const buffer = try gpa.alloc(u8, code_sig.size()); |
| 3019 | defer buffer.deinit(); | 3019 | defer gpa.free(buffer); |
| 3020 | try buffer.ensureTotalCapacityPrecise(code_sig.size()); | 3020 | var writer: Writer = .fixed(buffer); |
| 3021 | try code_sig.writeAdhocSignature(self, .{ | 3021 | try code_sig.writeAdhocSignature(self, .{ |
| 3022 | .file = self.base.file.?, | 3022 | .file = self.base.file.?, |
| 3023 | .exec_seg_base = seg.fileoff, | 3023 | .exec_seg_base = seg.fileoff, |
| 3024 | .exec_seg_limit = seg.filesize, | 3024 | .exec_seg_limit = seg.filesize, |
| 3025 | .file_size = offset, | 3025 | .file_size = offset, |
| 3026 | .dylib = self.base.isDynLib(), | 3026 | .dylib = self.base.isDynLib(), |
| 3027 | }, buffer.writer()); | 3027 | }, &writer); |
| 3028 | assert(buffer.items.len == code_sig.size()); | 3028 | assert(writer.buffered().len == code_sig.size()); |
| 3029 | 3029 | ||
| 3030 | log.debug("writing code signature from 0x{x} to 0x{x}", .{ | 3030 | log.debug("writing code signature from 0x{x} to 0x{x}", .{ |
| 3031 | offset, | 3031 | offset, |
| 3032 | offset + buffer.items.len, | 3032 | offset + writer.buffered().len, |
| 3033 | }); | 3033 | }); |
| 3034 | 3034 | ||
| 3035 | try self.pwriteAll(buffer.items, offset); | 3035 | try self.pwriteAll(writer.buffered(), offset); |
| 3036 | } | 3036 | } |
| 3037 | 3037 | ||
| 3038 | pub fn updateFunc( | 3038 | pub fn updateFunc( |
| ... | @@ -5372,7 +5372,7 @@ const macho = std.macho; | ... | @@ -5372,7 +5372,7 @@ const macho = std.macho; |
| 5372 | const math = std.math; | 5372 | const math = std.math; |
| 5373 | const mem = std.mem; | 5373 | const mem = std.mem; |
| 5374 | const meta = std.meta; | 5374 | const meta = std.meta; |
| 5375 | const Writer = std.io.Writer; | 5375 | const Writer = std.Io.Writer; |
| 5376 | 5376 | ||
| 5377 | const aarch64 = codegen.aarch64.encoding; | 5377 | const aarch64 = codegen.aarch64.encoding; |
| 5378 | const bind = @import("MachO/dyld_info/bind.zig"); | 5378 | const bind = @import("MachO/dyld_info/bind.zig"); |
src/link/MachO/Archive.zig+18-38| ... | @@ -81,34 +81,20 @@ pub fn writeHeader( | ... | @@ -81,34 +81,20 @@ pub fn writeHeader( |
| 81 | object_name: []const u8, | 81 | object_name: []const u8, |
| 82 | object_size: usize, | 82 | object_size: usize, |
| 83 | format: Format, | 83 | format: Format, |
| 84 | writer: anytype, | 84 | writer: *Writer, |
| 85 | ) !void { | 85 | ) !void { |
| 86 | var hdr: ar_hdr = .{ | 86 | var hdr: ar_hdr = .{}; |
| 87 | .ar_name = undefined, | ||
| 88 | .ar_date = undefined, | ||
| 89 | .ar_uid = undefined, | ||
| 90 | .ar_gid = undefined, | ||
| 91 | .ar_mode = undefined, | ||
| 92 | .ar_size = undefined, | ||
| 93 | .ar_fmag = undefined, | ||
| 94 | }; | ||
| 95 | @memset(mem.asBytes(&hdr), 0x20); | ||
| 96 | inline for (@typeInfo(ar_hdr).@"struct".fields) |field| { | ||
| 97 | var stream = std.io.fixedBufferStream(&@field(hdr, field.name)); | ||
| 98 | stream.writer().print("0", .{}) catch unreachable; | ||
| 99 | } | ||
| 100 | @memcpy(&hdr.ar_fmag, ARFMAG); | ||
| 101 | 87 | ||
| 102 | const object_name_len = mem.alignForward(usize, object_name.len + 1, ptrWidth(format)); | 88 | const object_name_len = mem.alignForward(usize, object_name.len + 1, ptrWidth(format)); |
| 103 | const total_object_size = object_size + object_name_len; | 89 | const total_object_size = object_size + object_name_len; |
| 104 | 90 | ||
| 105 | { | 91 | { |
| 106 | var stream = std.io.fixedBufferStream(&hdr.ar_name); | 92 | var stream: Writer = .fixed(&hdr.ar_name); |
| 107 | stream.writer().print("#1/{d}", .{object_name_len}) catch unreachable; | 93 | stream.print("#1/{d}", .{object_name_len}) catch unreachable; |
| 108 | } | 94 | } |
| 109 | { | 95 | { |
| 110 | var stream = std.io.fixedBufferStream(&hdr.ar_size); | 96 | var stream: Writer = .fixed(&hdr.ar_size); |
| 111 | stream.writer().print("{d}", .{total_object_size}) catch unreachable; | 97 | stream.print("{d}", .{total_object_size}) catch unreachable; |
| 112 | } | 98 | } |
| 113 | 99 | ||
| 114 | try writer.writeAll(mem.asBytes(&hdr)); | 100 | try writer.writeAll(mem.asBytes(&hdr)); |
| ... | @@ -116,7 +102,7 @@ pub fn writeHeader( | ... | @@ -116,7 +102,7 @@ pub fn writeHeader( |
| 116 | 102 | ||
| 117 | const padding = object_name_len - object_name.len - 1; | 103 | const padding = object_name_len - object_name.len - 1; |
| 118 | if (padding > 0) { | 104 | if (padding > 0) { |
| 119 | try writer.writeByteNTimes(0, padding); | 105 | try writer.splatByteAll(0, padding); |
| 120 | } | 106 | } |
| 121 | } | 107 | } |
| 122 | 108 | ||
| ... | @@ -138,25 +124,19 @@ pub const SYMDEF64_SORTED = "__.SYMDEF_64 SORTED"; | ... | @@ -138,25 +124,19 @@ pub const SYMDEF64_SORTED = "__.SYMDEF_64 SORTED"; |
| 138 | 124 | ||
| 139 | pub const ar_hdr = extern struct { | 125 | pub const ar_hdr = extern struct { |
| 140 | /// Member file name, sometimes / terminated. | 126 | /// Member file name, sometimes / terminated. |
| 141 | ar_name: [16]u8, | 127 | ar_name: [16]u8 = "0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20".*, |
| 142 | |||
| 143 | /// File date, decimal seconds since Epoch. | 128 | /// File date, decimal seconds since Epoch. |
| 144 | ar_date: [12]u8, | 129 | ar_date: [12]u8 = "0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20".*, |
| 145 | |||
| 146 | /// User ID, in ASCII format. | 130 | /// User ID, in ASCII format. |
| 147 | ar_uid: [6]u8, | 131 | ar_uid: [6]u8 = "0\x20\x20\x20\x20\x20".*, |
| 148 | |||
| 149 | /// Group ID, in ASCII format. | 132 | /// Group ID, in ASCII format. |
| 150 | ar_gid: [6]u8, | 133 | ar_gid: [6]u8 = "0\x20\x20\x20\x20\x20".*, |
| 151 | |||
| 152 | /// File mode, in ASCII octal. | 134 | /// File mode, in ASCII octal. |
| 153 | ar_mode: [8]u8, | 135 | ar_mode: [8]u8 = "0\x20\x20\x20\x20\x20\x20\x20".*, |
| 154 | |||
| 155 | /// File size, in ASCII decimal. | 136 | /// File size, in ASCII decimal. |
| 156 | ar_size: [10]u8, | 137 | ar_size: [10]u8 = "0\x20\x20\x20\x20\x20\x20\x20\x20\x20".*, |
| 157 | |||
| 158 | /// Always contains ARFMAG. | 138 | /// Always contains ARFMAG. |
| 159 | ar_fmag: [2]u8, | 139 | ar_fmag: [2]u8 = ARFMAG.*, |
| 160 | 140 | ||
| 161 | fn date(self: ar_hdr) !u64 { | 141 | fn date(self: ar_hdr) !u64 { |
| 162 | const value = mem.trimEnd(u8, &self.ar_date, &[_]u8{@as(u8, 0x20)}); | 142 | const value = mem.trimEnd(u8, &self.ar_date, &[_]u8{@as(u8, 0x20)}); |
| ... | @@ -201,7 +181,7 @@ pub const ArSymtab = struct { | ... | @@ -201,7 +181,7 @@ pub const ArSymtab = struct { |
| 201 | return ptr_width + ar.entries.items.len * 2 * ptr_width + ptr_width + mem.alignForward(usize, ar.strtab.buffer.items.len, ptr_width); | 181 | return ptr_width + ar.entries.items.len * 2 * ptr_width + ptr_width + mem.alignForward(usize, ar.strtab.buffer.items.len, ptr_width); |
| 202 | } | 182 | } |
| 203 | 183 | ||
| 204 | pub fn write(ar: ArSymtab, format: Format, macho_file: *MachO, writer: anytype) !void { | 184 | pub fn write(ar: ArSymtab, format: Format, macho_file: *MachO, writer: *Writer) !void { |
| 205 | const ptr_width = ptrWidth(format); | 185 | const ptr_width = ptrWidth(format); |
| 206 | // Header | 186 | // Header |
| 207 | try writeHeader(SYMDEF, ar.size(format), format, writer); | 187 | try writeHeader(SYMDEF, ar.size(format), format, writer); |
| ... | @@ -226,7 +206,7 @@ pub const ArSymtab = struct { | ... | @@ -226,7 +206,7 @@ pub const ArSymtab = struct { |
| 226 | // Strtab | 206 | // Strtab |
| 227 | try writer.writeAll(ar.strtab.buffer.items); | 207 | try writer.writeAll(ar.strtab.buffer.items); |
| 228 | if (padding > 0) { | 208 | if (padding > 0) { |
| 229 | try writer.writeByteNTimes(0, padding); | 209 | try writer.splatByteAll(0, padding); |
| 230 | } | 210 | } |
| 231 | } | 211 | } |
| 232 | 212 | ||
| ... | @@ -275,7 +255,7 @@ pub fn ptrWidth(format: Format) usize { | ... | @@ -275,7 +255,7 @@ pub fn ptrWidth(format: Format) usize { |
| 275 | }; | 255 | }; |
| 276 | } | 256 | } |
| 277 | 257 | ||
| 278 | pub fn writeInt(format: Format, value: u64, writer: anytype) !void { | 258 | pub fn writeInt(format: Format, value: u64, writer: *Writer) !void { |
| 279 | switch (format) { | 259 | switch (format) { |
| 280 | .p32 => try writer.writeInt(u32, std.math.cast(u32, value) orelse return error.Overflow, .little), | 260 | .p32 => try writer.writeInt(u32, std.math.cast(u32, value) orelse return error.Overflow, .little), |
| 281 | .p64 => try writer.writeInt(u64, value, .little), | 261 | .p64 => try writer.writeInt(u64, value, .little), |
| ... | @@ -299,7 +279,7 @@ const mem = std.mem; | ... | @@ -299,7 +279,7 @@ const mem = std.mem; |
| 299 | const std = @import("std"); | 279 | const std = @import("std"); |
| 300 | const Allocator = std.mem.Allocator; | 280 | const Allocator = std.mem.Allocator; |
| 301 | const Path = std.Build.Cache.Path; | 281 | const Path = std.Build.Cache.Path; |
| 302 | const Writer = std.io.Writer; | 282 | const Writer = std.Io.Writer; |
| 303 | 283 | ||
| 304 | const Archive = @This(); | 284 | const Archive = @This(); |
| 305 | const File = @import("file.zig").File; | 285 | const File = @import("file.zig").File; |
src/link/MachO/Atom.zig+6-5| ... | @@ -581,7 +581,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { | ... | @@ -581,7 +581,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { |
| 581 | relocs_log.debug("{x}: {s}", .{ self.value, name }); | 581 | relocs_log.debug("{x}: {s}", .{ self.value, name }); |
| 582 | 582 | ||
| 583 | var has_error = false; | 583 | var has_error = false; |
| 584 | var stream = std.io.fixedBufferStream(buffer); | 584 | var stream: Writer = .fixed(buffer); |
| 585 | var i: usize = 0; | 585 | var i: usize = 0; |
| 586 | while (i < relocs.len) : (i += 1) { | 586 | while (i < relocs.len) : (i += 1) { |
| 587 | const rel = relocs[i]; | 587 | const rel = relocs[i]; |
| ... | @@ -592,8 +592,8 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { | ... | @@ -592,8 +592,8 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { |
| 592 | if (rel.getTargetSymbol(self, macho_file).getFile(macho_file) == null) continue; | 592 | if (rel.getTargetSymbol(self, macho_file).getFile(macho_file) == null) continue; |
| 593 | } | 593 | } |
| 594 | 594 | ||
| 595 | try stream.seekTo(rel_offset); | 595 | stream.end = rel_offset; |
| 596 | self.resolveRelocInner(rel, subtractor, buffer, macho_file, stream.writer()) catch |err| { | 596 | self.resolveRelocInner(rel, subtractor, buffer, macho_file, &stream) catch |err| { |
| 597 | switch (err) { | 597 | switch (err) { |
| 598 | error.RelaxFail => { | 598 | error.RelaxFail => { |
| 599 | const target = switch (rel.tag) { | 599 | const target = switch (rel.tag) { |
| ... | @@ -630,6 +630,7 @@ const ResolveError = error{ | ... | @@ -630,6 +630,7 @@ const ResolveError = error{ |
| 630 | UnexpectedRemainder, | 630 | UnexpectedRemainder, |
| 631 | Overflow, | 631 | Overflow, |
| 632 | OutOfMemory, | 632 | OutOfMemory, |
| 633 | WriteFailed, | ||
| 633 | }; | 634 | }; |
| 634 | 635 | ||
| 635 | fn resolveRelocInner( | 636 | fn resolveRelocInner( |
| ... | @@ -638,7 +639,7 @@ fn resolveRelocInner( | ... | @@ -638,7 +639,7 @@ fn resolveRelocInner( |
| 638 | subtractor: ?Relocation, | 639 | subtractor: ?Relocation, |
| 639 | code: []u8, | 640 | code: []u8, |
| 640 | macho_file: *MachO, | 641 | macho_file: *MachO, |
| 641 | writer: anytype, | 642 | writer: *Writer, |
| 642 | ) ResolveError!void { | 643 | ) ResolveError!void { |
| 643 | const t = &macho_file.base.comp.root_mod.resolved_target.result; | 644 | const t = &macho_file.base.comp.root_mod.resolved_target.result; |
| 644 | const cpu_arch = t.cpu.arch; | 645 | const cpu_arch = t.cpu.arch; |
| ... | @@ -1147,7 +1148,7 @@ const math = std.math; | ... | @@ -1147,7 +1148,7 @@ const math = std.math; |
| 1147 | const mem = std.mem; | 1148 | const mem = std.mem; |
| 1148 | const log = std.log.scoped(.link); | 1149 | const log = std.log.scoped(.link); |
| 1149 | const relocs_log = std.log.scoped(.link_relocs); | 1150 | const relocs_log = std.log.scoped(.link_relocs); |
| 1150 | const Writer = std.io.Writer; | 1151 | const Writer = std.Io.Writer; |
| 1151 | const Allocator = mem.Allocator; | 1152 | const Allocator = mem.Allocator; |
| 1152 | const AtomicBool = std.atomic.Value(bool); | 1153 | const AtomicBool = std.atomic.Value(bool); |
| 1153 | 1154 |
src/link/MachO/CodeSignature.zig+8-8| ... | @@ -304,10 +304,10 @@ pub fn writeAdhocSignature( | ... | @@ -304,10 +304,10 @@ pub fn writeAdhocSignature( |
| 304 | var hash: [hash_size]u8 = undefined; | 304 | var hash: [hash_size]u8 = undefined; |
| 305 | 305 | ||
| 306 | if (self.requirements) |*req| { | 306 | if (self.requirements) |*req| { |
| 307 | var buf = std.array_list.Managed(u8).init(allocator); | 307 | var a: std.Io.Writer.Allocating = .init(allocator); |
| 308 | defer buf.deinit(); | 308 | defer a.deinit(); |
| 309 | try req.write(buf.writer()); | 309 | try req.write(&a.writer); |
| 310 | Sha256.hash(buf.items, &hash, .{}); | 310 | Sha256.hash(a.written(), &hash, .{}); |
| 311 | self.code_directory.addSpecialHash(req.slotType(), hash); | 311 | self.code_directory.addSpecialHash(req.slotType(), hash); |
| 312 | 312 | ||
| 313 | try blobs.append(.{ .requirements = req }); | 313 | try blobs.append(.{ .requirements = req }); |
| ... | @@ -316,10 +316,10 @@ pub fn writeAdhocSignature( | ... | @@ -316,10 +316,10 @@ pub fn writeAdhocSignature( |
| 316 | } | 316 | } |
| 317 | 317 | ||
| 318 | if (self.entitlements) |*ents| { | 318 | if (self.entitlements) |*ents| { |
| 319 | var buf = std.array_list.Managed(u8).init(allocator); | 319 | var a: std.Io.Writer.Allocating = .init(allocator); |
| 320 | defer buf.deinit(); | 320 | defer a.deinit(); |
| 321 | try ents.write(buf.writer()); | 321 | try ents.write(&a.writer); |
| 322 | Sha256.hash(buf.items, &hash, .{}); | 322 | Sha256.hash(a.written(), &hash, .{}); |
| 323 | self.code_directory.addSpecialHash(ents.slotType(), hash); | 323 | self.code_directory.addSpecialHash(ents.slotType(), hash); |
| 324 | 324 | ||
| 325 | try blobs.append(.{ .entitlements = ents }); | 325 | try blobs.append(.{ .entitlements = ents }); |
src/link/MachO/DebugSymbols.zig+9-10| ... | @@ -273,14 +273,13 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u | ... | @@ -273,14 +273,13 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u |
| 273 | const buffer = try gpa.alloc(u8, needed_size); | 273 | const buffer = try gpa.alloc(u8, needed_size); |
| 274 | defer gpa.free(buffer); | 274 | defer gpa.free(buffer); |
| 275 | 275 | ||
| 276 | var stream = std.io.fixedBufferStream(buffer); | 276 | var writer: Writer = .fixed(buffer); |
| 277 | const writer = stream.writer(); | ||
| 278 | 277 | ||
| 279 | var ncmds: usize = 0; | 278 | var ncmds: usize = 0; |
| 280 | 279 | ||
| 281 | // UUID comes first presumably to speed up lookup by the consumer like lldb. | 280 | // UUID comes first presumably to speed up lookup by the consumer like lldb. |
| 282 | @memcpy(&self.uuid_cmd.uuid, &macho_file.uuid_cmd.uuid); | 281 | @memcpy(&self.uuid_cmd.uuid, &macho_file.uuid_cmd.uuid); |
| 283 | try writer.writeStruct(self.uuid_cmd); | 282 | try writer.writeStruct(self.uuid_cmd, .little); |
| 284 | ncmds += 1; | 283 | ncmds += 1; |
| 285 | 284 | ||
| 286 | // Segment and section load commands | 285 | // Segment and section load commands |
| ... | @@ -293,11 +292,11 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u | ... | @@ -293,11 +292,11 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u |
| 293 | var out_seg = seg; | 292 | var out_seg = seg; |
| 294 | out_seg.fileoff = 0; | 293 | out_seg.fileoff = 0; |
| 295 | out_seg.filesize = 0; | 294 | out_seg.filesize = 0; |
| 296 | try writer.writeStruct(out_seg); | 295 | try writer.writeStruct(out_seg, .little); |
| 297 | for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| { | 296 | for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| { |
| 298 | var out_header = header; | 297 | var out_header = header; |
| 299 | out_header.offset = 0; | 298 | out_header.offset = 0; |
| 300 | try writer.writeStruct(out_header); | 299 | try writer.writeStruct(out_header, .little); |
| 301 | } | 300 | } |
| 302 | sect_id += seg.nsects; | 301 | sect_id += seg.nsects; |
| 303 | } | 302 | } |
| ... | @@ -306,19 +305,19 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u | ... | @@ -306,19 +305,19 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u |
| 306 | // Next, commit DSYM's __LINKEDIT and __DWARF segments headers. | 305 | // Next, commit DSYM's __LINKEDIT and __DWARF segments headers. |
| 307 | sect_id = 0; | 306 | sect_id = 0; |
| 308 | for (self.segments.items) |seg| { | 307 | for (self.segments.items) |seg| { |
| 309 | try writer.writeStruct(seg); | 308 | try writer.writeStruct(seg, .little); |
| 310 | for (self.sections.items[sect_id..][0..seg.nsects]) |header| { | 309 | for (self.sections.items[sect_id..][0..seg.nsects]) |header| { |
| 311 | try writer.writeStruct(header); | 310 | try writer.writeStruct(header, .little); |
| 312 | } | 311 | } |
| 313 | sect_id += seg.nsects; | 312 | sect_id += seg.nsects; |
| 314 | } | 313 | } |
| 315 | ncmds += self.segments.items.len; | 314 | ncmds += self.segments.items.len; |
| 316 | } | 315 | } |
| 317 | 316 | ||
| 318 | try writer.writeStruct(self.symtab_cmd); | 317 | try writer.writeStruct(self.symtab_cmd, .little); |
| 319 | ncmds += 1; | 318 | ncmds += 1; |
| 320 | 319 | ||
| 321 | assert(stream.pos == needed_size); | 320 | assert(writer.end == needed_size); |
| 322 | 321 | ||
| 323 | try self.file.?.pwriteAll(buffer, @sizeOf(macho.mach_header_64)); | 322 | try self.file.?.pwriteAll(buffer, @sizeOf(macho.mach_header_64)); |
| 324 | 323 | ||
| ... | @@ -460,7 +459,7 @@ const math = std.math; | ... | @@ -460,7 +459,7 @@ const math = std.math; |
| 460 | const mem = std.mem; | 459 | const mem = std.mem; |
| 461 | const padToIdeal = MachO.padToIdeal; | 460 | const padToIdeal = MachO.padToIdeal; |
| 462 | const trace = @import("../../tracy.zig").trace; | 461 | const trace = @import("../../tracy.zig").trace; |
| 463 | const Writer = std.io.Writer; | 462 | const Writer = std.Io.Writer; |
| 464 | 463 | ||
| 465 | const Allocator = mem.Allocator; | 464 | const Allocator = mem.Allocator; |
| 466 | const MachO = @import("../MachO.zig"); | 465 | const MachO = @import("../MachO.zig"); |
src/link/MachO/InternalObject.zig+1-1| ... | @@ -261,7 +261,7 @@ fn addObjcMethnameSection(self: *InternalObject, methname: []const u8, macho_fil | ... | @@ -261,7 +261,7 @@ fn addObjcMethnameSection(self: *InternalObject, methname: []const u8, macho_fil |
| 261 | 261 | ||
| 262 | sect.offset = @intCast(self.objc_methnames.items.len); | 262 | sect.offset = @intCast(self.objc_methnames.items.len); |
| 263 | try self.objc_methnames.ensureUnusedCapacity(gpa, methname.len + 1); | 263 | try self.objc_methnames.ensureUnusedCapacity(gpa, methname.len + 1); |
| 264 | self.objc_methnames.writer(gpa).print("{s}\x00", .{methname}) catch unreachable; | 264 | self.objc_methnames.print(gpa, "{s}\x00", .{methname}) catch unreachable; |
| 265 | 265 | ||
| 266 | const name_str = try self.addString(gpa, "ltmp"); | 266 | const name_str = try self.addString(gpa, "ltmp"); |
| 267 | const sym_index = try self.addSymbol(gpa); | 267 | const sym_index = try self.addSymbol(gpa); |
src/link/MachO/UnwindInfo.zig+23-24| ... | @@ -293,8 +293,7 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void { | ... | @@ -293,8 +293,7 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void { |
| 293 | const seg = macho_file.getTextSegment(); | 293 | const seg = macho_file.getTextSegment(); |
| 294 | const header = macho_file.sections.items(.header)[macho_file.unwind_info_sect_index.?]; | 294 | const header = macho_file.sections.items(.header)[macho_file.unwind_info_sect_index.?]; |
| 295 | 295 | ||
| 296 | var stream = std.io.fixedBufferStream(buffer); | 296 | var writer: Writer = .fixed(buffer); |
| 297 | const writer = stream.writer(); | ||
| 298 | 297 | ||
| 299 | const common_encodings_offset: u32 = @sizeOf(macho.unwind_info_section_header); | 298 | const common_encodings_offset: u32 = @sizeOf(macho.unwind_info_section_header); |
| 300 | const common_encodings_count: u32 = info.common_encodings_count; | 299 | const common_encodings_count: u32 = info.common_encodings_count; |
| ... | @@ -303,14 +302,14 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void { | ... | @@ -303,14 +302,14 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void { |
| 303 | const indexes_offset: u32 = personalities_offset + personalities_count * @sizeOf(u32); | 302 | const indexes_offset: u32 = personalities_offset + personalities_count * @sizeOf(u32); |
| 304 | const indexes_count: u32 = @as(u32, @intCast(info.pages.items.len + 1)); | 303 | const indexes_count: u32 = @as(u32, @intCast(info.pages.items.len + 1)); |
| 305 | 304 | ||
| 306 | try writer.writeStruct(macho.unwind_info_section_header{ | 305 | try writer.writeStruct(@as(macho.unwind_info_section_header, .{ |
| 307 | .commonEncodingsArraySectionOffset = common_encodings_offset, | 306 | .commonEncodingsArraySectionOffset = common_encodings_offset, |
| 308 | .commonEncodingsArrayCount = common_encodings_count, | 307 | .commonEncodingsArrayCount = common_encodings_count, |
| 309 | .personalityArraySectionOffset = personalities_offset, | 308 | .personalityArraySectionOffset = personalities_offset, |
| 310 | .personalityArrayCount = personalities_count, | 309 | .personalityArrayCount = personalities_count, |
| 311 | .indexSectionOffset = indexes_offset, | 310 | .indexSectionOffset = indexes_offset, |
| 312 | .indexCount = indexes_count, | 311 | .indexCount = indexes_count, |
| 313 | }); | 312 | }), .little); |
| 314 | 313 | ||
| 315 | try writer.writeAll(mem.sliceAsBytes(info.common_encodings[0..info.common_encodings_count])); | 314 | try writer.writeAll(mem.sliceAsBytes(info.common_encodings[0..info.common_encodings_count])); |
| 316 | 315 | ||
| ... | @@ -325,42 +324,42 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void { | ... | @@ -325,42 +324,42 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void { |
| 325 | for (info.pages.items, 0..) |page, i| { | 324 | for (info.pages.items, 0..) |page, i| { |
| 326 | assert(page.count > 0); | 325 | assert(page.count > 0); |
| 327 | const rec = info.records.items[page.start].getUnwindRecord(macho_file); | 326 | const rec = info.records.items[page.start].getUnwindRecord(macho_file); |
| 328 | try writer.writeStruct(macho.unwind_info_section_header_index_entry{ | 327 | try writer.writeStruct(@as(macho.unwind_info_section_header_index_entry, .{ |
| 329 | .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)), | 328 | .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)), |
| 330 | .secondLevelPagesSectionOffset = @as(u32, @intCast(pages_base_offset + i * second_level_page_bytes)), | 329 | .secondLevelPagesSectionOffset = @as(u32, @intCast(pages_base_offset + i * second_level_page_bytes)), |
| 331 | .lsdaIndexArraySectionOffset = lsda_base_offset + | 330 | .lsdaIndexArraySectionOffset = lsda_base_offset + |
| 332 | info.lsdas_lookup.items[page.start] * @sizeOf(macho.unwind_info_section_header_lsda_index_entry), | 331 | info.lsdas_lookup.items[page.start] * @sizeOf(macho.unwind_info_section_header_lsda_index_entry), |
| 333 | }); | 332 | }), .little); |
| 334 | } | 333 | } |
| 335 | 334 | ||
| 336 | const last_rec = info.records.items[info.records.items.len - 1].getUnwindRecord(macho_file); | 335 | const last_rec = info.records.items[info.records.items.len - 1].getUnwindRecord(macho_file); |
| 337 | const sentinel_address = @as(u32, @intCast(last_rec.getAtomAddress(macho_file) + last_rec.length - seg.vmaddr)); | 336 | const sentinel_address = @as(u32, @intCast(last_rec.getAtomAddress(macho_file) + last_rec.length - seg.vmaddr)); |
| 338 | try writer.writeStruct(macho.unwind_info_section_header_index_entry{ | 337 | try writer.writeStruct(@as(macho.unwind_info_section_header_index_entry, .{ |
| 339 | .functionOffset = sentinel_address, | 338 | .functionOffset = sentinel_address, |
| 340 | .secondLevelPagesSectionOffset = 0, | 339 | .secondLevelPagesSectionOffset = 0, |
| 341 | .lsdaIndexArraySectionOffset = lsda_base_offset + | 340 | .lsdaIndexArraySectionOffset = lsda_base_offset + |
| 342 | @as(u32, @intCast(info.lsdas.items.len)) * @sizeOf(macho.unwind_info_section_header_lsda_index_entry), | 341 | @as(u32, @intCast(info.lsdas.items.len)) * @sizeOf(macho.unwind_info_section_header_lsda_index_entry), |
| 343 | }); | 342 | }), .little); |
| 344 | 343 | ||
| 345 | for (info.lsdas.items) |index| { | 344 | for (info.lsdas.items) |index| { |
| 346 | const rec = info.records.items[index].getUnwindRecord(macho_file); | 345 | const rec = info.records.items[index].getUnwindRecord(macho_file); |
| 347 | try writer.writeStruct(macho.unwind_info_section_header_lsda_index_entry{ | 346 | try writer.writeStruct(@as(macho.unwind_info_section_header_lsda_index_entry, .{ |
| 348 | .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)), | 347 | .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)), |
| 349 | .lsdaOffset = @as(u32, @intCast(rec.getLsdaAddress(macho_file) - seg.vmaddr)), | 348 | .lsdaOffset = @as(u32, @intCast(rec.getLsdaAddress(macho_file) - seg.vmaddr)), |
| 350 | }); | 349 | }), .little); |
| 351 | } | 350 | } |
| 352 | 351 | ||
| 353 | for (info.pages.items) |page| { | 352 | for (info.pages.items) |page| { |
| 354 | const start = stream.pos; | 353 | const start = writer.end; |
| 355 | try page.write(info, macho_file, writer); | 354 | try page.write(info, macho_file, &writer); |
| 356 | const nwritten = stream.pos - start; | 355 | const nwritten = writer.end - start; |
| 357 | if (nwritten < second_level_page_bytes) { | 356 | if (nwritten < second_level_page_bytes) { |
| 358 | const padding = math.cast(usize, second_level_page_bytes - nwritten) orelse return error.Overflow; | 357 | const padding = math.cast(usize, second_level_page_bytes - nwritten) orelse return error.Overflow; |
| 359 | try writer.writeByteNTimes(0, padding); | 358 | try writer.splatByteAll(0, padding); |
| 360 | } | 359 | } |
| 361 | } | 360 | } |
| 362 | 361 | ||
| 363 | @memset(buffer[stream.pos..], 0); | 362 | @memset(buffer[writer.end..], 0); |
| 364 | } | 363 | } |
| 365 | 364 | ||
| 366 | fn getOrPutPersonalityFunction(info: *UnwindInfo, ref: MachO.Ref) error{TooManyPersonalities}!u2 { | 365 | fn getOrPutPersonalityFunction(info: *UnwindInfo, ref: MachO.Ref) error{TooManyPersonalities}!u2 { |
| ... | @@ -611,33 +610,33 @@ const Page = struct { | ... | @@ -611,33 +610,33 @@ const Page = struct { |
| 611 | } }; | 610 | } }; |
| 612 | } | 611 | } |
| 613 | 612 | ||
| 614 | fn write(page: Page, info: UnwindInfo, macho_file: *MachO, writer: anytype) !void { | 613 | fn write(page: Page, info: UnwindInfo, macho_file: *MachO, writer: *Writer) !void { |
| 615 | const seg = macho_file.getTextSegment(); | 614 | const seg = macho_file.getTextSegment(); |
| 616 | 615 | ||
| 617 | switch (page.kind) { | 616 | switch (page.kind) { |
| 618 | .regular => { | 617 | .regular => { |
| 619 | try writer.writeStruct(macho.unwind_info_regular_second_level_page_header{ | 618 | try writer.writeStruct(@as(macho.unwind_info_regular_second_level_page_header, .{ |
| 620 | .entryPageOffset = @sizeOf(macho.unwind_info_regular_second_level_page_header), | 619 | .entryPageOffset = @sizeOf(macho.unwind_info_regular_second_level_page_header), |
| 621 | .entryCount = page.count, | 620 | .entryCount = page.count, |
| 622 | }); | 621 | }), .little); |
| 623 | 622 | ||
| 624 | for (info.records.items[page.start..][0..page.count]) |ref| { | 623 | for (info.records.items[page.start..][0..page.count]) |ref| { |
| 625 | const rec = ref.getUnwindRecord(macho_file); | 624 | const rec = ref.getUnwindRecord(macho_file); |
| 626 | try writer.writeStruct(macho.unwind_info_regular_second_level_entry{ | 625 | try writer.writeStruct(@as(macho.unwind_info_regular_second_level_entry, .{ |
| 627 | .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)), | 626 | .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)), |
| 628 | .encoding = rec.enc.enc, | 627 | .encoding = rec.enc.enc, |
| 629 | }); | 628 | }), .little); |
| 630 | } | 629 | } |
| 631 | }, | 630 | }, |
| 632 | .compressed => { | 631 | .compressed => { |
| 633 | const entry_offset = @sizeOf(macho.unwind_info_compressed_second_level_page_header) + | 632 | const entry_offset = @sizeOf(macho.unwind_info_compressed_second_level_page_header) + |
| 634 | @as(u16, @intCast(page.page_encodings_count)) * @sizeOf(u32); | 633 | @as(u16, @intCast(page.page_encodings_count)) * @sizeOf(u32); |
| 635 | try writer.writeStruct(macho.unwind_info_compressed_second_level_page_header{ | 634 | try writer.writeStruct(@as(macho.unwind_info_compressed_second_level_page_header, .{ |
| 636 | .entryPageOffset = entry_offset, | 635 | .entryPageOffset = entry_offset, |
| 637 | .entryCount = page.count, | 636 | .entryCount = page.count, |
| 638 | .encodingsPageOffset = @sizeOf(macho.unwind_info_compressed_second_level_page_header), | 637 | .encodingsPageOffset = @sizeOf(macho.unwind_info_compressed_second_level_page_header), |
| 639 | .encodingsCount = page.page_encodings_count, | 638 | .encodingsCount = page.page_encodings_count, |
| 640 | }); | 639 | }), .little); |
| 641 | 640 | ||
| 642 | for (page.page_encodings[0..page.page_encodings_count]) |enc| { | 641 | for (page.page_encodings[0..page.page_encodings_count]) |enc| { |
| 643 | try writer.writeInt(u32, enc.enc, .little); | 642 | try writer.writeInt(u32, enc.enc, .little); |
| ... | @@ -656,7 +655,7 @@ const Page = struct { | ... | @@ -656,7 +655,7 @@ const Page = struct { |
| 656 | .funcOffset = @as(u24, @intCast(rec.getAtomAddress(macho_file) - first_rec.getAtomAddress(macho_file))), | 655 | .funcOffset = @as(u24, @intCast(rec.getAtomAddress(macho_file) - first_rec.getAtomAddress(macho_file))), |
| 657 | .encodingIndex = @as(u8, @intCast(enc_index)), | 656 | .encodingIndex = @as(u8, @intCast(enc_index)), |
| 658 | }; | 657 | }; |
| 659 | try writer.writeStruct(compressed); | 658 | try writer.writeStruct(compressed, .little); |
| 660 | } | 659 | } |
| 661 | }, | 660 | }, |
| 662 | } | 661 | } |
| ... | @@ -673,7 +672,7 @@ const macho = std.macho; | ... | @@ -673,7 +672,7 @@ const macho = std.macho; |
| 673 | const math = std.math; | 672 | const math = std.math; |
| 674 | const mem = std.mem; | 673 | const mem = std.mem; |
| 675 | const trace = @import("../../tracy.zig").trace; | 674 | const trace = @import("../../tracy.zig").trace; |
| 676 | const Writer = std.io.Writer; | 675 | const Writer = std.Io.Writer; |
| 677 | 676 | ||
| 678 | const Allocator = mem.Allocator; | 677 | const Allocator = mem.Allocator; |
| 679 | const Atom = @import("Atom.zig"); | 678 | const Atom = @import("Atom.zig"); |
src/link/MachO/dyld_info/Rebase.zig+4-2| ... | @@ -110,12 +110,14 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void { | ... | @@ -110,12 +110,14 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void { |
| 110 | fn finalize(rebase: *Rebase, gpa: Allocator) !void { | 110 | fn finalize(rebase: *Rebase, gpa: Allocator) !void { |
| 111 | if (rebase.entries.items.len == 0) return; | 111 | if (rebase.entries.items.len == 0) return; |
| 112 | 112 | ||
| 113 | const writer = rebase.buffer.writer(gpa); | ||
| 114 | |||
| 115 | log.debug("rebase opcodes", .{}); | 113 | log.debug("rebase opcodes", .{}); |
| 116 | 114 | ||
| 117 | std.mem.sort(Entry, rebase.entries.items, {}, Entry.lessThan); | 115 | std.mem.sort(Entry, rebase.entries.items, {}, Entry.lessThan); |
| 118 | 116 | ||
| 117 | var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &rebase.buffer); | ||
| 118 | defer rebase.buffer = allocating.toArrayList(); | ||
| 119 | const writer = &allocating.writer; | ||
| 120 | |||
| 119 | try setTypePointer(writer); | 121 | try setTypePointer(writer); |
| 120 | 122 | ||
| 121 | var start: usize = 0; | 123 | var start: usize = 0; |
src/link/MachO/dyld_info/Trie.zig+15-10| ... | @@ -170,8 +170,13 @@ fn finalize(self: *Trie, allocator: Allocator) !void { | ... | @@ -170,8 +170,13 @@ fn finalize(self: *Trie, allocator: Allocator) !void { |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | try self.buffer.ensureTotalCapacityPrecise(allocator, size); | 172 | try self.buffer.ensureTotalCapacityPrecise(allocator, size); |
| 173 | |||
| 174 | var allocating: std.Io.Writer.Allocating = .fromArrayList(allocator, &self.buffer); | ||
| 175 | defer self.buffer = allocating.toArrayList(); | ||
| 176 | const writer = &allocating.writer; | ||
| 177 | |||
| 173 | for (ordered_nodes.items) |node_index| { | 178 | for (ordered_nodes.items) |node_index| { |
| 174 | try self.writeNode(node_index, self.buffer.writer(allocator)); | 179 | try self.writeNode(node_index, writer); |
| 175 | } | 180 | } |
| 176 | } | 181 | } |
| 177 | 182 | ||
| ... | @@ -232,7 +237,7 @@ pub fn deinit(self: *Trie, allocator: Allocator) void { | ... | @@ -232,7 +237,7 @@ pub fn deinit(self: *Trie, allocator: Allocator) void { |
| 232 | self.buffer.deinit(allocator); | 237 | self.buffer.deinit(allocator); |
| 233 | } | 238 | } |
| 234 | 239 | ||
| 235 | pub fn write(self: Trie, writer: anytype) !void { | 240 | pub fn write(self: Trie, writer: *std.Io.Writer) !void { |
| 236 | if (self.buffer.items.len == 0) return; | 241 | if (self.buffer.items.len == 0) return; |
| 237 | try writer.writeAll(self.buffer.items); | 242 | try writer.writeAll(self.buffer.items); |
| 238 | } | 243 | } |
| ... | @@ -243,7 +248,7 @@ pub fn write(self: Trie, writer: anytype) !void { | ... | @@ -243,7 +248,7 @@ pub fn write(self: Trie, writer: anytype) !void { |
| 243 | /// iterate over `Trie.ordered_nodes` and call this method on each node. | 248 | /// iterate over `Trie.ordered_nodes` and call this method on each node. |
| 244 | /// This is one of the requirements of the MachO. | 249 | /// This is one of the requirements of the MachO. |
| 245 | /// Panics if `finalize` was not called before calling this method. | 250 | /// Panics if `finalize` was not called before calling this method. |
| 246 | fn writeNode(self: *Trie, node_index: Node.Index, writer: anytype) !void { | 251 | fn writeNode(self: *Trie, node_index: Node.Index, writer: *std.Io.Writer) !void { |
| 247 | const slice = self.nodes.slice(); | 252 | const slice = self.nodes.slice(); |
| 248 | const edges = slice.items(.edges)[node_index]; | 253 | const edges = slice.items(.edges)[node_index]; |
| 249 | const is_terminal = slice.items(.is_terminal)[node_index]; | 254 | const is_terminal = slice.items(.is_terminal)[node_index]; |
| ... | @@ -253,21 +258,21 @@ fn writeNode(self: *Trie, node_index: Node.Index, writer: anytype) !void { | ... | @@ -253,21 +258,21 @@ fn writeNode(self: *Trie, node_index: Node.Index, writer: anytype) !void { |
| 253 | if (is_terminal) { | 258 | if (is_terminal) { |
| 254 | // Terminal node info: encode export flags and vmaddr offset of this symbol. | 259 | // Terminal node info: encode export flags and vmaddr offset of this symbol. |
| 255 | var info_buf: [@sizeOf(u64) * 2]u8 = undefined; | 260 | var info_buf: [@sizeOf(u64) * 2]u8 = undefined; |
| 256 | var info_stream = std.io.fixedBufferStream(&info_buf); | 261 | var info_stream: std.Io.Writer = .fixed(&info_buf); |
| 257 | // TODO Implement for special flags. | 262 | // TODO Implement for special flags. |
| 258 | assert(export_flags & macho.EXPORT_SYMBOL_FLAGS_REEXPORT == 0 and | 263 | assert(export_flags & macho.EXPORT_SYMBOL_FLAGS_REEXPORT == 0 and |
| 259 | export_flags & macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER == 0); | 264 | export_flags & macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER == 0); |
| 260 | try leb.writeUleb128(info_stream.writer(), export_flags); | 265 | try leb.writeUleb128(&info_stream, export_flags); |
| 261 | try leb.writeUleb128(info_stream.writer(), vmaddr_offset); | 266 | try leb.writeUleb128(&info_stream, vmaddr_offset); |
| 262 | 267 | ||
| 263 | // Encode the size of the terminal node info. | 268 | // Encode the size of the terminal node info. |
| 264 | var size_buf: [@sizeOf(u64)]u8 = undefined; | 269 | var size_buf: [@sizeOf(u64)]u8 = undefined; |
| 265 | var size_stream = std.io.fixedBufferStream(&size_buf); | 270 | var size_stream: std.Io.Writer = .fixed(&size_buf); |
| 266 | try leb.writeUleb128(size_stream.writer(), info_stream.pos); | 271 | try leb.writeUleb128(&size_stream, info_stream.end); |
| 267 | 272 | ||
| 268 | // Now, write them to the output stream. | 273 | // Now, write them to the output stream. |
| 269 | try writer.writeAll(size_buf[0..size_stream.pos]); | 274 | try writer.writeAll(size_buf[0..size_stream.end]); |
| 270 | try writer.writeAll(info_buf[0..info_stream.pos]); | 275 | try writer.writeAll(info_buf[0..info_stream.end]); |
| 271 | } else { | 276 | } else { |
| 272 | // Non-terminal node is delimited by 0 byte. | 277 | // Non-terminal node is delimited by 0 byte. |
| 273 | try writer.writeByte(0); | 278 | try writer.writeByte(0); |
src/link/MachO/dyld_info/bind.zig+26-21| ... | @@ -132,12 +132,14 @@ pub const Bind = struct { | ... | @@ -132,12 +132,14 @@ pub const Bind = struct { |
| 132 | fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void { | 132 | fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void { |
| 133 | if (self.entries.items.len == 0) return; | 133 | if (self.entries.items.len == 0) return; |
| 134 | 134 | ||
| 135 | const writer = self.buffer.writer(gpa); | ||
| 136 | |||
| 137 | log.debug("bind opcodes", .{}); | 135 | log.debug("bind opcodes", .{}); |
| 138 | 136 | ||
| 139 | std.mem.sort(Entry, self.entries.items, ctx, Entry.lessThan); | 137 | std.mem.sort(Entry, self.entries.items, ctx, Entry.lessThan); |
| 140 | 138 | ||
| 139 | var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &self.buffer); | ||
| 140 | defer self.buffer = allocating.toArrayList(); | ||
| 141 | const writer = &allocating.writer; | ||
| 142 | |||
| 141 | var start: usize = 0; | 143 | var start: usize = 0; |
| 142 | var seg_id: ?u8 = null; | 144 | var seg_id: ?u8 = null; |
| 143 | for (self.entries.items, 0..) |entry, i| { | 145 | for (self.entries.items, 0..) |entry, i| { |
| ... | @@ -151,7 +153,7 @@ pub const Bind = struct { | ... | @@ -151,7 +153,7 @@ pub const Bind = struct { |
| 151 | try done(writer); | 153 | try done(writer); |
| 152 | } | 154 | } |
| 153 | 155 | ||
| 154 | fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: anytype) !void { | 156 | fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: *std.Io.Writer) !void { |
| 155 | if (entries.len == 0) return; | 157 | if (entries.len == 0) return; |
| 156 | 158 | ||
| 157 | const seg_id = entries[0].segment_id; | 159 | const seg_id = entries[0].segment_id; |
| ... | @@ -263,7 +265,7 @@ pub const Bind = struct { | ... | @@ -263,7 +265,7 @@ pub const Bind = struct { |
| 263 | } | 265 | } |
| 264 | } | 266 | } |
| 265 | 267 | ||
| 266 | pub fn write(self: Self, writer: anytype) !void { | 268 | pub fn write(self: Self, writer: *std.Io.Writer) !void { |
| 267 | try writer.writeAll(self.buffer.items); | 269 | try writer.writeAll(self.buffer.items); |
| 268 | } | 270 | } |
| 269 | }; | 271 | }; |
| ... | @@ -385,12 +387,14 @@ pub const WeakBind = struct { | ... | @@ -385,12 +387,14 @@ pub const WeakBind = struct { |
| 385 | fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void { | 387 | fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void { |
| 386 | if (self.entries.items.len == 0) return; | 388 | if (self.entries.items.len == 0) return; |
| 387 | 389 | ||
| 388 | const writer = self.buffer.writer(gpa); | ||
| 389 | |||
| 390 | log.debug("weak bind opcodes", .{}); | 390 | log.debug("weak bind opcodes", .{}); |
| 391 | 391 | ||
| 392 | std.mem.sort(Entry, self.entries.items, ctx, Entry.lessThan); | 392 | std.mem.sort(Entry, self.entries.items, ctx, Entry.lessThan); |
| 393 | 393 | ||
| 394 | var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &self.buffer); | ||
| 395 | defer self.buffer = allocating.toArrayList(); | ||
| 396 | const writer = &allocating.writer; | ||
| 397 | |||
| 394 | var start: usize = 0; | 398 | var start: usize = 0; |
| 395 | var seg_id: ?u8 = null; | 399 | var seg_id: ?u8 = null; |
| 396 | for (self.entries.items, 0..) |entry, i| { | 400 | for (self.entries.items, 0..) |entry, i| { |
| ... | @@ -404,7 +408,7 @@ pub const WeakBind = struct { | ... | @@ -404,7 +408,7 @@ pub const WeakBind = struct { |
| 404 | try done(writer); | 408 | try done(writer); |
| 405 | } | 409 | } |
| 406 | 410 | ||
| 407 | fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: anytype) !void { | 411 | fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: *std.Io.Writer) !void { |
| 408 | if (entries.len == 0) return; | 412 | if (entries.len == 0) return; |
| 409 | 413 | ||
| 410 | const seg_id = entries[0].segment_id; | 414 | const seg_id = entries[0].segment_id; |
| ... | @@ -505,7 +509,7 @@ pub const WeakBind = struct { | ... | @@ -505,7 +509,7 @@ pub const WeakBind = struct { |
| 505 | } | 509 | } |
| 506 | } | 510 | } |
| 507 | 511 | ||
| 508 | pub fn write(self: Self, writer: anytype) !void { | 512 | pub fn write(self: Self, writer: *std.Io.Writer) !void { |
| 509 | try writer.writeAll(self.buffer.items); | 513 | try writer.writeAll(self.buffer.items); |
| 510 | } | 514 | } |
| 511 | }; | 515 | }; |
| ... | @@ -555,8 +559,6 @@ pub const LazyBind = struct { | ... | @@ -555,8 +559,6 @@ pub const LazyBind = struct { |
| 555 | fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void { | 559 | fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void { |
| 556 | try self.offsets.ensureTotalCapacityPrecise(gpa, self.entries.items.len); | 560 | try self.offsets.ensureTotalCapacityPrecise(gpa, self.entries.items.len); |
| 557 | 561 | ||
| 558 | const writer = self.buffer.writer(gpa); | ||
| 559 | |||
| 560 | log.debug("lazy bind opcodes", .{}); | 562 | log.debug("lazy bind opcodes", .{}); |
| 561 | 563 | ||
| 562 | var addend: i64 = 0; | 564 | var addend: i64 = 0; |
| ... | @@ -578,6 +580,9 @@ pub const LazyBind = struct { | ... | @@ -578,6 +580,9 @@ pub const LazyBind = struct { |
| 578 | break :ord macho.BIND_SPECIAL_DYLIB_SELF; | 580 | break :ord macho.BIND_SPECIAL_DYLIB_SELF; |
| 579 | }; | 581 | }; |
| 580 | 582 | ||
| 583 | var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &self.buffer); | ||
| 584 | defer self.buffer = allocating.toArrayList(); | ||
| 585 | const writer = &allocating.writer; | ||
| 581 | try setSegmentOffset(entry.segment_id, entry.offset, writer); | 586 | try setSegmentOffset(entry.segment_id, entry.offset, writer); |
| 582 | try setSymbol(name, flags, writer); | 587 | try setSymbol(name, flags, writer); |
| 583 | try setDylibOrdinal(ordinal, writer); | 588 | try setDylibOrdinal(ordinal, writer); |
| ... | @@ -592,30 +597,30 @@ pub const LazyBind = struct { | ... | @@ -592,30 +597,30 @@ pub const LazyBind = struct { |
| 592 | } | 597 | } |
| 593 | } | 598 | } |
| 594 | 599 | ||
| 595 | pub fn write(self: Self, writer: anytype) !void { | 600 | pub fn write(self: Self, writer: *std.Io.Writer) !void { |
| 596 | try writer.writeAll(self.buffer.items); | 601 | try writer.writeAll(self.buffer.items); |
| 597 | } | 602 | } |
| 598 | }; | 603 | }; |
| 599 | 604 | ||
| 600 | fn setSegmentOffset(segment_id: u8, offset: u64, writer: anytype) !void { | 605 | fn setSegmentOffset(segment_id: u8, offset: u64, writer: *std.Io.Writer) !void { |
| 601 | log.debug(">>> set segment: {d} and offset: {x}", .{ segment_id, offset }); | 606 | log.debug(">>> set segment: {d} and offset: {x}", .{ segment_id, offset }); |
| 602 | try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @as(u4, @truncate(segment_id))); | 607 | try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @as(u4, @truncate(segment_id))); |
| 603 | try std.leb.writeUleb128(writer, offset); | 608 | try std.leb.writeUleb128(writer, offset); |
| 604 | } | 609 | } |
| 605 | 610 | ||
| 606 | fn setSymbol(name: []const u8, flags: u8, writer: anytype) !void { | 611 | fn setSymbol(name: []const u8, flags: u8, writer: *std.Io.Writer) !void { |
| 607 | log.debug(">>> set symbol: {s} with flags: {x}", .{ name, flags }); | 612 | log.debug(">>> set symbol: {s} with flags: {x}", .{ name, flags }); |
| 608 | try writer.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | @as(u4, @truncate(flags))); | 613 | try writer.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | @as(u4, @truncate(flags))); |
| 609 | try writer.writeAll(name); | 614 | try writer.writeAll(name); |
| 610 | try writer.writeByte(0); | 615 | try writer.writeByte(0); |
| 611 | } | 616 | } |
| 612 | 617 | ||
| 613 | fn setTypePointer(writer: anytype) !void { | 618 | fn setTypePointer(writer: *std.Io.Writer) !void { |
| 614 | log.debug(">>> set type: {d}", .{macho.BIND_TYPE_POINTER}); | 619 | log.debug(">>> set type: {d}", .{macho.BIND_TYPE_POINTER}); |
| 615 | try writer.writeByte(macho.BIND_OPCODE_SET_TYPE_IMM | @as(u4, @truncate(macho.BIND_TYPE_POINTER))); | 620 | try writer.writeByte(macho.BIND_OPCODE_SET_TYPE_IMM | @as(u4, @truncate(macho.BIND_TYPE_POINTER))); |
| 616 | } | 621 | } |
| 617 | 622 | ||
| 618 | fn setDylibOrdinal(ordinal: i16, writer: anytype) !void { | 623 | fn setDylibOrdinal(ordinal: i16, writer: *std.Io.Writer) !void { |
| 619 | if (ordinal <= 0) { | 624 | if (ordinal <= 0) { |
| 620 | switch (ordinal) { | 625 | switch (ordinal) { |
| 621 | macho.BIND_SPECIAL_DYLIB_SELF, | 626 | macho.BIND_SPECIAL_DYLIB_SELF, |
| ... | @@ -639,18 +644,18 @@ fn setDylibOrdinal(ordinal: i16, writer: anytype) !void { | ... | @@ -639,18 +644,18 @@ fn setDylibOrdinal(ordinal: i16, writer: anytype) !void { |
| 639 | } | 644 | } |
| 640 | } | 645 | } |
| 641 | 646 | ||
| 642 | fn setAddend(addend: i64, writer: anytype) !void { | 647 | fn setAddend(addend: i64, writer: *std.Io.Writer) !void { |
| 643 | log.debug(">>> set addend: {x}", .{addend}); | 648 | log.debug(">>> set addend: {x}", .{addend}); |
| 644 | try writer.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB); | 649 | try writer.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB); |
| 645 | try std.leb.writeIleb128(writer, addend); | 650 | try std.leb.writeIleb128(writer, addend); |
| 646 | } | 651 | } |
| 647 | 652 | ||
| 648 | fn doBind(writer: anytype) !void { | 653 | fn doBind(writer: *std.Io.Writer) !void { |
| 649 | log.debug(">>> bind", .{}); | 654 | log.debug(">>> bind", .{}); |
| 650 | try writer.writeByte(macho.BIND_OPCODE_DO_BIND); | 655 | try writer.writeByte(macho.BIND_OPCODE_DO_BIND); |
| 651 | } | 656 | } |
| 652 | 657 | ||
| 653 | fn doBindAddAddr(addr: u64, writer: anytype) !void { | 658 | fn doBindAddAddr(addr: u64, writer: *std.Io.Writer) !void { |
| 654 | log.debug(">>> bind with add: {x}", .{addr}); | 659 | log.debug(">>> bind with add: {x}", .{addr}); |
| 655 | if (std.mem.isAlignedGeneric(u64, addr, @sizeOf(u64))) { | 660 | if (std.mem.isAlignedGeneric(u64, addr, @sizeOf(u64))) { |
| 656 | const imm = @divExact(addr, @sizeOf(u64)); | 661 | const imm = @divExact(addr, @sizeOf(u64)); |
| ... | @@ -665,20 +670,20 @@ fn doBindAddAddr(addr: u64, writer: anytype) !void { | ... | @@ -665,20 +670,20 @@ fn doBindAddAddr(addr: u64, writer: anytype) !void { |
| 665 | try std.leb.writeUleb128(writer, addr); | 670 | try std.leb.writeUleb128(writer, addr); |
| 666 | } | 671 | } |
| 667 | 672 | ||
| 668 | fn doBindTimesSkip(count: usize, skip: u64, writer: anytype) !void { | 673 | fn doBindTimesSkip(count: usize, skip: u64, writer: *std.Io.Writer) !void { |
| 669 | log.debug(">>> bind with count: {d} and skip: {x}", .{ count, skip }); | 674 | log.debug(">>> bind with count: {d} and skip: {x}", .{ count, skip }); |
| 670 | try writer.writeByte(macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB); | 675 | try writer.writeByte(macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB); |
| 671 | try std.leb.writeUleb128(writer, count); | 676 | try std.leb.writeUleb128(writer, count); |
| 672 | try std.leb.writeUleb128(writer, skip); | 677 | try std.leb.writeUleb128(writer, skip); |
| 673 | } | 678 | } |
| 674 | 679 | ||
| 675 | fn addAddr(addr: u64, writer: anytype) !void { | 680 | fn addAddr(addr: u64, writer: *std.Io.Writer) !void { |
| 676 | log.debug(">>> add: {x}", .{addr}); | 681 | log.debug(">>> add: {x}", .{addr}); |
| 677 | try writer.writeByte(macho.BIND_OPCODE_ADD_ADDR_ULEB); | 682 | try writer.writeByte(macho.BIND_OPCODE_ADD_ADDR_ULEB); |
| 678 | try std.leb.writeUleb128(writer, addr); | 683 | try std.leb.writeUleb128(writer, addr); |
| 679 | } | 684 | } |
| 680 | 685 | ||
| 681 | fn done(writer: anytype) !void { | 686 | fn done(writer: *std.Io.Writer) !void { |
| 682 | log.debug(">>> done", .{}); | 687 | log.debug(">>> done", .{}); |
| 683 | try writer.writeByte(macho.BIND_OPCODE_DONE); | 688 | try writer.writeByte(macho.BIND_OPCODE_DONE); |
| 684 | } | 689 | } |
src/link/MachO/load_commands.zig+19-19| ... | @@ -3,9 +3,9 @@ const assert = std.debug.assert; | ... | @@ -3,9 +3,9 @@ const assert = std.debug.assert; |
| 3 | const log = std.log.scoped(.link); | 3 | const log = std.log.scoped(.link); |
| 4 | const macho = std.macho; | 4 | const macho = std.macho; |
| 5 | const mem = std.mem; | 5 | const mem = std.mem; |
| 6 | const Writer = std.io.Writer; | 6 | const Writer = std.Io.Writer; |
| 7 | const Allocator = std.mem.Allocator; | ||
| 7 | 8 | ||
| 8 | const Allocator = mem.Allocator; | ||
| 9 | const DebugSymbols = @import("DebugSymbols.zig"); | 9 | const DebugSymbols = @import("DebugSymbols.zig"); |
| 10 | const Dylib = @import("Dylib.zig"); | 10 | const Dylib = @import("Dylib.zig"); |
| 11 | const MachO = @import("../MachO.zig"); | 11 | const MachO = @import("../MachO.zig"); |
| ... | @@ -181,22 +181,22 @@ pub fn calcMinHeaderPadSize(macho_file: *MachO) !u32 { | ... | @@ -181,22 +181,22 @@ pub fn calcMinHeaderPadSize(macho_file: *MachO) !u32 { |
| 181 | return offset; | 181 | return offset; |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | pub fn writeDylinkerLC(writer: anytype) !void { | 184 | pub fn writeDylinkerLC(writer: *Writer) !void { |
| 185 | const name_len = mem.sliceTo(default_dyld_path, 0).len; | 185 | const name_len = mem.sliceTo(default_dyld_path, 0).len; |
| 186 | const cmdsize = @as(u32, @intCast(mem.alignForward( | 186 | const cmdsize = @as(u32, @intCast(mem.alignForward( |
| 187 | u64, | 187 | u64, |
| 188 | @sizeOf(macho.dylinker_command) + name_len, | 188 | @sizeOf(macho.dylinker_command) + name_len, |
| 189 | @sizeOf(u64), | 189 | @sizeOf(u64), |
| 190 | ))); | 190 | ))); |
| 191 | try writer.writeStruct(macho.dylinker_command{ | 191 | try writer.writeStruct(@as(macho.dylinker_command, .{ |
| 192 | .cmd = .LOAD_DYLINKER, | 192 | .cmd = .LOAD_DYLINKER, |
| 193 | .cmdsize = cmdsize, | 193 | .cmdsize = cmdsize, |
| 194 | .name = @sizeOf(macho.dylinker_command), | 194 | .name = @sizeOf(macho.dylinker_command), |
| 195 | }); | 195 | }), .little); |
| 196 | try writer.writeAll(mem.sliceTo(default_dyld_path, 0)); | 196 | try writer.writeAll(mem.sliceTo(default_dyld_path, 0)); |
| 197 | const padding = cmdsize - @sizeOf(macho.dylinker_command) - name_len; | 197 | const padding = cmdsize - @sizeOf(macho.dylinker_command) - name_len; |
| 198 | if (padding > 0) { | 198 | if (padding > 0) { |
| 199 | try writer.writeByteNTimes(0, padding); | 199 | try writer.splatByteAll(0, padding); |
| 200 | } | 200 | } |
| 201 | } | 201 | } |
| 202 | 202 | ||
| ... | @@ -208,14 +208,14 @@ const WriteDylibLCCtx = struct { | ... | @@ -208,14 +208,14 @@ const WriteDylibLCCtx = struct { |
| 208 | compatibility_version: u32 = 0x10000, | 208 | compatibility_version: u32 = 0x10000, |
| 209 | }; | 209 | }; |
| 210 | 210 | ||
| 211 | pub fn writeDylibLC(ctx: WriteDylibLCCtx, writer: anytype) !void { | 211 | pub fn writeDylibLC(ctx: WriteDylibLCCtx, writer: *Writer) !void { |
| 212 | const name_len = ctx.name.len + 1; | 212 | const name_len = ctx.name.len + 1; |
| 213 | const cmdsize = @as(u32, @intCast(mem.alignForward( | 213 | const cmdsize = @as(u32, @intCast(mem.alignForward( |
| 214 | u64, | 214 | u64, |
| 215 | @sizeOf(macho.dylib_command) + name_len, | 215 | @sizeOf(macho.dylib_command) + name_len, |
| 216 | @sizeOf(u64), | 216 | @sizeOf(u64), |
| 217 | ))); | 217 | ))); |
| 218 | try writer.writeStruct(macho.dylib_command{ | 218 | try writer.writeStruct(@as(macho.dylib_command, .{ |
| 219 | .cmd = ctx.cmd, | 219 | .cmd = ctx.cmd, |
| 220 | .cmdsize = cmdsize, | 220 | .cmdsize = cmdsize, |
| 221 | .dylib = .{ | 221 | .dylib = .{ |
| ... | @@ -224,16 +224,16 @@ pub fn writeDylibLC(ctx: WriteDylibLCCtx, writer: anytype) !void { | ... | @@ -224,16 +224,16 @@ pub fn writeDylibLC(ctx: WriteDylibLCCtx, writer: anytype) !void { |
| 224 | .current_version = ctx.current_version, | 224 | .current_version = ctx.current_version, |
| 225 | .compatibility_version = ctx.compatibility_version, | 225 | .compatibility_version = ctx.compatibility_version, |
| 226 | }, | 226 | }, |
| 227 | }); | 227 | }), .little); |
| 228 | try writer.writeAll(ctx.name); | 228 | try writer.writeAll(ctx.name); |
| 229 | try writer.writeByte(0); | 229 | try writer.writeByte(0); |
| 230 | const padding = cmdsize - @sizeOf(macho.dylib_command) - name_len; | 230 | const padding = cmdsize - @sizeOf(macho.dylib_command) - name_len; |
| 231 | if (padding > 0) { | 231 | if (padding > 0) { |
| 232 | try writer.writeByteNTimes(0, padding); | 232 | try writer.splatByteAll(0, padding); |
| 233 | } | 233 | } |
| 234 | } | 234 | } |
| 235 | 235 | ||
| 236 | pub fn writeDylibIdLC(macho_file: *MachO, writer: anytype) !void { | 236 | pub fn writeDylibIdLC(macho_file: *MachO, writer: *Writer) !void { |
| 237 | const comp = macho_file.base.comp; | 237 | const comp = macho_file.base.comp; |
| 238 | const gpa = comp.gpa; | 238 | const gpa = comp.gpa; |
| 239 | assert(comp.config.output_mode == .Lib and comp.config.link_mode == .dynamic); | 239 | assert(comp.config.output_mode == .Lib and comp.config.link_mode == .dynamic); |
| ... | @@ -259,26 +259,26 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: anytype) !void { | ... | @@ -259,26 +259,26 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: anytype) !void { |
| 259 | }, writer); | 259 | }, writer); |
| 260 | } | 260 | } |
| 261 | 261 | ||
| 262 | pub fn writeRpathLC(rpath: []const u8, writer: anytype) !void { | 262 | pub fn writeRpathLC(rpath: []const u8, writer: *Writer) !void { |
| 263 | const rpath_len = rpath.len + 1; | 263 | const rpath_len = rpath.len + 1; |
| 264 | const cmdsize = @as(u32, @intCast(mem.alignForward( | 264 | const cmdsize = @as(u32, @intCast(mem.alignForward( |
| 265 | u64, | 265 | u64, |
| 266 | @sizeOf(macho.rpath_command) + rpath_len, | 266 | @sizeOf(macho.rpath_command) + rpath_len, |
| 267 | @sizeOf(u64), | 267 | @sizeOf(u64), |
| 268 | ))); | 268 | ))); |
| 269 | try writer.writeStruct(macho.rpath_command{ | 269 | try writer.writeStruct(@as(macho.rpath_command, .{ |
| 270 | .cmdsize = cmdsize, | 270 | .cmdsize = cmdsize, |
| 271 | .path = @sizeOf(macho.rpath_command), | 271 | .path = @sizeOf(macho.rpath_command), |
| 272 | }); | 272 | }), .little); |
| 273 | try writer.writeAll(rpath); | 273 | try writer.writeAll(rpath); |
| 274 | try writer.writeByte(0); | 274 | try writer.writeByte(0); |
| 275 | const padding = cmdsize - @sizeOf(macho.rpath_command) - rpath_len; | 275 | const padding = cmdsize - @sizeOf(macho.rpath_command) - rpath_len; |
| 276 | if (padding > 0) { | 276 | if (padding > 0) { |
| 277 | try writer.writeByteNTimes(0, padding); | 277 | try writer.splatByteAll(0, padding); |
| 278 | } | 278 | } |
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: anytype) !void { | 281 | pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: *Writer) !void { |
| 282 | const cmd: macho.LC = switch (platform.os_tag) { | 282 | const cmd: macho.LC = switch (platform.os_tag) { |
| 283 | .macos => .VERSION_MIN_MACOSX, | 283 | .macos => .VERSION_MIN_MACOSX, |
| 284 | .ios => .VERSION_MIN_IPHONEOS, | 284 | .ios => .VERSION_MIN_IPHONEOS, |
| ... | @@ -296,9 +296,9 @@ pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVer | ... | @@ -296,9 +296,9 @@ pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVer |
| 296 | })); | 296 | })); |
| 297 | } | 297 | } |
| 298 | 298 | ||
| 299 | pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: anytype) !void { | 299 | pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: *Writer) !void { |
| 300 | const cmdsize = @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version); | 300 | const cmdsize = @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version); |
| 301 | try writer.writeStruct(macho.build_version_command{ | 301 | try writer.writeStruct(@as(macho.build_version_command, .{ |
| 302 | .cmdsize = cmdsize, | 302 | .cmdsize = cmdsize, |
| 303 | .platform = platform.toApplePlatform(), | 303 | .platform = platform.toApplePlatform(), |
| 304 | .minos = platform.toAppleVersion(), | 304 | .minos = platform.toAppleVersion(), |
| ... | @@ -307,7 +307,7 @@ pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticV | ... | @@ -307,7 +307,7 @@ pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticV |
| 307 | else | 307 | else |
| 308 | platform.toAppleVersion(), | 308 | platform.toAppleVersion(), |
| 309 | .ntools = 1, | 309 | .ntools = 1, |
| 310 | }); | 310 | }), .little); |
| 311 | try writer.writeAll(mem.asBytes(&macho.build_tool_version{ | 311 | try writer.writeAll(mem.asBytes(&macho.build_tool_version{ |
| 312 | .tool = .ZIG, | 312 | .tool = .ZIG, |
| 313 | .version = 0x0, | 313 | .version = 0x0, |
src/link/MachO/relocatable.zig+29-33| ... | @@ -205,35 +205,32 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? | ... | @@ -205,35 +205,32 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? |
| 205 | state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(macho_file)}); | 205 | state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(macho_file)}); |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | var buffer = std.array_list.Managed(u8).init(gpa); | 208 | const buffer = try gpa.alloc(u8, total_size); |
| 209 | defer buffer.deinit(); | 209 | defer gpa.free(buffer); |
| 210 | try buffer.ensureTotalCapacityPrecise(total_size); | 210 | var writer: Writer = .fixed(buffer); |
| 211 | const writer = buffer.writer(); | ||
| 212 | 211 | ||
| 213 | // Write magic | 212 | // Write magic |
| 214 | try writer.writeAll(Archive.ARMAG); | 213 | writer.writeAll(Archive.ARMAG) catch unreachable; |
| 215 | 214 | ||
| 216 | // Write symtab | 215 | // Write symtab |
| 217 | ar_symtab.write(format, macho_file, writer) catch |err| switch (err) { | 216 | ar_symtab.write(format, macho_file, &writer) catch |err| |
| 218 | error.OutOfMemory => return error.OutOfMemory, | 217 | return diags.fail("failed to write archive symbol table: {t}", .{err}); |
| 219 | else => |e| return diags.fail("failed to write archive symbol table: {s}", .{@errorName(e)}), | ||
| 220 | }; | ||
| 221 | 218 | ||
| 222 | // Write object files | 219 | // Write object files |
| 223 | for (files.items) |index| { | 220 | for (files.items) |index| { |
| 224 | const aligned = mem.alignForward(usize, buffer.items.len, 2); | 221 | const aligned = mem.alignForward(usize, writer.end, 2); |
| 225 | const padding = aligned - buffer.items.len; | 222 | const padding = aligned - writer.end; |
| 226 | if (padding > 0) { | 223 | if (padding > 0) { |
| 227 | try writer.writeByteNTimes(0, padding); | 224 | writer.splatByteAll(0, padding) catch unreachable; |
| 228 | } | 225 | } |
| 229 | macho_file.getFile(index).?.writeAr(format, macho_file, writer) catch |err| | 226 | macho_file.getFile(index).?.writeAr(format, macho_file, &writer) catch |err| |
| 230 | return diags.fail("failed to write archive: {s}", .{@errorName(err)}); | 227 | return diags.fail("failed to write archive: {t}", .{err}); |
| 231 | } | 228 | } |
| 232 | 229 | ||
| 233 | assert(buffer.items.len == total_size); | 230 | assert(writer.end == total_size); |
| 234 | 231 | ||
| 235 | try macho_file.setEndPos(total_size); | 232 | try macho_file.setEndPos(total_size); |
| 236 | try macho_file.pwriteAll(buffer.items, 0); | 233 | try macho_file.pwriteAll(writer.buffered(), 0); |
| 237 | 234 | ||
| 238 | if (diags.hasErrors()) return error.LinkFailure; | 235 | if (diags.hasErrors()) return error.LinkFailure; |
| 239 | } | 236 | } |
| ... | @@ -693,8 +690,7 @@ fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struc | ... | @@ -693,8 +690,7 @@ fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struc |
| 693 | const buffer = try gpa.alloc(u8, needed_size); | 690 | const buffer = try gpa.alloc(u8, needed_size); |
| 694 | defer gpa.free(buffer); | 691 | defer gpa.free(buffer); |
| 695 | 692 | ||
| 696 | var stream = std.io.fixedBufferStream(buffer); | 693 | var writer: Writer = .fixed(buffer); |
| 697 | const writer = stream.writer(); | ||
| 698 | 694 | ||
| 699 | var ncmds: usize = 0; | 695 | var ncmds: usize = 0; |
| 700 | 696 | ||
| ... | @@ -702,43 +698,43 @@ fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struc | ... | @@ -702,43 +698,43 @@ fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struc |
| 702 | { | 698 | { |
| 703 | assert(macho_file.segments.items.len == 1); | 699 | assert(macho_file.segments.items.len == 1); |
| 704 | const seg = macho_file.segments.items[0]; | 700 | const seg = macho_file.segments.items[0]; |
| 705 | writer.writeStruct(seg) catch |err| switch (err) { | 701 | writer.writeStruct(seg, .little) catch |err| switch (err) { |
| 706 | error.NoSpaceLeft => unreachable, | 702 | error.WriteFailed => unreachable, |
| 707 | }; | 703 | }; |
| 708 | for (macho_file.sections.items(.header)) |header| { | 704 | for (macho_file.sections.items(.header)) |header| { |
| 709 | writer.writeStruct(header) catch |err| switch (err) { | 705 | writer.writeStruct(header, .little) catch |err| switch (err) { |
| 710 | error.NoSpaceLeft => unreachable, | 706 | error.WriteFailed => unreachable, |
| 711 | }; | 707 | }; |
| 712 | } | 708 | } |
| 713 | ncmds += 1; | 709 | ncmds += 1; |
| 714 | } | 710 | } |
| 715 | 711 | ||
| 716 | writer.writeStruct(macho_file.data_in_code_cmd) catch |err| switch (err) { | 712 | writer.writeStruct(macho_file.data_in_code_cmd, .little) catch |err| switch (err) { |
| 717 | error.NoSpaceLeft => unreachable, | 713 | error.WriteFailed => unreachable, |
| 718 | }; | 714 | }; |
| 719 | ncmds += 1; | 715 | ncmds += 1; |
| 720 | writer.writeStruct(macho_file.symtab_cmd) catch |err| switch (err) { | 716 | writer.writeStruct(macho_file.symtab_cmd, .little) catch |err| switch (err) { |
| 721 | error.NoSpaceLeft => unreachable, | 717 | error.WriteFailed => unreachable, |
| 722 | }; | 718 | }; |
| 723 | ncmds += 1; | 719 | ncmds += 1; |
| 724 | writer.writeStruct(macho_file.dysymtab_cmd) catch |err| switch (err) { | 720 | writer.writeStruct(macho_file.dysymtab_cmd, .little) catch |err| switch (err) { |
| 725 | error.NoSpaceLeft => unreachable, | 721 | error.WriteFailed => unreachable, |
| 726 | }; | 722 | }; |
| 727 | ncmds += 1; | 723 | ncmds += 1; |
| 728 | 724 | ||
| 729 | if (macho_file.platform.isBuildVersionCompatible()) { | 725 | if (macho_file.platform.isBuildVersionCompatible()) { |
| 730 | load_commands.writeBuildVersionLC(macho_file.platform, macho_file.sdk_version, writer) catch |err| switch (err) { | 726 | load_commands.writeBuildVersionLC(macho_file.platform, macho_file.sdk_version, &writer) catch |err| switch (err) { |
| 731 | error.NoSpaceLeft => unreachable, | 727 | error.WriteFailed => unreachable, |
| 732 | }; | 728 | }; |
| 733 | ncmds += 1; | 729 | ncmds += 1; |
| 734 | } else { | 730 | } else { |
| 735 | load_commands.writeVersionMinLC(macho_file.platform, macho_file.sdk_version, writer) catch |err| switch (err) { | 731 | load_commands.writeVersionMinLC(macho_file.platform, macho_file.sdk_version, &writer) catch |err| switch (err) { |
| 736 | error.NoSpaceLeft => unreachable, | 732 | error.WriteFailed => unreachable, |
| 737 | }; | 733 | }; |
| 738 | ncmds += 1; | 734 | ncmds += 1; |
| 739 | } | 735 | } |
| 740 | 736 | ||
| 741 | assert(stream.pos == needed_size); | 737 | assert(writer.end == needed_size); |
| 742 | 738 | ||
| 743 | try macho_file.pwriteAll(buffer, @sizeOf(macho.mach_header_64)); | 739 | try macho_file.pwriteAll(buffer, @sizeOf(macho.mach_header_64)); |
| 744 | 740 |
src/link/MachO/synthetic.zig+12-12| ... | @@ -27,7 +27,7 @@ pub const GotSection = struct { | ... | @@ -27,7 +27,7 @@ pub const GotSection = struct { |
| 27 | return got.symbols.items.len * @sizeOf(u64); | 27 | return got.symbols.items.len * @sizeOf(u64); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | pub fn write(got: GotSection, macho_file: *MachO, writer: anytype) !void { | 30 | pub fn write(got: GotSection, macho_file: *MachO, writer: *Writer) !void { |
| 31 | const tracy = trace(@src()); | 31 | const tracy = trace(@src()); |
| 32 | defer tracy.end(); | 32 | defer tracy.end(); |
| 33 | for (got.symbols.items) |ref| { | 33 | for (got.symbols.items) |ref| { |
| ... | @@ -89,7 +89,7 @@ pub const StubsSection = struct { | ... | @@ -89,7 +89,7 @@ pub const StubsSection = struct { |
| 89 | return stubs.symbols.items.len * header.reserved2; | 89 | return stubs.symbols.items.len * header.reserved2; |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | pub fn write(stubs: StubsSection, macho_file: *MachO, writer: anytype) !void { | 92 | pub fn write(stubs: StubsSection, macho_file: *MachO, writer: *Writer) !void { |
| 93 | const tracy = trace(@src()); | 93 | const tracy = trace(@src()); |
| 94 | defer tracy.end(); | 94 | defer tracy.end(); |
| 95 | const cpu_arch = macho_file.getTarget().cpu.arch; | 95 | const cpu_arch = macho_file.getTarget().cpu.arch; |
| ... | @@ -174,7 +174,7 @@ pub const StubsHelperSection = struct { | ... | @@ -174,7 +174,7 @@ pub const StubsHelperSection = struct { |
| 174 | return s; | 174 | return s; |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | pub fn write(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: anytype) !void { | 177 | pub fn write(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: *Writer) !void { |
| 178 | const tracy = trace(@src()); | 178 | const tracy = trace(@src()); |
| 179 | defer tracy.end(); | 179 | defer tracy.end(); |
| 180 | 180 | ||
| ... | @@ -217,7 +217,7 @@ pub const StubsHelperSection = struct { | ... | @@ -217,7 +217,7 @@ pub const StubsHelperSection = struct { |
| 217 | } | 217 | } |
| 218 | } | 218 | } |
| 219 | 219 | ||
| 220 | fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: anytype) !void { | 220 | fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: *Writer) !void { |
| 221 | _ = stubs_helper; | 221 | _ = stubs_helper; |
| 222 | const obj = macho_file.getInternalObject().?; | 222 | const obj = macho_file.getInternalObject().?; |
| 223 | const cpu_arch = macho_file.getTarget().cpu.arch; | 223 | const cpu_arch = macho_file.getTarget().cpu.arch; |
| ... | @@ -273,7 +273,7 @@ pub const LaSymbolPtrSection = struct { | ... | @@ -273,7 +273,7 @@ pub const LaSymbolPtrSection = struct { |
| 273 | return macho_file.stubs.symbols.items.len * @sizeOf(u64); | 273 | return macho_file.stubs.symbols.items.len * @sizeOf(u64); |
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | pub fn write(laptr: LaSymbolPtrSection, macho_file: *MachO, writer: anytype) !void { | 276 | pub fn write(laptr: LaSymbolPtrSection, macho_file: *MachO, writer: *Writer) !void { |
| 277 | const tracy = trace(@src()); | 277 | const tracy = trace(@src()); |
| 278 | defer tracy.end(); | 278 | defer tracy.end(); |
| 279 | _ = laptr; | 279 | _ = laptr; |
| ... | @@ -323,7 +323,7 @@ pub const TlvPtrSection = struct { | ... | @@ -323,7 +323,7 @@ pub const TlvPtrSection = struct { |
| 323 | return tlv.symbols.items.len * @sizeOf(u64); | 323 | return tlv.symbols.items.len * @sizeOf(u64); |
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | pub fn write(tlv: TlvPtrSection, macho_file: *MachO, writer: anytype) !void { | 326 | pub fn write(tlv: TlvPtrSection, macho_file: *MachO, writer: *Writer) !void { |
| 327 | const tracy = trace(@src()); | 327 | const tracy = trace(@src()); |
| 328 | defer tracy.end(); | 328 | defer tracy.end(); |
| 329 | 329 | ||
| ... | @@ -394,7 +394,7 @@ pub const ObjcStubsSection = struct { | ... | @@ -394,7 +394,7 @@ pub const ObjcStubsSection = struct { |
| 394 | return objc.symbols.items.len * entrySize(macho_file.getTarget().cpu.arch); | 394 | return objc.symbols.items.len * entrySize(macho_file.getTarget().cpu.arch); |
| 395 | } | 395 | } |
| 396 | 396 | ||
| 397 | pub fn write(objc: ObjcStubsSection, macho_file: *MachO, writer: anytype) !void { | 397 | pub fn write(objc: ObjcStubsSection, macho_file: *MachO, writer: *Writer) !void { |
| 398 | const tracy = trace(@src()); | 398 | const tracy = trace(@src()); |
| 399 | defer tracy.end(); | 399 | defer tracy.end(); |
| 400 | 400 | ||
| ... | @@ -487,7 +487,7 @@ pub const Indsymtab = struct { | ... | @@ -487,7 +487,7 @@ pub const Indsymtab = struct { |
| 487 | macho_file.dysymtab_cmd.nindirectsyms = ind.nsyms(macho_file); | 487 | macho_file.dysymtab_cmd.nindirectsyms = ind.nsyms(macho_file); |
| 488 | } | 488 | } |
| 489 | 489 | ||
| 490 | pub fn write(ind: Indsymtab, macho_file: *MachO, writer: anytype) !void { | 490 | pub fn write(ind: Indsymtab, macho_file: *MachO, writer: *Writer) !void { |
| 491 | const tracy = trace(@src()); | 491 | const tracy = trace(@src()); |
| 492 | defer tracy.end(); | 492 | defer tracy.end(); |
| 493 | 493 | ||
| ... | @@ -564,7 +564,7 @@ pub const DataInCode = struct { | ... | @@ -564,7 +564,7 @@ pub const DataInCode = struct { |
| 564 | macho_file.data_in_code_cmd.datasize = math.cast(u32, dice.size()) orelse return error.Overflow; | 564 | macho_file.data_in_code_cmd.datasize = math.cast(u32, dice.size()) orelse return error.Overflow; |
| 565 | } | 565 | } |
| 566 | 566 | ||
| 567 | pub fn write(dice: DataInCode, macho_file: *MachO, writer: anytype) !void { | 567 | pub fn write(dice: DataInCode, macho_file: *MachO, writer: *Writer) !void { |
| 568 | const base_address = if (!macho_file.base.isRelocatable()) | 568 | const base_address = if (!macho_file.base.isRelocatable()) |
| 569 | macho_file.getTextSegment().vmaddr | 569 | macho_file.getTextSegment().vmaddr |
| 570 | else | 570 | else |
| ... | @@ -572,11 +572,11 @@ pub const DataInCode = struct { | ... | @@ -572,11 +572,11 @@ pub const DataInCode = struct { |
| 572 | for (dice.entries.items) |entry| { | 572 | for (dice.entries.items) |entry| { |
| 573 | const atom_address = entry.atom_ref.getAtom(macho_file).?.getAddress(macho_file); | 573 | const atom_address = entry.atom_ref.getAtom(macho_file).?.getAddress(macho_file); |
| 574 | const offset = atom_address + entry.offset - base_address; | 574 | const offset = atom_address + entry.offset - base_address; |
| 575 | try writer.writeStruct(macho.data_in_code_entry{ | 575 | try writer.writeStruct(@as(macho.data_in_code_entry, .{ |
| 576 | .offset = @intCast(offset), | 576 | .offset = @intCast(offset), |
| 577 | .length = entry.length, | 577 | .length = entry.length, |
| 578 | .kind = entry.kind, | 578 | .kind = entry.kind, |
| 579 | }); | 579 | }), .little); |
| 580 | } | 580 | } |
| 581 | } | 581 | } |
| 582 | 582 | ||
| ... | @@ -594,7 +594,7 @@ const assert = std.debug.assert; | ... | @@ -594,7 +594,7 @@ const assert = std.debug.assert; |
| 594 | const macho = std.macho; | 594 | const macho = std.macho; |
| 595 | const math = std.math; | 595 | const math = std.math; |
| 596 | const Allocator = std.mem.Allocator; | 596 | const Allocator = std.mem.Allocator; |
| 597 | const Writer = std.io.Writer; | 597 | const Writer = std.Io.Writer; |
| 598 | 598 | ||
| 599 | const trace = @import("../../tracy.zig").trace; | 599 | const trace = @import("../../tracy.zig").trace; |
| 600 | const MachO = @import("../MachO.zig"); | 600 | const MachO = @import("../MachO.zig"); |