mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
link.MachO: update to not use GenericWriter
This commit is contained in:
parent
2dc6ddd7e8
commit
cc931660eb
@ -2381,6 +2381,7 @@ pub fn fromArrayList(array_list: *ArrayList(u8)) Writer {
|
||||
.vtable = &.{
|
||||
.drain = fixedDrain,
|
||||
.flush = noopFlush,
|
||||
.rebase = failingRebase,
|
||||
},
|
||||
.buffer = array_list.allocatedSlice(),
|
||||
.end = array_list.items.len,
|
||||
|
||||
@ -1883,10 +1883,8 @@ pub const GenericBlob = extern struct {
|
||||
pub const data_in_code_entry = extern struct {
|
||||
/// From mach_header to start of data range.
|
||||
offset: u32,
|
||||
|
||||
/// Number of bytes in data range.
|
||||
length: u16,
|
||||
|
||||
/// A DICE_KIND value.
|
||||
kind: u16,
|
||||
};
|
||||
|
||||
@ -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();
|
||||
var writer: Writer = .fixed(buffer);
|
||||
|
||||
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);
|
||||
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");
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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 });
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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));
|
||||
|
||||
|
||||
@ -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");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user