Commit 377ecc6afb

Dillen Meijboom <dillen@brainhive.nl>
2024-02-22 23:39:16
feat: add support for --enable-new-dtags and --disable-new-dtags
1 parent aa7d16a
Changed files (7)
lib/std/Build/Step/Compile.zig
@@ -113,6 +113,9 @@ linker_allow_shlib_undefined: ?bool = null,
 /// Allow version scripts to refer to undefined symbols.
 linker_allow_undefined_version: ?bool = null,
 
+// Enable (or disable) the new DT_RUNPATH tag in the dynamic section.
+linker_enable_new_dtags: ?bool = null,
+
 /// Permit read-only relocations in read-only segments. Disallowed by default.
 link_z_notext: bool = false,
 
@@ -1490,6 +1493,10 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
         try zig_args.append(if (x) "--undefined-version" else "--no-undefined-version");
     }
 
+    if (self.linker_enable_new_dtags) |enabled| {
+        try zig_args.append(if (enabled) "--enable-new-dtags" else "--disable-new-dtags");
+    }
+
     if (self.kind == .@"test") {
         if (self.exec_cmd_args) |exec_cmd_args| {
             for (exec_cmd_args) |cmd_arg| {
src/link/Coff/lld.zig
@@ -70,7 +70,7 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, prog_node: *std.Progress.Node)
         man = comp.cache_parent.obtain();
         self.base.releaseLock();
 
-        comptime assert(Compilation.link_hash_implementation_version == 12);
+        comptime assert(Compilation.link_hash_implementation_version == 13);
 
         for (comp.objects) |obj| {
             _ = try man.addFile(obj.path, null);
src/link/Elf.zig
@@ -22,6 +22,7 @@ bind_global_refs_locally: bool,
 linker_script: ?[]const u8,
 version_script: ?[]const u8,
 allow_undefined_version: bool,
+enable_new_dtags: ?bool,
 print_icf_sections: bool,
 print_map: bool,
 entry_name: ?[]const u8,
@@ -330,6 +331,7 @@ pub fn createEmpty(
         .linker_script = options.linker_script,
         .version_script = options.version_script,
         .allow_undefined_version = options.allow_undefined_version,
+        .enable_new_dtags = options.enable_new_dtags,
         .print_icf_sections = options.print_icf_sections,
         .print_map = options.print_map,
     };
@@ -2170,11 +2172,12 @@ fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) !voi
         // We are about to obtain this lock, so here we give other processes a chance first.
         self.base.releaseLock();
 
-        comptime assert(Compilation.link_hash_implementation_version == 12);
+        comptime assert(Compilation.link_hash_implementation_version == 13);
 
         try man.addOptionalFile(self.linker_script);
         try man.addOptionalFile(self.version_script);
         man.hash.add(self.allow_undefined_version);
+        man.hash.addOptional(self.enable_new_dtags);
         for (comp.objects) |obj| {
             _ = try man.addFile(obj.path, null);
             man.hash.add(obj.must_link);
@@ -2529,6 +2532,13 @@ fn linkWithLLD(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node) !voi
             } else {
                 try argv.append("--no-undefined-version");
             }
+            if (self.enable_new_dtags) |enable_new_dtags| {
+                if (enable_new_dtags) {
+                    try argv.append("--enable-new-dtags");
+                } else {
+                    try argv.append("--disable-new-dtags");
+                }
+            }
         }
 
         // Positional arguments to the linker such as object files.
src/link/Wasm.zig
@@ -3375,7 +3375,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, prog_node: *std.Progress.Node) !vo
         // We are about to obtain this lock, so here we give other processes a chance first.
         wasm.base.releaseLock();
 
