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.
This commit is contained in:
Kenta Iwasaki 2021-10-29 18:03:55 +09:00 committed by Andrew Kelley
parent 83a4bb6e69
commit 2cdffc97f0
5 changed files with 50 additions and 0 deletions

View File

@ -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");
}

View File

@ -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,

View File

@ -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,

View File

@ -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");

View File

@ -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,