diff --git a/src/Compilation.zig b/src/Compilation.zig index b6c82c2dbb..c7bb260aa7 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -468,6 +468,11 @@ pub const InitOptions = struct { disable_c_depfile: bool = false, linker_z_nodelete: bool = false, linker_z_defs: bool = false, + linker_tsaware: bool = false, + linker_nxcompat: bool = false, + linker_dynamicbase: bool = false, + major_subsystem_version: ?u32 = null, + minor_subsystem_version: ?u32 = null, clang_passthrough_mode: bool = false, verbose_cc: bool = false, verbose_link: bool = false, @@ -1035,6 +1040,11 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false, .z_nodelete = options.linker_z_nodelete, .z_defs = options.linker_z_defs, + .tsaware = options.linker_tsaware, + .nxcompat = options.linker_nxcompat, + .dynamicbase = options.linker_dynamicbase, + .major_subsystem_version = options.major_subsystem_version, + .minor_subsystem_version = options.minor_subsystem_version, .stack_size_override = options.stack_size_override, .image_base_override = options.image_base_override, .include_compiler_rt = include_compiler_rt, diff --git a/src/link.zig b/src/link.zig index 16222b5a79..82ff0bb3f8 100644 --- a/src/link.zig +++ b/src/link.zig @@ -69,6 +69,9 @@ pub const Options = struct { rdynamic: bool, z_nodelete: bool, z_defs: bool, + tsaware: bool, + nxcompat: bool, + dynamicbase: bool, bind_global_refs_locally: bool, is_native_os: bool, is_native_abi: bool, @@ -88,6 +91,8 @@ pub const Options = struct { each_lib_rpath: bool, disable_lld_caching: bool, is_test: bool, + major_subsystem_version: ?u32, + minor_subsystem_version: ?u32, gc_sections: ?bool = null, allow_shlib_undefined: ?bool, subsystem: ?std.Target.SubSystem, diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 1acf09a1dc..0dfa3d54a1 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -877,6 +877,11 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { man.hash.addStringSet(self.base.options.system_libs); man.hash.addOptional(self.base.options.subsystem); man.hash.add(self.base.options.is_test); + man.hash.add(self.base.options.tsaware); + man.hash.add(self.base.options.nxcompat); + man.hash.add(self.base.options.dynamicbase); + man.hash.addOptional(self.base.options.major_subsystem_version); + man.hash.addOptional(self.base.options.minor_subsystem_version); // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. _ = try man.hit(); @@ -976,6 +981,26 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { try argv.append("-DLL"); } + if (self.base.options.tsaware) { + try argv.append("-tsaware"); + } + if (self.base.options.nxcompat) { + try argv.append("-nxcompat"); + } + if (self.base.options.dynamicbase) { + try argv.append("-dynamicbase"); + } + const subsystem_suffix = ss: { + if (self.base.options.major_subsystem_version) |major| { + if (self.base.options.minor_subsystem_version) |minor| { + break :ss try allocPrint(arena, ",{d}.{d}", .{ major, minor }); + } else { + break :ss try allocPrint(arena, ",{d}", .{major}); + } + } + break :ss ""; + }; + try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path})); if (self.base.options.link_libc) { @@ -1029,35 +1054,51 @@ fn linkWithLLD(self: *Coff, comp: *Compilation) !void { const mode: Mode = mode: { if (resolved_subsystem) |subsystem| switch (subsystem) { .Console => { - try argv.append("-SUBSYSTEM:console"); + try argv.append(try allocPrint(arena, "-SUBSYSTEM:console{s}", .{ + subsystem_suffix, + })); break :mode .win32; }, .EfiApplication => { - try argv.append("-SUBSYSTEM:efi_application"); + try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_application{s}", .{ + subsystem_suffix, + })); break :mode .uefi; }, .EfiBootServiceDriver => { - try argv.append("-SUBSYSTEM:efi_boot_service_driver"); + try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_boot_service_driver{s}", .{ + subsystem_suffix, + })); break :mode .uefi; }, .EfiRom => { - try argv.append("-SUBSYSTEM:efi_rom"); + try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_rom{s}", .{ + subsystem_suffix, + })); break :mode .uefi; }, .EfiRuntimeDriver => { - try argv.append("-SUBSYSTEM:efi_runtime_driver"); + try argv.append(try allocPrint(arena, "-SUBSYSTEM:efi_runtime_driver{s}", .{ + subsystem_suffix, + })); break :mode .uefi; }, .Native => { - try argv.append("-SUBSYSTEM:native"); + try argv.append(try allocPrint(arena, "-SUBSYSTEM:native{s}", .{ + subsystem_suffix, + })); break :mode .win32; }, .Posix => { - try argv.append("-SUBSYSTEM:posix"); + try argv.append(try allocPrint(arena, "-SUBSYSTEM:posix{s}", .{ + subsystem_suffix, + })); break :mode .win32; }, .Windows => { - try argv.append("-SUBSYSTEM:windows"); + try argv.append(try allocPrint(arena, "-SUBSYSTEM:windows{s}", .{ + subsystem_suffix, + })); break :mode .win32; }, } else if (target.os.tag == .uefi) { diff --git a/src/main.zig b/src/main.zig index 32c35739cd..26e222016a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -529,6 +529,9 @@ fn buildOutputType( var linker_bind_global_refs_locally: ?bool = null; var linker_z_nodelete = false; var linker_z_defs = false; + var linker_tsaware = false; + var linker_nxcompat = false; + var linker_dynamicbase = false; var test_evented_io = false; var stack_size_override: ?u64 = null; var image_base_override: ?u64 = null; @@ -549,6 +552,8 @@ fn buildOutputType( var main_pkg_path: ?[]const u8 = null; var clang_preprocessor_mode: Compilation.ClangPreprocessorMode = .no; var subsystem: ?std.Target.SubSystem = null; + var major_subsystem_version: ?u32 = null; + var minor_subsystem_version: ?u32 = null; var system_libs = std.ArrayList([]const u8).init(gpa); defer system_libs.deinit(); @@ -1307,10 +1312,56 @@ fn buildOutputType( image_base_override = std.fmt.parseUnsigned(u64, linker_args.items[i], 0) catch |err| { fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); }; + } else if (mem.eql(u8, arg, "-T")) { + i += 1; + if (i >= linker_args.items.len) { + fatal("expected linker arg after '{s}'", .{arg}); + } + linker_script = linker_args.items[i]; } else if (mem.eql(u8, arg, "--eh-frame-hdr")) { link_eh_frame_hdr = true; } else if (mem.eql(u8, arg, "--no-eh-frame-hdr")) { link_eh_frame_hdr = false; + } else if (mem.eql(u8, arg, "--tsaware")) { + linker_tsaware = true; + } else if (mem.eql(u8, arg, "--nxcompat")) { + linker_nxcompat = true; + } else if (mem.eql(u8, arg, "--dynamicbase")) { + linker_dynamicbase = true; + } else if (mem.eql(u8, arg, "--high-entropy-va")) { + // This option does not do anything. + } else if (mem.eql(u8, arg, "--export-all-symbols")) { + rdynamic = true; + } else if (mem.eql(u8, arg, "--start-group") or + mem.eql(u8, arg, "--end-group")) + { + // We don't need to care about these because these args are + // for resolving circular dependencies but our linker takes + // care of this without explicit args. + } else if (mem.startsWith(u8, arg, "--major-os-version") or + mem.startsWith(u8, arg, "--minor-os-version")) + { + // This option does not do anything. + } else if (mem.startsWith(u8, arg, "--major-subsystem-version=")) { + major_subsystem_version = std.fmt.parseUnsigned( + u32, + arg["--major-subsystem-version=".len..], + 10, + ) catch |err| { + fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); + }; + } else if (mem.startsWith(u8, arg, "--minor-subsystem-version=")) { + minor_subsystem_version = std.fmt.parseUnsigned( + u32, + arg["--minor-subsystem-version=".len..], + 10, + ) catch |err| { + fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); + }; + } else if (mem.startsWith(u8, arg, "--major-os-version=") or + mem.startsWith(u8, arg, "--minor-os-version=")) + { + // These args do nothing. } else { warn("unsupported linker arg: {s}", .{arg}); } @@ -1800,6 +1851,11 @@ fn buildOutputType( .linker_bind_global_refs_locally = linker_bind_global_refs_locally, .linker_z_nodelete = linker_z_nodelete, .linker_z_defs = linker_z_defs, + .linker_tsaware = linker_tsaware, + .linker_nxcompat = linker_nxcompat, + .linker_dynamicbase = linker_dynamicbase, + .major_subsystem_version = major_subsystem_version, + .minor_subsystem_version = minor_subsystem_version, .link_eh_frame_hdr = link_eh_frame_hdr, .link_emit_relocs = link_emit_relocs, .stack_size_override = stack_size_override,