diff --git a/lib/std/build.zig b/lib/std/build.zig index a2b9aa30308c..3f56b5752c76 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1489,6 +1489,9 @@ pub const LibExeObjStep = struct { linker_allow_shlib_undefined: ?bool = null, + /// Permit read-only relocations in read-only segments. Disallowed by default. + link_z_notext: bool = false, + /// Uses system Wine installation to run cross compiled Windows build artifacts. enable_wine: bool = false, @@ -2354,6 +2357,10 @@ pub const LibExeObjStep = struct { if (self.linker_allow_shlib_undefined) |x| { try zig_args.append(if (x) "-fallow-shlib-undefined" else "-fno-allow-shlib-undefined"); } + if (self.link_z_notext) { + try zig_args.append("-z"); + try zig_args.append("notext"); + } if (self.single_threaded) { try zig_args.append("--single-threaded"); } diff --git a/src/Compilation.zig b/src/Compilation.zig index 8ea6b545b8d5..719daabbaa31 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -718,6 +718,7 @@ pub const InitOptions = struct { each_lib_rpath: ?bool = null, disable_c_depfile: bool = false, linker_z_nodelete: bool = false, + linker_z_notext: bool = false, linker_z_defs: bool = false, linker_z_origin: bool = false, linker_z_noexecstack: bool = false, @@ -1400,6 +1401,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .allow_shlib_undefined = options.linker_allow_shlib_undefined, .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false, .z_nodelete = options.linker_z_nodelete, + .z_notext = options.linker_z_notext, .z_defs = options.linker_z_defs, .z_origin = options.linker_z_origin, .z_noexecstack = options.linker_z_noexecstack, diff --git a/src/link.zig b/src/link.zig index a1df48f7599b..3ff73fb7bfd6 100644 --- a/src/link.zig +++ b/src/link.zig @@ -72,6 +72,7 @@ pub const Options = struct { emit_relocs: bool, rdynamic: bool, z_nodelete: bool, + z_notext: bool, z_defs: bool, z_origin: bool, z_noexecstack: bool, diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 705daaf99758..a881e78e7e25 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1332,6 +1332,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { man.hash.add(self.base.options.each_lib_rpath); man.hash.add(self.base.options.skip_linker_dependencies); man.hash.add(self.base.options.z_nodelete); + man.hash.add(self.base.options.z_notext); man.hash.add(self.base.options.z_defs); man.hash.add(self.base.options.z_origin); man.hash.add(self.base.options.z_noexecstack); @@ -1470,6 +1471,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { try argv.append("-z"); try argv.append("nodelete"); } + if (self.base.options.z_notext) { + try argv.append("-z"); + try argv.append("notext"); + } if (self.base.options.z_defs) { try argv.append("-z"); try argv.append("defs"); diff --git a/src/main.zig b/src/main.zig index afe5e324c22c..f3837ef734ce 100644 --- a/src/main.zig +++ b/src/main.zig @@ -401,6 +401,14 @@ const usage_build_generic = \\ -fno-allow-shlib-undefined Disallows undefined symbols in shared libraries \\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker \\ --emit-relocs Enable output of relocation sections for post build tools + \\ -z [arg] Append linker arguments + \\ nodelete Indicate that the object cannot be deleted from a process + \\ notext Permit read-only relocations in read-only segments + \\ defs Force a fatal error if any undefined symbols remain + \\ origin Indicate that the object must have its origin processed + \\ noexecstack Indicate that the object requires an executable stack + \\ now Force all relocations to be processed on load + \\ relro Force all relocations to be resolved and be read-only on load \\ -dynamic Force output to be dynamically linked \\ -static Force output to be statically linked \\ -Bsymbolic Bind global references locally @@ -595,6 +603,7 @@ fn buildOutputType( var linker_allow_shlib_undefined: ?bool = null; var linker_bind_global_refs_locally: ?bool = null; var linker_z_nodelete = false; + var linker_z_notext = false; var linker_z_defs = false; var linker_z_origin = false; var linker_z_noexecstack = false; @@ -1086,6 +1095,29 @@ fn buildOutputType( linker_allow_shlib_undefined = true; } else if (mem.eql(u8, arg, "-fno-allow-shlib-undefined")) { linker_allow_shlib_undefined = false; + } else if (mem.eql(u8, arg, "-z")) { + i += 1; + if (i >= args.len) { + fatal("expected linker arg after '{s}'", .{arg}); + } + const z_arg = args[i]; + if (mem.eql(u8, z_arg, "nodelete")) { + linker_z_nodelete = true; + } else if (mem.eql(u8, z_arg, "notext")) { + linker_z_notext = true; + } else if (mem.eql(u8, z_arg, "defs")) { + linker_z_defs = true; + } else if (mem.eql(u8, z_arg, "origin")) { + linker_z_origin = true; + } else if (mem.eql(u8, z_arg, "noexecstack")) { + linker_z_noexecstack = true; + } else if (mem.eql(u8, z_arg, "now")) { + linker_z_now = true; + } else if (mem.eql(u8, z_arg, "relro")) { + linker_z_relro = true; + } else { + warn("unsupported linker arg: -z {s}", .{z_arg}); + } } else if (mem.eql(u8, arg, "-Bsymbolic")) { linker_bind_global_refs_locally = true; } else if (mem.eql(u8, arg, "--debug-compile-errors")) { @@ -1422,6 +1454,8 @@ fn buildOutputType( const z_arg = linker_args.items[i]; if (mem.eql(u8, z_arg, "nodelete")) { linker_z_nodelete = true; + } else if (mem.eql(u8, z_arg, "notext")) { + linker_z_notext = true; } else if (mem.eql(u8, z_arg, "defs")) { linker_z_defs = true; } else if (mem.eql(u8, z_arg, "origin")) { @@ -2108,6 +2142,7 @@ fn buildOutputType( .linker_allow_shlib_undefined = linker_allow_shlib_undefined, .linker_bind_global_refs_locally = linker_bind_global_refs_locally, .linker_z_nodelete = linker_z_nodelete, + .linker_z_notext = linker_z_notext, .linker_z_defs = linker_z_defs, .linker_z_origin = linker_z_origin, .linker_z_noexecstack = linker_z_noexecstack,