authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-07 07:51:39-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-07 07:54:47-07:00
logb086b7da9e9adbb4445363f635d3bb37177b2f18
treee288dc1b7191c94b74a2f300524bfbd1d7459d37
parent1fdea551b22726783356c5bed90bce63706b550f

zig cc: complete the -wrap flag implementation

* use a set instead of a list * use of this flag currently requires LLD * add documentation * make it only a zig cc compatibility flag for now because I personally think this is an anti-feature.

4 files changed, 19 insertions(+), 26 deletions(-)

src/Compilation.zig+5-4
......@@ -494,7 +494,7 @@ pub const InitOptions = struct {
494494 clang_argv: []const []const u8 = &[0][]const u8{},
495495 lib_dirs: []const []const u8 = &[0][]const u8{},
496496 rpath_list: []const []const u8 = &[0][]const u8{},
497 wrap_list: []const []const u8 = &[0][]const u8{},
497 symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{},
498498 c_source_files: []const CSourceFile = &[0]CSourceFile{},
499499 link_objects: []LinkObject = &[0]LinkObject{},
500500 framework_dirs: []const []const u8 = &[0][]const u8{},
......@@ -826,7 +826,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
826826 options.output_mode == .Lib or
827827 options.linker_script != null or options.version_script != null or
828828 options.emit_implib != null or
829 build_id)
829 build_id or
830 options.symbol_wrap_set.count() > 0)
830831 {
831832 break :blk true;
832833 }
......@@ -1439,7 +1440,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
14391440 .wasi_emulated_libs = options.wasi_emulated_libs,
14401441 .lib_dirs = options.lib_dirs,
14411442 .rpath_list = options.rpath_list,
1442 .wrap_list = options.wrap_list,
1443 .symbol_wrap_set = options.symbol_wrap_set,
14431444 .strip = strip,
14441445 .is_native_os = options.is_native_os,
14451446 .is_native_abi = options.is_native_abi,
......@@ -2261,7 +2262,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
22612262 man.hash.add(comp.bin_file.options.rdynamic);
22622263 man.hash.addListOfBytes(comp.bin_file.options.lib_dirs);
22632264 man.hash.addListOfBytes(comp.bin_file.options.rpath_list);
2264 man.hash.addListOfBytes(comp.bin_file.options.wrap_list);
2265 man.hash.addListOfBytes(comp.bin_file.options.symbol_wrap_set.keys());
22652266 man.hash.add(comp.bin_file.options.each_lib_rpath);
22662267 man.hash.add(comp.bin_file.options.build_id);
22672268 man.hash.add(comp.bin_file.options.skip_linker_dependencies);
src/link.zig+7-1
......@@ -183,12 +183,18 @@ pub const Options = struct {
183183 wasi_emulated_libs: []const wasi_libc.CRTFile,
184184 lib_dirs: []const []const u8,
185185 rpath_list: []const []const u8,
186 wrap_list: []const []const u8,
187186
188187 /// List of symbols forced as undefined in the symbol table
189188 /// thus forcing their resolution by the linker.
190189 /// Corresponds to `-u <symbol>` for ELF/MachO and `/include:<symbol>` for COFF/PE.
191190 force_undefined_symbols: std.StringArrayHashMapUnmanaged(void),
191 /// Use a wrapper function for symbol. Any undefined reference to symbol
192 /// will be resolved to __wrap_symbol. Any undefined reference to
193 /// __real_symbol will be resolved to symbol. This can be used to provide a
194 /// wrapper for a system function. The wrapper function should be called
195 /// __wrap_symbol. If it wishes to call the system function, it should call
196 /// __real_symbol.
197 symbol_wrap_set: std.StringArrayHashMapUnmanaged(void),
192198
193199 version: ?std.builtin.Version,
194200 compatibility_version: ?std.builtin.Version,
src/link/Elf.zig+3-9
......@@ -1386,7 +1386,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
13861386 man.hash.add(stack_size);
13871387 man.hash.add(self.base.options.build_id);
13881388 }
1389 man.hash.addListOfBytes(self.base.options.wrap_list);
1389 man.hash.addListOfBytes(self.base.options.symbol_wrap_set.keys());
13901390 man.hash.add(self.base.options.skip_linker_dependencies);
13911391 man.hash.add(self.base.options.z_nodelete);
13921392 man.hash.add(self.base.options.z_notext);
......@@ -1667,14 +1667,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
16671667 }
16681668 }
16691669
1670 // wrap
1671 var wrap_table = std.StringHashMap(void).init(self.base.allocator);
1672 defer wrap_table.deinit();
1673 for (self.base.options.wrap_list) |wrap| {
1674 if ((try wrap_table.fetchPut(wrap, {})) == null) {
1675 try argv.append("-wrap");
1676 try argv.append(wrap);
1677 }
1670 for (self.base.options.symbol_wrap_set.keys()) |symbol_name| {
1671 try argv.appendSlice(&.{ "-wrap", symbol_name });
16781672 }
16791673
16801674 if (self.base.options.each_lib_rpath) {
src/main.zig+4-12
......@@ -487,7 +487,6 @@ const usage_build_generic =
487487 \\ -fno-compiler-rt Prevent including compiler-rt symbols in output
488488 \\ -rdynamic Add all symbols to the dynamic symbol table
489489 \\ -rpath [path] Add directory to the runtime library search path
490 \\ -wrap [symbol] Override the symbol with the wrapped symbol definition
491490 \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library
492491 \\ -fno-each-lib-rpath Prevent adding rpath for each used dynamic library
493492 \\ -fallow-shlib-undefined Allows undefined symbols in shared libraries
......@@ -875,8 +874,7 @@ fn buildOutputType(
875874 var rpath_list = std.ArrayList([]const u8).init(gpa);
876875 defer rpath_list.deinit();
877876
878 var wrap_list = std.ArrayList([]const u8).init(gpa);
879 defer wrap_list.deinit();
877 var symbol_wrap_set: std.StringArrayHashMapUnmanaged(void) = .{};
880878
881879 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(gpa);
882880 defer c_source_files.deinit();
......@@ -1479,9 +1477,6 @@ fn buildOutputType(
14791477 try system_libs.put(arg["-needed-l".len..], .{ .needed = true });
14801478 } else if (mem.startsWith(u8, arg, "-weak-l")) {
14811479 try system_libs.put(arg["-weak-l".len..], .{ .weak = true });
1482 } else if (mem.eql(u8, arg, "-wrap")){
1483 try wrap_list.append(arg);
1484 try wrap_list.append(args_iter.nextOrFatal());
14851480 } else if (mem.startsWith(u8, arg, "-D")) {
14861481 try clang_argv.append(arg);
14871482 } else if (mem.startsWith(u8, arg, "-I")) {
......@@ -2163,11 +2158,8 @@ fn buildOutputType(
21632158 });
21642159 };
21652160 } else if (mem.eql(u8, arg, "-wrap")) {
2166 i += 1;
2167 if (i >= linker_args.items.len) {
2168 fatal("expected linker arg after '{s}'", .{arg});
2169 }
2170 try wrap_list.append(linker_args.items[i]);
2161 const next_arg = linker_args_it.nextOrFatal();
2162 try symbol_wrap_set.put(arena, next_arg, {});
21712163 } else if (mem.startsWith(u8, arg, "/subsystem:")) {
21722164 var split_it = mem.splitBackwards(u8, arg, ":");
21732165 subsystem = try parseSubSystem(split_it.first());
......@@ -3052,7 +3044,7 @@ fn buildOutputType(
30523044 .clang_argv = clang_argv.items,
30533045 .lib_dirs = lib_dirs.items,
30543046 .rpath_list = rpath_list.items,
3055 .wrap_list = wrap_list.items,
3047 .symbol_wrap_set = symbol_wrap_set,
30563048 .c_source_files = c_source_files.items,
30573049 .link_objects = link_objects.items,
30583050 .framework_dirs = framework_dirs.items,