authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-21 10:54:03+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-24 12:34:42+01:00
log060406a52665e9c70012a7148757bd6d9797cf34
tree2009c00599dc4b8402322014e651a0e4c8de0894
parent3a6410959ca6df6f020547c58845730753dc9e97

macho: ensure we zero-out regions after copying them over

This is to ensure that the loader correctly zeroes-out zerofill sections when mapping them. For context, Apple's loader dyld will map the regions where any zerofill would theoretically reside as belonging to zerofill section.

2 files changed, 16 insertions(+), 9 deletions(-)

src/arch/x86_64/Lower.zig+1-3
......@@ -440,9 +440,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
440440 });
441441 lower.result_insts_len += 1;
442442 emit_mnemonic = .mov;
443 break :op .{ .mem = Memory.sib(mem_op.sib.ptr_size, .{
444 .base = .{ .reg = .rax },
445 }) };
443 break :op .{ .reg = .rax };
446444 }
447445
448446 _ = lower.reloc(.{ .linker_reloc = sym });
src/link/MachO.zig+15-6
......@@ -2346,9 +2346,7 @@ fn allocateSections(self: *MachO) !void {
23462346 new_offset + existing_size,
23472347 });
23482348
2349 const amt = try self.base.file.?.copyRangeAll(header.offset, self.base.file.?, new_offset, existing_size);
2350 // TODO figure out what to about this error condition - how to communicate it up.
2351 if (amt != existing_size) return error.InputOutput;
2349 try self.copyRangeAllZeroOut(header.offset, new_offset, existing_size);
23522350
23532351 header.offset = @intCast(new_offset);
23542352 header.size = existing_size;
......@@ -3268,6 +3266,19 @@ fn findFreeSpace(self: *MachO, object_size: u64, min_alignment: u32) u64 {
32683266 return start;
32693267}
32703268
3269/// Like File.copyRangeAll but also ensures the source region is zeroed out after copy.
3270/// This is so that we guarantee zeroed out regions for mapping of zerofill sections by the loader.
3271fn copyRangeAllZeroOut(self: *MachO, old_offset: u64, new_offset: u64, size: u64) !void {
3272 const gpa = self.base.comp.gpa;
3273 const file = self.base.file.?;
3274 const amt = try file.copyRangeAll(old_offset, file, new_offset, size);
3275 if (amt != size) return error.InputOutput;
3276 const zeroes = try gpa.alloc(u8, size);
3277 defer gpa.free(zeroes);
3278 @memset(zeroes, 0);
3279 try file.pwriteAll(zeroes, old_offset);
3280}
3281
32713282const InitMetadataOptions = struct {
32723283 symbol_count_hint: u64,
32733284 program_code_size_hint: u64,
......@@ -3408,9 +3419,7 @@ pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {
34083419 new_offset + existing_size,
34093420 });
34103421
3411 const amt = try self.base.file.?.copyRangeAll(sect.offset, self.base.file.?, new_offset, existing_size);
3412 // TODO figure out what to about this error condition - how to communicate it up.
3413 if (amt != existing_size) return error.InputOutput;
3422 try self.copyRangeAllZeroOut(sect.offset, new_offset, existing_size);
34143423
34153424 sect.offset = @intCast(new_offset);
34163425 seg.fileoff = new_offset;