diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-06-20 10:13:39 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-06-20 13:39:33 +0200 |
| commit | ea9b7a0626c0191aa513549773c4d3b04e04de7c (patch) | |
| tree | ca93cad2889dc9fb1d0e9229e3ced706ecb3de73 /src | |
| parent | 98138ba78c1540830a4fdb0537ed6ad5c7b57e7a (diff) | |
| download | zig-ea9b7a0626c0191aa513549773c4d3b04e04de7c.tar.gz zig-ea9b7a0626c0191aa513549773c4d3b04e04de7c.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Compilation.zig | 3 | ||||
| -rw-r--r-- | src/link/MachO.zig | 26 | ||||
| -rw-r--r-- | src/main.zig | 7 |
3 files changed, 27 insertions, 9 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig index 98d69ee78e..525835ce61 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1744,6 +1744,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .native_darwin_sdk = options.native_darwin_sdk, .install_name = options.install_name, .entitlements = options.entitlements, + .pagezero_size = options.pagezero_size, }); errdefer bin_file.destroy(); comp.* = .{ @@ -2476,7 +2477,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.addListOfBytes(comp.bin_file.options.framework_dirs); man.hash.addListOfBytes(comp.bin_file.options.frameworks); try man.addOptionalFile(comp.bin_file.options.entitlements); - if (comp.bin_file.options.pagezero_size) |value| man.hash.add(value); + man.hash.addOptional(comp.bin_file.options.pagezero_size); // COFF specific stuff man.hash.addOptional(comp.bin_file.options.subsystem); diff --git a/src/link/MachO.zig b/src/link/MachO.zig index ef56cbe548..b19b850d80 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -286,9 +286,9 @@ const default_dyld_path: [*:0]const u8 = "/usr/lib/dyld"; const minimum_text_block_size = 64; pub const min_text_capacity = padToIdeal(minimum_text_block_size); -/// Virtual memory offset corresponds to the size of __PAGEZERO segment and +/// Default virtual memory offset corresponds to the size of __PAGEZERO segment and /// start of __TEXT segment. -const pagezero_vmsize: u64 = 0x100000000; +const default_pagezero_vmsize: u64 = 0x100000000; pub const Export = struct { sym_index: ?u32 = null, @@ -549,7 +549,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No // We can skip hashing libc and libc++ components that we are in charge of building from Zig // installation sources because they are always a product of the compiler version + target information. man.hash.add(stack_size); - if (self.base.options.pagezero_size) |value| man.hash.add(value); + man.hash.addOptional(self.base.options.pagezero_size); man.hash.addListOfBytes(self.base.options.lib_dirs); man.hash.addListOfBytes(self.base.options.framework_dirs); man.hash.addListOfBytes(self.base.options.frameworks); @@ -4366,14 +4366,21 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil fn populateMissingMetadata(self: *MachO) !void { const cpu_arch = self.base.options.target.cpu.arch; - - if (self.pagezero_segment_cmd_index == null) { + const pagezero_vmsize = self.base.options.pagezero_size orelse default_pagezero_vmsize; + const aligned_pagezero_vmsize = mem.alignBackwardGeneric(u64, pagezero_vmsize, self.page_size); + + if (self.pagezero_segment_cmd_index == null) blk: { + if (aligned_pagezero_vmsize == 0) break :blk; + if (aligned_pagezero_vmsize != pagezero_vmsize) { + log.warn("requested __PAGEZERO size is not page aligned", .{}); + log.warn(" rounding down to 0x{x}", .{aligned_pagezero_vmsize}); + } self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len); try self.load_commands.append(self.base.allocator, .{ .segment = .{ .inner = .{ .segname = makeStaticString("__PAGEZERO"), - .vmsize = self.base.options.pagezero_size orelse pagezero_vmsize, + .vmsize = aligned_pagezero_vmsize, .cmdsize = @sizeOf(macho.segment_command_64), }, }, @@ -4395,7 +4402,7 @@ fn populateMissingMetadata(self: *MachO) !void { .segment = .{ .inner = .{ .segname = makeStaticString("__TEXT"), - .vmaddr = self.base.options.pagezero_size orelse pagezero_vmsize, + .vmaddr = aligned_pagezero_vmsize, .vmsize = needed_size, .filesize = needed_size, .maxprot = macho.PROT.READ | macho.PROT.EXEC, @@ -4882,7 +4889,10 @@ fn populateMissingMetadata(self: *MachO) !void { fn allocateTextSegment(self: *MachO) !void { const seg = &self.load_commands.items[self.text_segment_cmd_index.?].segment; - const base_vmaddr = self.load_commands.items[self.pagezero_segment_cmd_index.?].segment.inner.vmsize; + const base_vmaddr = if (self.pagezero_segment_cmd_index) |index| + self.load_commands.items[index].segment.inner.vmsize + else + 0; seg.inner.fileoff = 0; seg.inner.vmaddr = base_vmaddr; diff --git a/src/main.zig b/src/main.zig index bfd711fff7..cbba4a33b3 100644 --- a/src/main.zig +++ b/src/main.zig @@ -910,6 +910,13 @@ fn buildOutputType( install_name = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); }; + } else if (mem.eql(u8, arg, "-pagezero_size")) { + const next_arg = args_iter.next() orelse { + fatal("expected parameter after {s}", .{arg}); + }; + pagezero_size = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| { + fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); + }; } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) { linker_script = args_iter.next() orelse { fatal("expected parameter after {s}", .{arg}); |
