authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-16 19:32:05-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-28 18:30:57-07:00
logcc931660eb3e5b7251944c727808aa36e72c1e52
treec6564aff1d2e77163cfce1cd8e599a187ce9274a
parent2dc6ddd7e8cfb83f5ffd57b8b40f33dde9de892d

link.MachO: update to not use GenericWriter


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 {
23812381 .vtable = &.{
23822382 .drain = fixedDrain,
23832383 .flush = noopFlush,
2384 .rebase = failingRebase,
23842385 },
23852386 .buffer = array_list.allocatedSlice(),
23862387 .end = array_list.items.len,
lib/std/macho.zig-2
......@@ -1883,10 +1883,8 @@ pub const GenericBlob = extern struct {
18831883pub const data_in_code_entry = extern struct {
18841884 /// From mach_header to start of data range.
18851885 offset: u32,
1886
18871886 /// Number of bytes in data range.
18881887 length: u16,
1889
18901888 /// A DICE_KIND value.
18911889 kind: u16,
18921890};
src/link/MachO.zig+65-65
......@@ -589,7 +589,7 @@ pub fn flush(
589589 );
590590
591591 const ncmds, const sizeofcmds, const uuid_cmd_offset = self.writeLoadCommands() catch |err| switch (err) {
592 error.NoSpaceLeft => unreachable,
592 error.WriteFailed => unreachable,
593593 error.OutOfMemory => return error.OutOfMemory,
594594 error.LinkFailure => return error.LinkFailure,
595595 };
......@@ -1074,7 +1074,7 @@ fn accessLibPath(
10741074
10751075 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
10761076 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 });
10781078 try checked_paths.append(try arena.dupe(u8, test_path.items));
10791079 fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {
10801080 error.FileNotFound => continue,
......@@ -1097,7 +1097,7 @@ fn accessFrameworkPath(
10971097
10981098 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
10991099 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}", .{
11011101 search_dir,
11021102 name,
11031103 name,
......@@ -1178,9 +1178,9 @@ fn parseDependentDylibs(self: *MachO) !void {
11781178 for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| {
11791179 test_path.clearRetainingCapacity();
11801180 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 });
11821182 } else {
1183 try test_path.writer().print("{s}{s}", .{ path, ext });
1183 try test_path.print("{s}{s}", .{ path, ext });
11841184 }
11851185 try checked_paths.append(try arena.dupe(u8, test_path.items));
11861186 fs.cwd().access(test_path.items, .{}) catch |err| switch (err) {
......@@ -2528,8 +2528,8 @@ fn writeThunkWorker(self: *MachO, thunk: Thunk) void {
25282528 fn doWork(th: Thunk, buffer: []u8, macho_file: *MachO) !void {
25292529 const off = try macho_file.cast(usize, th.value);
25302530 const size = th.size();
2531 var stream = std.io.fixedBufferStream(buffer[off..][0..size]);
2532 try th.write(macho_file, stream.writer());
2531 var stream: Writer = .fixed(buffer[off..][0..size]);
2532 try th.write(macho_file, &stream);
25332533 }
25342534 }.doWork;
25352535 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 {
25562556
25572557 const doWork = struct {
25582558 fn doWork(macho_file: *MachO, tag: Tag, buffer: []u8) !void {
2559 var stream = std.io.fixedBufferStream(buffer);
2559 var stream: Writer = .fixed(buffer);
25602560 switch (tag) {
25612561 .eh_frame => eh_frame.write(macho_file, buffer),
25622562 .unwind_info => try macho_file.unwind_info.write(macho_file, buffer),
2563 .got => try macho_file.got.write(macho_file, stream.writer()),
2564 .stubs => try macho_file.stubs.write(macho_file, stream.writer()),
2565 .la_symbol_ptr => try macho_file.la_symbol_ptr.write(macho_file, stream.writer()),
2566 .tlv_ptr => try macho_file.tlv_ptr.write(macho_file, stream.writer()),
2567 .objc_stubs => try macho_file.objc_stubs.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),
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),
2567 .objc_stubs => try macho_file.objc_stubs.write(macho_file, &stream),
25682568 }
25692569 }
25702570 }.doWork;
......@@ -2605,8 +2605,8 @@ fn updateLazyBindSizeWorker(self: *MachO) void {
26052605 try macho_file.lazy_bind_section.updateSize(macho_file);
26062606 const sect_id = macho_file.stubs_helper_sect_index.?;
26072607 const out = &macho_file.sections.items(.out)[sect_id];
2608 var stream = std.io.fixedBufferStream(out.items);
2609 try macho_file.stubs_helper.write(macho_file, stream.writer());
2608 var stream: Writer = .fixed(out.items);
2609 try macho_file.stubs_helper.write(macho_file, &stream);
26102610 }
26112611 }.doWork;
26122612 doWork(self) catch |err|
......@@ -2669,18 +2669,17 @@ fn writeDyldInfo(self: *MachO) !void {
26692669 defer gpa.free(buffer);
26702670 @memset(buffer, 0);
26712671
2672 var stream = std.io.fixedBufferStream(buffer);
2673 const writer = stream.writer();
2674
2675 try self.rebase_section.write(writer);
2676 try stream.seekTo(cmd.bind_off - base_off);
2677 try self.bind_section.write(writer);
2678 try stream.seekTo(cmd.weak_bind_off - base_off);
2679 try self.weak_bind_section.write(writer);
2680 try stream.seekTo(cmd.lazy_bind_off - base_off);
2681 try self.lazy_bind_section.write(writer);
2682 try stream.seekTo(cmd.export_off - base_off);
2683 try self.export_trie.write(writer);
2672 var writer: Writer = .fixed(buffer);
2673
2674 try self.rebase_section.write(&writer);
2675 writer.end = cmd.bind_off - base_off;
2676 try self.bind_section.write(&writer);
2677 writer.end = cmd.weak_bind_off - base_off;
2678 try self.weak_bind_section.write(&writer);
2679 writer.end = cmd.lazy_bind_off - base_off;
2680 try self.lazy_bind_section.write(&writer);
2681 writer.end = cmd.export_off - base_off;
2682 try self.export_trie.write(&writer);
26842683 try self.pwriteAll(buffer, cmd.rebase_off);
26852684}
26862685
......@@ -2689,10 +2688,10 @@ pub fn writeDataInCode(self: *MachO) !void {
26892688 defer tracy.end();
26902689 const gpa = self.base.comp.gpa;
26912690 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());
26932692 defer buffer.deinit();
2694 try self.data_in_code.write(self, buffer.writer());
2695 try self.pwriteAll(buffer.items, cmd.dataoff);
2693 self.data_in_code.write(self, &buffer.writer) catch return error.OutOfMemory;
2694 try self.pwriteAll(buffer.written(), cmd.dataoff);
26962695}
26972696
26982697fn writeIndsymtab(self: *MachO) !void {
......@@ -2701,10 +2700,11 @@ fn writeIndsymtab(self: *MachO) !void {
27012700 const gpa = self.base.comp.gpa;
27022701 const cmd = self.dysymtab_cmd;
27032702 const needed_size = cmd.nindirectsyms * @sizeOf(u32);
2704 var buffer = try std.array_list.Managed(u8).initCapacity(gpa, needed_size);
2705 defer buffer.deinit();
2706 try self.indsymtab.write(self, buffer.writer());
2707 try self.pwriteAll(buffer.items, cmd.indirectsymoff);
2703 const buffer = try gpa.alloc(u8, needed_size);
2704 defer gpa.free(buffer);
2705 var writer: Writer = .fixed(buffer);
2706 try self.indsymtab.write(self, &writer);
2707 try self.pwriteAll(buffer, cmd.indirectsymoff);
27082708}
27092709
27102710pub fn writeSymtabToFile(self: *MachO) !void {
......@@ -2821,8 +2821,7 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {
28212821 const buffer = try gpa.alloc(u8, needed_size);
28222822 defer gpa.free(buffer);
28232823
2824 var stream = std.io.fixedBufferStream(buffer);
2825 const writer = stream.writer();
2824 var writer: Writer = .fixed(buffer);
28262825
28272826 var ncmds: usize = 0;
28282827
......@@ -2831,26 +2830,26 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {
28312830 const slice = self.sections.slice();
28322831 var sect_id: usize = 0;
28332832 for (self.segments.items) |seg| {
2834 try writer.writeStruct(seg);
2833 try writer.writeStruct(seg, .little);
28352834 for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| {
2836 try writer.writeStruct(header);
2835 try writer.writeStruct(header, .little);
28372836 }
28382837 sect_id += seg.nsects;
28392838 }
28402839 ncmds += self.segments.items.len;
28412840 }
28422841
2843 try writer.writeStruct(self.dyld_info_cmd);
2842 try writer.writeStruct(self.dyld_info_cmd, .little);
28442843 ncmds += 1;
2845 try writer.writeStruct(self.function_starts_cmd);
2844 try writer.writeStruct(self.function_starts_cmd, .little);
28462845 ncmds += 1;
2847 try writer.writeStruct(self.data_in_code_cmd);
2846 try writer.writeStruct(self.data_in_code_cmd, .little);
28482847 ncmds += 1;
2849 try writer.writeStruct(self.symtab_cmd);
2848 try writer.writeStruct(self.symtab_cmd, .little);
28502849 ncmds += 1;
2851 try writer.writeStruct(self.dysymtab_cmd);
2850 try writer.writeStruct(self.dysymtab_cmd, .little);
28522851 ncmds += 1;
2853 try load_commands.writeDylinkerLC(writer);
2852 try load_commands.writeDylinkerLC(&writer);
28542853 ncmds += 1;
28552854
28562855 if (self.getInternalObject()) |obj| {
......@@ -2861,44 +2860,44 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {
28612860 0
28622861 else
28632862 @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, .{
28652864 .entryoff = entryoff,
28662865 .stacksize = self.base.stack_size,
2867 });
2866 }), .little);
28682867 ncmds += 1;
28692868 }
28702869 }
28712870
28722871 if (self.base.isDynLib()) {
2873 try load_commands.writeDylibIdLC(self, writer);
2872 try load_commands.writeDylibIdLC(self, &writer);
28742873 ncmds += 1;
28752874 }
28762875
28772876 for (self.rpath_list) |rpath| {
2878 try load_commands.writeRpathLC(rpath, writer);
2877 try load_commands.writeRpathLC(rpath, &writer);
28792878 ncmds += 1;
28802879 }
28812880 if (comp.config.any_sanitize_thread) {
28822881 const path = try comp.tsan_lib.?.full_object_path.toString(gpa);
28832882 defer gpa.free(path);
28842883 const rpath = std.fs.path.dirname(path) orelse ".";
2885 try load_commands.writeRpathLC(rpath, writer);
2884 try load_commands.writeRpathLC(rpath, &writer);
28862885 ncmds += 1;
28872886 }
28882887
2889 try writer.writeStruct(macho.source_version_command{ .version = 0 });
2888 try writer.writeStruct(@as(macho.source_version_command, .{ .version = 0 }), .little);
28902889 ncmds += 1;
28912890
28922891 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);
28942893 ncmds += 1;
28952894 } else {
2896 try load_commands.writeVersionMinLC(self.platform, self.sdk_version, writer);
2895 try load_commands.writeVersionMinLC(self.platform, self.sdk_version, &writer);
28972896 ncmds += 1;
28982897 }
28992898
2900 const uuid_cmd_offset = @sizeOf(macho.mach_header_64) + stream.pos;
2901 try writer.writeStruct(self.uuid_cmd);
2899 const uuid_cmd_offset = @sizeOf(macho.mach_header_64) + writer.end;
2900 try writer.writeStruct(self.uuid_cmd, .little);
29022901 ncmds += 1;
29032902
29042903 for (self.dylibs.items) |index| {
......@@ -2916,16 +2915,16 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } {
29162915 .timestamp = dylib_id.timestamp,
29172916 .current_version = dylib_id.current_version,
29182917 .compatibility_version = dylib_id.compatibility_version,
2919 }, writer);
2918 }, &writer);
29202919 ncmds += 1;
29212920 }
29222921
29232922 if (self.requiresCodeSig()) {
2924 try writer.writeStruct(self.codesig_cmd);
2923 try writer.writeStruct(self.codesig_cmd, .little);
29252924 ncmds += 1;
29262925 }
29272926
2928 assert(stream.pos == needed_size);
2927 assert(writer.end == needed_size);
29292928
29302929 try self.pwriteAll(buffer, @sizeOf(macho.mach_header_64));
29312930
......@@ -3014,25 +3013,26 @@ pub fn writeCodeSignaturePadding(self: *MachO, code_sig: *CodeSignature) !void {
30143013pub fn writeCodeSignature(self: *MachO, code_sig: *CodeSignature) !void {
30153014 const seg = self.getTextSegment();
30163015 const offset = self.codesig_cmd.dataoff;
3016 const gpa = self.base.comp.gpa;
30173017
3018 var buffer = std.array_list.Managed(u8).init(self.base.comp.gpa);
3019 defer buffer.deinit();
3020 try buffer.ensureTotalCapacityPrecise(code_sig.size());
3018 const buffer = try gpa.alloc(u8, code_sig.size());
3019 defer gpa.free(buffer);
3020 var writer: Writer = .fixed(buffer);
30213021 try code_sig.writeAdhocSignature(self, .{
30223022 .file = self.base.file.?,
30233023 .exec_seg_base = seg.fileoff,
30243024 .exec_seg_limit = seg.filesize,
30253025 .file_size = offset,
30263026 .dylib = self.base.isDynLib(),
3027 }, buffer.writer());
3028 assert(buffer.items.len == code_sig.size());
3027 }, &writer);
3028 assert(writer.buffered().len == code_sig.size());
30293029
30303030 log.debug("writing code signature from 0x{x} to 0x{x}", .{
30313031 offset,
3032 offset + buffer.items.len,
3032 offset + writer.buffered().len,
30333033 });
30343034
3035 try self.pwriteAll(buffer.items, offset);
3035 try self.pwriteAll(writer.buffered(), offset);
30363036}
30373037
30383038pub fn updateFunc(
......@@ -5372,7 +5372,7 @@ const macho = std.macho;
53725372const math = std.math;
53735373const mem = std.mem;
53745374const meta = std.meta;
5375const Writer = std.io.Writer;
5375const Writer = std.Io.Writer;
53765376
53775377const aarch64 = codegen.aarch64.encoding;
53785378const bind = @import("MachO/dyld_info/bind.zig");
src/link/MachO/Archive.zig+18-38
......@@ -81,34 +81,20 @@ pub fn writeHeader(
8181 object_name: []const u8,
8282 object_size: usize,
8383 format: Format,
84 writer: anytype,
84 writer: *Writer,
8585) !void {
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);
86 var hdr: ar_hdr = .{};
10187
10288 const object_name_len = mem.alignForward(usize, object_name.len + 1, ptrWidth(format));
10389 const total_object_size = object_size + object_name_len;
10490
10591 {
106 var stream = std.io.fixedBufferStream(&hdr.ar_name);
107 stream.writer().print("#1/{d}", .{object_name_len}) catch unreachable;
92 var stream: Writer = .fixed(&hdr.ar_name);
93 stream.print("#1/{d}", .{object_name_len}) catch unreachable;
10894 }
10995 {
110 var stream = std.io.fixedBufferStream(&hdr.ar_size);
111 stream.writer().print("{d}", .{total_object_size}) catch unreachable;
96 var stream: Writer = .fixed(&hdr.ar_size);
97 stream.print("{d}", .{total_object_size}) catch unreachable;
11298 }
11399
114100 try writer.writeAll(mem.asBytes(&hdr));
......@@ -116,7 +102,7 @@ pub fn writeHeader(
116102
117103 const padding = object_name_len - object_name.len - 1;
118104 if (padding > 0) {
119 try writer.writeByteNTimes(0, padding);
105 try writer.splatByteAll(0, padding);
120106 }
121107}
122108
......@@ -138,25 +124,19 @@ pub const SYMDEF64_SORTED = "__.SYMDEF_64 SORTED";
138124
139125pub const ar_hdr = extern struct {
140126 /// Member file name, sometimes / terminated.
141 ar_name: [16]u8,
142
127 ar_name: [16]u8 = "0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20".*,
143128 /// File date, decimal seconds since Epoch.
144 ar_date: [12]u8,
145
129 ar_date: [12]u8 = "0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20".*,
146130 /// User ID, in ASCII format.
147 ar_uid: [6]u8,
148
131 ar_uid: [6]u8 = "0\x20\x20\x20\x20\x20".*,
149132 /// Group ID, in ASCII format.
150 ar_gid: [6]u8,
151
133 ar_gid: [6]u8 = "0\x20\x20\x20\x20\x20".*,
152134 /// File mode, in ASCII octal.
153 ar_mode: [8]u8,
154
135 ar_mode: [8]u8 = "0\x20\x20\x20\x20\x20\x20\x20".*,
155136 /// File size, in ASCII decimal.
156 ar_size: [10]u8,
157
137 ar_size: [10]u8 = "0\x20\x20\x20\x20\x20\x20\x20\x20\x20".*,
158138 /// Always contains ARFMAG.
159 ar_fmag: [2]u8,
139 ar_fmag: [2]u8 = ARFMAG.*,
160140
161141 fn date(self: ar_hdr) !u64 {
162142 const value = mem.trimEnd(u8, &self.ar_date, &[_]u8{@as(u8, 0x20)});
......@@ -201,7 +181,7 @@ pub const ArSymtab = struct {
201181 return ptr_width + ar.entries.items.len * 2 * ptr_width + ptr_width + mem.alignForward(usize, ar.strtab.buffer.items.len, ptr_width);
202182 }
203183
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 {
205185 const ptr_width = ptrWidth(format);
206186 // Header
207187 try writeHeader(SYMDEF, ar.size(format), format, writer);
......@@ -226,7 +206,7 @@ pub const ArSymtab = struct {
226206 // Strtab
227207 try writer.writeAll(ar.strtab.buffer.items);
228208 if (padding > 0) {
229 try writer.writeByteNTimes(0, padding);
209 try writer.splatByteAll(0, padding);
230210 }
231211 }
232212
......@@ -275,7 +255,7 @@ pub fn ptrWidth(format: Format) usize {
275255 };
276256}
277257
278pub fn writeInt(format: Format, value: u64, writer: anytype) !void {
258pub fn writeInt(format: Format, value: u64, writer: *Writer) !void {
279259 switch (format) {
280260 .p32 => try writer.writeInt(u32, std.math.cast(u32, value) orelse return error.Overflow, .little),
281261 .p64 => try writer.writeInt(u64, value, .little),
......@@ -299,7 +279,7 @@ const mem = std.mem;
299279const std = @import("std");
300280const Allocator = std.mem.Allocator;
301281const Path = std.Build.Cache.Path;
302const Writer = std.io.Writer;
282const Writer = std.Io.Writer;
303283
304284const Archive = @This();
305285const 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 {
581581 relocs_log.debug("{x}: {s}", .{ self.value, name });
582582
583583 var has_error = false;
584 var stream = std.io.fixedBufferStream(buffer);
584 var stream: Writer = .fixed(buffer);
585585 var i: usize = 0;
586586 while (i < relocs.len) : (i += 1) {
587587 const rel = relocs[i];
......@@ -592,8 +592,8 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void {
592592 if (rel.getTargetSymbol(self, macho_file).getFile(macho_file) == null) continue;
593593 }
594594
595 try stream.seekTo(rel_offset);
596 self.resolveRelocInner(rel, subtractor, buffer, macho_file, stream.writer()) catch |err| {
595 stream.end = rel_offset;
596 self.resolveRelocInner(rel, subtractor, buffer, macho_file, &stream) catch |err| {
597597 switch (err) {
598598 error.RelaxFail => {
599599 const target = switch (rel.tag) {
......@@ -630,6 +630,7 @@ const ResolveError = error{
630630 UnexpectedRemainder,
631631 Overflow,
632632 OutOfMemory,
633 WriteFailed,
633634};
634635
635636fn resolveRelocInner(
......@@ -638,7 +639,7 @@ fn resolveRelocInner(
638639 subtractor: ?Relocation,
639640 code: []u8,
640641 macho_file: *MachO,
641 writer: anytype,
642 writer: *Writer,
642643) ResolveError!void {
643644 const t = &macho_file.base.comp.root_mod.resolved_target.result;
644645 const cpu_arch = t.cpu.arch;
......@@ -1147,7 +1148,7 @@ const math = std.math;
11471148const mem = std.mem;
11481149const log = std.log.scoped(.link);
11491150const relocs_log = std.log.scoped(.link_relocs);
1150const Writer = std.io.Writer;
1151const Writer = std.Io.Writer;
11511152const Allocator = mem.Allocator;
11521153const AtomicBool = std.atomic.Value(bool);
11531154
src/link/MachO/CodeSignature.zig+8-8
......@@ -304,10 +304,10 @@ pub fn writeAdhocSignature(
304304 var hash: [hash_size]u8 = undefined;
305305
306306 if (self.requirements) |*req| {
307 var buf = std.array_list.Managed(u8).init(allocator);
308 defer buf.deinit();
309 try req.write(buf.writer());
310 Sha256.hash(buf.items, &hash, .{});
307 var a: std.Io.Writer.Allocating = .init(allocator);
308 defer a.deinit();
309 try req.write(&a.writer);
310 Sha256.hash(a.written(), &hash, .{});
311311 self.code_directory.addSpecialHash(req.slotType(), hash);
312312
313313 try blobs.append(.{ .requirements = req });
......@@ -316,10 +316,10 @@ pub fn writeAdhocSignature(
316316 }
317317
318318 if (self.entitlements) |*ents| {
319 var buf = std.array_list.Managed(u8).init(allocator);
320 defer buf.deinit();
321 try ents.write(buf.writer());
322 Sha256.hash(buf.items, &hash, .{});
319 var a: std.Io.Writer.Allocating = .init(allocator);
320 defer a.deinit();
321 try ents.write(&a.writer);
322 Sha256.hash(a.written(), &hash, .{});
323323 self.code_directory.addSpecialHash(ents.slotType(), hash);
324324
325325 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
273273 const buffer = try gpa.alloc(u8, needed_size);
274274 defer gpa.free(buffer);
275275
276 var stream = std.io.fixedBufferStream(buffer);
277 const writer = stream.writer();
276 var writer: Writer = .fixed(buffer);
278277
279278 var ncmds: usize = 0;
280279
281280 // UUID comes first presumably to speed up lookup by the consumer like lldb.
282281 @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);
284283 ncmds += 1;
285284
286285 // Segment and section load commands
......@@ -293,11 +292,11 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u
293292 var out_seg = seg;
294293 out_seg.fileoff = 0;
295294 out_seg.filesize = 0;
296 try writer.writeStruct(out_seg);
295 try writer.writeStruct(out_seg, .little);
297296 for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| {
298297 var out_header = header;
299298 out_header.offset = 0;
300 try writer.writeStruct(out_header);
299 try writer.writeStruct(out_header, .little);
301300 }
302301 sect_id += seg.nsects;
303302 }
......@@ -306,19 +305,19 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u
306305 // Next, commit DSYM's __LINKEDIT and __DWARF segments headers.
307306 sect_id = 0;
308307 for (self.segments.items) |seg| {
309 try writer.writeStruct(seg);
308 try writer.writeStruct(seg, .little);
310309 for (self.sections.items[sect_id..][0..seg.nsects]) |header| {
311 try writer.writeStruct(header);
310 try writer.writeStruct(header, .little);
312311 }
313312 sect_id += seg.nsects;
314313 }
315314 ncmds += self.segments.items.len;
316315 }
317316
318 try writer.writeStruct(self.symtab_cmd);
317 try writer.writeStruct(self.symtab_cmd, .little);
319318 ncmds += 1;
320319
321 assert(stream.pos == needed_size);
320 assert(writer.end == needed_size);
322321
323322 try self.file.?.pwriteAll(buffer, @sizeOf(macho.mach_header_64));
324323
......@@ -460,7 +459,7 @@ const math = std.math;
460459const mem = std.mem;
461460const padToIdeal = MachO.padToIdeal;
462461const trace = @import("../../tracy.zig").trace;
463const Writer = std.io.Writer;
462const Writer = std.Io.Writer;
464463
465464const Allocator = mem.Allocator;
466465const MachO = @import("../MachO.zig");
src/link/MachO/InternalObject.zig+1-1
......@@ -261,7 +261,7 @@ fn addObjcMethnameSection(self: *InternalObject, methname: []const u8, macho_fil
261261
262262 sect.offset = @intCast(self.objc_methnames.items.len);
263263 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;
265265
266266 const name_str = try self.addString(gpa, "ltmp");
267267 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 {
293293 const seg = macho_file.getTextSegment();
294294 const header = macho_file.sections.items(.header)[macho_file.unwind_info_sect_index.?];
295295
296 var stream = std.io.fixedBufferStream(buffer);
297 const writer = stream.writer();
296 var writer: Writer = .fixed(buffer);
298297
299298 const common_encodings_offset: u32 = @sizeOf(macho.unwind_info_section_header);
300299 const common_encodings_count: u32 = info.common_encodings_count;
......@@ -303,14 +302,14 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {
303302 const indexes_offset: u32 = personalities_offset + personalities_count * @sizeOf(u32);
304303 const indexes_count: u32 = @as(u32, @intCast(info.pages.items.len + 1));
305304
306 try writer.writeStruct(macho.unwind_info_section_header{
305 try writer.writeStruct(@as(macho.unwind_info_section_header, .{
307306 .commonEncodingsArraySectionOffset = common_encodings_offset,
308307 .commonEncodingsArrayCount = common_encodings_count,
309308 .personalityArraySectionOffset = personalities_offset,
310309 .personalityArrayCount = personalities_count,
311310 .indexSectionOffset = indexes_offset,
312311 .indexCount = indexes_count,
313 });
312 }), .little);
314313
315314 try writer.writeAll(mem.sliceAsBytes(info.common_encodings[0..info.common_encodings_count]));
316315
......@@ -325,42 +324,42 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void {
325324 for (info.pages.items, 0..) |page, i| {
326325 assert(page.count > 0);
327326 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, .{
329328 .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)),
330329 .secondLevelPagesSectionOffset = @as(u32, @intCast(pages_base_offset + i * second_level_page_bytes)),
331330 .lsdaIndexArraySectionOffset = lsda_base_offset +
332331 info.lsdas_lookup.items[page.start] * @sizeOf(macho.unwind_info_section_header_lsda_index_entry),
333 });
332 }), .little);
334333 }
335334
336335 const last_rec = info.records.items[info.records.items.len - 1].getUnwindRecord(macho_file);
337336 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, .{
339338 .functionOffset = sentinel_address,
340339 .secondLevelPagesSectionOffset = 0,
341340 .lsdaIndexArraySectionOffset = lsda_base_offset +
342341 @as(u32, @intCast(info.lsdas.items.len)) * @sizeOf(macho.unwind_info_section_header_lsda_index_entry),
343 });
342 }), .little);
344343
345344 for (info.lsdas.items) |index| {
346345 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, .{
348347 .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)),
349348 .lsdaOffset = @as(u32, @intCast(rec.getLsdaAddress(macho_file) - seg.vmaddr)),
350 });
349 }), .little);
351350 }
352351
353352 for (info.pages.items) |page| {
354 const start = stream.pos;
355 try page.write(info, macho_file, writer);
356 const nwritten = stream.pos - start;
353 const start = writer.end;
354 try page.write(info, macho_file, &writer);
355 const nwritten = writer.end - start;
357356 if (nwritten < second_level_page_bytes) {
358357 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);
360359 }
361360 }
362361
363 @memset(buffer[stream.pos..], 0);
362 @memset(buffer[writer.end..], 0);
364363}
365364
366365fn getOrPutPersonalityFunction(info: *UnwindInfo, ref: MachO.Ref) error{TooManyPersonalities}!u2 {
......@@ -611,33 +610,33 @@ const Page = struct {
611610 } };
612611 }
613612
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 {
615614 const seg = macho_file.getTextSegment();
616615
617616 switch (page.kind) {
618617 .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, .{
620619 .entryPageOffset = @sizeOf(macho.unwind_info_regular_second_level_page_header),
621620 .entryCount = page.count,
622 });
621 }), .little);
623622
624623 for (info.records.items[page.start..][0..page.count]) |ref| {
625624 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, .{
627626 .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)),
628627 .encoding = rec.enc.enc,
629 });
628 }), .little);
630629 }
631630 },
632631 .compressed => {
633632 const entry_offset = @sizeOf(macho.unwind_info_compressed_second_level_page_header) +
634633 @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, .{
636635 .entryPageOffset = entry_offset,
637636 .entryCount = page.count,
638637 .encodingsPageOffset = @sizeOf(macho.unwind_info_compressed_second_level_page_header),
639638 .encodingsCount = page.page_encodings_count,
640 });
639 }), .little);
641640
642641 for (page.page_encodings[0..page.page_encodings_count]) |enc| {
643642 try writer.writeInt(u32, enc.enc, .little);
......@@ -656,7 +655,7 @@ const Page = struct {
656655 .funcOffset = @as(u24, @intCast(rec.getAtomAddress(macho_file) - first_rec.getAtomAddress(macho_file))),
657656 .encodingIndex = @as(u8, @intCast(enc_index)),
658657 };
659 try writer.writeStruct(compressed);
658 try writer.writeStruct(compressed, .little);
660659 }
661660 },
662661 }
......@@ -673,7 +672,7 @@ const macho = std.macho;
673672const math = std.math;
674673const mem = std.mem;
675674const trace = @import("../../tracy.zig").trace;
676const Writer = std.io.Writer;
675const Writer = std.Io.Writer;
677676
678677const Allocator = mem.Allocator;
679678const 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 {
110110fn finalize(rebase: *Rebase, gpa: Allocator) !void {
111111 if (rebase.entries.items.len == 0) return;
112112
113 const writer = rebase.buffer.writer(gpa);
114
115113 log.debug("rebase opcodes", .{});
116114
117115 std.mem.sort(Entry, rebase.entries.items, {}, Entry.lessThan);
118116
117 var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &rebase.buffer);
118 defer rebase.buffer = allocating.toArrayList();
119 const writer = &allocating.writer;
120
119121 try setTypePointer(writer);
120122
121123 var start: usize = 0;
src/link/MachO/dyld_info/Trie.zig+15-10
......@@ -170,8 +170,13 @@ fn finalize(self: *Trie, allocator: Allocator) !void {
170170 }
171171
172172 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
173178 for (ordered_nodes.items) |node_index| {
174 try self.writeNode(node_index, self.buffer.writer(allocator));
179 try self.writeNode(node_index, writer);
175180 }
176181}
177182
......@@ -232,7 +237,7 @@ pub fn deinit(self: *Trie, allocator: Allocator) void {
232237 self.buffer.deinit(allocator);
233238}
234239
235pub fn write(self: Trie, writer: anytype) !void {
240pub fn write(self: Trie, writer: *std.Io.Writer) !void {
236241 if (self.buffer.items.len == 0) return;
237242 try writer.writeAll(self.buffer.items);
238243}
......@@ -243,7 +248,7 @@ pub fn write(self: Trie, writer: anytype) !void {
243248/// iterate over `Trie.ordered_nodes` and call this method on each node.
244249/// This is one of the requirements of the MachO.
245250/// Panics if `finalize` was not called before calling this method.
246fn writeNode(self: *Trie, node_index: Node.Index, writer: anytype) !void {
251fn writeNode(self: *Trie, node_index: Node.Index, writer: *std.Io.Writer) !void {
247252 const slice = self.nodes.slice();
248253 const edges = slice.items(.edges)[node_index];
249254 const is_terminal = slice.items(.is_terminal)[node_index];
......@@ -253,21 +258,21 @@ fn writeNode(self: *Trie, node_index: Node.Index, writer: anytype) !void {
253258 if (is_terminal) {
254259 // Terminal node info: encode export flags and vmaddr offset of this symbol.
255260 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);
257262 // TODO Implement for special flags.
258263 assert(export_flags & macho.EXPORT_SYMBOL_FLAGS_REEXPORT == 0 and
259264 export_flags & macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER == 0);
260 try leb.writeUleb128(info_stream.writer(), export_flags);
261 try leb.writeUleb128(info_stream.writer(), vmaddr_offset);
265 try leb.writeUleb128(&info_stream, export_flags);
266 try leb.writeUleb128(&info_stream, vmaddr_offset);
262267
263268 // Encode the size of the terminal node info.
264269 var size_buf: [@sizeOf(u64)]u8 = undefined;
265 var size_stream = std.io.fixedBufferStream(&size_buf);
266 try leb.writeUleb128(size_stream.writer(), info_stream.pos);
270 var size_stream: std.Io.Writer = .fixed(&size_buf);
271 try leb.writeUleb128(&size_stream, info_stream.end);
267272
268273 // Now, write them to the output stream.
269 try writer.writeAll(size_buf[0..size_stream.pos]);
270 try writer.writeAll(info_buf[0..info_stream.pos]);
274 try writer.writeAll(size_buf[0..size_stream.end]);
275 try writer.writeAll(info_buf[0..info_stream.end]);
271276 } else {
272277 // Non-terminal node is delimited by 0 byte.
273278 try writer.writeByte(0);
src/link/MachO/dyld_info/bind.zig+26-21
......@@ -132,12 +132,14 @@ pub const Bind = struct {
132132 fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void {
133133 if (self.entries.items.len == 0) return;
134134
135 const writer = self.buffer.writer(gpa);
136
137135 log.debug("bind opcodes", .{});
138136
139137 std.mem.sort(Entry, self.entries.items, ctx, Entry.lessThan);
140138
139 var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &self.buffer);
140 defer self.buffer = allocating.toArrayList();
141 const writer = &allocating.writer;
142
141143 var start: usize = 0;
142144 var seg_id: ?u8 = null;
143145 for (self.entries.items, 0..) |entry, i| {
......@@ -151,7 +153,7 @@ pub const Bind = struct {
151153 try done(writer);
152154 }
153155
154 fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: anytype) !void {
156 fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: *std.Io.Writer) !void {
155157 if (entries.len == 0) return;
156158
157159 const seg_id = entries[0].segment_id;
......@@ -263,7 +265,7 @@ pub const Bind = struct {
263265 }
264266 }
265267
266 pub fn write(self: Self, writer: anytype) !void {
268 pub fn write(self: Self, writer: *std.Io.Writer) !void {
267269 try writer.writeAll(self.buffer.items);
268270 }
269271};
......@@ -385,12 +387,14 @@ pub const WeakBind = struct {
385387 fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void {
386388 if (self.entries.items.len == 0) return;
387389
388 const writer = self.buffer.writer(gpa);
389
390390 log.debug("weak bind opcodes", .{});
391391
392392 std.mem.sort(Entry, self.entries.items, ctx, Entry.lessThan);
393393
394 var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &self.buffer);
395 defer self.buffer = allocating.toArrayList();
396 const writer = &allocating.writer;
397
394398 var start: usize = 0;
395399 var seg_id: ?u8 = null;
396400 for (self.entries.items, 0..) |entry, i| {
......@@ -404,7 +408,7 @@ pub const WeakBind = struct {
404408 try done(writer);
405409 }
406410
407 fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: anytype) !void {
411 fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: *std.Io.Writer) !void {
408412 if (entries.len == 0) return;
409413
410414 const seg_id = entries[0].segment_id;
......@@ -505,7 +509,7 @@ pub const WeakBind = struct {
505509 }
506510 }
507511
508 pub fn write(self: Self, writer: anytype) !void {
512 pub fn write(self: Self, writer: *std.Io.Writer) !void {
509513 try writer.writeAll(self.buffer.items);
510514 }
511515};
......@@ -555,8 +559,6 @@ pub const LazyBind = struct {
555559 fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void {
556560 try self.offsets.ensureTotalCapacityPrecise(gpa, self.entries.items.len);
557561
558 const writer = self.buffer.writer(gpa);
559
560562 log.debug("lazy bind opcodes", .{});
561563
562564 var addend: i64 = 0;
......@@ -578,6 +580,9 @@ pub const LazyBind = struct {
578580 break :ord macho.BIND_SPECIAL_DYLIB_SELF;
579581 };
580582
583 var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &self.buffer);
584 defer self.buffer = allocating.toArrayList();
585 const writer = &allocating.writer;
581586 try setSegmentOffset(entry.segment_id, entry.offset, writer);
582587 try setSymbol(name, flags, writer);
583588 try setDylibOrdinal(ordinal, writer);
......@@ -592,30 +597,30 @@ pub const LazyBind = struct {
592597 }
593598 }
594599
595 pub fn write(self: Self, writer: anytype) !void {
600 pub fn write(self: Self, writer: *std.Io.Writer) !void {
596601 try writer.writeAll(self.buffer.items);
597602 }
598603};
599604
600fn setSegmentOffset(segment_id: u8, offset: u64, writer: anytype) !void {
605fn setSegmentOffset(segment_id: u8, offset: u64, writer: *std.Io.Writer) !void {
601606 log.debug(">>> set segment: {d} and offset: {x}", .{ segment_id, offset });
602607 try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @as(u4, @truncate(segment_id)));
603608 try std.leb.writeUleb128(writer, offset);
604609}
605610
606fn setSymbol(name: []const u8, flags: u8, writer: anytype) !void {
611fn setSymbol(name: []const u8, flags: u8, writer: *std.Io.Writer) !void {
607612 log.debug(">>> set symbol: {s} with flags: {x}", .{ name, flags });
608613 try writer.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | @as(u4, @truncate(flags)));
609614 try writer.writeAll(name);
610615 try writer.writeByte(0);
611616}
612617
613fn setTypePointer(writer: anytype) !void {
618fn setTypePointer(writer: *std.Io.Writer) !void {
614619 log.debug(">>> set type: {d}", .{macho.BIND_TYPE_POINTER});
615620 try writer.writeByte(macho.BIND_OPCODE_SET_TYPE_IMM | @as(u4, @truncate(macho.BIND_TYPE_POINTER)));
616621}
617622
618fn setDylibOrdinal(ordinal: i16, writer: anytype) !void {
623fn setDylibOrdinal(ordinal: i16, writer: *std.Io.Writer) !void {
619624 if (ordinal <= 0) {
620625 switch (ordinal) {
621626 macho.BIND_SPECIAL_DYLIB_SELF,
......@@ -639,18 +644,18 @@ fn setDylibOrdinal(ordinal: i16, writer: anytype) !void {
639644 }
640645}
641646
642fn setAddend(addend: i64, writer: anytype) !void {
647fn setAddend(addend: i64, writer: *std.Io.Writer) !void {
643648 log.debug(">>> set addend: {x}", .{addend});
644649 try writer.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB);
645650 try std.leb.writeIleb128(writer, addend);
646651}
647652
648fn doBind(writer: anytype) !void {
653fn doBind(writer: *std.Io.Writer) !void {
649654 log.debug(">>> bind", .{});
650655 try writer.writeByte(macho.BIND_OPCODE_DO_BIND);
651656}
652657
653fn doBindAddAddr(addr: u64, writer: anytype) !void {
658fn doBindAddAddr(addr: u64, writer: *std.Io.Writer) !void {
654659 log.debug(">>> bind with add: {x}", .{addr});
655660 if (std.mem.isAlignedGeneric(u64, addr, @sizeOf(u64))) {
656661 const imm = @divExact(addr, @sizeOf(u64));
......@@ -665,20 +670,20 @@ fn doBindAddAddr(addr: u64, writer: anytype) !void {
665670 try std.leb.writeUleb128(writer, addr);
666671}
667672
668fn doBindTimesSkip(count: usize, skip: u64, writer: anytype) !void {
673fn doBindTimesSkip(count: usize, skip: u64, writer: *std.Io.Writer) !void {
669674 log.debug(">>> bind with count: {d} and skip: {x}", .{ count, skip });
670675 try writer.writeByte(macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB);
671676 try std.leb.writeUleb128(writer, count);
672677 try std.leb.writeUleb128(writer, skip);
673678}
674679
675fn addAddr(addr: u64, writer: anytype) !void {
680fn addAddr(addr: u64, writer: *std.Io.Writer) !void {
676681 log.debug(">>> add: {x}", .{addr});
677682 try writer.writeByte(macho.BIND_OPCODE_ADD_ADDR_ULEB);
678683 try std.leb.writeUleb128(writer, addr);
679684}
680685
681fn done(writer: anytype) !void {
686fn done(writer: *std.Io.Writer) !void {
682687 log.debug(">>> done", .{});
683688 try writer.writeByte(macho.BIND_OPCODE_DONE);
684689}
src/link/MachO/load_commands.zig+19-19
......@@ -3,9 +3,9 @@ const assert = std.debug.assert;
33const log = std.log.scoped(.link);
44const macho = std.macho;
55const mem = std.mem;
6const Writer = std.io.Writer;
6const Writer = std.Io.Writer;
7const Allocator = std.mem.Allocator;
78
8const Allocator = mem.Allocator;
99const DebugSymbols = @import("DebugSymbols.zig");
1010const Dylib = @import("Dylib.zig");
1111const MachO = @import("../MachO.zig");
......@@ -181,22 +181,22 @@ pub fn calcMinHeaderPadSize(macho_file: *MachO) !u32 {
181181 return offset;
182182}
183183
184pub fn writeDylinkerLC(writer: anytype) !void {
184pub fn writeDylinkerLC(writer: *Writer) !void {
185185 const name_len = mem.sliceTo(default_dyld_path, 0).len;
186186 const cmdsize = @as(u32, @intCast(mem.alignForward(
187187 u64,
188188 @sizeOf(macho.dylinker_command) + name_len,
189189 @sizeOf(u64),
190190 )));
191 try writer.writeStruct(macho.dylinker_command{
191 try writer.writeStruct(@as(macho.dylinker_command, .{
192192 .cmd = .LOAD_DYLINKER,
193193 .cmdsize = cmdsize,
194194 .name = @sizeOf(macho.dylinker_command),
195 });
195 }), .little);
196196 try writer.writeAll(mem.sliceTo(default_dyld_path, 0));
197197 const padding = cmdsize - @sizeOf(macho.dylinker_command) - name_len;
198198 if (padding > 0) {
199 try writer.writeByteNTimes(0, padding);
199 try writer.splatByteAll(0, padding);
200200 }
201201}
202202
......@@ -208,14 +208,14 @@ const WriteDylibLCCtx = struct {
208208 compatibility_version: u32 = 0x10000,
209209};
210210
211pub fn writeDylibLC(ctx: WriteDylibLCCtx, writer: anytype) !void {
211pub fn writeDylibLC(ctx: WriteDylibLCCtx, writer: *Writer) !void {
212212 const name_len = ctx.name.len + 1;
213213 const cmdsize = @as(u32, @intCast(mem.alignForward(
214214 u64,
215215 @sizeOf(macho.dylib_command) + name_len,
216216 @sizeOf(u64),
217217 )));
218 try writer.writeStruct(macho.dylib_command{
218 try writer.writeStruct(@as(macho.dylib_command, .{
219219 .cmd = ctx.cmd,
220220 .cmdsize = cmdsize,
221221 .dylib = .{
......@@ -224,16 +224,16 @@ pub fn writeDylibLC(ctx: WriteDylibLCCtx, writer: anytype) !void {
224224 .current_version = ctx.current_version,
225225 .compatibility_version = ctx.compatibility_version,
226226 },
227 });
227 }), .little);
228228 try writer.writeAll(ctx.name);
229229 try writer.writeByte(0);
230230 const padding = cmdsize - @sizeOf(macho.dylib_command) - name_len;
231231 if (padding > 0) {
232 try writer.writeByteNTimes(0, padding);
232 try writer.splatByteAll(0, padding);
233233 }
234234}
235235
236pub fn writeDylibIdLC(macho_file: *MachO, writer: anytype) !void {
236pub fn writeDylibIdLC(macho_file: *MachO, writer: *Writer) !void {
237237 const comp = macho_file.base.comp;
238238 const gpa = comp.gpa;
239239 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 {
259259 }, writer);
260260}
261261
262pub fn writeRpathLC(rpath: []const u8, writer: anytype) !void {
262pub fn writeRpathLC(rpath: []const u8, writer: *Writer) !void {
263263 const rpath_len = rpath.len + 1;
264264 const cmdsize = @as(u32, @intCast(mem.alignForward(
265265 u64,
266266 @sizeOf(macho.rpath_command) + rpath_len,
267267 @sizeOf(u64),
268268 )));
269 try writer.writeStruct(macho.rpath_command{
269 try writer.writeStruct(@as(macho.rpath_command, .{
270270 .cmdsize = cmdsize,
271271 .path = @sizeOf(macho.rpath_command),
272 });
272 }), .little);
273273 try writer.writeAll(rpath);
274274 try writer.writeByte(0);
275275 const padding = cmdsize - @sizeOf(macho.rpath_command) - rpath_len;
276276 if (padding > 0) {
277 try writer.writeByteNTimes(0, padding);
277 try writer.splatByteAll(0, padding);
278278 }
279279}
280280
281pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: anytype) !void {
281pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: *Writer) !void {
282282 const cmd: macho.LC = switch (platform.os_tag) {
283283 .macos => .VERSION_MIN_MACOSX,
284284 .ios => .VERSION_MIN_IPHONEOS,
......@@ -296,9 +296,9 @@ pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVer
296296 }));
297297}
298298
299pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: anytype) !void {
299pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: *Writer) !void {
300300 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, .{
302302 .cmdsize = cmdsize,
303303 .platform = platform.toApplePlatform(),
304304 .minos = platform.toAppleVersion(),
......@@ -307,7 +307,7 @@ pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticV
307307 else
308308 platform.toAppleVersion(),
309309 .ntools = 1,
310 });
310 }), .little);
311311 try writer.writeAll(mem.asBytes(&macho.build_tool_version{
312312 .tool = .ZIG,
313313 .version = 0x0,
src/link/MachO/relocatable.zig+29-33
......@@ -205,35 +205,32 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ?
205205 state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(macho_file)});
206206 }
207207
208 var buffer = std.array_list.Managed(u8).init(gpa);
209 defer buffer.deinit();
210 try buffer.ensureTotalCapacityPrecise(total_size);
211 const writer = buffer.writer();
208 const buffer = try gpa.alloc(u8, total_size);
209 defer gpa.free(buffer);
210 var writer: Writer = .fixed(buffer);
212211
213212 // Write magic
214 try writer.writeAll(Archive.ARMAG);
213 writer.writeAll(Archive.ARMAG) catch unreachable;
215214
216215 // Write symtab
217 ar_symtab.write(format, macho_file, writer) catch |err| switch (err) {
218 error.OutOfMemory => return error.OutOfMemory,
219 else => |e| return diags.fail("failed to write archive symbol table: {s}", .{@errorName(e)}),
220 };
216 ar_symtab.write(format, macho_file, &writer) catch |err|
217 return diags.fail("failed to write archive symbol table: {t}", .{err});
221218
222219 // Write object files
223220 for (files.items) |index| {
224 const aligned = mem.alignForward(usize, buffer.items.len, 2);
225 const padding = aligned - buffer.items.len;
221 const aligned = mem.alignForward(usize, writer.end, 2);
222 const padding = aligned - writer.end;
226223 if (padding > 0) {
227 try writer.writeByteNTimes(0, padding);
224 writer.splatByteAll(0, padding) catch unreachable;
228225 }
229 macho_file.getFile(index).?.writeAr(format, macho_file, writer) catch |err|
230 return diags.fail("failed to write archive: {s}", .{@errorName(err)});
226 macho_file.getFile(index).?.writeAr(format, macho_file, &writer) catch |err|
227 return diags.fail("failed to write archive: {t}", .{err});
231228 }
232229
233 assert(buffer.items.len == total_size);
230 assert(writer.end == total_size);
234231
235232 try macho_file.setEndPos(total_size);
236 try macho_file.pwriteAll(buffer.items, 0);
233 try macho_file.pwriteAll(writer.buffered(), 0);
237234
238235 if (diags.hasErrors()) return error.LinkFailure;
239236}
......@@ -693,8 +690,7 @@ fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struc
693690 const buffer = try gpa.alloc(u8, needed_size);
694691 defer gpa.free(buffer);
695692
696 var stream = std.io.fixedBufferStream(buffer);
697 const writer = stream.writer();
693 var writer: Writer = .fixed(buffer);
698694
699695 var ncmds: usize = 0;
700696
......@@ -702,43 +698,43 @@ fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struc
702698 {
703699 assert(macho_file.segments.items.len == 1);
704700 const seg = macho_file.segments.items[0];
705 writer.writeStruct(seg) catch |err| switch (err) {
706 error.NoSpaceLeft => unreachable,
701 writer.writeStruct(seg, .little) catch |err| switch (err) {
702 error.WriteFailed => unreachable,
707703 };
708704 for (macho_file.sections.items(.header)) |header| {
709 writer.writeStruct(header) catch |err| switch (err) {
710 error.NoSpaceLeft => unreachable,
705 writer.writeStruct(header, .little) catch |err| switch (err) {
706 error.WriteFailed => unreachable,
711707 };
712708 }
713709 ncmds += 1;
714710 }
715711
716 writer.writeStruct(macho_file.data_in_code_cmd) catch |err| switch (err) {
717 error.NoSpaceLeft => unreachable,
712 writer.writeStruct(macho_file.data_in_code_cmd, .little) catch |err| switch (err) {
713 error.WriteFailed => unreachable,
718714 };
719715 ncmds += 1;
720 writer.writeStruct(macho_file.symtab_cmd) catch |err| switch (err) {
721 error.NoSpaceLeft => unreachable,
716 writer.writeStruct(macho_file.symtab_cmd, .little) catch |err| switch (err) {
717 error.WriteFailed => unreachable,
722718 };
723719 ncmds += 1;
724 writer.writeStruct(macho_file.dysymtab_cmd) catch |err| switch (err) {
725 error.NoSpaceLeft => unreachable,
720 writer.writeStruct(macho_file.dysymtab_cmd, .little) catch |err| switch (err) {
721 error.WriteFailed => unreachable,
726722 };
727723 ncmds += 1;
728724
729725 if (macho_file.platform.isBuildVersionCompatible()) {
730 load_commands.writeBuildVersionLC(macho_file.platform, macho_file.sdk_version, writer) catch |err| switch (err) {
731 error.NoSpaceLeft => unreachable,
726 load_commands.writeBuildVersionLC(macho_file.platform, macho_file.sdk_version, &writer) catch |err| switch (err) {
727 error.WriteFailed => unreachable,
732728 };
733729 ncmds += 1;
734730 } else {
735 load_commands.writeVersionMinLC(macho_file.platform, macho_file.sdk_version, writer) catch |err| switch (err) {
736 error.NoSpaceLeft => unreachable,
731 load_commands.writeVersionMinLC(macho_file.platform, macho_file.sdk_version, &writer) catch |err| switch (err) {
732 error.WriteFailed => unreachable,
737733 };
738734 ncmds += 1;
739735 }
740736
741 assert(stream.pos == needed_size);
737 assert(writer.end == needed_size);
742738
743739 try macho_file.pwriteAll(buffer, @sizeOf(macho.mach_header_64));
744740
src/link/MachO/synthetic.zig+12-12
......@@ -27,7 +27,7 @@ pub const GotSection = struct {
2727 return got.symbols.items.len * @sizeOf(u64);
2828 }
2929
30 pub fn write(got: GotSection, macho_file: *MachO, writer: anytype) !void {
30 pub fn write(got: GotSection, macho_file: *MachO, writer: *Writer) !void {
3131 const tracy = trace(@src());
3232 defer tracy.end();
3333 for (got.symbols.items) |ref| {
......@@ -89,7 +89,7 @@ pub const StubsSection = struct {
8989 return stubs.symbols.items.len * header.reserved2;
9090 }
9191
92 pub fn write(stubs: StubsSection, macho_file: *MachO, writer: anytype) !void {
92 pub fn write(stubs: StubsSection, macho_file: *MachO, writer: *Writer) !void {
9393 const tracy = trace(@src());
9494 defer tracy.end();
9595 const cpu_arch = macho_file.getTarget().cpu.arch;
......@@ -174,7 +174,7 @@ pub const StubsHelperSection = struct {
174174 return s;
175175 }
176176
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 {
178178 const tracy = trace(@src());
179179 defer tracy.end();
180180
......@@ -217,7 +217,7 @@ pub const StubsHelperSection = struct {
217217 }
218218 }
219219
220 fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: anytype) !void {
220 fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: *Writer) !void {
221221 _ = stubs_helper;
222222 const obj = macho_file.getInternalObject().?;
223223 const cpu_arch = macho_file.getTarget().cpu.arch;
......@@ -273,7 +273,7 @@ pub const LaSymbolPtrSection = struct {
273273 return macho_file.stubs.symbols.items.len * @sizeOf(u64);
274274 }
275275
276 pub fn write(laptr: LaSymbolPtrSection, macho_file: *MachO, writer: anytype) !void {
276 pub fn write(laptr: LaSymbolPtrSection, macho_file: *MachO, writer: *Writer) !void {
277277 const tracy = trace(@src());
278278 defer tracy.end();
279279 _ = laptr;
......@@ -323,7 +323,7 @@ pub const TlvPtrSection = struct {
323323 return tlv.symbols.items.len * @sizeOf(u64);
324324 }
325325
326 pub fn write(tlv: TlvPtrSection, macho_file: *MachO, writer: anytype) !void {
326 pub fn write(tlv: TlvPtrSection, macho_file: *MachO, writer: *Writer) !void {
327327 const tracy = trace(@src());
328328 defer tracy.end();
329329
......@@ -394,7 +394,7 @@ pub const ObjcStubsSection = struct {
394394 return objc.symbols.items.len * entrySize(macho_file.getTarget().cpu.arch);
395395 }
396396
397 pub fn write(objc: ObjcStubsSection, macho_file: *MachO, writer: anytype) !void {
397 pub fn write(objc: ObjcStubsSection, macho_file: *MachO, writer: *Writer) !void {
398398 const tracy = trace(@src());
399399 defer tracy.end();
400400
......@@ -487,7 +487,7 @@ pub const Indsymtab = struct {
487487 macho_file.dysymtab_cmd.nindirectsyms = ind.nsyms(macho_file);
488488 }
489489
490 pub fn write(ind: Indsymtab, macho_file: *MachO, writer: anytype) !void {
490 pub fn write(ind: Indsymtab, macho_file: *MachO, writer: *Writer) !void {
491491 const tracy = trace(@src());
492492 defer tracy.end();
493493
......@@ -564,7 +564,7 @@ pub const DataInCode = struct {
564564 macho_file.data_in_code_cmd.datasize = math.cast(u32, dice.size()) orelse return error.Overflow;
565565 }
566566
567 pub fn write(dice: DataInCode, macho_file: *MachO, writer: anytype) !void {
567 pub fn write(dice: DataInCode, macho_file: *MachO, writer: *Writer) !void {
568568 const base_address = if (!macho_file.base.isRelocatable())
569569 macho_file.getTextSegment().vmaddr
570570 else
......@@ -572,11 +572,11 @@ pub const DataInCode = struct {
572572 for (dice.entries.items) |entry| {
573573 const atom_address = entry.atom_ref.getAtom(macho_file).?.getAddress(macho_file);
574574 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, .{
576576 .offset = @intCast(offset),
577577 .length = entry.length,
578578 .kind = entry.kind,
579 });
579 }), .little);
580580 }
581581 }
582582
......@@ -594,7 +594,7 @@ const assert = std.debug.assert;
594594const macho = std.macho;
595595const math = std.math;
596596const Allocator = std.mem.Allocator;
597const Writer = std.io.Writer;
597const Writer = std.Io.Writer;
598598
599599const trace = @import("../../tracy.zig").trace;
600600const MachO = @import("../MachO.zig");