-        comptime assert(Compilation.link_hash_implementation_version == 12);
+        comptime assert(Compilation.link_hash_implementation_version == 13);
 
         for (comp.objects) |obj| {
             _ = try man.addFile(obj.path, null);
src/Compilation.zig
@@ -1034,6 +1034,7 @@ pub const CreateOptions = struct {
     linker_script: ?[]const u8 = null,
     version_script: ?[]const u8 = null,
     linker_allow_undefined_version: bool = false,
+    linker_enable_new_dtags: ?bool = null,
     soname: ?[]const u8 = null,
     linker_gc_sections: ?bool = null,
     linker_allow_shlib_undefined: ?bool = null,
@@ -1581,6 +1582,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
             .image_base = options.image_base,
             .version_script = options.version_script,
             .allow_undefined_version = options.linker_allow_undefined_version,
+            .enable_new_dtags = options.linker_enable_new_dtags,
             .gc_sections = options.linker_gc_sections,
             .emit_relocs = options.link_emit_relocs,
             .soname = options.soname,
@@ -2460,7 +2462,7 @@ fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemo
 /// to remind the programmer to update multiple related pieces of code that
 /// are in different locations. Bump this number when adding or deleting
 /// anything from the link cache manifest.
-pub const link_hash_implementation_version = 12;
+pub const link_hash_implementation_version = 13;
 
 fn addNonIncrementalStuffToCacheManifest(
     comp: *Compilation,
@@ -2469,7 +2471,7 @@ fn addNonIncrementalStuffToCacheManifest(
 ) !void {
     const gpa = comp.gpa;
 
-    comptime assert(link_hash_implementation_version == 12);
+    comptime assert(link_hash_implementation_version == 13);
 
     if (comp.module) |mod| {
         try addModuleTableToCacheHash(gpa, arena, &man.hash, mod.root_mod, mod.main_mod, .{ .files = man });
@@ -2541,6 +2543,7 @@ fn addNonIncrementalStuffToCacheManifest(
     try man.addOptionalFile(opts.linker_script);
     try man.addOptionalFile(opts.version_script);
     man.hash.add(opts.allow_undefined_version);
+    man.hash.addOptional(opts.enable_new_dtags);
 
     man.hash.addOptional(opts.stack_size);
     man.hash.addOptional(opts.image_base);
src/link.zig
@@ -113,6 +113,7 @@ pub const File = struct {
         gc_sections: ?bool,
         allow_shlib_undefined: ?bool,
         allow_undefined_version: bool,
+        enable_new_dtags: ?bool,
         subsystem: ?std.Target.SubSystem,
         linker_script: ?[]const u8,
         version_script: ?[]const u8,
src/main.zig
@@ -496,6 +496,8 @@ const usage_build_generic =
     \\  --version-script [path]        Provide a version .map file
     \\  --undefined-version            Allow version scripts to refer to undefined symbols
     \\  --no-undefined-version         (default) Disallow version scripts from referring to undefined symbols
+    \\  --enable-new-dtags             Use the new behavior for dynamic tags (RUNPATH)
+    \\  --disable-new-dtags            Use the old behavior for dynamic tags (RPATH)
     \\  --dynamic-linker [path]        Set the dynamic interpreter path (usually ld.so)
     \\  --sysroot [path]               Set the system root directory (usually /)
     \\  --version [ver]                Dynamic library semver
@@ -824,6 +826,7 @@ fn buildOutputType(
     var linker_script: ?[]const u8 = null;
     var version_script: ?[]const u8 = null;
     var linker_allow_undefined_version: bool = false;
+    var linker_enable_new_dtags: ?bool = null;
     var disable_c_depfile = false;
     var linker_sort_section: ?link.File.Elf.SortSection = null;
     var linker_gc_sections: ?bool = null;
@@ -1191,6 +1194,10 @@ fn buildOutputType(
                         linker_allow_undefined_version = true;
                     } else if (mem.eql(u8, arg, "--no-undefined-version")) {
                         linker_allow_undefined_version = false;
+                    } else if (mem.eql(u8, arg, "--enable-new-dtags")) {
+                        linker_enable_new_dtags = true;
+                    } else if (mem.eql(u8, arg, "--disable-new-dtags")) {
+                        linker_enable_new_dtags = false;
                     } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) {
                         // We don't know whether this library is part of libc
                         // or libc++ until we resolve the target, so we append
@@ -2153,6 +2160,10 @@ fn buildOutputType(
                     linker_allow_undefined_version = true;
                 } else if (mem.eql(u8, arg, "--no-undefined-version")) {
                     linker_allow_undefined_version = false;
+                } else if (mem.eql(u8, arg, "--enable-new-dtags")) {
+                    linker_enable_new_dtags = true;
+                } else if (mem.eql(u8, arg, "--disable-new-dtags")) {
+                    linker_enable_new_dtags = false;
                 } else if (mem.eql(u8, arg, "-O")) {
                     linker_optimization = linker_args_it.nextOrFatal();
                 } else if (mem.startsWith(u8, arg, "-O")) {
@@ -3181,6 +3192,7 @@ fn buildOutputType(
         .linker_script = linker_script,
         .version_script = version_script,
         .linker_allow_undefined_version = linker_allow_undefined_version,
+        .linker_enable_new_dtags = linker_enable_new_dtags,
         .disable_c_depfile = disable_c_depfile,
         .soname = resolved_soname,
         .linker_sort_section = linker_sort_section,