authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2023-01-05 21:21:29+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-05 19:39:17-07:00
log6ad92108e2cbba06064724d8d91abaede20f355a
tree4551c42980bf7044fd67edcbe51f7d9a257344c6
parentc28c38d1e5648a45e8b3b2edbd1c732edb8d2642

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

5 files changed, 46 insertions(+), 0 deletions(-)

lib/std/build/LibExeObjStep.zig+14
......@@ -155,6 +155,12 @@ link_z_relro: bool = true,
155155/// Allow relocations to be lazily processed after load.
156156link_z_lazy: bool = false,
157157
158/// Common page size
159link_z_common_page_size: ?u64 = null,
160
161/// Maximum page size
162link_z_max_page_size: ?u64 = null,
163
158164/// (Darwin) Install name for the dylib
159165install_name: ?[]const u8 = null,
160166
......@@ -1338,6 +1344,14 @@ fn make(step: *Step) !void {
13381344 try zig_args.append("-z");
13391345 try zig_args.append("lazy");
13401346 }
1347 if (self.link_z_common_page_size) |size| {
1348 try zig_args.append("-z");
1349 try zig_args.append(builder.fmt("common-page-size={d}", .{size}));
1350 }
1351 if (self.link_z_max_page_size) |size| {
1352 try zig_args.append("-z");
1353 try zig_args.append(builder.fmt("max-page-size={d}", .{size}));
1354 }
13411355
13421356 if (self.libc_file) |libc_file| {
13431357 try zig_args.append("--libc");
src/Compilation.zig+6
......@@ -979,6 +979,8 @@ pub const InitOptions = struct {
979979 linker_z_now: bool = true,
980980 linker_z_relro: bool = true,
981981 linker_z_nocopyreloc: bool = false,
982 linker_z_common_page_size: ?u64 = null,
983 linker_z_max_page_size: ?u64 = null,
982984 linker_tsaware: bool = false,
983985 linker_nxcompat: bool = false,
984986 linker_dynamicbase: bool = false,
......@@ -1842,6 +1844,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
18421844 .z_nocopyreloc = options.linker_z_nocopyreloc,
18431845 .z_now = options.linker_z_now,
18441846 .z_relro = options.linker_z_relro,
1847 .z_common_page_size = options.linker_z_common_page_size,
1848 .z_max_page_size = options.linker_z_max_page_size,
18451849 .tsaware = options.linker_tsaware,
18461850 .nxcompat = options.linker_nxcompat,
18471851 .dynamicbase = options.linker_dynamicbase,
......@@ -2637,6 +2641,8 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
26372641 man.hash.add(comp.bin_file.options.z_nocopyreloc);
26382642 man.hash.add(comp.bin_file.options.z_now);
26392643 man.hash.add(comp.bin_file.options.z_relro);
2644 man.hash.add(comp.bin_file.options.z_common_page_size orelse 0);
2645 man.hash.add(comp.bin_file.options.z_max_page_size orelse 0);
26402646 man.hash.add(comp.bin_file.options.hash_style);
26412647 man.hash.add(comp.bin_file.options.compress_debug_sections);
26422648 man.hash.add(comp.bin_file.options.include_compiler_rt);
src/link.zig+2
......@@ -121,6 +121,8 @@ pub const Options = struct {
121121 z_nocopyreloc: bool,
122122 z_now: bool,
123123 z_relro: bool,
124 z_common_page_size: ?u64,
125 z_max_page_size: ?u64,
124126 tsaware: bool,
125127 nxcompat: bool,
126128 dynamicbase: bool,
src/link/Elf.zig+10
......@@ -1390,6 +1390,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
13901390 man.hash.add(self.base.options.z_nocopyreloc);
13911391 man.hash.add(self.base.options.z_now);
13921392 man.hash.add(self.base.options.z_relro);
1393 man.hash.add(self.base.options.z_common_page_size orelse 0);
1394 man.hash.add(self.base.options.z_max_page_size orelse 0);
13931395 man.hash.add(self.base.options.hash_style);
13941396 // strip does not need to go into the linker hash because it is part of the hash namespace
13951397 if (self.base.options.link_libc) {
......@@ -1594,6 +1596,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
15941596 // LLD defaults to -zrelro
15951597 try argv.append("-znorelro");
15961598 }
1599 if (self.base.options.z_common_page_size) |size| {
1600 try argv.append("-z");
1601 try argv.append(try std.fmt.allocPrint(arena, "common-page-size={d}", .{size}));
1602 }
1603 if (self.base.options.z_max_page_size) |size| {
1604 try argv.append("-z");
1605 try argv.append(try std.fmt.allocPrint(arena, "max-page-size={d}", .{size}));
1606 }
15971607
15981608 if (getLDMOption(target)) |ldm| {
15991609 // Any target ELF will use the freebsd osabi if suffixed with "_fbsd".
src/main.zig+14
......@@ -495,6 +495,8 @@ const usage_build_generic =
495495 \\ lazy Don't force all relocations to be processed on load
496496 \\ relro (default) Force all relocations to be read-only after processing
497497 \\ norelro Don't force all relocations to be read-only after processing
498 \\ common-page-size=[bytes] Set the common page size for ELF binaries
499 \\ max-page-size=[bytes] Set the max page size for ELF binaries
498500 \\ -dynamic Force output to be dynamically linked
499501 \\ -static Force output to be statically linked
500502 \\ -Bsymbolic Bind global references locally
......@@ -744,6 +746,8 @@ fn buildOutputType(
744746 var linker_z_origin = false;
745747 var linker_z_now = true;
746748 var linker_z_relro = true;
749 var linker_z_common_page_size: ?u64 = null;
750 var linker_z_max_page_size: ?u64 = null;
747751 var linker_tsaware = false;
748752 var linker_nxcompat = false;
749753 var linker_dynamicbase = false;
......@@ -1325,6 +1329,10 @@ fn buildOutputType(
13251329 linker_z_relro = true;
13261330 } else if (mem.eql(u8, z_arg, "norelro")) {
13271331 linker_z_relro = false;
1332 } else if (mem.startsWith(u8, z_arg, "common-page-size=")) {
1333 linker_z_common_page_size = parseIntSuffix(z_arg, "common-page-size=".len);
1334 } else if (mem.startsWith(u8, z_arg, "max-page-size=")) {
1335 linker_z_max_page_size = parseIntSuffix(z_arg, "max-page-size=".len);
13281336 } else {
13291337 warn("unsupported linker extension flag: -z {s}", .{z_arg});
13301338 }
......@@ -1923,6 +1931,10 @@ fn buildOutputType(
19231931 stack_size_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| {
19241932 fatal("unable to parse stack size '{s}': {s}", .{ next_arg, @errorName(err) });
19251933 };
1934 } else if (mem.startsWith(u8, z_arg, "common-page-size=")) {
1935 linker_z_common_page_size = parseIntSuffix(z_arg, "common-page-size=".len);
1936 } else if (mem.startsWith(u8, z_arg, "max-page-size=")) {
1937 linker_z_max_page_size = parseIntSuffix(z_arg, "max-page-size=".len);
19261938 } else {
19271939 warn("unsupported linker extension flag: -z {s}", .{z_arg});
19281940 }
......@@ -3042,6 +3054,8 @@ fn buildOutputType(
30423054 .linker_z_origin = linker_z_origin,
30433055 .linker_z_now = linker_z_now,
30443056 .linker_z_relro = linker_z_relro,
3057 .linker_z_common_page_size = linker_z_common_page_size,
3058 .linker_z_max_page_size = linker_z_max_page_size,
30453059 .linker_tsaware = linker_tsaware,
30463060 .linker_nxcompat = linker_nxcompat,
30473061 .linker_dynamicbase = linker_dynamicbase,