mirror of
https://github.com/ziglang/zig.git
synced 2024-11-28 16:12:33 +00:00
Merge pull request #11875 from motiejus/pagezero-size
[MachO] add -pagezero_size
This commit is contained in:
commit
74ed7c1f09
@ -903,6 +903,8 @@ pub const InitOptions = struct {
|
|||||||
install_name: ?[]const u8 = null,
|
install_name: ?[]const u8 = null,
|
||||||
/// (Darwin) Path to entitlements file
|
/// (Darwin) Path to entitlements file
|
||||||
entitlements: ?[]const u8 = null,
|
entitlements: ?[]const u8 = null,
|
||||||
|
/// (Darwin) size of the __PAGEZERO segment
|
||||||
|
pagezero_size: ?u64 = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn addPackageTableToCacheHash(
|
fn addPackageTableToCacheHash(
|
||||||
@ -1742,6 +1744,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
|
|||||||
.native_darwin_sdk = options.native_darwin_sdk,
|
.native_darwin_sdk = options.native_darwin_sdk,
|
||||||
.install_name = options.install_name,
|
.install_name = options.install_name,
|
||||||
.entitlements = options.entitlements,
|
.entitlements = options.entitlements,
|
||||||
|
.pagezero_size = options.pagezero_size,
|
||||||
});
|
});
|
||||||
errdefer bin_file.destroy();
|
errdefer bin_file.destroy();
|
||||||
comp.* = .{
|
comp.* = .{
|
||||||
@ -2359,7 +2362,7 @@ fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemo
|
|||||||
/// to remind the programmer to update multiple related pieces of code that
|
/// to remind the programmer to update multiple related pieces of code that
|
||||||
/// are in different locations. Bump this number when adding or deleting
|
/// are in different locations. Bump this number when adding or deleting
|
||||||
/// anything from the link cache manifest.
|
/// anything from the link cache manifest.
|
||||||
pub const link_hash_implementation_version = 3;
|
pub const link_hash_implementation_version = 4;
|
||||||
|
|
||||||
fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifest) !void {
|
fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifest) !void {
|
||||||
const gpa = comp.gpa;
|
const gpa = comp.gpa;
|
||||||
@ -2369,7 +2372,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
|
|||||||
defer arena_allocator.deinit();
|
defer arena_allocator.deinit();
|
||||||
const arena = arena_allocator.allocator();
|
const arena = arena_allocator.allocator();
|
||||||
|
|
||||||
comptime assert(link_hash_implementation_version == 3);
|
comptime assert(link_hash_implementation_version == 4);
|
||||||
|
|
||||||
if (comp.bin_file.options.module) |mod| {
|
if (comp.bin_file.options.module) |mod| {
|
||||||
const main_zig_file = try mod.main_pkg.root_src_directory.join(arena, &[_][]const u8{
|
const main_zig_file = try mod.main_pkg.root_src_directory.join(arena, &[_][]const u8{
|
||||||
@ -2474,6 +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.framework_dirs);
|
||||||
man.hash.addListOfBytes(comp.bin_file.options.frameworks);
|
man.hash.addListOfBytes(comp.bin_file.options.frameworks);
|
||||||
try man.addOptionalFile(comp.bin_file.options.entitlements);
|
try man.addOptionalFile(comp.bin_file.options.entitlements);
|
||||||
|
man.hash.addOptional(comp.bin_file.options.pagezero_size);
|
||||||
|
|
||||||
// COFF specific stuff
|
// COFF specific stuff
|
||||||
man.hash.addOptional(comp.bin_file.options.subsystem);
|
man.hash.addOptional(comp.bin_file.options.subsystem);
|
||||||
|
@ -187,6 +187,9 @@ pub const Options = struct {
|
|||||||
/// (Darwin) Path to entitlements file
|
/// (Darwin) Path to entitlements file
|
||||||
entitlements: ?[]const u8 = null,
|
entitlements: ?[]const u8 = null,
|
||||||
|
|
||||||
|
/// (Darwin) size of the __PAGEZERO segment
|
||||||
|
pagezero_size: ?u64 = null,
|
||||||
|
|
||||||
pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {
|
pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {
|
||||||
return if (options.use_lld) .Obj else options.output_mode;
|
return if (options.use_lld) .Obj else options.output_mode;
|
||||||
}
|
}
|
||||||
|
@ -969,7 +969,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !
|
|||||||
man = comp.cache_parent.obtain();
|
man = comp.cache_parent.obtain();
|
||||||
self.base.releaseLock();
|
self.base.releaseLock();
|
||||||
|
|
||||||
comptime assert(Compilation.link_hash_implementation_version == 3);
|
comptime assert(Compilation.link_hash_implementation_version == 4);
|
||||||
|
|
||||||
for (self.base.options.objects) |obj| {
|
for (self.base.options.objects) |obj| {
|
||||||
_ = try man.addFile(obj.path, null);
|
_ = try man.addFile(obj.path, null);
|
||||||
|
@ -1298,7 +1298,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
|
|||||||
// We are about to obtain this lock, so here we give other processes a chance first.
|
// We are about to obtain this lock, so here we give other processes a chance first.
|
||||||
self.base.releaseLock();
|
self.base.releaseLock();
|
||||||
|
|
||||||
comptime assert(Compilation.link_hash_implementation_version == 3);
|
comptime assert(Compilation.link_hash_implementation_version == 4);
|
||||||
|
|
||||||
try man.addOptionalFile(self.base.options.linker_script);
|
try man.addOptionalFile(self.base.options.linker_script);
|
||||||
try man.addOptionalFile(self.base.options.version_script);
|
try man.addOptionalFile(self.base.options.version_script);
|
||||||
|
@ -286,9 +286,9 @@ const default_dyld_path: [*:0]const u8 = "/usr/lib/dyld";
|
|||||||
const minimum_text_block_size = 64;
|
const minimum_text_block_size = 64;
|
||||||
pub const min_text_capacity = padToIdeal(minimum_text_block_size);
|
pub const min_text_capacity = padToIdeal(minimum_text_block_size);
|
||||||
|
|
||||||
/// Virtual memory offset corresponds to the size of __PAGEZERO segment and start of
|
/// Default virtual memory offset corresponds to the size of __PAGEZERO segment and
|
||||||
/// __TEXT segment.
|
/// start of __TEXT segment.
|
||||||
const pagezero_vmsize: u64 = 0x100000000;
|
const default_pagezero_vmsize: u64 = 0x100000000;
|
||||||
|
|
||||||
pub const Export = struct {
|
pub const Export = struct {
|
||||||
sym_index: ?u32 = null,
|
sym_index: ?u32 = null,
|
||||||
@ -536,7 +536,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
|
|||||||
// We are about to obtain this lock, so here we give other processes a chance first.
|
// We are about to obtain this lock, so here we give other processes a chance first.
|
||||||
self.base.releaseLock();
|
self.base.releaseLock();
|
||||||
|
|
||||||
comptime assert(Compilation.link_hash_implementation_version == 3);
|
comptime assert(Compilation.link_hash_implementation_version == 4);
|
||||||
|
|
||||||
for (self.base.options.objects) |obj| {
|
for (self.base.options.objects) |obj| {
|
||||||
_ = try man.addFile(obj.path, null);
|
_ = try man.addFile(obj.path, null);
|
||||||
@ -549,6 +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
|
// 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.
|
// installation sources because they are always a product of the compiler version + target information.
|
||||||
man.hash.add(stack_size);
|
man.hash.add(stack_size);
|
||||||
|
man.hash.addOptional(self.base.options.pagezero_size);
|
||||||
man.hash.addListOfBytes(self.base.options.lib_dirs);
|
man.hash.addListOfBytes(self.base.options.lib_dirs);
|
||||||
man.hash.addListOfBytes(self.base.options.framework_dirs);
|
man.hash.addListOfBytes(self.base.options.framework_dirs);
|
||||||
man.hash.addListOfBytes(self.base.options.frameworks);
|
man.hash.addListOfBytes(self.base.options.frameworks);
|
||||||
@ -928,6 +929,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
|
|||||||
try argv.append(rpath);
|
try argv.append(rpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (self.base.options.pagezero_size) |pagezero_size| {
|
||||||
|
try argv.append("-pagezero_size");
|
||||||
|
try argv.append(try std.fmt.allocPrint(arena, "0x{x}", .{pagezero_size}));
|
||||||
|
}
|
||||||
|
|
||||||
try argv.appendSlice(positionals.items);
|
try argv.appendSlice(positionals.items);
|
||||||
|
|
||||||
try argv.append("-o");
|
try argv.append("-o");
|
||||||
@ -4365,14 +4371,21 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil
|
|||||||
|
|
||||||
fn populateMissingMetadata(self: *MachO) !void {
|
fn populateMissingMetadata(self: *MachO) !void {
|
||||||
const cpu_arch = self.base.options.target.cpu.arch;
|
const cpu_arch = self.base.options.target.cpu.arch;
|
||||||
|
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) {
|
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 (0x{x}) is not page aligned", .{pagezero_vmsize});
|
||||||
|
log.warn(" rounding down to 0x{x}", .{aligned_pagezero_vmsize});
|
||||||
|
}
|
||||||
self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
|
self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
|
||||||
try self.load_commands.append(self.base.allocator, .{
|
try self.load_commands.append(self.base.allocator, .{
|
||||||
.segment = .{
|
.segment = .{
|
||||||
.inner = .{
|
.inner = .{
|
||||||
.segname = makeStaticString("__PAGEZERO"),
|
.segname = makeStaticString("__PAGEZERO"),
|
||||||
.vmsize = pagezero_vmsize,
|
.vmsize = aligned_pagezero_vmsize,
|
||||||
.cmdsize = @sizeOf(macho.segment_command_64),
|
.cmdsize = @sizeOf(macho.segment_command_64),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -4394,7 +4407,7 @@ fn populateMissingMetadata(self: *MachO) !void {
|
|||||||
.segment = .{
|
.segment = .{
|
||||||
.inner = .{
|
.inner = .{
|
||||||
.segname = makeStaticString("__TEXT"),
|
.segname = makeStaticString("__TEXT"),
|
||||||
.vmaddr = pagezero_vmsize,
|
.vmaddr = aligned_pagezero_vmsize,
|
||||||
.vmsize = needed_size,
|
.vmsize = needed_size,
|
||||||
.filesize = needed_size,
|
.filesize = needed_size,
|
||||||
.maxprot = macho.PROT.READ | macho.PROT.EXEC,
|
.maxprot = macho.PROT.READ | macho.PROT.EXEC,
|
||||||
@ -4881,7 +4894,10 @@ fn populateMissingMetadata(self: *MachO) !void {
|
|||||||
|
|
||||||
fn allocateTextSegment(self: *MachO) !void {
|
fn allocateTextSegment(self: *MachO) !void {
|
||||||
const seg = &self.load_commands.items[self.text_segment_cmd_index.?].segment;
|
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.fileoff = 0;
|
||||||
seg.inner.vmaddr = base_vmaddr;
|
seg.inner.vmaddr = base_vmaddr;
|
||||||
|
|
||||||
|
@ -2274,7 +2274,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
|
|||||||
// We are about to obtain this lock, so here we give other processes a chance first.
|
// We are about to obtain this lock, so here we give other processes a chance first.
|
||||||
self.base.releaseLock();
|
self.base.releaseLock();
|
||||||
|
|
||||||
comptime assert(Compilation.link_hash_implementation_version == 3);
|
comptime assert(Compilation.link_hash_implementation_version == 4);
|
||||||
|
|
||||||
for (self.base.options.objects) |obj| {
|
for (self.base.options.objects) |obj| {
|
||||||
_ = try man.addFile(obj.path, null);
|
_ = try man.addFile(obj.path, null);
|
||||||
|
31
src/main.zig
31
src/main.zig
@ -447,6 +447,7 @@ const usage_build_generic =
|
|||||||
\\ -F[dir] (Darwin) add search path for frameworks
|
\\ -F[dir] (Darwin) add search path for frameworks
|
||||||
\\ -install_name=[value] (Darwin) add dylib's install name
|
\\ -install_name=[value] (Darwin) add dylib's install name
|
||||||
\\ --entitlements [path] (Darwin) add path to entitlements file for embedding in code signature
|
\\ --entitlements [path] (Darwin) add path to entitlements file for embedding in code signature
|
||||||
|
\\ -pagezero_size [value] (Darwin) size of the __PAGEZERO segment in hexadecimal notation
|
||||||
\\ --import-memory (WebAssembly) import memory from the environment
|
\\ --import-memory (WebAssembly) import memory from the environment
|
||||||
\\ --import-table (WebAssembly) import function table from the host environment
|
\\ --import-table (WebAssembly) import function table from the host environment
|
||||||
\\ --export-table (WebAssembly) export function table to the host environment
|
\\ --export-table (WebAssembly) export function table to the host environment
|
||||||
@ -694,6 +695,7 @@ fn buildOutputType(
|
|||||||
var install_name: ?[]const u8 = null;
|
var install_name: ?[]const u8 = null;
|
||||||
var hash_style: link.HashStyle = .both;
|
var hash_style: link.HashStyle = .both;
|
||||||
var entitlements: ?[]const u8 = null;
|
var entitlements: ?[]const u8 = null;
|
||||||
|
var pagezero_size: ?u64 = null;
|
||||||
|
|
||||||
// e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
|
// e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
|
||||||
// This array is populated by zig cc frontend and then has to be converted to zig-style
|
// This array is populated by zig cc frontend and then has to be converted to zig-style
|
||||||
@ -908,6 +910,13 @@ fn buildOutputType(
|
|||||||
install_name = args_iter.next() orelse {
|
install_name = args_iter.next() orelse {
|
||||||
fatal("expected parameter after {s}", .{arg});
|
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, eatIntPrefix(next_arg, 16), 16) catch |err| {
|
||||||
|
fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
|
||||||
|
};
|
||||||
} else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) {
|
} else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) {
|
||||||
linker_script = args_iter.next() orelse {
|
linker_script = args_iter.next() orelse {
|
||||||
fatal("expected parameter after {s}", .{arg});
|
fatal("expected parameter after {s}", .{arg});
|
||||||
@ -1647,6 +1656,15 @@ fn buildOutputType(
|
|||||||
linker_optimization = std.fmt.parseUnsigned(u8, arg["-O".len..], 10) catch |err| {
|
linker_optimization = std.fmt.parseUnsigned(u8, arg["-O".len..], 10) catch |err| {
|
||||||
fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
|
fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
|
||||||
};
|
};
|
||||||
|
} else if (mem.eql(u8, arg, "-pagezero_size")) {
|
||||||
|
i += 1;
|
||||||
|
if (i >= linker_args.items.len) {
|
||||||
|
fatal("expected linker arg after '{s}'", .{arg});
|
||||||
|
}
|
||||||
|
const next_arg = linker_args.items[i];
|
||||||
|
pagezero_size = std.fmt.parseUnsigned(u64, eatIntPrefix(next_arg, 16), 16) catch |err| {
|
||||||
|
fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
|
||||||
|
};
|
||||||
} else if (mem.eql(u8, arg, "--gc-sections")) {
|
} else if (mem.eql(u8, arg, "--gc-sections")) {
|
||||||
linker_gc_sections = true;
|
linker_gc_sections = true;
|
||||||
} else if (mem.eql(u8, arg, "--no-gc-sections")) {
|
} else if (mem.eql(u8, arg, "--no-gc-sections")) {
|
||||||
@ -2763,6 +2781,7 @@ fn buildOutputType(
|
|||||||
.native_darwin_sdk = native_darwin_sdk,
|
.native_darwin_sdk = native_darwin_sdk,
|
||||||
.install_name = install_name,
|
.install_name = install_name,
|
||||||
.entitlements = entitlements,
|
.entitlements = entitlements,
|
||||||
|
.pagezero_size = pagezero_size,
|
||||||
}) catch |err| switch (err) {
|
}) catch |err| switch (err) {
|
||||||
error.LibCUnavailable => {
|
error.LibCUnavailable => {
|
||||||
const target = target_info.target;
|
const target = target_info.target;
|
||||||
@ -5048,6 +5067,18 @@ pub fn cmdChangelist(
|
|||||||
try bw.flush();
|
try bw.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn eatIntPrefix(arg: []const u8, radix: u8) []const u8 {
|
||||||
|
if (arg.len > 2 and arg[0] == '0') {
|
||||||
|
switch (std.ascii.toLower(arg[1])) {
|
||||||
|
'b' => if (radix == 2) return arg[2..],
|
||||||
|
'o' => if (radix == 8) return arg[2..],
|
||||||
|
'x' => if (radix == 16) return arg[2..],
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
fn parseIntSuffix(arg: []const u8, prefix_len: usize) u64 {
|
fn parseIntSuffix(arg: []const u8, prefix_len: usize) u64 {
|
||||||
return std.fmt.parseUnsigned(u64, arg[prefix_len..], 0) catch |err| {
|
return std.fmt.parseUnsigned(u64, arg[prefix_len..], 0) catch |err| {
|
||||||
fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
|
fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
|
||||||
|
Loading…
Reference in New Issue
Block a user