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 {...@@ -1744,6 +1744,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1744 .native_darwin_sdk = options.native_darwin_sdk,1744 .native_darwin_sdk = options.native_darwin_sdk,
1745 .install_name = options.install_name,1745 .install_name = options.install_name,
1746 .entitlements = options.entitlements,1746 .entitlements = options.entitlements,
1747 .pagezero_size = options.pagezero_size,
1747 });1748 });
1748 errdefer bin_file.destroy();1749 errdefer bin_file.destroy();
1749 comp.* = .{1750 comp.* = .{
...@@ -2476,7 +2477,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2476,7 +2477,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
2476 man.hash.addListOfBytes(comp.bin_file.options.framework_dirs);2477 man.hash.addListOfBytes(comp.bin_file.options.framework_dirs);
2477 man.hash.addListOfBytes(comp.bin_file.options.frameworks);2478 man.hash.addListOfBytes(comp.bin_file.options.frameworks);
2478 try man.addOptionalFile(comp.bin_file.options.entitlements);2479 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
2481 // COFF specific stuff2482 // COFF specific stuff
2482 man.hash.addOptional(comp.bin_file.options.subsystem);2483 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";...@@ -286,9 +286,9 @@ const default_dyld_path: [*:0]const u8 = "/usr/lib/dyld";
286const minimum_text_block_size = 64;286const minimum_text_block_size = 64;
287pub const min_text_capacity = padToIdeal(minimum_text_block_size);287pub const min_text_capacity = padToIdeal(minimum_text_block_size);
288288
289/// Virtual memory offset corresponds to the size of __PAGEZERO segment and289/// Default virtual memory offset corresponds to the size of __PAGEZERO segment and
290/// start of __TEXT segment.290/// start of __TEXT segment.
291const pagezero_vmsize: u64 = 0x100000000;291const default_pagezero_vmsize: u64 = 0x100000000;
292292
293pub const Export = struct {293pub const Export = struct {
294 sym_index: ?u32 = null,294 sym_index: ?u32 = null,
...@@ -549,7 +549,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No...@@ -549,7 +549,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
549 // We can skip hashing libc and libc++ components that we are in charge of building from Zig549 // We can skip hashing libc and libc++ components that we are in charge of building from Zig
550 // installation sources because they are always a product of the compiler version + target information.550 // installation sources because they are always a product of the compiler version + target information.
551 man.hash.add(stack_size);551 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);
553 man.hash.addListOfBytes(self.base.options.lib_dirs);553 man.hash.addListOfBytes(self.base.options.lib_dirs);
554 man.hash.addListOfBytes(self.base.options.framework_dirs);554 man.hash.addListOfBytes(self.base.options.framework_dirs);
555 man.hash.addListOfBytes(self.base.options.frameworks);555 man.hash.addListOfBytes(self.base.options.frameworks);
...@@ -4366,14 +4366,21 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil...@@ -4366,14 +4366,21 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil
43664366
4367fn populateMissingMetadata(self: *MachO) !void {4367fn populateMissingMetadata(self: *MachO) !void {
4368 const cpu_arch = self.base.options.target.cpu.arch;4368 const cpu_arch = self.base.options.target.cpu.arch;
43694369 const pagezero_vmsize = self.base.options.pagezero_size orelse default_pagezero_vmsize;
4370 if (self.pagezero_segment_cmd_index == null) {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 }
4371 self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len);4378 self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
4372 try self.load_commands.append(self.base.allocator, .{4379 try self.load_commands.append(self.base.allocator, .{
4373 .segment = .{4380 .segment = .{
4374 .inner = .{4381 .inner = .{
4375 .segname = makeStaticString("__PAGEZERO"),4382 .segname = makeStaticString("__PAGEZERO"),
4376 .vmsize = self.base.options.pagezero_size orelse pagezero_vmsize,4383 .vmsize = aligned_pagezero_vmsize,
4377 .cmdsize = @sizeOf(macho.segment_command_64),4384 .cmdsize = @sizeOf(macho.segment_command_64),
4378 },4385 },
4379 },4386 },
...@@ -4395,7 +4402,7 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4395,7 +4402,7 @@ fn populateMissingMetadata(self: *MachO) !void {
4395 .segment = .{4402 .segment = .{
4396 .inner = .{4403 .inner = .{
4397 .segname = makeStaticString("__TEXT"),4404 .segname = makeStaticString("__TEXT"),
4398 .vmaddr = self.base.options.pagezero_size orelse pagezero_vmsize,4405 .vmaddr = aligned_pagezero_vmsize,
4399 .vmsize = needed_size,4406 .vmsize = needed_size,
4400 .filesize = needed_size,4407 .filesize = needed_size,
4401 .maxprot = macho.PROT.READ | macho.PROT.EXEC,4408 .maxprot = macho.PROT.READ | macho.PROT.EXEC,
...@@ -4882,7 +4889,10 @@ fn populateMissingMetadata(self: *MachO) !void {...@@ -4882,7 +4889,10 @@ fn populateMissingMetadata(self: *MachO) !void {
48824889
4883fn allocateTextSegment(self: *MachO) !void {4890fn allocateTextSegment(self: *MachO) !void {
4884 const seg = &self.load_commands.items[self.text_segment_cmd_index.?].segment;4891 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;
4886 seg.inner.fileoff = 0;4896 seg.inner.fileoff = 0;
4887 seg.inner.vmaddr = base_vmaddr;4897 seg.inner.vmaddr = base_vmaddr;
48884898
src/main.zig+7
...@@ -910,6 +910,13 @@ fn buildOutputType(...@@ -910,6 +910,13 @@ fn buildOutputType(
910 install_name = args_iter.next() orelse {910 install_name = args_iter.next() orelse {
911 fatal("expected parameter after {s}", .{arg});911 fatal("expected parameter after {s}", .{arg});
912 };912 };
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 };
913 } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) {920 } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) {
914 linker_script = args_iter.next() orelse {921 linker_script = args_iter.next() orelse {
915 fatal("expected parameter after {s}", .{arg});922 fatal("expected parameter after {s}", .{arg});