diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2025-08-16 19:32:05 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2025-08-28 18:30:57 -0700 |
| commit | cc931660eb3e5b7251944c727808aa36e72c1e52 (patch) | |
| tree | c6564aff1d2e77163cfce1cd8e599a187ce9274a /src | |
| parent | 2dc6ddd7e8cfb83f5ffd57b8b40f33dde9de892d (diff) | |
| download | zig-cc931660eb3e5b7251944c727808aa36e72c1e52.tar.gz zig-cc931660eb3e5b7251944c727808aa36e72c1e52.zip | |
link.MachO: update to not use GenericWriter
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/MachO.zig | 130 | ||||
| -rw-r--r-- | src/link/MachO/Archive.zig | 56 | ||||
| -rw-r--r-- | src/link/MachO/Atom.zig | 11 | ||||
| -rw-r--r-- | src/link/MachO/CodeSignature.zig | 16 | ||||
| -rw-r--r-- | src/link/MachO/DebugSymbols.zig | 19 | ||||
| -rw-r--r-- | src/link/MachO/InternalObject.zig | 2 | ||||
| -rw-r--r-- | src/link/MachO/UnwindInfo.zig | 47 | ||||
| -rw-r--r-- | src/link/MachO/dyld_info/Rebase.zig | 6 | ||||
| -rw-r--r-- | src/link/MachO/dyld_info/Trie.zig | 25 | ||||
| -rw-r--r-- | src/link/MachO/dyld_info/bind.zig | 47 | ||||
| -rw-r--r-- | src/link/MachO/load_commands.zig | 38 | ||||
| -rw-r--r-- | src/link/MachO/relocatable.zig | 62 | ||||
| -rw-r--r-- | src/link/MachO/synthetic.zig | 24 |
13 files changed, 235 insertions, 248 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 434c27bfa3..4dd2c28006 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -589,7 +589,7 @@ pub fn flush( ); const ncmds, const sizeofcmds, const uuid_cmd_offset = self.writeLoadCommands() catch |err| switch (err) { - error.NoSpaceLeft => unreachable, + error.WriteFailed => unreachable, error.OutOfMemory => return error.OutOfMemory, error.LinkFailure => return error.LinkFailure, }; @@ -1074,7 +1074,7 @@ fn accessLibPath( for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { test_path.clearRetainingCapacity(); - try test_path.writer().print("{s}" ++ sep ++ "lib{s}{s}", .{ search_dir, name, ext }); + try test_path.print("{s}" ++ sep ++ "lib{s}{s}", .{ search_dir, name, ext }); try checked_paths.append(try arena.dupe(u8, test_path.items)); fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { error.FileNotFound => continue, @@ -1097,7 +1097,7 @@ fn accessFrameworkPath( for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { test_path.clearRetainingCapacity(); - try test_path.writer().print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{ + try test_path.print("{s}" ++ sep ++ "{s}.framework" ++ sep ++ "{s}{s}", .{ search_dir, name, name, @@ -1178,9 +1178,9 @@ fn parseDependentDylibs(self: *MachO) !void { for (&[_][]const u8{ ".tbd", ".dylib", "" }) |ext| { test_path.clearRetainingCapacity(); if (self.base.comp.sysroot) |root| { - try test_path.writer().print("{s}" ++ fs.path.sep_str ++ "{s}{s}", .{ root, path, ext }); + try test_path.print("{s}" ++ fs.path.sep_str ++ "{s}{s}", .{ root, path, ext }); } else { - try test_path.writer().print("{s}{s}", .{ path, ext }); + try test_path.print("{s}{s}", .{ path, ext }); } try checked_paths.append(try arena.dupe(u8, test_path.items)); fs.cwd().access(test_path.items, .{}) catch |err| switch (err) { @@ -2528,8 +2528,8 @@ fn writeThunkWorker(self: *MachO, thunk: Thunk) void { fn doWork(th: Thunk, buffer: []u8, macho_file: *MachO) !void { const off = try macho_file.cast(usize, th.value); const size = th.size(); - var stream = std.io.fixedBufferStream(buffer[off..][0..size]); - try th.write(macho_file, stream.writer()); + var stream: Writer = .fixed(buffer[off..][0..size]); + try th.write(macho_file, &stream); } }.doWork; 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 { const doWork = struct { fn doWork(macho_file: *MachO, tag: Tag, buffer: []u8) !void { - var stream = std.io.fixedBufferStream(buffer); + var stream: Writer = .fixed(buffer); switch (tag) { .eh_frame => eh_frame.write(macho_file, buffer), .unwind_info => try macho_file.unwind_info.write(macho_file, buffer), - .got => try macho_file.got.write(macho_file, stream.writer()), - .stubs => try macho_file.stubs.write(macho_file, stream.writer()), - .la_symbol_ptr => try macho_file.la_symbol_ptr.write(macho_file, stream.writer()), - .tlv_ptr => try macho_file.tlv_ptr.write(macho_file, stream.writer()), - .objc_stubs => try macho_file.objc_stubs.write(macho_file, stream.writer()), + .got => try macho_file.got.write(macho_file, &stream), + .stubs => try macho_file.stubs.write(macho_file, &stream), + .la_symbol_ptr => try macho_file.la_symbol_ptr.write(macho_file, &stream), + .tlv_ptr => try macho_file.tlv_ptr.write(macho_file, &stream), + .objc_stubs => try macho_file.objc_stubs.write(macho_file, &stream), } } }.doWork; @@ -2605,8 +2605,8 @@ fn updateLazyBindSizeWorker(self: *MachO) void { try macho_file.lazy_bind_section.updateSize(macho_file); const sect_id = macho_file.stubs_helper_sect_index.?; const out = &macho_file.sections.items(.out)[sect_id]; - var stream = std.io.fixedBufferStream(out.items); - try macho_file.stubs_helper.write(macho_file, stream.writer()); + var stream: Writer = .fixed(out.items); + try macho_file.stubs_helper.write(macho_file, &stream); } }.doWork; doWork(self) catch |err| @@ -2669,18 +2669,17 @@ fn writeDyldInfo(self: *MachO) !void { defer gpa.free(buffer); @memset(buffer, 0); - var stream = std.io.fixedBufferStream(buffer); - const writer = stream.writer(); - - try self.rebase_section.write(writer); - try stream.seekTo(cmd.bind_off - base_off); - try self.bind_section.write(writer); - try stream.seekTo(cmd.weak_bind_off - base_off); - try self.weak_bind_section.write(writer); - try stream.seekTo(cmd.lazy_bind_off - base_off); - try self.lazy_bind_section.write(writer); - try stream.seekTo(cmd.export_off - base_off); - try self.export_trie.write(writer); + var writer: Writer = .fixed(buffer); + + try self.rebase_section.write(&writer); + writer.end = cmd.bind_off - base_off; + try self.bind_section.write(&writer); + writer.end = cmd.weak_bind_off - base_off; + try self.weak_bind_section.write(&writer); + writer.end = cmd.lazy_bind_off - base_off; + try self.lazy_bind_section.write(&writer); + writer.end = cmd.export_off - base_off; + try self.export_trie.write(&writer); try self.pwriteAll(buffer, cmd.rebase_off); } @@ -2689,10 +2688,10 @@ pub fn writeDataInCode(self: *MachO) !void { defer tracy.end(); const gpa = self.base.comp.gpa; const cmd = self.data_in_code_cmd; - var buffer = try std.array_list.Managed(u8).initCapacity(gpa, self.data_in_code.size()); + var buffer = try std.Io.Writer.Allocating.initCapacity(gpa, self.data_in_code.size()); defer buffer.deinit(); - try self.data_in_code.write(self, buffer.writer()); - try self.pwriteAll(buffer.items, cmd.dataoff); + self.data_in_code.write(self, &buffer.writer) catch return error.OutOfMemory; + try self.pwriteAll(buffer.written(), cmd.dataoff); } fn writeIndsymtab(self: *MachO) !void { @@ -2701,10 +2700,11 @@ fn writeIndsymtab(self: *MachO) !void { const gpa = self.base.comp.gpa; const cmd = self.dysymtab_cmd; const needed_size = cmd.nindirectsyms * @sizeOf(u32); - var buffer = try std.array_list.Managed(u8).initCapacity(gpa, needed_size); - defer buffer.deinit(); - try self.indsymtab.write(self, buffer.writer()); - try self.pwriteAll(buffer.items, cmd.indirectsymoff); + const buffer = try gpa.alloc(u8, needed_size); + defer gpa.free(buffer); + var writer: Writer = .fixed(buffer); + try self.indsymtab.write(self, &writer); + try self.pwriteAll(buffer, cmd.indirectsymoff); } pub fn writeSymtabToFile(self: *MachO) !void { @@ -2821,8 +2821,7 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { const buffer = try gpa.alloc(u8, needed_size); defer gpa.free(buffer); - var stream = std.io.fixedBufferStream(buffer); - const writer = stream.writer(); + var writer: Writer = .fixed(buffer); var ncmds: usize = 0; @@ -2831,26 +2830,26 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { const slice = self.sections.slice(); var sect_id: usize = 0; for (self.segments.items) |seg| { - try writer.writeStruct(seg); + try writer.writeStruct(seg, .little); for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| { - try writer.writeStruct(header); + try writer.writeStruct(header, .little); } sect_id += seg.nsects; } ncmds += self.segments.items.len; } - try writer.writeStruct(self.dyld_info_cmd); + try writer.writeStruct(self.dyld_info_cmd, .little); ncmds += 1; - try writer.writeStruct(self.function_starts_cmd); + try writer.writeStruct(self.function_starts_cmd, .little); ncmds += 1; - try writer.writeStruct(self.data_in_code_cmd); + try writer.writeStruct(self.data_in_code_cmd, .little); ncmds += 1; - try writer.writeStruct(self.symtab_cmd); + try writer.writeStruct(self.symtab_cmd, .little); ncmds += 1; - try writer.writeStruct(self.dysymtab_cmd); + try writer.writeStruct(self.dysymtab_cmd, .little); ncmds += 1; - try load_commands.writeDylinkerLC(writer); + try load_commands.writeDylinkerLC(&writer); ncmds += 1; if (self.getInternalObject()) |obj| { @@ -2861,44 +2860,44 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { 0 else @as(u32, @intCast(sym.getAddress(.{ .stubs = true }, self) - seg.vmaddr)); - try writer.writeStruct(macho.entry_point_command{ + try writer.writeStruct(@as(macho.entry_point_command, .{ .entryoff = entryoff, .stacksize = self.base.stack_size, - }); + }), .little); ncmds += 1; } } if (self.base.isDynLib()) { - try load_commands.writeDylibIdLC(self, writer); + try load_commands.writeDylibIdLC(self, &writer); ncmds += 1; } for (self.rpath_list) |rpath| { - try load_commands.writeRpathLC(rpath, writer); + try load_commands.writeRpathLC(rpath, &writer); ncmds += 1; } if (comp.config.any_sanitize_thread) { const path = try comp.tsan_lib.?.full_object_path.toString(gpa); defer gpa.free(path); const rpath = std.fs.path.dirname(path) orelse "."; - try load_commands.writeRpathLC(rpath, writer); + try load_commands.writeRpathLC(rpath, &writer); ncmds += 1; } - try writer.writeStruct(macho.source_version_command{ .version = 0 }); + try writer.writeStruct(@as(macho.source_version_command, .{ .version = 0 }), .little); ncmds += 1; if (self.platform.isBuildVersionCompatible()) { - try load_commands.writeBuildVersionLC(self.platform, self.sdk_version, writer); + try load_commands.writeBuildVersionLC(self.platform, self.sdk_version, &writer); ncmds += 1; } else { - try load_commands.writeVersionMinLC(self.platform, self.sdk_version, writer); + try load_commands.writeVersionMinLC(self.platform, self.sdk_version, &writer); ncmds += 1; } - const uuid_cmd_offset = @sizeOf(macho.mach_header_64) + stream.pos; - try writer.writeStruct(self.uuid_cmd); + const uuid_cmd_offset = @sizeOf(macho.mach_header_64) + writer.end; + try writer.writeStruct(self.uuid_cmd, .little); ncmds += 1; for (self.dylibs.items) |index| { @@ -2916,16 +2915,16 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { .timestamp = dylib_id.timestamp, .current_version = dylib_id.current_version, .compatibility_version = dylib_id.compatibility_version, - }, writer); + }, &writer); ncmds += 1; } if (self.requiresCodeSig()) { - try writer.writeStruct(self.codesig_cmd); + try writer.writeStruct(self.codesig_cmd, .little); ncmds += 1; } - assert(stream.pos == needed_size); + assert(writer.end == needed_size); try self.pwriteAll(buffer, @sizeOf(macho.mach_header_64)); @@ -3014,25 +3013,26 @@ pub fn writeCodeSignaturePadding(self: *MachO, code_sig: *CodeSignature) !void { pub fn writeCodeSignature(self: *MachO, code_sig: *CodeSignature) !void { const seg = self.getTextSegment(); const offset = self.codesig_cmd.dataoff; + const gpa = self.base.comp.gpa; - var buffer = std.array_list.Managed(u8).init(self.base.comp.gpa); - defer buffer.deinit(); - try buffer.ensureTotalCapacityPrecise(code_sig.size()); + const buffer = try gpa.alloc(u8, code_sig.size()); + defer gpa.free(buffer); + var writer: Writer = .fixed(buffer); try code_sig.writeAdhocSignature(self, .{ .file = self.base.file.?, .exec_seg_base = seg.fileoff, .exec_seg_limit = seg.filesize, .file_size = offset, .dylib = self.base.isDynLib(), - }, buffer.writer()); - assert(buffer.items.len == code_sig.size()); + }, &writer); + assert(writer.buffered().len == code_sig.size()); log.debug("writing code signature from 0x{x} to 0x{x}", .{ offset, - offset + buffer.items.len, + offset + writer.buffered().len, }); - try self.pwriteAll(buffer.items, offset); + try self.pwriteAll(writer.buffered(), offset); } pub fn updateFunc( @@ -5372,7 +5372,7 @@ const macho = std.macho; const math = std.math; const mem = std.mem; const meta = std.meta; -const Writer = std.io.Writer; +const Writer = std.Io.Writer; const aarch64 = codegen.aarch64.encoding; const bind = @import("MachO/dyld_info/bind.zig"); diff --git a/src/link/MachO/Archive.zig b/src/link/MachO/Archive.zig index ae71dcde8d..1c7e285eb7 100644 --- a/src/link/MachO/Archive.zig +++ b/src/link/MachO/Archive.zig @@ -81,34 +81,20 @@ pub fn writeHeader( object_name: []const u8, object_size: usize, format: Format, - writer: anytype, + writer: *Writer, ) !void { - var hdr: ar_hdr = .{ - .ar_name = undefined, - .ar_date = undefined, - .ar_uid = undefined, - .ar_gid = undefined, - .ar_mode = undefined, - .ar_size = undefined, - .ar_fmag = undefined, - }; - @memset(mem.asBytes(&hdr), 0x20); - inline for (@typeInfo(ar_hdr).@"struct".fields) |field| { - var stream = std.io.fixedBufferStream(&@field(hdr, field.name)); - stream.writer().print("0", .{}) catch unreachable; - } - @memcpy(&hdr.ar_fmag, ARFMAG); + var hdr: ar_hdr = .{}; const object_name_len = mem.alignForward(usize, object_name.len + 1, ptrWidth(format)); const total_object_size = object_size + object_name_len; { - var stream = std.io.fixedBufferStream(&hdr.ar_name); - stream.writer().print("#1/{d}", .{object_name_len}) catch unreachable; + var stream: Writer = .fixed(&hdr.ar_name); + stream.print("#1/{d}", .{object_name_len}) catch unreachable; } { - var stream = std.io.fixedBufferStream(&hdr.ar_size); - stream.writer().print("{d}", .{total_object_size}) catch unreachable; + var stream: Writer = .fixed(&hdr.ar_size); + stream.print("{d}", .{total_object_size}) catch unreachable; } try writer.writeAll(mem.asBytes(&hdr)); @@ -116,7 +102,7 @@ pub fn writeHeader( const padding = object_name_len - object_name.len - 1; if (padding > 0) { - try writer.writeByteNTimes(0, padding); + try writer.splatByteAll(0, padding); } } @@ -138,25 +124,19 @@ pub const SYMDEF64_SORTED = "__.SYMDEF_64 SORTED"; pub const ar_hdr = extern struct { /// Member file name, sometimes / terminated. - ar_name: [16]u8, - + ar_name: [16]u8 = "0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20".*, /// File date, decimal seconds since Epoch. - ar_date: [12]u8, - + ar_date: [12]u8 = "0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20".*, /// User ID, in ASCII format. - ar_uid: [6]u8, - + ar_uid: [6]u8 = "0\x20\x20\x20\x20\x20".*, /// Group ID, in ASCII format. - ar_gid: [6]u8, - + ar_gid: [6]u8 = "0\x20\x20\x20\x20\x20".*, /// File mode, in ASCII octal. - ar_mode: [8]u8, - + ar_mode: [8]u8 = "0\x20\x20\x20\x20\x20\x20\x20".*, /// File size, in ASCII decimal. - ar_size: [10]u8, - + ar_size: [10]u8 = "0\x20\x20\x20\x20\x20\x20\x20\x20\x20".*, /// Always contains ARFMAG. - ar_fmag: [2]u8, + ar_fmag: [2]u8 = ARFMAG.*, fn date(self: ar_hdr) !u64 { const value = mem.trimEnd(u8, &self.ar_date, &[_]u8{@as(u8, 0x20)}); @@ -201,7 +181,7 @@ pub const ArSymtab = struct { return ptr_width + ar.entries.items.len * 2 * ptr_width + ptr_width + mem.alignForward(usize, ar.strtab.buffer.items.len, ptr_width); } - pub fn write(ar: ArSymtab, format: Format, macho_file: *MachO, writer: anytype) !void { + pub fn write(ar: ArSymtab, format: Format, macho_file: *MachO, writer: *Writer) !void { const ptr_width = ptrWidth(format); // Header try writeHeader(SYMDEF, ar.size(format), format, writer); @@ -226,7 +206,7 @@ pub const ArSymtab = struct { // Strtab try writer.writeAll(ar.strtab.buffer.items); if (padding > 0) { - try writer.writeByteNTimes(0, padding); + try writer.splatByteAll(0, padding); } } @@ -275,7 +255,7 @@ pub fn ptrWidth(format: Format) usize { }; } -pub fn writeInt(format: Format, value: u64, writer: anytype) !void { +pub fn writeInt(format: Format, value: u64, writer: *Writer) !void { switch (format) { .p32 => try writer.writeInt(u32, std.math.cast(u32, value) orelse return error.Overflow, .little), .p64 => try writer.writeInt(u64, value, .little), @@ -299,7 +279,7 @@ const mem = std.mem; const std = @import("std"); const Allocator = std.mem.Allocator; const Path = std.Build.Cache.Path; -const Writer = std.io.Writer; +const Writer = std.Io.Writer; const Archive = @This(); const File = @import("file.zig").File; diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index 93b3bdde37..904bb2d222 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -581,7 +581,7 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { relocs_log.debug("{x}: {s}", .{ self.value, name }); var has_error = false; - var stream = std.io.fixedBufferStream(buffer); + var stream: Writer = .fixed(buffer); var i: usize = 0; while (i < relocs.len) : (i += 1) { const rel = relocs[i]; @@ -592,8 +592,8 @@ pub fn resolveRelocs(self: Atom, macho_file: *MachO, buffer: []u8) !void { if (rel.getTargetSymbol(self, macho_file).getFile(macho_file) == null) continue; } - try stream.seekTo(rel_offset); - self.resolveRelocInner(rel, subtractor, buffer, macho_file, stream.writer()) catch |err| { + stream.end = rel_offset; + self.resolveRelocInner(rel, subtractor, buffer, macho_file, &stream) catch |err| { switch (err) { error.RelaxFail => { const target = switch (rel.tag) { @@ -630,6 +630,7 @@ const ResolveError = error{ UnexpectedRemainder, Overflow, OutOfMemory, + WriteFailed, }; fn resolveRelocInner( @@ -638,7 +639,7 @@ fn resolveRelocInner( subtractor: ?Relocation, code: []u8, macho_file: *MachO, - writer: anytype, + writer: *Writer, ) ResolveError!void { const t = &macho_file.base.comp.root_mod.resolved_target.result; const cpu_arch = t.cpu.arch; @@ -1147,7 +1148,7 @@ const math = std.math; const mem = std.mem; const log = std.log.scoped(.link); const relocs_log = std.log.scoped(.link_relocs); -const Writer = std.io.Writer; +const Writer = std.Io.Writer; const Allocator = mem.Allocator; const AtomicBool = std.atomic.Value(bool); diff --git a/src/link/MachO/CodeSignature.zig b/src/link/MachO/CodeSignature.zig index 6736505037..158777b896 100644 --- a/src/link/MachO/CodeSignature.zig +++ b/src/link/MachO/CodeSignature.zig @@ -304,10 +304,10 @@ pub fn writeAdhocSignature( var hash: [hash_size]u8 = undefined; if (self.requirements) |*req| { - var buf = std.array_list.Managed(u8).init(allocator); - defer buf.deinit(); - try req.write(buf.writer()); - Sha256.hash(buf.items, &hash, .{}); + var a: std.Io.Writer.Allocating = .init(allocator); + defer a.deinit(); + try req.write(&a.writer); + Sha256.hash(a.written(), &hash, .{}); self.code_directory.addSpecialHash(req.slotType(), hash); try blobs.append(.{ .requirements = req }); @@ -316,10 +316,10 @@ pub fn writeAdhocSignature( } if (self.entitlements) |*ents| { - var buf = std.array_list.Managed(u8).init(allocator); - defer buf.deinit(); - try ents.write(buf.writer()); - Sha256.hash(buf.items, &hash, .{}); + var a: std.Io.Writer.Allocating = .init(allocator); + defer a.deinit(); + try ents.write(&a.writer); + Sha256.hash(a.written(), &hash, .{}); self.code_directory.addSpecialHash(ents.slotType(), hash); try blobs.append(.{ .entitlements = ents }); diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index 4212827b2c..550dd3d63d 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/src/link/MachO/DebugSymbols.zig @@ -273,14 +273,13 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u const buffer = try gpa.alloc(u8, needed_size); defer gpa.free(buffer); - var stream = std.io.fixedBufferStream(buffer); - const writer = stream.writer(); + var writer: Writer = .fixed(buffer); var ncmds: usize = 0; // UUID comes first presumably to speed up lookup by the consumer like lldb. @memcpy(&self.uuid_cmd.uuid, &macho_file.uuid_cmd.uuid); - try writer.writeStruct(self.uuid_cmd); + try writer.writeStruct(self.uuid_cmd, .little); ncmds += 1; // Segment and section load commands @@ -293,11 +292,11 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u var out_seg = seg; out_seg.fileoff = 0; out_seg.filesize = 0; - try writer.writeStruct(out_seg); + try writer.writeStruct(out_seg, .little); for (slice.items(.header)[sect_id..][0..seg.nsects]) |header| { var out_header = header; out_header.offset = 0; - try writer.writeStruct(out_header); + try writer.writeStruct(out_header, .little); } sect_id += seg.nsects; } @@ -306,19 +305,19 @@ fn writeLoadCommands(self: *DebugSymbols, macho_file: *MachO) !struct { usize, u // Next, commit DSYM's __LINKEDIT and __DWARF segments headers. sect_id = 0; for (self.segments.items) |seg| { - try writer.writeStruct(seg); + try writer.writeStruct(seg, .little); for (self.sections.items[sect_id..][0..seg.nsects]) |header| { - try writer.writeStruct(header); + try writer.writeStruct(header, .little); } sect_id += seg.nsects; } ncmds += self.segments.items.len; } - try writer.writeStruct(self.symtab_cmd); + try writer.writeStruct(self.symtab_cmd, .little); ncmds += 1; - assert(stream.pos == needed_size); + assert(writer.end == needed_size); try self.file.?.pwriteAll(buffer, @sizeOf(macho.mach_header_64)); @@ -460,7 +459,7 @@ const math = std.math; const mem = std.mem; const padToIdeal = MachO.padToIdeal; const trace = @import("../../tracy.zig").trace; -const Writer = std.io.Writer; +const Writer = std.Io.Writer; const Allocator = mem.Allocator; const MachO = @import("../MachO.zig"); diff --git a/src/link/MachO/InternalObject.zig b/src/link/MachO/InternalObject.zig index d284df299a..9e21d49178 100644 --- a/src/link/MachO/InternalObject.zig +++ b/src/link/MachO/InternalObject.zig @@ -261,7 +261,7 @@ fn addObjcMethnameSection(self: *InternalObject, methname: []const u8, macho_fil sect.offset = @intCast(self.objc_methnames.items.len); try self.objc_methnames.ensureUnusedCapacity(gpa, methname.len + 1); - self.objc_methnames.writer(gpa).print("{s}\x00", .{methname}) catch unreachable; + self.objc_methnames.print(gpa, "{s}\x00", .{methname}) catch unreachable; const name_str = try self.addString(gpa, "ltmp"); const sym_index = try self.addSymbol(gpa); diff --git a/src/link/MachO/UnwindInfo.zig b/src/link/MachO/UnwindInfo.zig index a0ffdfe06a..9b7185743b 100644 --- a/src/link/MachO/UnwindInfo.zig +++ b/src/link/MachO/UnwindInfo.zig @@ -293,8 +293,7 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void { const seg = macho_file.getTextSegment(); const header = macho_file.sections.items(.header)[macho_file.unwind_info_sect_index.?]; - var stream = std.io.fixedBufferStream(buffer); - const writer = stream.writer(); + var writer: Writer = .fixed(buffer); const common_encodings_offset: u32 = @sizeOf(macho.unwind_info_section_header); const common_encodings_count: u32 = info.common_encodings_count; @@ -303,14 +302,14 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void { const indexes_offset: u32 = personalities_offset + personalities_count * @sizeOf(u32); const indexes_count: u32 = @as(u32, @intCast(info.pages.items.len + 1)); - try writer.writeStruct(macho.unwind_info_section_header{ + try writer.writeStruct(@as(macho.unwind_info_section_header, .{ .commonEncodingsArraySectionOffset = common_encodings_offset, .commonEncodingsArrayCount = common_encodings_count, .personalityArraySectionOffset = personalities_offset, .personalityArrayCount = personalities_count, .indexSectionOffset = indexes_offset, .indexCount = indexes_count, - }); + }), .little); try writer.writeAll(mem.sliceAsBytes(info.common_encodings[0..info.common_encodings_count])); @@ -325,42 +324,42 @@ pub fn write(info: UnwindInfo, macho_file: *MachO, buffer: []u8) !void { for (info.pages.items, 0..) |page, i| { assert(page.count > 0); const rec = info.records.items[page.start].getUnwindRecord(macho_file); - try writer.writeStruct(macho.unwind_info_section_header_index_entry{ + try writer.writeStruct(@as(macho.unwind_info_section_header_index_entry, .{ .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)), .secondLevelPagesSectionOffset = @as(u32, @intCast(pages_base_offset + i * second_level_page_bytes)), .lsdaIndexArraySectionOffset = lsda_base_offset + info.lsdas_lookup.items[page.start] * @sizeOf(macho.unwind_info_section_header_lsda_index_entry), - }); + }), .little); } const last_rec = info.records.items[info.records.items.len - 1].getUnwindRecord(macho_file); const sentinel_address = @as(u32, @intCast(last_rec.getAtomAddress(macho_file) + last_rec.length - seg.vmaddr)); - try writer.writeStruct(macho.unwind_info_section_header_index_entry{ + try writer.writeStruct(@as(macho.unwind_info_section_header_index_entry, .{ .functionOffset = sentinel_address, .secondLevelPagesSectionOffset = 0, .lsdaIndexArraySectionOffset = lsda_base_offset + @as(u32, @intCast(info.lsdas.items.len)) * @sizeOf(macho.unwind_info_section_header_lsda_index_entry), - }); + }), .little); for (info.lsdas.items) |index| { const rec = info.records.items[index].getUnwindRecord(macho_file); - try writer.writeStruct(macho.unwind_info_section_header_lsda_index_entry{ + try writer.writeStruct(@as(macho.unwind_info_section_header_lsda_index_entry, .{ .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)), .lsdaOffset = @as(u32, @intCast(rec.getLsdaAddress(macho_file) - seg.vmaddr)), - }); + }), .little); } for (info.pages.items) |page| { - const start = stream.pos; - try page.write(info, macho_file, writer); - const nwritten = stream.pos - start; + const start = writer.end; + try page.write(info, macho_file, &writer); + const nwritten = writer.end - start; if (nwritten < second_level_page_bytes) { const padding = math.cast(usize, second_level_page_bytes - nwritten) orelse return error.Overflow; - try writer.writeByteNTimes(0, padding); + try writer.splatByteAll(0, padding); } } - @memset(buffer[stream.pos..], 0); + @memset(buffer[writer.end..], 0); } fn getOrPutPersonalityFunction(info: *UnwindInfo, ref: MachO.Ref) error{TooManyPersonalities}!u2 { @@ -611,33 +610,33 @@ const Page = struct { } }; } - fn write(page: Page, info: UnwindInfo, macho_file: *MachO, writer: anytype) !void { + fn write(page: Page, info: UnwindInfo, macho_file: *MachO, writer: *Writer) !void { const seg = macho_file.getTextSegment(); switch (page.kind) { .regular => { - try writer.writeStruct(macho.unwind_info_regular_second_level_page_header{ + try writer.writeStruct(@as(macho.unwind_info_regular_second_level_page_header, .{ .entryPageOffset = @sizeOf(macho.unwind_info_regular_second_level_page_header), .entryCount = page.count, - }); + }), .little); for (info.records.items[page.start..][0..page.count]) |ref| { const rec = ref.getUnwindRecord(macho_file); - try writer.writeStruct(macho.unwind_info_regular_second_level_entry{ + try writer.writeStruct(@as(macho.unwind_info_regular_second_level_entry, .{ .functionOffset = @as(u32, @intCast(rec.getAtomAddress(macho_file) - seg.vmaddr)), .encoding = rec.enc.enc, - }); + }), .little); } }, .compressed => { const entry_offset = @sizeOf(macho.unwind_info_compressed_second_level_page_header) + @as(u16, @intCast(page.page_encodings_count)) * @sizeOf(u32); - try writer.writeStruct(macho.unwind_info_compressed_second_level_page_header{ + try writer.writeStruct(@as(macho.unwind_info_compressed_second_level_page_header, .{ .entryPageOffset = entry_offset, .entryCount = page.count, .encodingsPageOffset = @sizeOf(macho.unwind_info_compressed_second_level_page_header), .encodingsCount = page.page_encodings_count, - }); + }), .little); for (page.page_encodings[0..page.page_encodings_count]) |enc| { try writer.writeInt(u32, enc.enc, .little); @@ -656,7 +655,7 @@ const Page = struct { .funcOffset = @as(u24, @intCast(rec.getAtomAddress(macho_file) - first_rec.getAtomAddress(macho_file))), .encodingIndex = @as(u8, @intCast(enc_index)), }; - try writer.writeStruct(compressed); + try writer.writeStruct(compressed, .little); } }, } @@ -673,7 +672,7 @@ const macho = std.macho; const math = std.math; const mem = std.mem; const trace = @import("../../tracy.zig").trace; -const Writer = std.io.Writer; +const Writer = std.Io.Writer; const Allocator = mem.Allocator; const Atom = @import("Atom.zig"); diff --git a/src/link/MachO/dyld_info/Rebase.zig b/src/link/MachO/dyld_info/Rebase.zig index dae0d3ffeb..1cf2ea68bf 100644 --- a/src/link/MachO/dyld_info/Rebase.zig +++ b/src/link/MachO/dyld_info/Rebase.zig @@ -110,12 +110,14 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void { fn finalize(rebase: *Rebase, gpa: Allocator) !void { if (rebase.entries.items.len == 0) return; - const writer = rebase.buffer.writer(gpa); - log.debug("rebase opcodes", .{}); std.mem.sort(Entry, rebase.entries.items, {}, Entry.lessThan); + var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &rebase.buffer); + defer rebase.buffer = allocating.toArrayList(); + const writer = &allocating.writer; + try setTypePointer(writer); var start: usize = 0; diff --git a/src/link/MachO/dyld_info/Trie.zig b/src/link/MachO/dyld_info/Trie.zig index 18ea348e7a..609e489f1b 100644 --- a/src/link/MachO/dyld_info/Trie.zig +++ b/src/link/MachO/dyld_info/Trie.zig @@ -170,8 +170,13 @@ fn finalize(self: *Trie, allocator: Allocator) !void { } try self.buffer.ensureTotalCapacityPrecise(allocator, size); + + var allocating: std.Io.Writer.Allocating = .fromArrayList(allocator, &self.buffer); + defer self.buffer = allocating.toArrayList(); + const writer = &allocating.writer; + for (ordered_nodes.items) |node_index| { - try self.writeNode(node_index, self.buffer.writer(allocator)); + try self.writeNode(node_index, writer); } } @@ -232,7 +237,7 @@ pub fn deinit(self: *Trie, allocator: Allocator) void { self.buffer.deinit(allocator); } -pub fn write(self: Trie, writer: anytype) !void { +pub fn write(self: Trie, writer: *std.Io.Writer) !void { if (self.buffer.items.len == 0) return; try writer.writeAll(self.buffer.items); } @@ -243,7 +248,7 @@ pub fn write(self: Trie, writer: anytype) !void { /// iterate over `Trie.ordered_nodes` and call this method on each node. /// This is one of the requirements of the MachO. /// Panics if `finalize` was not called before calling this method. -fn writeNode(self: *Trie, node_index: Node.Index, writer: anytype) !void { +fn writeNode(self: *Trie, node_index: Node.Index, writer: *std.Io.Writer) !void { const slice = self.nodes.slice(); const edges = slice.items(.edges)[node_index]; const is_terminal = slice.items(.is_terminal)[node_index]; @@ -253,21 +258,21 @@ fn writeNode(self: *Trie, node_index: Node.Index, writer: anytype) !void { if (is_terminal) { // Terminal node info: encode export flags and vmaddr offset of this symbol. var info_buf: [@sizeOf(u64) * 2]u8 = undefined; - var info_stream = std.io.fixedBufferStream(&info_buf); + var info_stream: std.Io.Writer = .fixed(&info_buf); // TODO Implement for special flags. assert(export_flags & macho.EXPORT_SYMBOL_FLAGS_REEXPORT == 0 and export_flags & macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER == 0); - try leb.writeUleb128(info_stream.writer(), export_flags); - try leb.writeUleb128(info_stream.writer(), vmaddr_offset); + try leb.writeUleb128(&info_stream, export_flags); + try leb.writeUleb128(&info_stream, vmaddr_offset); // Encode the size of the terminal node info. var size_buf: [@sizeOf(u64)]u8 = undefined; - var size_stream = std.io.fixedBufferStream(&size_buf); - try leb.writeUleb128(size_stream.writer(), info_stream.pos); + var size_stream: std.Io.Writer = .fixed(&size_buf); + try leb.writeUleb128(&size_stream, info_stream.end); // Now, write them to the output stream. - try writer.writeAll(size_buf[0..size_stream.pos]); - try writer.writeAll(info_buf[0..info_stream.pos]); + try writer.writeAll(size_buf[0..size_stream.end]); + try writer.writeAll(info_buf[0..info_stream.end]); } else { // Non-terminal node is delimited by 0 byte. try writer.writeByte(0); diff --git a/src/link/MachO/dyld_info/bind.zig b/src/link/MachO/dyld_info/bind.zig index bc5484a846..cfc7eff4a2 100644 --- a/src/link/MachO/dyld_info/bind.zig +++ b/src/link/MachO/dyld_info/bind.zig @@ -132,12 +132,14 @@ pub const Bind = struct { fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void { if (self.entries.items.len == 0) return; - const writer = self.buffer.writer(gpa); - log.debug("bind opcodes", .{}); std.mem.sort(Entry, self.entries.items, ctx, Entry.lessThan); + var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &self.buffer); + defer self.buffer = allocating.toArrayList(); + const writer = &allocating.writer; + var start: usize = 0; var seg_id: ?u8 = null; for (self.entries.items, 0..) |entry, i| { @@ -151,7 +153,7 @@ pub const Bind = struct { try done(writer); } - fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: anytype) !void { + fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: *std.Io.Writer) !void { if (entries.len == 0) return; const seg_id = entries[0].segment_id; @@ -263,7 +265,7 @@ pub const Bind = struct { } } - pub fn write(self: Self, writer: anytype) !void { + pub fn write(self: Self, writer: *std.Io.Writer) !void { try writer.writeAll(self.buffer.items); } }; @@ -385,12 +387,14 @@ pub const WeakBind = struct { fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void { if (self.entries.items.len == 0) return; - const writer = self.buffer.writer(gpa); - log.debug("weak bind opcodes", .{}); std.mem.sort(Entry, self.entries.items, ctx, Entry.lessThan); + var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &self.buffer); + defer self.buffer = allocating.toArrayList(); + const writer = &allocating.writer; + var start: usize = 0; var seg_id: ?u8 = null; for (self.entries.items, 0..) |entry, i| { @@ -404,7 +408,7 @@ pub const WeakBind = struct { try done(writer); } - fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: anytype) !void { + fn finalizeSegment(entries: []const Entry, ctx: *MachO, writer: *std.Io.Writer) !void { if (entries.len == 0) return; const seg_id = entries[0].segment_id; @@ -505,7 +509,7 @@ pub const WeakBind = struct { } } - pub fn write(self: Self, writer: anytype) !void { + pub fn write(self: Self, writer: *std.Io.Writer) !void { try writer.writeAll(self.buffer.items); } }; @@ -555,8 +559,6 @@ pub const LazyBind = struct { fn finalize(self: *Self, gpa: Allocator, ctx: *MachO) !void { try self.offsets.ensureTotalCapacityPrecise(gpa, self.entries.items.len); - const writer = self.buffer.writer(gpa); - log.debug("lazy bind opcodes", .{}); var addend: i64 = 0; @@ -578,6 +580,9 @@ pub const LazyBind = struct { break :ord macho.BIND_SPECIAL_DYLIB_SELF; }; + var allocating: std.Io.Writer.Allocating = .fromArrayList(gpa, &self.buffer); + defer self.buffer = allocating.toArrayList(); + const writer = &allocating.writer; try setSegmentOffset(entry.segment_id, entry.offset, writer); try setSymbol(name, flags, writer); try setDylibOrdinal(ordinal, writer); @@ -592,30 +597,30 @@ pub const LazyBind = struct { } } - pub fn write(self: Self, writer: anytype) !void { + pub fn write(self: Self, writer: *std.Io.Writer) !void { try writer.writeAll(self.buffer.items); } }; -fn setSegmentOffset(segment_id: u8, offset: u64, writer: anytype) !void { +fn setSegmentOffset(segment_id: u8, offset: u64, writer: *std.Io.Writer) !void { log.debug(">>> set segment: {d} and offset: {x}", .{ segment_id, offset }); try writer.writeByte(macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB | @as(u4, @truncate(segment_id))); try std.leb.writeUleb128(writer, offset); } -fn setSymbol(name: []const u8, flags: u8, writer: anytype) !void { +fn setSymbol(name: []const u8, flags: u8, writer: *std.Io.Writer) !void { log.debug(">>> set symbol: {s} with flags: {x}", .{ name, flags }); try writer.writeByte(macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | @as(u4, @truncate(flags))); try writer.writeAll(name); try writer.writeByte(0); } -fn setTypePointer(writer: anytype) !void { +fn setTypePointer(writer: *std.Io.Writer) !void { log.debug(">>> set type: {d}", .{macho.BIND_TYPE_POINTER}); try writer.writeByte(macho.BIND_OPCODE_SET_TYPE_IMM | @as(u4, @truncate(macho.BIND_TYPE_POINTER))); } -fn setDylibOrdinal(ordinal: i16, writer: anytype) !void { +fn setDylibOrdinal(ordinal: i16, writer: *std.Io.Writer) !void { if (ordinal <= 0) { switch (ordinal) { macho.BIND_SPECIAL_DYLIB_SELF, @@ -639,18 +644,18 @@ fn setDylibOrdinal(ordinal: i16, writer: anytype) !void { } } -fn setAddend(addend: i64, writer: anytype) !void { +fn setAddend(addend: i64, writer: *std.Io.Writer) !void { log.debug(">>> set addend: {x}", .{addend}); try writer.writeByte(macho.BIND_OPCODE_SET_ADDEND_SLEB); try std.leb.writeIleb128(writer, addend); } -fn doBind(writer: anytype) !void { +fn doBind(writer: *std.Io.Writer) !void { log.debug(">>> bind", .{}); try writer.writeByte(macho.BIND_OPCODE_DO_BIND); } -fn doBindAddAddr(addr: u64, writer: anytype) !void { +fn doBindAddAddr(addr: u64, writer: *std.Io.Writer) !void { log.debug(">>> bind with add: {x}", .{addr}); if (std.mem.isAlignedGeneric(u64, addr, @sizeOf(u64))) { const imm = @divExact(addr, @sizeOf(u64)); @@ -665,20 +670,20 @@ fn doBindAddAddr(addr: u64, writer: anytype) !void { try std.leb.writeUleb128(writer, addr); } -fn doBindTimesSkip(count: usize, skip: u64, writer: anytype) !void { +fn doBindTimesSkip(count: usize, skip: u64, writer: *std.Io.Writer) !void { log.debug(">>> bind with count: {d} and skip: {x}", .{ count, skip }); try writer.writeByte(macho.BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB); try std.leb.writeUleb128(writer, count); try std.leb.writeUleb128(writer, skip); } -fn addAddr(addr: u64, writer: anytype) !void { +fn addAddr(addr: u64, writer: *std.Io.Writer) !void { log.debug(">>> add: {x}", .{addr}); try writer.writeByte(macho.BIND_OPCODE_ADD_ADDR_ULEB); try std.leb.writeUleb128(writer, addr); } -fn done(writer: anytype) !void { +fn done(writer: *std.Io.Writer) !void { log.debug(">>> done", .{}); try writer.writeByte(macho.BIND_OPCODE_DONE); } diff --git a/src/link/MachO/load_commands.zig b/src/link/MachO/load_commands.zig index 7c7b4416f4..59717dc9c9 100644 --- a/src/link/MachO/load_commands.zig +++ b/src/link/MachO/load_commands.zig @@ -3,9 +3,9 @@ const assert = std.debug.assert; const log = std.log.scoped(.link); const macho = std.macho; const mem = std.mem; -const Writer = std.io.Writer; +const Writer = std.Io.Writer; +const Allocator = std.mem.Allocator; -const Allocator = mem.Allocator; const DebugSymbols = @import("DebugSymbols.zig"); const Dylib = @import("Dylib.zig"); const MachO = @import("../MachO.zig"); @@ -181,22 +181,22 @@ pub fn calcMinHeaderPadSize(macho_file: *MachO) !u32 { return offset; } -pub fn writeDylinkerLC(writer: anytype) !void { +pub fn writeDylinkerLC(writer: *Writer) !void { const name_len = mem.sliceTo(default_dyld_path, 0).len; const cmdsize = @as(u32, @intCast(mem.alignForward( u64, @sizeOf(macho.dylinker_command) + name_len, @sizeOf(u64), ))); - try writer.writeStruct(macho.dylinker_command{ + try writer.writeStruct(@as(macho.dylinker_command, .{ .cmd = .LOAD_DYLINKER, .cmdsize = cmdsize, .name = @sizeOf(macho.dylinker_command), - }); + }), .little); try writer.writeAll(mem.sliceTo(default_dyld_path, 0)); const padding = cmdsize - @sizeOf(macho.dylinker_command) - name_len; if (padding > 0) { - try writer.writeByteNTimes(0, padding); + try writer.splatByteAll(0, padding); } } @@ -208,14 +208,14 @@ const WriteDylibLCCtx = struct { compatibility_version: u32 = 0x10000, }; -pub fn writeDylibLC(ctx: WriteDylibLCCtx, writer: anytype) !void { +pub fn writeDylibLC(ctx: WriteDylibLCCtx, writer: *Writer) !void { const name_len = ctx.name.len + 1; const cmdsize = @as(u32, @intCast(mem.alignForward( u64, @sizeOf(macho.dylib_command) + name_len, @sizeOf(u64), ))); - try writer.writeStruct(macho.dylib_command{ + try writer.writeStruct(@as(macho.dylib_command, .{ .cmd = ctx.cmd, .cmdsize = cmdsize, .dylib = .{ @@ -224,16 +224,16 @@ pub fn writeDylibLC(ctx: WriteDylibLCCtx, writer: anytype) !void { .current_version = ctx.current_version, .compatibility_version = ctx.compatibility_version, }, - }); + }), .little); try writer.writeAll(ctx.name); try writer.writeByte(0); const padding = cmdsize - @sizeOf(macho.dylib_command) - name_len; if (padding > 0) { - try writer.writeByteNTimes(0, padding); + try writer.splatByteAll(0, padding); } } -pub fn writeDylibIdLC(macho_file: *MachO, writer: anytype) !void { +pub fn writeDylibIdLC(macho_file: *MachO, writer: *Writer) !void { const comp = macho_file.base.comp; const gpa = comp.gpa; 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 { }, writer); } -pub fn writeRpathLC(rpath: []const u8, writer: anytype) !void { +pub fn writeRpathLC(rpath: []const u8, writer: *Writer) !void { const rpath_len = rpath.len + 1; const cmdsize = @as(u32, @intCast(mem.alignForward( u64, @sizeOf(macho.rpath_command) + rpath_len, @sizeOf(u64), ))); - try writer.writeStruct(macho.rpath_command{ + try writer.writeStruct(@as(macho.rpath_command, .{ .cmdsize = cmdsize, .path = @sizeOf(macho.rpath_command), - }); + }), .little); try writer.writeAll(rpath); try writer.writeByte(0); const padding = cmdsize - @sizeOf(macho.rpath_command) - rpath_len; if (padding > 0) { - try writer.writeByteNTimes(0, padding); + try writer.splatByteAll(0, padding); } } -pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: anytype) !void { +pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: *Writer) !void { const cmd: macho.LC = switch (platform.os_tag) { .macos => .VERSION_MIN_MACOSX, .ios => .VERSION_MIN_IPHONEOS, @@ -296,9 +296,9 @@ pub fn writeVersionMinLC(platform: MachO.Platform, sdk_version: ?std.SemanticVer })); } -pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: anytype) !void { +pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticVersion, writer: *Writer) !void { const cmdsize = @sizeOf(macho.build_version_command) + @sizeOf(macho.build_tool_version); - try writer.writeStruct(macho.build_version_command{ + try writer.writeStruct(@as(macho.build_version_command, .{ .cmdsize = cmdsize, .platform = platform.toApplePlatform(), .minos = platform.toAppleVersion(), @@ -307,7 +307,7 @@ pub fn writeBuildVersionLC(platform: MachO.Platform, sdk_version: ?std.SemanticV else platform.toAppleVersion(), .ntools = 1, - }); + }), .little); try writer.writeAll(mem.asBytes(&macho.build_tool_version{ .tool = .ZIG, .version = 0x0, diff --git a/src/link/MachO/relocatable.zig b/src/link/MachO/relocatable.zig index e962ce3fd2..a9f4d51ea6 100644 --- a/src/link/MachO/relocatable.zig +++ b/src/link/MachO/relocatable.zig @@ -205,35 +205,32 @@ pub fn flushStaticLib(macho_file: *MachO, comp: *Compilation, module_obj_path: ? state_log.debug("ar_symtab\n{f}\n", .{ar_symtab.fmt(macho_file)}); } - var buffer = std.array_list.Managed(u8).init(gpa); - defer buffer.deinit(); - try buffer.ensureTotalCapacityPrecise(total_size); - const writer = buffer.writer(); + const buffer = try gpa.alloc(u8, total_size); + defer gpa.free(buffer); + var writer: Writer = .fixed(buffer); // Write magic - try writer.writeAll(Archive.ARMAG); + writer.writeAll(Archive.ARMAG) catch unreachable; // Write symtab - ar_symtab.write(format, macho_file, writer) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - else => |e| return diags.fail("failed to write archive symbol table: {s}", .{@errorName(e)}), - }; + ar_symtab.write(format, macho_file, &writer) catch |err| + return diags.fail("failed to write archive symbol table: {t}", .{err}); // Write object files for (files.items) |index| { - const aligned = mem.alignForward(usize, buffer.items.len, 2); - const padding = aligned - buffer.items.len; + const aligned = mem.alignForward(usize, writer.end, 2); + const padding = aligned - writer.end; if (padding > 0) { - try writer.writeByteNTimes(0, padding); + writer.splatByteAll(0, padding) catch unreachable; } - macho_file.getFile(index).?.writeAr(format, macho_file, writer) catch |err| - return diags.fail("failed to write archive: {s}", .{@errorName(err)}); + macho_file.getFile(index).?.writeAr(format, macho_file, &writer) catch |err| + return diags.fail("failed to write archive: {t}", .{err}); } - assert(buffer.items.len == total_size); + assert(writer.end == total_size); try macho_file.setEndPos(total_size); - try macho_file.pwriteAll(buffer.items, 0); + try macho_file.pwriteAll(writer.buffered(), 0); if (diags.hasErrors()) return error.LinkFailure; } @@ -693,8 +690,7 @@ fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struc const buffer = try gpa.alloc(u8, needed_size); defer gpa.free(buffer); - var stream = std.io.fixedBufferStream(buffer); - const writer = stream.writer(); + var writer: Writer = .fixed(buffer); var ncmds: usize = 0; @@ -702,43 +698,43 @@ fn writeLoadCommands(macho_file: *MachO) error{ LinkFailure, OutOfMemory }!struc { assert(macho_file.segments.items.len == 1); const seg = macho_file.segments.items[0]; - writer.writeStruct(seg) catch |err| switch (err) { - error.NoSpaceLeft => unreachable, + writer.writeStruct(seg, .little) catch |err| switch (err) { + error.WriteFailed => unreachable, }; for (macho_file.sections.items(.header)) |header| { - writer.writeStruct(header) catch |err| switch (err) { - error.NoSpaceLeft => unreachable, + writer.writeStruct(header, .little) catch |err| switch (err) { + error.WriteFailed => unreachable, }; } ncmds += 1; } - writer.writeStruct(macho_file.data_in_code_cmd) catch |err| switch (err) { - error.NoSpaceLeft => unreachable, + writer.writeStruct(macho_file.data_in_code_cmd, .little) catch |err| switch (err) { + error.WriteFailed => unreachable, }; ncmds += 1; - writer.writeStruct(macho_file.symtab_cmd) catch |err| switch (err) { - error.NoSpaceLeft => unreachable, + writer.writeStruct(macho_file.symtab_cmd, .little) catch |err| switch (err) { + error.WriteFailed => unreachable, }; ncmds += 1; - writer.writeStruct(macho_file.dysymtab_cmd) catch |err| switch (err) { - error.NoSpaceLeft => unreachable, + writer.writeStruct(macho_file.dysymtab_cmd, .little) catch |err| switch (err) { + error.WriteFailed => unreachable, }; ncmds += 1; if (macho_file.platform.isBuildVersionCompatible()) { - load_commands.writeBuildVersionLC(macho_file.platform, macho_file.sdk_version, writer) catch |err| switch (err) { - error.NoSpaceLeft => unreachable, + load_commands.writeBuildVersionLC(macho_file.platform, macho_file.sdk_version, &writer) catch |err| switch (err) { + error.WriteFailed => unreachable, }; ncmds += 1; } else { - load_commands.writeVersionMinLC(macho_file.platform, macho_file.sdk_version, writer) catch |err| switch (err) { - error.NoSpaceLeft => unreachable, + load_commands.writeVersionMinLC(macho_file.platform, macho_file.sdk_version, &writer) catch |err| switch (err) { + error.WriteFailed => unreachable, }; ncmds += 1; } - assert(stream.pos == needed_size); + assert(writer.end == needed_size); try macho_file.pwriteAll(buffer, @sizeOf(macho.mach_header_64)); diff --git a/src/link/MachO/synthetic.zig b/src/link/MachO/synthetic.zig index 22c44d2f7a..6761a4a340 100644 --- a/src/link/MachO/synthetic.zig +++ b/src/link/MachO/synthetic.zig @@ -27,7 +27,7 @@ pub const GotSection = struct { return got.symbols.items.len * @sizeOf(u64); } - pub fn write(got: GotSection, macho_file: *MachO, writer: anytype) !void { + pub fn write(got: GotSection, macho_file: *MachO, writer: *Writer) !void { const tracy = trace(@src()); defer tracy.end(); for (got.symbols.items) |ref| { @@ -89,7 +89,7 @@ pub const StubsSection = struct { return stubs.symbols.items.len * header.reserved2; } - pub fn write(stubs: StubsSection, macho_file: *MachO, writer: anytype) !void { + pub fn write(stubs: StubsSection, macho_file: *MachO, writer: *Writer) !void { const tracy = trace(@src()); defer tracy.end(); const cpu_arch = macho_file.getTarget().cpu.arch; @@ -174,7 +174,7 @@ pub const StubsHelperSection = struct { return s; } - pub fn write(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: anytype) !void { + pub fn write(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: *Writer) !void { const tracy = trace(@src()); defer tracy.end(); @@ -217,7 +217,7 @@ pub const StubsHelperSection = struct { } } - fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: anytype) !void { + fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: *Writer) !void { _ = stubs_helper; const obj = macho_file.getInternalObject().?; const cpu_arch = macho_file.getTarget().cpu.arch; @@ -273,7 +273,7 @@ pub const LaSymbolPtrSection = struct { return macho_file.stubs.symbols.items.len * @sizeOf(u64); } - pub fn write(laptr: LaSymbolPtrSection, macho_file: *MachO, writer: anytype) !void { + pub fn write(laptr: LaSymbolPtrSection, macho_file: *MachO, writer: *Writer) !void { const tracy = trace(@src()); defer tracy.end(); _ = laptr; @@ -323,7 +323,7 @@ pub const TlvPtrSection = struct { return tlv.symbols.items.len * @sizeOf(u64); } - pub fn write(tlv: TlvPtrSection, macho_file: *MachO, writer: anytype) !void { + pub fn write(tlv: TlvPtrSection, macho_file: *MachO, writer: *Writer) !void { const tracy = trace(@src()); defer tracy.end(); @@ -394,7 +394,7 @@ pub const ObjcStubsSection = struct { return objc.symbols.items.len * entrySize(macho_file.getTarget().cpu.arch); } - pub fn write(objc: ObjcStubsSection, macho_file: *MachO, writer: anytype) !void { + pub fn write(objc: ObjcStubsSection, macho_file: *MachO, writer: *Writer) !void { const tracy = trace(@src()); defer tracy.end(); @@ -487,7 +487,7 @@ pub const Indsymtab = struct { macho_file.dysymtab_cmd.nindirectsyms = ind.nsyms(macho_file); } - pub fn write(ind: Indsymtab, macho_file: *MachO, writer: anytype) !void { + pub fn write(ind: Indsymtab, macho_file: *MachO, writer: *Writer) !void { const tracy = trace(@src()); defer tracy.end(); @@ -564,7 +564,7 @@ pub const DataInCode = struct { macho_file.data_in_code_cmd.datasize = math.cast(u32, dice.size()) orelse return error.Overflow; } - pub fn write(dice: DataInCode, macho_file: *MachO, writer: anytype) !void { + pub fn write(dice: DataInCode, macho_file: *MachO, writer: *Writer) !void { const base_address = if (!macho_file.base.isRelocatable()) macho_file.getTextSegment().vmaddr else @@ -572,11 +572,11 @@ pub const DataInCode = struct { for (dice.entries.items) |entry| { const atom_address = entry.atom_ref.getAtom(macho_file).?.getAddress(macho_file); const offset = atom_address + entry.offset - base_address; - try writer.writeStruct(macho.data_in_code_entry{ + try writer.writeStruct(@as(macho.data_in_code_entry, .{ .offset = @intCast(offset), .length = entry.length, .kind = entry.kind, - }); + }), .little); } } @@ -594,7 +594,7 @@ const assert = std.debug.assert; const macho = std.macho; const math = std.math; const Allocator = std.mem.Allocator; -const Writer = std.io.Writer; +const Writer = std.Io.Writer; const trace = @import("../../tracy.zig").trace; const MachO = @import("../MachO.zig"); |
