aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-06-20 10:13:39 +0200
committerJakub Konka <kubkon@jakubkonka.com>2022-06-20 13:39:33 +0200
commitea9b7a0626c0191aa513549773c4d3b04e04de7c (patch)
treeca93cad2889dc9fb1d0e9229e3ced706ecb3de73 /src
parent98138ba78c1540830a4fdb0537ed6ad5c7b57e7a (diff)
downloadzig-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.zig3
-rw-r--r--src/link/MachO.zig26
-rw-r--r--src/main.zig7
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});