| author | |
| committer | |
| log | 74ed7c1f0998e9dd89aa3f3480fff845afd6b422 |
| tree | ce9809fd8d6f92bf0d502cd1f50e3d7a43fb6c64 |
| parent | a97a39bea6022fb7449620384641cdfa70303f8d |
| parent | 8752db3285060c6f2d85c0fa744c44094239a792 |
| signature |
[MachO] add -pagezero_size7 files changed, 68 insertions(+), 14 deletions(-)
src/Compilation.zig+6-2| ... | ... | @@ -903,6 +903,8 @@ pub const InitOptions = struct { |
| 903 | 903 | install_name: ?[]const u8 = null, |
| 904 | 904 | /// (Darwin) Path to entitlements file |
| 905 | 905 | entitlements: ?[]const u8 = null, |
| 906 | /// (Darwin) size of the __PAGEZERO segment | |
| 907 | pagezero_size: ?u64 = null, | |
| 906 | 908 | }; |
| 907 | 909 | |
| 908 | 910 | fn addPackageTableToCacheHash( |
| ... | ... | @@ -1742,6 +1744,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1742 | 1744 | .native_darwin_sdk = options.native_darwin_sdk, |
| 1743 | 1745 | .install_name = options.install_name, |
| 1744 | 1746 | .entitlements = options.entitlements, |
| 1747 | .pagezero_size = options.pagezero_size, | |
| 1745 | 1748 | }); |
| 1746 | 1749 | errdefer bin_file.destroy(); |
| 1747 | 1750 | comp.* = .{ |
| ... | ... | @@ -2359,7 +2362,7 @@ fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemo |
| 2359 | 2362 | /// to remind the programmer to update multiple related pieces of code that |
| 2360 | 2363 | /// are in different locations. Bump this number when adding or deleting |
| 2361 | 2364 | /// anything from the link cache manifest. |
| 2362 | pub const link_hash_implementation_version = 3; | |
| 2365 | pub const link_hash_implementation_version = 4; | |
| 2363 | 2366 | |
| 2364 | 2367 | fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifest) !void { |
| 2365 | 2368 | const gpa = comp.gpa; |
| ... | ... | @@ -2369,7 +2372,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes |
| 2369 | 2372 | defer arena_allocator.deinit(); |
| 2370 | 2373 | const arena = arena_allocator.allocator(); |
| 2371 | 2374 | |
| 2372 | comptime assert(link_hash_implementation_version == 3); | |
| 2375 | comptime assert(link_hash_implementation_version == 4); | |
| 2373 | 2376 | |
| 2374 | 2377 | if (comp.bin_file.options.module) |mod| { |
| 2375 | 2378 | 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 |
| 2474 | 2477 | man.hash.addListOfBytes(comp.bin_file.options.framework_dirs); |
| 2475 | 2478 | man.hash.addListOfBytes(comp.bin_file.options.frameworks); |
| 2476 | 2479 | try man.addOptionalFile(comp.bin_file.options.entitlements); |
| 2480 | man.hash.addOptional(comp.bin_file.options.pagezero_size); | |
| 2477 | 2481 | |
| 2478 | 2482 | // COFF specific stuff |
| 2479 | 2483 | man.hash.addOptional(comp.bin_file.options.subsystem); |
src/link.zig+3| ... | ... | @@ -187,6 +187,9 @@ pub const Options = struct { |
| 187 | 187 | /// (Darwin) Path to entitlements file |
| 188 | 188 | entitlements: ?[]const u8 = null, |
| 189 | 189 | |
| 190 | /// (Darwin) size of the __PAGEZERO segment | |
| 191 | pagezero_size: ?u64 = null, | |
| 192 | ||
| 190 | 193 | pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode { |
| 191 | 194 | return if (options.use_lld) .Obj else options.output_mode; |
| 192 | 195 | } |
src/link/Coff.zig+1-1| ... | ... | @@ -969,7 +969,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) ! |
| 969 | 969 | man = comp.cache_parent.obtain(); |
| 970 | 970 | self.base.releaseLock(); |
| 971 | 971 | |
| 972 | comptime assert(Compilation.link_hash_implementation_version == 3); | |
| 972 | comptime assert(Compilation.link_hash_implementation_version == 4); | |
| 973 | 973 | |
| 974 | 974 | for (self.base.options.objects) |obj| { |
| 975 | 975 | _ = try man.addFile(obj.path, null); |
src/link/Elf.zig+1-1| ... | ... | @@ -1298,7 +1298,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v |
| 1298 | 1298 | // We are about to obtain this lock, so here we give other processes a chance first. |
| 1299 | 1299 | self.base.releaseLock(); |
| 1300 | 1300 | |
| 1301 | comptime assert(Compilation.link_hash_implementation_version == 3); | |
| 1301 | comptime assert(Compilation.link_hash_implementation_version == 4); | |
| 1302 | 1302 | |
| 1303 | 1303 | try man.addOptionalFile(self.base.options.linker_script); |
| 1304 | 1304 | try man.addOptionalFile(self.base.options.version_script); |
src/link/MachO.zig+25-9| ... | ... | @@ -286,9 +286,9 @@ const default_dyld_path: [*:0]const u8 = "/usr/lib/dyld"; |
| 286 | 286 | const minimum_text_block_size = 64; |
| 287 | 287 | pub const min_text_capacity = padToIdeal(minimum_text_block_size); |
| 288 | 288 | |
| 289 | /// Virtual memory offset corresponds to the size of __PAGEZERO segment and start of | |
| 290 | /// __TEXT segment. | |
| 291 | const pagezero_vmsize: u64 = 0x100000000; | |
| 289 | /// Default virtual memory offset corresponds to the size of __PAGEZERO segment and | |
| 290 | /// start of __TEXT segment. | |
| 291 | const default_pagezero_vmsize: u64 = 0x100000000; | |
| 292 | 292 | |
| 293 | 293 | pub const Export = struct { |
| 294 | 294 | sym_index: ?u32 = null, |
| ... | ... | @@ -536,7 +536,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 536 | 536 | // We are about to obtain this lock, so here we give other processes a chance first. |
| 537 | 537 | self.base.releaseLock(); |
| 538 | 538 | |
| 539 | comptime assert(Compilation.link_hash_implementation_version == 3); | |
| 539 | comptime assert(Compilation.link_hash_implementation_version == 4); | |
| 540 | 540 | |
| 541 | 541 | for (self.base.options.objects) |obj| { |
| 542 | 542 | _ = try man.addFile(obj.path, null); |
| ... | ... | @@ -549,6 +549,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 549 | 549 | // We can skip hashing libc and libc++ components that we are in charge of building from Zig |
| 550 | 550 | // installation sources because they are always a product of the compiler version + target information. |
| 551 | 551 | man.hash.add(stack_size); |
| 552 | man.hash.addOptional(self.base.options.pagezero_size); | |
| 552 | 553 | man.hash.addListOfBytes(self.base.options.lib_dirs); |
| 553 | 554 | man.hash.addListOfBytes(self.base.options.framework_dirs); |
| 554 | 555 | man.hash.addListOfBytes(self.base.options.frameworks); |
| ... | ... | @@ -928,6 +929,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 928 | 929 | try argv.append(rpath); |
| 929 | 930 | } |
| 930 | 931 | |
| 932 | if (self.base.options.pagezero_size) |pagezero_size| { | |
| 933 | try argv.append("-pagezero_size"); | |
| 934 | try argv.append(try std.fmt.allocPrint(arena, "0x{x}", .{pagezero_size})); | |
| 935 | } | |
| 936 | ||
| 931 | 937 | try argv.appendSlice(positionals.items); |
| 932 | 938 | |
| 933 | 939 | try argv.append("-o"); |
| ... | ... | @@ -4365,14 +4371,21 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil |
| 4365 | 4371 | |
| 4366 | 4372 | fn populateMissingMetadata(self: *MachO) !void { |
| 4367 | 4373 | const cpu_arch = self.base.options.target.cpu.arch; |
| 4368 | ||
| 4369 | if (self.pagezero_segment_cmd_index == null) { | |
| 4374 | const pagezero_vmsize = self.base.options.pagezero_size orelse default_pagezero_vmsize; | |
| 4375 | const aligned_pagezero_vmsize = mem.alignBackwardGeneric(u64, pagezero_vmsize, self.page_size); | |
| 4376 | ||
| 4377 | if (self.pagezero_segment_cmd_index == null) blk: { | |
| 4378 | if (aligned_pagezero_vmsize == 0) break :blk; | |
| 4379 | if (aligned_pagezero_vmsize != pagezero_vmsize) { | |
| 4380 | log.warn("requested __PAGEZERO size (0x{x}) is not page aligned", .{pagezero_vmsize}); | |
| 4381 | log.warn(" rounding down to 0x{x}", .{aligned_pagezero_vmsize}); | |
| 4382 | } | |
| 4370 | 4383 | self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 4371 | 4384 | try self.load_commands.append(self.base.allocator, .{ |
| 4372 | 4385 | .segment = .{ |
| 4373 | 4386 | .inner = .{ |
| 4374 | 4387 | .segname = makeStaticString("__PAGEZERO"), |
| 4375 | .vmsize = pagezero_vmsize, | |
| 4388 | .vmsize = aligned_pagezero_vmsize, | |
| 4376 | 4389 | .cmdsize = @sizeOf(macho.segment_command_64), |
| 4377 | 4390 | }, |
| 4378 | 4391 | }, |
| ... | ... | @@ -4394,7 +4407,7 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4394 | 4407 | .segment = .{ |
| 4395 | 4408 | .inner = .{ |
| 4396 | 4409 | .segname = makeStaticString("__TEXT"), |
| 4397 | .vmaddr = pagezero_vmsize, | |
| 4410 | .vmaddr = aligned_pagezero_vmsize, | |
| 4398 | 4411 | .vmsize = needed_size, |
| 4399 | 4412 | .filesize = needed_size, |
| 4400 | 4413 | .maxprot = macho.PROT.READ | macho.PROT.EXEC, |
| ... | ... | @@ -4881,7 +4894,10 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4881 | 4894 | |
| 4882 | 4895 | fn allocateTextSegment(self: *MachO) !void { |
| 4883 | 4896 | const seg = &self.load_commands.items[self.text_segment_cmd_index.?].segment; |
| 4884 | const base_vmaddr = self.load_commands.items[self.pagezero_segment_cmd_index.?].segment.inner.vmsize; | |
| 4897 | const base_vmaddr = if (self.pagezero_segment_cmd_index) |index| | |
| 4898 | self.load_commands.items[index].segment.inner.vmsize | |
| 4899 | else | |
| 4900 | 0; | |
| 4885 | 4901 | seg.inner.fileoff = 0; |
| 4886 | 4902 | seg.inner.vmaddr = base_vmaddr; |
| 4887 | 4903 |
src/link/Wasm.zig+1-1| ... | ... | @@ -2274,7 +2274,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! |
| 2274 | 2274 | // We are about to obtain this lock, so here we give other processes a chance first. |
| 2275 | 2275 | self.base.releaseLock(); |
| 2276 | 2276 | |
| 2277 | comptime assert(Compilation.link_hash_implementation_version == 3); | |
| 2277 | comptime assert(Compilation.link_hash_implementation_version == 4); | |
| 2278 | 2278 | |
| 2279 | 2279 | for (self.base.options.objects) |obj| { |
| 2280 | 2280 | _ = try man.addFile(obj.path, null); |
src/main.zig+31| ... | ... | @@ -447,6 +447,7 @@ const usage_build_generic = |
| 447 | 447 | \\ -F[dir] (Darwin) add search path for frameworks |
| 448 | 448 | \\ -install_name=[value] (Darwin) add dylib's install name |
| 449 | 449 | \\ --entitlements [path] (Darwin) add path to entitlements file for embedding in code signature |
| 450 | \\ -pagezero_size [value] (Darwin) size of the __PAGEZERO segment in hexadecimal notation | |
| 450 | 451 | \\ --import-memory (WebAssembly) import memory from the environment |
| 451 | 452 | \\ --import-table (WebAssembly) import function table from the host environment |
| 452 | 453 | \\ --export-table (WebAssembly) export function table to the host environment |
| ... | ... | @@ -694,6 +695,7 @@ fn buildOutputType( |
| 694 | 695 | var install_name: ?[]const u8 = null; |
| 695 | 696 | var hash_style: link.HashStyle = .both; |
| 696 | 697 | var entitlements: ?[]const u8 = null; |
| 698 | var pagezero_size: ?u64 = null; | |
| 697 | 699 | |
| 698 | 700 | // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names. |
| 699 | 701 | // This array is populated by zig cc frontend and then has to be converted to zig-style |
| ... | ... | @@ -908,6 +910,13 @@ fn buildOutputType( |
| 908 | 910 | install_name = args_iter.next() orelse { |
| 909 | 911 | fatal("expected parameter after {s}", .{arg}); |
| 910 | 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, eatIntPrefix(next_arg, 16), 16) catch |err| { | |
| 918 | fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); | |
| 919 | }; | |
| 911 | 920 | } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) { |
| 912 | 921 | linker_script = args_iter.next() orelse { |
| 913 | 922 | fatal("expected parameter after {s}", .{arg}); |
| ... | ... | @@ -1647,6 +1656,15 @@ fn buildOutputType( |
| 1647 | 1656 | linker_optimization = std.fmt.parseUnsigned(u8, arg["-O".len..], 10) catch |err| { |
| 1648 | 1657 | fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); |
| 1649 | 1658 | }; |
| 1659 | } else if (mem.eql(u8, arg, "-pagezero_size")) { | |
| 1660 | i += 1; | |
| 1661 | if (i >= linker_args.items.len) { | |
| 1662 | fatal("expected linker arg after '{s}'", .{arg}); | |
| 1663 | } | |
| 1664 | const next_arg = linker_args.items[i]; | |
| 1665 | pagezero_size = std.fmt.parseUnsigned(u64, eatIntPrefix(next_arg, 16), 16) catch |err| { | |
| 1666 | fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); | |
| 1667 | }; | |
| 1650 | 1668 | } else if (mem.eql(u8, arg, "--gc-sections")) { |
| 1651 | 1669 | linker_gc_sections = true; |
| 1652 | 1670 | } else if (mem.eql(u8, arg, "--no-gc-sections")) { |
| ... | ... | @@ -2763,6 +2781,7 @@ fn buildOutputType( |
| 2763 | 2781 | .native_darwin_sdk = native_darwin_sdk, |
| 2764 | 2782 | .install_name = install_name, |
| 2765 | 2783 | .entitlements = entitlements, |
| 2784 | .pagezero_size = pagezero_size, | |
| 2766 | 2785 | }) catch |err| switch (err) { |
| 2767 | 2786 | error.LibCUnavailable => { |
| 2768 | 2787 | const target = target_info.target; |
| ... | ... | @@ -5048,6 +5067,18 @@ pub fn cmdChangelist( |
| 5048 | 5067 | try bw.flush(); |
| 5049 | 5068 | } |
| 5050 | 5069 | |
| 5070 | fn eatIntPrefix(arg: []const u8, radix: u8) []const u8 { | |
| 5071 | if (arg.len > 2 and arg[0] == '0') { | |
| 5072 | switch (std.ascii.toLower(arg[1])) { | |
| 5073 | 'b' => if (radix == 2) return arg[2..], | |
| 5074 | 'o' => if (radix == 8) return arg[2..], | |
| 5075 | 'x' => if (radix == 16) return arg[2..], | |
| 5076 | else => {}, | |
| 5077 | } | |
| 5078 | } | |
| 5079 | return arg; | |
| 5080 | } | |
| 5081 | ||
| 5051 | 5082 | fn parseIntSuffix(arg: []const u8, prefix_len: usize) u64 { |
| 5052 | 5083 | return std.fmt.parseUnsigned(u64, arg[prefix_len..], 0) catch |err| { |
| 5053 | 5084 | fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); |