authorgravatar for me@dha.shdhash <me@dha.sh> 2023-09-29 13:38:54-04:00
committergravatar for carl@astholm.seCarl Åstholm <carl@astholm.se> 2024-01-09 17:24:11+01:00
log9bb643031864c8c3c2d4ac52aecb175283e335e3
tree20e8fa8787aa7e29e9771edff9d20f8a404ea70b
parent60094cc3fc979df0928c412c9fded457172f2060

Add support for `--(no-)undefined-version`

Co-authored-by: Motiejus Jakštys <motiejus@jakstys.lt> Co-authored-by: Jakub Konka <kubkon@jakubkonka.com> Co-authored-by: Samuel Cantero <scanterog@gmail.com> Co-authored-by: Giorgos Georgiou <giorgos.georgiou@datadoghq.com> Co-authored-by: Carl Åstholm <carl@astholm.se>

8 files changed, 37 insertions(+), 7 deletions(-)

lib/std/Build/Step/Compile.zig+6
...@@ -110,6 +110,9 @@ linker_dynamicbase: bool = true,...@@ -110,6 +110,9 @@ linker_dynamicbase: bool = true,
110110
111linker_allow_shlib_undefined: ?bool = null,111linker_allow_shlib_undefined: ?bool = null,
112112
113/// Allow version scripts to refer to undefined symbols.
114linker_allow_undefined_version: ?bool = null,
115
113/// Permit read-only relocations in read-only segments. Disallowed by default.116/// Permit read-only relocations in read-only segments. Disallowed by default.
114link_z_notext: bool = false,117link_z_notext: bool = false,
115118
...@@ -1451,6 +1454,9 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1451,6 +1454,9 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1451 try zig_args.append("--version-script");1454 try zig_args.append("--version-script");
1452 try zig_args.append(version_script.getPath(b));1455 try zig_args.append(version_script.getPath(b));
1453 }1456 }
1457 if (self.linker_allow_undefined_version) |x| {
1458 try zig_args.append(if (x) "--undefined-version" else "--no-undefined-version");
1459 }
14541460
1455 if (self.kind == .@"test") {1461 if (self.kind == .@"test") {
1456 if (self.exec_cmd_args) |exec_cmd_args| {1462 if (self.exec_cmd_args) |exec_cmd_args| {
src/Compilation.zig+5-2
...@@ -1033,6 +1033,7 @@ pub const CreateOptions = struct {...@@ -1033,6 +1033,7 @@ pub const CreateOptions = struct {
1033 link_emit_relocs: bool = false,1033 link_emit_relocs: bool = false,
1034 linker_script: ?[]const u8 = null,1034 linker_script: ?[]const u8 = null,
1035 version_script: ?[]const u8 = null,1035 version_script: ?[]const u8 = null,
1036 linker_allow_undefined_version: bool = false,
1036 soname: ?[]const u8 = null,1037 soname: ?[]const u8 = null,
1037 linker_gc_sections: ?bool = null,1038 linker_gc_sections: ?bool = null,
1038 linker_allow_shlib_undefined: ?bool = null,1039 linker_allow_shlib_undefined: ?bool = null,
...@@ -1572,6 +1573,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1572,6 +1573,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1572 .stack_size = options.stack_size,1573 .stack_size = options.stack_size,
1573 .image_base = options.image_base,1574 .image_base = options.image_base,
1574 .version_script = options.version_script,1575 .version_script = options.version_script,
1576 .allow_undefined_version = options.linker_allow_undefined_version,
1575 .gc_sections = options.linker_gc_sections,1577 .gc_sections = options.linker_gc_sections,
1576 .emit_relocs = options.link_emit_relocs,1578 .emit_relocs = options.link_emit_relocs,
1577 .soname = options.soname,1579 .soname = options.soname,
...@@ -2458,7 +2460,7 @@ fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemo...@@ -2458,7 +2460,7 @@ fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemo
2458/// to remind the programmer to update multiple related pieces of code that2460/// to remind the programmer to update multiple related pieces of code that
2459/// are in different locations. Bump this number when adding or deleting2461/// are in different locations. Bump this number when adding or deleting
2460/// anything from the link cache manifest.2462/// anything from the link cache manifest.
2461pub const link_hash_implementation_version = 10;2463pub const link_hash_implementation_version = 11;
24622464
2463fn addNonIncrementalStuffToCacheManifest(2465fn addNonIncrementalStuffToCacheManifest(
2464 comp: *Compilation,2466 comp: *Compilation,
...@@ -2467,7 +2469,7 @@ fn addNonIncrementalStuffToCacheManifest(...@@ -2467,7 +2469,7 @@ fn addNonIncrementalStuffToCacheManifest(
2467) !void {2469) !void {
2468 const gpa = comp.gpa;2470 const gpa = comp.gpa;
24692471
2470 comptime assert(link_hash_implementation_version == 10);2472 comptime assert(link_hash_implementation_version == 11);
24712473
2472 if (comp.module) |mod| {2474 if (comp.module) |mod| {
2473 const main_zig_file = try mod.main_mod.root.joinString(arena, mod.main_mod.root_src_path);2475 const main_zig_file = try mod.main_mod.root.joinString(arena, mod.main_mod.root_src_path);
...@@ -2541,6 +2543,7 @@ fn addNonIncrementalStuffToCacheManifest(...@@ -2541,6 +2543,7 @@ fn addNonIncrementalStuffToCacheManifest(
25412543
2542 try man.addOptionalFile(opts.linker_script);2544 try man.addOptionalFile(opts.linker_script);
2543 try man.addOptionalFile(opts.version_script);2545 try man.addOptionalFile(opts.version_script);
2546 man.hash.add(opts.allow_undefined_version);
25442547
2545 man.hash.addOptional(opts.stack_size);2548 man.hash.addOptional(opts.stack_size);
2546 man.hash.addOptional(opts.image_base);2549 man.hash.addOptional(opts.image_base);
src/link.zig+1
...@@ -113,6 +113,7 @@ pub const File = struct {...@@ -113,6 +113,7 @@ pub const File = struct {
113 minor_subsystem_version: ?u16,113 minor_subsystem_version: ?u16,
114 gc_sections: ?bool,114 gc_sections: ?bool,
115 allow_shlib_undefined: ?bool,115 allow_shlib_undefined: ?bool,
116 allow_undefined_version: bool,
116 subsystem: ?std.Target.SubSystem,117 subsystem: ?std.Target.SubSystem,
117 linker_script: ?[]const u8,118 linker_script: ?[]const u8,
118 version_script: ?[]const u8,119 version_script: ?[]const u8,
src/link/Coff/lld.zig+1-1
...@@ -70,7 +70,7 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node)...@@ -70,7 +70,7 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node)
70 man = comp.cache_parent.obtain();70 man = comp.cache_parent.obtain();
71 self.base.releaseLock();71 self.base.releaseLock();
7272
73 comptime assert(Compilation.link_hash_implementation_version == 10);73 comptime assert(Compilation.link_hash_implementation_version == 11);
7474
75 for (comp.objects) |obj| {75 for (comp.objects) |obj| {
76 _ = try man.addFile(obj.path, null);76 _ = try man.addFile(obj.path, null);
src/link/Elf.zig+9-1
...@@ -22,6 +22,7 @@ soname: ?[]const u8,...@@ -22,6 +22,7 @@ soname: ?[]const u8,
22bind_global_refs_locally: bool,22bind_global_refs_locally: bool,
23linker_script: ?[]const u8,23linker_script: ?[]const u8,
24version_script: ?[]const u8,24version_script: ?[]const u8,
25allow_undefined_version: bool,
25print_icf_sections: bool,26print_icf_sections: bool,
26print_map: bool,27print_map: bool,
27entry_name: ?[]const u8,28entry_name: ?[]const u8,
...@@ -325,6 +326,7 @@ pub fn createEmpty(...@@ -325,6 +326,7 @@ pub fn createEmpty(
325 .bind_global_refs_locally = options.bind_global_refs_locally,326 .bind_global_refs_locally = options.bind_global_refs_locally,
326 .linker_script = options.linker_script,327 .linker_script = options.linker_script,
327 .version_script = options.version_script,328 .version_script = options.version_script,
329 .allow_undefined_version = options.allow_undefined_version,
328 .print_icf_sections = options.print_icf_sections,330 .print_icf_sections = options.print_icf_sections,
329 .print_map = options.print_map,331 .print_map = options.print_map,
330 };332 };
...@@ -2410,10 +2412,11 @@ fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) !voi...@@ -2410,10 +2412,11 @@ fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) !voi
2410 // We are about to obtain this lock, so here we give other processes a chance first.2412 // We are about to obtain this lock, so here we give other processes a chance first.
2411 self.base.releaseLock();2413 self.base.releaseLock();
24122414
2413 comptime assert(Compilation.link_hash_implementation_version == 10);2415 comptime assert(Compilation.link_hash_implementation_version == 11);
24142416
2415 try man.addOptionalFile(self.linker_script);2417 try man.addOptionalFile(self.linker_script);
2416 try man.addOptionalFile(self.version_script);2418 try man.addOptionalFile(self.version_script);
2419 man.hash.add(self.allow_undefined_version);
2417 for (comp.objects) |obj| {2420 for (comp.objects) |obj| {
2418 _ = try man.addFile(obj.path, null);2421 _ = try man.addFile(obj.path, null);
2419 man.hash.add(obj.must_link);2422 man.hash.add(obj.must_link);
...@@ -2789,6 +2792,11 @@ fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) !voi...@@ -2789,6 +2792,11 @@ fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) !voi
2789 try argv.append("-version-script");2792 try argv.append("-version-script");
2790 try argv.append(version_script);2793 try argv.append(version_script);
2791 }2794 }
2795 if (self.allow_undefined_version) {
2796 try argv.append("--undefined-version");
2797 } else {
2798 try argv.append("--no-undefined-version");
2799 }
2792 }2800 }
27932801
2794 // Positional arguments to the linker such as object files.2802 // Positional arguments to the linker such as object files.
src/link/MachO/zld.zig+1-1
...@@ -55,7 +55,7 @@ pub fn linkWithZld(...@@ -55,7 +55,7 @@ pub fn linkWithZld(
55 // We are about to obtain this lock, so here we give other processes a chance first.55 // We are about to obtain this lock, so here we give other processes a chance first.
56 macho_file.base.releaseLock();56 macho_file.base.releaseLock();
5757
58 comptime assert(Compilation.link_hash_implementation_version == 10);58 comptime assert(Compilation.link_hash_implementation_version == 11);
5959
60 for (objects) |obj| {60 for (objects) |obj| {
61 _ = try man.addFile(obj.path, null);61 _ = try man.addFile(obj.path, null);
src/link/Wasm.zig+2-2
...@@ -3547,7 +3547,7 @@ fn linkWithZld(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) lin...@@ -3547,7 +3547,7 @@ fn linkWithZld(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) lin
3547 // We are about to obtain this lock, so here we give other processes a chance first.3547 // We are about to obtain this lock, so here we give other processes a chance first.
3548 wasm.base.releaseLock();3548 wasm.base.releaseLock();
35493549
3550 comptime assert(Compilation.link_hash_implementation_version == 10);3550 comptime assert(Compilation.link_hash_implementation_version == 11);
35513551
3552 for (objects) |obj| {3552 for (objects) |obj| {
3553 _ = try man.addFile(obj.path, null);3553 _ = try man.addFile(obj.path, null);
...@@ -4633,7 +4633,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) !vo...@@ -4633,7 +4633,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) !vo
4633 // We are about to obtain this lock, so here we give other processes a chance first.4633 // We are about to obtain this lock, so here we give other processes a chance first.
4634 wasm.base.releaseLock();4634 wasm.base.releaseLock();
46354635
4636 comptime assert(Compilation.link_hash_implementation_version == 10);4636 comptime assert(Compilation.link_hash_implementation_version == 11);
46374637
4638 for (comp.objects) |obj| {4638 for (comp.objects) |obj| {
4639 _ = try man.addFile(obj.path, null);4639 _ = try man.addFile(obj.path, null);
src/main.zig+12
...@@ -500,6 +500,8 @@ const usage_build_generic =...@@ -500,6 +500,8 @@ const usage_build_generic =
500 \\Global Link Options:500 \\Global Link Options:
501 \\ -T[script], --script [script] Use a custom linker script501 \\ -T[script], --script [script] Use a custom linker script
502 \\ --version-script [path] Provide a version .map file502 \\ --version-script [path] Provide a version .map file
503 \\ --undefined-version Allow version scripts to refer to undefined symbols
504 \\ --no-undefined-version (default) Disallow version scripts from referring to undefined symbols
503 \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)505 \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)
504 \\ --sysroot [path] Set the system root directory (usually /)506 \\ --sysroot [path] Set the system root directory (usually /)
505 \\ --version [ver] Dynamic library semver507 \\ --version [ver] Dynamic library semver
...@@ -826,6 +828,7 @@ fn buildOutputType(...@@ -826,6 +828,7 @@ fn buildOutputType(
826 var want_compiler_rt: ?bool = null;828 var want_compiler_rt: ?bool = null;
827 var linker_script: ?[]const u8 = null;829 var linker_script: ?[]const u8 = null;
828 var version_script: ?[]const u8 = null;830 var version_script: ?[]const u8 = null;
831 var linker_allow_undefined_version: bool = false;
829 var disable_c_depfile = false;832 var disable_c_depfile = false;
830 var linker_sort_section: ?link.File.Elf.SortSection = null;833 var linker_sort_section: ?link.File.Elf.SortSection = null;
831 var linker_gc_sections: ?bool = null;834 var linker_gc_sections: ?bool = null;
...@@ -1200,6 +1203,10 @@ fn buildOutputType(...@@ -1200,6 +1203,10 @@ fn buildOutputType(
1200 linker_script = args_iter.nextOrFatal();1203 linker_script = args_iter.nextOrFatal();
1201 } else if (mem.eql(u8, arg, "-version-script") or mem.eql(u8, arg, "--version-script")) {1204 } else if (mem.eql(u8, arg, "-version-script") or mem.eql(u8, arg, "--version-script")) {
1202 version_script = args_iter.nextOrFatal();1205 version_script = args_iter.nextOrFatal();
1206 } else if (mem.eql(u8, arg, "--undefined-version")) {
1207 linker_allow_undefined_version = true;
1208 } else if (mem.eql(u8, arg, "--no-undefined-version")) {
1209 linker_allow_undefined_version = false;
1203 } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) {1210 } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) {
1204 // We don't know whether this library is part of libc1211 // We don't know whether this library is part of libc
1205 // or libc++ until we resolve the target, so we append1212 // or libc++ until we resolve the target, so we append
...@@ -2153,6 +2160,10 @@ fn buildOutputType(...@@ -2153,6 +2160,10 @@ fn buildOutputType(
2153 create_module.opts.rdynamic = true;2160 create_module.opts.rdynamic = true;
2154 } else if (mem.eql(u8, arg, "-version-script") or mem.eql(u8, arg, "--version-script")) {2161 } else if (mem.eql(u8, arg, "-version-script") or mem.eql(u8, arg, "--version-script")) {
2155 version_script = linker_args_it.nextOrFatal();2162 version_script = linker_args_it.nextOrFatal();
2163 } else if (mem.eql(u8, arg, "--undefined-version")) {
2164 linker_allow_undefined_version = true;
2165 } else if (mem.eql(u8, arg, "--no-undefined-version")) {
2166 linker_allow_undefined_version = false;
2156 } else if (mem.eql(u8, arg, "-O")) {2167 } else if (mem.eql(u8, arg, "-O")) {
2157 linker_optimization = linker_args_it.nextOrFatal();2168 linker_optimization = linker_args_it.nextOrFatal();
2158 } else if (mem.startsWith(u8, arg, "-O")) {2169 } else if (mem.startsWith(u8, arg, "-O")) {
...@@ -3166,6 +3177,7 @@ fn buildOutputType(...@@ -3166,6 +3177,7 @@ fn buildOutputType(
3166 .hash_style = hash_style,3177 .hash_style = hash_style,
3167 .linker_script = linker_script,3178 .linker_script = linker_script,
3168 .version_script = version_script,3179 .version_script = version_script,
3180 .linker_allow_undefined_version = linker_allow_undefined_version,
3169 .disable_c_depfile = disable_c_depfile,3181 .disable_c_depfile = disable_c_depfile,
3170 .soname = resolved_soname,3182 .soname = resolved_soname,
3171 .linker_sort_section = linker_sort_section,3183 .linker_sort_section = linker_sort_section,