mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 05:48:31 +00:00
[MachO] add -pagezero_size
Pass `-pagezero_size` to the MachO linker. This is the final "unsupported linker arg" that I could chase that CGo uses. After this and #11874 we may be able to fail on an "unsupported linker arg" instead of emiting a warning. Test case: zig=/code/zig/build/zig CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 CC="$zig cc -target x86_64-macos" CXX="$zig c++ -target x86_64-macos" go build -a -ldflags "-s -w" cgo.go I compiled a trivial CGo program and executed it on an amd64 Darwin host. To be honest, I am not entirely sure what this is doing. This feels right after reading what this argument does in LLVM sources, but I am by no means qualified to make MachO pull requests. Will take feedback.
This commit is contained in:
parent
a97a39bea6
commit
98138ba78c
@ -903,6 +903,8 @@ pub const InitOptions = struct {
|
||||
install_name: ?[]const u8 = null,
|
||||
/// (Darwin) Path to entitlements file
|
||||
entitlements: ?[]const u8 = null,
|
||||
/// (Darwin) size of the __PAGEZERO segment
|
||||
pagezero_size: ?u64 = null,
|
||||
};
|
||||
|
||||
fn addPackageTableToCacheHash(
|
||||
@ -2359,7 +2361,7 @@ fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemo
|
||||
/// to remind the programmer to update multiple related pieces of code that
|
||||
/// are in different locations. Bump this number when adding or deleting
|
||||
/// 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 {
|
||||
const gpa = comp.gpa;
|
||||
@ -2369,7 +2371,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
|
||||
defer arena_allocator.deinit();
|
||||
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| {
|
||||
const main_zig_file = try mod.main_pkg.root_src_directory.join(arena, &[_][]const u8{
|
||||
@ -2474,6 +2476,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);
|
||||
|
||||
// COFF specific stuff
|
||||
man.hash.addOptional(comp.bin_file.options.subsystem);
|
||||
|
||||
@ -187,6 +187,9 @@ pub const Options = struct {
|
||||
/// (Darwin) Path to entitlements file
|
||||
entitlements: ?[]const u8 = null,
|
||||
|
||||
/// (Darwin) size of the __PAGEZERO segment
|
||||
pagezero_size: ?u64 = null,
|
||||
|
||||
pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {
|
||||
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();
|
||||
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| {
|
||||
_ = 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.
|
||||
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.version_script);
|
||||
|
||||
@ -286,8 +286,8 @@ 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 start of
|
||||
/// __TEXT segment.
|
||||
/// Virtual memory offset corresponds to the size of __PAGEZERO segment and
|
||||
/// start of __TEXT segment.
|
||||
const pagezero_vmsize: u64 = 0x100000000;
|
||||
|
||||
pub const Export = struct {
|
||||
@ -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.
|
||||
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| {
|
||||
_ = 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
|
||||
// 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.addListOfBytes(self.base.options.lib_dirs);
|
||||
man.hash.addListOfBytes(self.base.options.framework_dirs);
|
||||
man.hash.addListOfBytes(self.base.options.frameworks);
|
||||
@ -4372,7 +4373,7 @@ fn populateMissingMetadata(self: *MachO) !void {
|
||||
.segment = .{
|
||||
.inner = .{
|
||||
.segname = makeStaticString("__PAGEZERO"),
|
||||
.vmsize = pagezero_vmsize,
|
||||
.vmsize = self.base.options.pagezero_size orelse pagezero_vmsize,
|
||||
.cmdsize = @sizeOf(macho.segment_command_64),
|
||||
},
|
||||
},
|
||||
@ -4394,7 +4395,7 @@ fn populateMissingMetadata(self: *MachO) !void {
|
||||
.segment = .{
|
||||
.inner = .{
|
||||
.segname = makeStaticString("__TEXT"),
|
||||
.vmaddr = pagezero_vmsize,
|
||||
.vmaddr = self.base.options.pagezero_size orelse pagezero_vmsize,
|
||||
.vmsize = needed_size,
|
||||
.filesize = needed_size,
|
||||
.maxprot = macho.PROT.READ | macho.PROT.EXEC,
|
||||
|
||||
@ -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.
|
||||
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| {
|
||||
_ = try man.addFile(obj.path, null);
|
||||
|
||||
12
src/main.zig
12
src/main.zig
@ -447,6 +447,7 @@ const usage_build_generic =
|
||||
\\ -F[dir] (Darwin) add search path for frameworks
|
||||
\\ -install_name=[value] (Darwin) add dylib's install name
|
||||
\\ --entitlements [path] (Darwin) add path to entitlements file for embedding in code signature
|
||||
\\ -pagezero_size [value] (Darwin) size of the __PAGEZERO segment
|
||||
\\ --import-memory (WebAssembly) import memory from the environment
|
||||
\\ --import-table (WebAssembly) import function table from 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 hash_style: link.HashStyle = .both;
|
||||
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.
|
||||
// This array is populated by zig cc frontend and then has to be converted to zig-style
|
||||
@ -1647,6 +1649,15 @@ fn buildOutputType(
|
||||
linker_optimization = std.fmt.parseUnsigned(u8, arg["-O".len..], 10) catch |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, next_arg, 0) catch |err| {
|
||||
fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
|
||||
};
|
||||
} else if (mem.eql(u8, arg, "--gc-sections")) {
|
||||
linker_gc_sections = true;
|
||||
} else if (mem.eql(u8, arg, "--no-gc-sections")) {
|
||||
@ -2763,6 +2774,7 @@ fn buildOutputType(
|
||||
.native_darwin_sdk = native_darwin_sdk,
|
||||
.install_name = install_name,
|
||||
.entitlements = entitlements,
|
||||
.pagezero_size = pagezero_size,
|
||||
}) catch |err| switch (err) {
|
||||
error.LibCUnavailable => {
|
||||
const target = target_info.target;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user