From 6ad92108e2cbba06064724d8d91abaede20f355a Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Thu, 5 Jan 2023 21:21:29 +0100 Subject: ELF linker: support common-page-size and max-page-size lld opts These linker flags are required to build static ELF binaries that can run under the Blink emulator: https://github.com/jart/blink/issues/14 --- src/Compilation.zig | 6 ++++++ src/link.zig | 2 ++ src/link/Elf.zig | 10 ++++++++++ src/main.zig | 14 ++++++++++++++ 4 files changed, 32 insertions(+) (limited to 'src') diff --git a/src/Compilation.zig b/src/Compilation.zig index f90b8f28d1..cd0761315a 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -979,6 +979,8 @@ pub const InitOptions = struct { linker_z_now: bool = true, linker_z_relro: bool = true, linker_z_nocopyreloc: bool = false, + linker_z_common_page_size: ?u64 = null, + linker_z_max_page_size: ?u64 = null, linker_tsaware: bool = false, linker_nxcompat: bool = false, linker_dynamicbase: bool = false, @@ -1842,6 +1844,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .z_nocopyreloc = options.linker_z_nocopyreloc, .z_now = options.linker_z_now, .z_relro = options.linker_z_relro, + .z_common_page_size = options.linker_z_common_page_size, + .z_max_page_size = options.linker_z_max_page_size, .tsaware = options.linker_tsaware, .nxcompat = options.linker_nxcompat, .dynamicbase = options.linker_dynamicbase, @@ -2637,6 +2641,8 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.add(comp.bin_file.options.z_nocopyreloc); man.hash.add(comp.bin_file.options.z_now); man.hash.add(comp.bin_file.options.z_relro); + man.hash.add(comp.bin_file.options.z_common_page_size orelse 0); + man.hash.add(comp.bin_file.options.z_max_page_size orelse 0); man.hash.add(comp.bin_file.options.hash_style); man.hash.add(comp.bin_file.options.compress_debug_sections); man.hash.add(comp.bin_file.options.include_compiler_rt); diff --git a/src/link.zig b/src/link.zig index 222c0e4918..15bff217f0 100644 --- a/src/link.zig +++ b/src/link.zig @@ -121,6 +121,8 @@ pub const Options = struct { z_nocopyreloc: bool, z_now: bool, z_relro: bool, + z_common_page_size: ?u64, + z_max_page_size: ?u64, tsaware: bool, nxcompat: bool, dynamicbase: bool, diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 4910f4b599..c27e4f166f 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1390,6 +1390,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v man.hash.add(self.base.options.z_nocopyreloc); man.hash.add(self.base.options.z_now); man.hash.add(self.base.options.z_relro); + man.hash.add(self.base.options.z_common_page_size orelse 0); + man.hash.add(self.base.options.z_max_page_size orelse 0); man.hash.add(self.base.options.hash_style); // strip does not need to go into the linker hash because it is part of the hash namespace if (self.base.options.link_libc) { @@ -1594,6 +1596,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v // LLD defaults to -zrelro try argv.append("-znorelro"); } + if (self.base.options.z_common_page_size) |size| { + try argv.append("-z"); + try argv.append(try std.fmt.allocPrint(arena, "common-page-size={d}", .{size})); + } + if (self.base.options.z_max_page_size) |size| { + try argv.append("-z"); + try argv.append(try std.fmt.allocPrint(arena, "max-page-size={d}", .{size})); + } if (getLDMOption(target)) |ldm| { // Any target ELF will use the freebsd osabi if suffixed with "_fbsd". diff --git a/src/main.zig b/src/main.zig index 04d1b45d2a..15207a57e1 100644 --- a/src/main.zig +++ b/src/main.zig @@ -495,6 +495,8 @@ const usage_build_generic = \\ lazy Don't force all relocations to be processed on load \\ relro (default) Force all relocations to be read-only after processing \\ norelro Don't force all relocations to be read-only after processing + \\ common-page-size=[bytes] Set the common page size for ELF binaries + \\ max-page-size=[bytes] Set the max page size for ELF binaries \\ -dynamic Force output to be dynamically linked \\ -static Force output to be statically linked \\ -Bsymbolic Bind global references locally @@ -744,6 +746,8 @@ fn buildOutputType( var linker_z_origin = false; var linker_z_now = true; var linker_z_relro = true; + var linker_z_common_page_size: ?u64 = null; + var linker_z_max_page_size: ?u64 = null; var linker_tsaware = false; var linker_nxcompat = false; var linker_dynamicbase = false; @@ -1325,6 +1329,10 @@ fn buildOutputType( linker_z_relro = true; } else if (mem.eql(u8, z_arg, "norelro")) { linker_z_relro = false; + } else if (mem.startsWith(u8, z_arg, "common-page-size=")) { + linker_z_common_page_size = parseIntSuffix(z_arg, "common-page-size=".len); + } else if (mem.startsWith(u8, z_arg, "max-page-size=")) { + linker_z_max_page_size = parseIntSuffix(z_arg, "max-page-size=".len); } else { warn("unsupported linker extension flag: -z {s}", .{z_arg}); } @@ -1923,6 +1931,10 @@ fn buildOutputType( stack_size_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| { fatal("unable to parse stack size '{s}': {s}", .{ next_arg, @errorName(err) }); }; + } else if (mem.startsWith(u8, z_arg, "common-page-size=")) { + linker_z_common_page_size = parseIntSuffix(z_arg, "common-page-size=".len); + } else if (mem.startsWith(u8, z_arg, "max-page-size=")) { + linker_z_max_page_size = parseIntSuffix(z_arg, "max-page-size=".len); } else { warn("unsupported linker extension flag: -z {s}", .{z_arg}); } @@ -3042,6 +3054,8 @@ fn buildOutputType( .linker_z_origin = linker_z_origin, .linker_z_now = linker_z_now, .linker_z_relro = linker_z_relro, + .linker_z_common_page_size = linker_z_common_page_size, + .linker_z_max_page_size = linker_z_max_page_size, .linker_tsaware = linker_tsaware, .linker_nxcompat = linker_nxcompat, .linker_dynamicbase = linker_dynamicbase, -- cgit v1.2.3