authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-20 10:13:39+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-20 13:39:33+02:00
logea9b7a0626c0191aa513549773c4d3b04e04de7c
treeca93cad2889dc9fb1d0e9229e3ced706ecb3de73
parent98138ba78c1540830a4fdb0537ed6ad5c7b57e7a

macho: round down pagezero size to page size

If page aligned requested pagezero size is 0, skip generating __PAGEZERO segment. Add misc improvements to the pipeline, and correctly transfer the requested __PAGEZERO size to the linker.

3 files changed, 27 insertions(+), 9 deletions(-)

src/Compilation.zig+2-1
......@@ -1744,6 +1744,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
17441744 .native_darwin_sdk = options.native_darwin_sdk,
17451745 .install_name = options.install_name,
17461746 .entitlements = options.entitlements,
1747 .pagezero_size = options.pagezero_size,
17471748 });
17481749 errdefer bin_file.destroy();
17491750 comp.* = .{
......@@ -2476,7 +2477,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
24762477 man.hash.addListOfBytes(comp.bin_file.options.framework_dirs);
24772478 man.hash.addListOfBytes(comp.bin_file.options.frameworks);
24782479 try man.addOptionalFile(comp.bin_file.options.entitlements);
2479 if (comp.bin_file.options.pagezero_size) |value| man.hash.add(value);
2480 man.hash.addOptional(comp.bin_file.options.pagezero_size);
24802481
24812482 // COFF specific stuff
24822483 man.hash.addOptional(comp.bin_file.options.subsystem);
src/link/MachO.zig+18-8
......@@ -286,9 +286,9 @@ const default_dyld_path: [*:0]const u8 = "/usr/lib/dyld";
286286const minimum_text_block_size = 64;
287287pub const min_text_capacity = padToIdeal(minimum_text_block_size);
288288
289/// Virtual memory offset corresponds to the size of __PAGEZERO segment and
289/// Default virtual memory offset corresponds to the size of __PAGEZERO segment and
290290/// start of __TEXT segment.
291const pagezero_vmsize: u64 = 0x100000000;
291const default_pagezero_vmsize: u64 = 0x100000000;
292292
293293pub const Export = struct {
294294 sym_index: ?u32 = null,
......@@ -549,7 +549,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
549549 // We can skip hashing libc and libc++ components that we are in charge of building from Zig
550550 // installation sources because they are always a product of the compiler version + target information.
551551 man.hash.add(stack_size);
552 if (self.base.options.pagezero_size) |value| man.hash.add(value);
552 man.hash.addOptional(self.base.options.pagezero_size);
553553 man.hash.addListOfBytes(self.base.options.lib_dirs);
554554 man.hash.addListOfBytes(self.base.options.framework_dirs);
555555 man.hash.addListOfBytes(self.base.options.frameworks);
......@@ -4366,14 +4366,21 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil
43664366
43674367fn populateMissingMetadata(self: *MachO) !void {
43684368 const cpu_arch = self.base.options.target.cpu.arch;
4369
4370 if (self.pagezero_segment_cmd_index == null) {
4369 const pagezero_vmsize = self.base.options.pagezero_size orelse default_pagezero_vmsize;
4370 const aligned_pagezero_vmsize = mem.alignBackwardGeneric(u64, pagezero_vmsize, self.page_size);
4371
4372 if (self.pagezero_segment_cmd_index == null) blk: {
4373 if (aligned_pagezero_vmsize == 0) break :blk;
4374 if (aligned_pagezero_vmsize != pagezero_vmsize) {
4375 log.warn("requested __PAGEZERO size is not page aligned", .{});
4376 log.warn(" rounding down to 0x{x}", .{aligned_pagezero_vmsize});
4377 }
43714378 self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
43724379 try self.load_commands.append(self.base.allocator, .{
43734380 .segment = .{
43744381 .inner = .{
43754382 .segname = makeStaticString("__PAGEZERO"),
4376 .vmsize = self.base.options.pagezero_size orelse pagezero_vmsize,
4383 .vmsize = aligned_pagezero_vmsize,
43774384 .cmdsize = @sizeOf(macho.segment_command_64),
43784385 },
43794386 },
......@@ -4395,7 +4402,7 @@ fn populateMissingMetadata(self: *MachO) !void {
43954402 .segment = .{
43964403 .inner = .{
43974404 .segname = makeStaticString("__TEXT"),
4398 .vmaddr = self.base.options.pagezero_size orelse pagezero_vmsize,
4405 .vmaddr = aligned_pagezero_vmsize,
43994406 .vmsize = needed_size,
44004407 .filesize = needed_size,
44014408 .maxprot = macho.PROT.READ | macho.PROT.EXEC,
......@@ -4882,7 +4889,10 @@ fn populateMissingMetadata(self: *MachO) !void {
48824889
48834890fn allocateTextSegment(self: *MachO) !void {
48844891 const seg = &self.load_commands.items[self.text_segment_cmd_index.?].segment;
4885 const base_vmaddr = self.load_commands.items[self.pagezero_segment_cmd_index.?].segment.inner.vmsize;
4892 const base_vmaddr = if (self.pagezero_segment_cmd_index) |index|
4893 self.load_commands.items[index].segment.inner.vmsize
4894 else
4895 0;
48864896 seg.inner.fileoff = 0;
48874897 seg.inner.vmaddr = base_vmaddr;
48884898
src/main.zig+7
......@@ -910,6 +910,13 @@ fn buildOutputType(
910910 install_name = args_iter.next() orelse {
911911 fatal("expected parameter after {s}", .{arg});
912912 };
913 } else if (mem.eql(u8, arg, "-pagezero_size")) {
914 const next_arg = args_iter.next() orelse {
915 fatal("expected parameter after {s}", .{arg});
916 };
917 pagezero_size = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| {
918 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
919 };
913920 } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) {
914921 linker_script = args_iter.next() orelse {
915922 fatal("expected parameter after {s}", .{arg});