mirror of
https://github.com/ziglang/zig.git
synced 2026-01-10 17:35:12 +00:00
macho: prefill any space between __DATA and __LINKEDIT with 0s if required
If there are zerofill sections, the loader may copy the contents of the physical space in file directly into memory and attach that to the zerofill section. This is a performance optimisation in the loader but requires us, the linker, to properly zero-out any space between __DATA and __LINKEDIT segments in file. This is of course completely skipped if there are no zerofill sections present.
This commit is contained in:
parent
0ae2ea671b
commit
8378cde743
@ -1157,6 +1157,28 @@ fn linkOneShot(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node)
|
||||
var ncmds: u32 = 0;
|
||||
|
||||
try self.writeLinkeditSegmentData(&ncmds, lc_writer);
|
||||
|
||||
// If the last section of __DATA segment is zerofill section, we need to ensure
|
||||
// that the free space between the end of the last non-zerofill section of __DATA
|
||||
// segment and the beginning of __LINKEDIT segment is zerofilled as the loader will
|
||||
// copy-paste this space into memory for quicker zerofill operation.
|
||||
if (self.data_segment_cmd_index) |data_seg_id| blk: {
|
||||
var physical_zerofill_start: u64 = 0;
|
||||
const section_indexes = self.getSectionIndexes(data_seg_id);
|
||||
for (self.sections.items(.header)[section_indexes.start..section_indexes.end]) |header| {
|
||||
if (header.isZerofill() and header.size > 0) break;
|
||||
physical_zerofill_start = header.offset + header.size;
|
||||
} else break :blk;
|
||||
const linkedit = self.segments.items[self.linkedit_segment_cmd_index.?];
|
||||
const physical_zerofill_size = linkedit.fileoff - physical_zerofill_start;
|
||||
if (physical_zerofill_size > 0) {
|
||||
var padding = try self.base.allocator.alloc(u8, physical_zerofill_size);
|
||||
defer self.base.allocator.free(padding);
|
||||
mem.set(u8, padding, 0);
|
||||
try self.base.file.?.pwriteAll(padding, physical_zerofill_start);
|
||||
}
|
||||
}
|
||||
|
||||
try writeDylinkerLC(&ncmds, lc_writer);
|
||||
try self.writeMainLC(&ncmds, lc_writer);
|
||||
try self.writeDylibIdLC(&ncmds, lc_writer);
|
||||
@ -5690,8 +5712,10 @@ fn writeHeader(self: *MachO, ncmds: u32, sizeofcmds: u32) !void {
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
if (self.getSectionByName("__DATA", "__thread_vars")) |_| {
|
||||
header.flags |= macho.MH_HAS_TLV_DESCRIPTORS;
|
||||
if (self.getSectionByName("__DATA", "__thread_vars")) |sect_id| {
|
||||
if (self.sections.items(.header)[sect_id].size > 0) {
|
||||
header.flags |= macho.MH_HAS_TLV_DESCRIPTORS;
|
||||
}
|
||||
}
|
||||
|
||||
header.ncmds = ncmds;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user