Commit 1fdea551b2

Zach Cheung <zach.cheung@uber.com>
2023-03-24 01:16:39
add linker -wrap flag
1 parent 0866396
Changed files (4)
src/link/Elf.zig
@@ -1386,6 +1386,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
             man.hash.add(stack_size);
             man.hash.add(self.base.options.build_id);
         }
+        man.hash.addListOfBytes(self.base.options.wrap_list);
         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);
@@ -1665,6 +1666,17 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
                 try argv.append(rpath);
             }
         }
+
+        // wrap
+        var wrap_table = std.StringHashMap(void).init(self.base.allocator);
+        defer wrap_table.deinit();
+        for (self.base.options.wrap_list) |wrap| {
+            if ((try wrap_table.fetchPut(wrap, {})) == null) {
+                try argv.append("-wrap");
+                try argv.append(wrap);
+            }
+        }
+
         if (self.base.options.each_lib_rpath) {
             var test_path = std.ArrayList(u8).init(self.base.allocator);
             defer test_path.deinit();
src/Compilation.zig
@@ -494,6 +494,7 @@ pub const InitOptions = struct {
     clang_argv: []const []const u8 = &[0][]const u8{},
     lib_dirs: []const []const u8 = &[0][]const u8{},
     rpath_list: []const []const u8 = &[0][]const u8{},
+    wrap_list: []const []const u8 = &[0][]const u8{},
     c_source_files: []const CSourceFile = &[0]CSourceFile{},
     link_objects: []LinkObject = &[0]LinkObject{},
     framework_dirs: []const []const u8 = &[0][]const u8{},
@@ -1438,6 +1439,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
             .wasi_emulated_libs = options.wasi_emulated_libs,
             .lib_dirs = options.lib_dirs,
             .rpath_list = options.rpath_list,
+            .wrap_list = options.wrap_list,
             .strip = strip,
             .is_native_os = options.is_native_os,
             .is_native_abi = options.is_native_abi,
@@ -2259,6 +2261,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
     man.hash.add(comp.bin_file.options.rdynamic);
     man.hash.addListOfBytes(comp.bin_file.options.lib_dirs);
     man.hash.addListOfBytes(comp.bin_file.options.rpath_list);
+    man.hash.addListOfBytes(comp.bin_file.options.wrap_list);
     man.hash.add(comp.bin_file.options.each_lib_rpath);
     man.hash.add(comp.bin_file.options.build_id);
     man.hash.add(comp.bin_file.options.skip_linker_dependencies);
src/link.zig
@@ -183,6 +183,7 @@ pub const Options = struct {
     wasi_emulated_libs: []const wasi_libc.CRTFile,
     lib_dirs: []const []const u8,
     rpath_list: []const []const u8,
+    wrap_list: []const []const u8,
 
     /// List of symbols forced as undefined in the symbol table
     /// thus forcing their resolution by the linker.
src/main.zig
@@ -487,6 +487,7 @@ const usage_build_generic =
     \\  -fno-compiler-rt               Prevent including compiler-rt symbols in output
     \\  -rdynamic                      Add all symbols to the dynamic symbol table
     \\  -rpath [path]                  Add directory to the runtime library search path
+    \\  -wrap [symbol]                 Override the symbol with the wrapped symbol definition
     \\  -feach-lib-rpath               Ensure adding rpath for each used dynamic library
     \\  -fno-each-lib-rpath            Prevent adding rpath for each used dynamic library
     \\  -fallow-shlib-undefined        Allows undefined symbols in shared libraries
@@ -874,6 +875,9 @@ fn buildOutputType(
     var rpath_list = std.ArrayList([]const u8).init(gpa);
     defer rpath_list.deinit();
 
+    var wrap_list = std.ArrayList([]const u8).init(gpa);
+    defer wrap_list.deinit();
+
     var c_source_files = std.ArrayList(Compilation.CSourceFile).init(gpa);
     defer c_source_files.deinit();
 
@@ -1475,6 +1479,9 @@ fn buildOutputType(
                         try system_libs.put(arg["-needed-l".len..], .{ .needed = true });
                     } else if (mem.startsWith(u8, arg, "-weak-l")) {
                         try system_libs.put(arg["-weak-l".len..], .{ .weak = true });
+                    } else if (mem.eql(u8, arg, "-wrap")){
+                        try wrap_list.append(arg);
+                        try wrap_list.append(args_iter.nextOrFatal());
                     } else if (mem.startsWith(u8, arg, "-D")) {
                         try clang_argv.append(arg);
                     } else if (mem.startsWith(u8, arg, "-I")) {
@@ -2155,6 +2162,12 @@ fn buildOutputType(
                             next_arg,
                         });
                     };
+                } else if (mem.eql(u8, arg, "-wrap")) {
+                    i += 1;
+                    if (i >= linker_args.items.len) {
+                        fatal("expected linker arg after '{s}'", .{arg});
+                    }
+                    try wrap_list.append(linker_args.items[i]);
                 } else if (mem.startsWith(u8, arg, "/subsystem:")) {
                     var split_it = mem.splitBackwards(u8, arg, ":");
                     subsystem = try parseSubSystem(split_it.first());
@@ -3039,6 +3052,7 @@ fn buildOutputType(
         .clang_argv = clang_argv.items,
         .lib_dirs = lib_dirs.items,
         .rpath_list = rpath_list.items,
+        .wrap_list = wrap_list.items,
         .c_source_files = c_source_files.items,
         .link_objects = link_objects.items,
         .framework_dirs = framework_dirs.items,