Commit 2cdffc97f0

Kenta Iwasaki <kenta@lithdew.net>
2021-10-29 11:03:55
zig: expose linker options and include '-z notext'
Add an option to allow the '-z notext' option to be passed to the linker via. the compiler frontend, which is a flag that tells the linker that relocations in read-only sections are permitted. Certain targets such as Solana BPF rely on this flag. Expose all linker options i.e. '-z nodelete', '-z now', '-z relro' in the compiler frontend. Usage documentation has been updated accordingly. Expose the '-z notext' flag in the standard library build runner.
1 parent 83a4bb6
Changed files (5)
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");
         }
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");
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,
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,
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,