diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-08-25 12:38:56 +0200 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-08-25 16:23:01 -0400 |
| commit | d5233ee85ce13cba3dd03e4c0c938cee193b9b19 (patch) | |
| tree | 3824be936b8854e15916159dd8eb5636fd84168c /src | |
| parent | ba346ecfe9b8ee246e084183f34fa9ed941f9fa3 (diff) | |
| download | zig-d5233ee85ce13cba3dd03e4c0c938cee193b9b19.tar.gz zig-d5233ee85ce13cba3dd03e4c0c938cee193b9b19.zip | |
add ability to pass force undefined symbols to the linker
This commit enables `-u <symbol>` for ELF and `-include:<symbol>` for
COFF linkers for use internally. This means we do not expose these
flags to the users just yet, however, we make use of them internally
whenever required. One such use case is forcing inclusion of
`_tls_index` when linking for Windows with mingw and LTO and dead
code stripping enabled. This ensures we add `_tls_index` to the symbol
resolver as an undefined symbol and force the linker to include an atom
that provides it marking it a dead-code-stripping root - meaning it will
not be garbage collected by the linker no matter what.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Compilation.zig | 8 | ||||
| -rw-r--r-- | src/link.zig | 6 | ||||
| -rw-r--r-- | src/link/Coff.zig | 4 | ||||
| -rw-r--r-- | src/link/Elf.zig | 5 | ||||
| -rw-r--r-- | src/mingw.zig | 6 |
5 files changed, 20 insertions, 9 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig index 03d7962ccc..353a2f1ca3 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1165,9 +1165,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { break :blk false; } else if (options.c_source_files.len == 0) { break :blk false; - } else if (options.target.os.tag == .windows and link_libcpp) { - // https://github.com/ziglang/zig/issues/8531 - break :blk false; } else if (options.target.cpu.arch.isRISCV()) { // Clang and LLVM currently don't support RISC-V target-abi for LTO. // Compiling with LTO may fail or produce undesired results. @@ -1793,6 +1790,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .headerpad_size = options.headerpad_size, .headerpad_max_install_names = options.headerpad_max_install_names, .dead_strip_dylibs = options.dead_strip_dylibs, + .force_undefined_symbols = .{}, }); errdefer bin_file.destroy(); comp.* = .{ @@ -1943,6 +1941,10 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { for (mingw.always_link_libs) |name| { try comp.bin_file.options.system_libs.put(comp.gpa, name, .{}); } + + // LLD might drop some symbols as unused during LTO and GCing, therefore, + // we force mark them for resolution here. + try comp.bin_file.options.force_undefined_symbols.put(comp.gpa, "_tls_index", {}); } // Generate Windows import libs. if (target.os.tag == .windows) { diff --git a/src/link.zig b/src/link.zig index a85969d61e..b46ea51013 100644 --- a/src/link.zig +++ b/src/link.zig @@ -175,6 +175,12 @@ pub const Options = struct { lib_dirs: []const []const u8, rpath_list: []const []const u8, + /// List of symbols forced as undefined in the symbol table + /// thus forcing their resolution by the linker. + /// Corresponds to `-u <symbol>` for ELF and `/include:<symbol>` for COFF/PE. + /// TODO add handling for MachO. + force_undefined_symbols: std.StringArrayHashMapUnmanaged(void), + version: ?std.builtin.Version, compatibility_version: ?std.builtin.Version, libc_installation: ?*const LibCInstallation, diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 6536fbd1ac..c30544d3b7 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1133,6 +1133,10 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) ! } } + for (self.base.options.force_undefined_symbols.keys()) |symbol| { + try argv.append(try allocPrint(arena, "-INCLUDE:{s}", .{symbol})); + } + if (is_dyn_lib) { try argv.append("-DLL"); } diff --git a/src/link/Elf.zig b/src/link/Elf.zig index ade4f62f91..293771dd2a 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1448,6 +1448,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append(entry); } + for (self.base.options.force_undefined_symbols.keys()) |symbol| { + try argv.append("-u"); + try argv.append(symbol); + } + switch (self.base.options.hash_style) { .gnu => try argv.append("--hash-style=gnu"), .sysv => try argv.append("--hash-style=sysv"), diff --git a/src/mingw.zig b/src/mingw.zig index e99a1af8fc..b50cc4b009 100644 --- a/src/mingw.zig +++ b/src/mingw.zig @@ -93,12 +93,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { "-D_WIN32_WINNT=0x0f00", "-D__MSVCRT_VERSION__=0x700", }); - if (std.mem.eql(u8, dep, "tlssup.c") and comp.bin_file.options.lto) { - // LLD will incorrectly drop the `_tls_index` symbol. Here we work - // around it by not using LTO for this one file. - // https://github.com/ziglang/zig/issues/8531 - try args.append("-fno-lto"); - } c_source_files[i] = .{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "crt", dep, |
