authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-11-10 16:52:43+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-11-10 16:52:43+01:00
log04b8ce5fd32776cb5c8d34c424efd40cee86412a
treef74dd9c60e879caf8552459acd2b66b700171bd2
parent4b3637820d0f43bc5b0e2c938b51ea1545b1c84e
parent1357790ec969bb6ee19ade6e8a348bd9d7cbbc4d

Merge branch 'jcmoyer-lld-explicit-pdb'


4 files changed, 41 insertions(+), 1 deletions(-)

src/Compilation.zig+25
...@@ -1016,6 +1016,9 @@ pub const InitOptions = struct {...@@ -1016,6 +1016,9 @@ pub const InitOptions = struct {
1016 /// (Darwin) remove dylibs that are unreachable by the entry point or exported symbols1016 /// (Darwin) remove dylibs that are unreachable by the entry point or exported symbols
1017 dead_strip_dylibs: bool = false,1017 dead_strip_dylibs: bool = false,
1018 libcxx_abi_version: libcxx.AbiVersion = libcxx.AbiVersion.default,1018 libcxx_abi_version: libcxx.AbiVersion = libcxx.AbiVersion.default,
1019 /// (Windows) PDB source path prefix to instruct the linker how to resolve relative
1020 /// paths when consolidating CodeView streams into a single PDB file.
1021 pdb_source_path: ?[]const u8 = null,
1019};1022};
10201023
1021fn addPackageTableToCacheHash(1024fn addPackageTableToCacheHash(
...@@ -1719,6 +1722,27 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1719,6 +1722,27 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1719 };1722 };
1720 };1723 };
17211724
1725 const pdb_source_path: ?[]const u8 = options.pdb_source_path orelse blk: {
1726 if (builtin.target.os.tag == .windows) {
1727 // PDB requires all file paths to be fully resolved, and it is really the
1728 // linker's responsibility to canonicalize any path extracted from the CodeView
1729 // in the object file. However, LLD-link has some very questionable defaults, and
1730 // in particular, it purposely bakes in path separator of the host system it was
1731 // built on rather than the targets, or just throw an error. Thankfully, they have
1732 // left a backdoor we can use via -PDBSOURCEPATH.
1733 const mod = module orelse break :blk null;
1734 var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
1735 const resolved_path = if (mod.main_pkg.root_src_directory.path) |base_path| p: {
1736 if (std.fs.path.isAbsolute(base_path)) break :blk base_path;
1737 const resolved_path = std.os.realpath(base_path, &buffer) catch break :blk null;
1738 const pos = std.mem.lastIndexOfLinear(u8, resolved_path, base_path) orelse resolved_path.len;
1739 break :p resolved_path[0..pos];
1740 } else std.os.realpath(".", &buffer) catch break :blk null;
1741 break :blk try arena.dupe(u8, resolved_path);
1742 }
1743 break :blk null;
1744 };
1745
1722 const implib_emit: ?link.Emit = blk: {1746 const implib_emit: ?link.Emit = blk: {
1723 const emit_implib = options.emit_implib orelse break :blk null;1747 const emit_implib = options.emit_implib orelse break :blk null;
17241748
...@@ -1865,6 +1889,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1865,6 +1889,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1865 .headerpad_max_install_names = options.headerpad_max_install_names,1889 .headerpad_max_install_names = options.headerpad_max_install_names,
1866 .dead_strip_dylibs = options.dead_strip_dylibs,1890 .dead_strip_dylibs = options.dead_strip_dylibs,
1867 .force_undefined_symbols = .{},1891 .force_undefined_symbols = .{},
1892 .pdb_source_path = pdb_source_path,
1868 });1893 });
1869 errdefer bin_file.destroy();1894 errdefer bin_file.destroy();
1870 comp.* = .{1895 comp.* = .{
src/link.zig+4
...@@ -218,6 +218,10 @@ pub const Options = struct {...@@ -218,6 +218,10 @@ pub const Options = struct {
218 /// (Darwin) remove dylibs that are unreachable by the entry point or exported symbols218 /// (Darwin) remove dylibs that are unreachable by the entry point or exported symbols
219 dead_strip_dylibs: bool = false,219 dead_strip_dylibs: bool = false,
220220
221 /// (Windows) PDB source path prefix to instruct the linker how to resolve relative
222 /// paths when consolidating CodeView streams into a single PDB file.
223 pdb_source_path: ?[]const u8 = null,
224
221 pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {225 pub fn effectiveOutputMode(options: Options) std.builtin.OutputMode {
222 return if (options.use_lld) .Obj else options.output_mode;226 return if (options.use_lld) .Obj else options.output_mode;
223 }227 }
src/link/Coff/lld.zig+11
...@@ -181,6 +181,17 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -181,6 +181,17 @@ pub fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
181 try argv.append("-NOLOGO");181 try argv.append("-NOLOGO");
182 if (!self.base.options.strip) {182 if (!self.base.options.strip) {
183 try argv.append("-DEBUG");183 try argv.append("-DEBUG");
184
185 const out_ext = std.fs.path.extension(full_out_path);
186 const out_pdb = try allocPrint(arena, "{s}.pdb", .{
187 full_out_path[0 .. full_out_path.len - out_ext.len],
188 });
189 try argv.append(try allocPrint(arena, "-PDB:{s}", .{out_pdb}));
190 try argv.append(try allocPrint(arena, "-PDBALTPATH:{s}", .{out_pdb}));
191
192 if (self.base.options.pdb_source_path) |path| {
193 try argv.append(try std.fmt.allocPrint(arena, "-PDBSOURCEPATH:{s}", .{path}));
194 }
184 }195 }
185 if (self.base.options.lto) {196 if (self.base.options.lto) {
186 switch (self.base.options.optimize_mode) {197 switch (self.base.options.optimize_mode) {
test/tests.zig+1-1
...@@ -960,7 +960,7 @@ pub const StackTracesContext = struct {...@@ -960,7 +960,7 @@ pub const StackTracesContext = struct {
960 pos = marks[i] + delim.len;960 pos = marks[i] + delim.len;
961 }961 }
962 // locate source basename962 // locate source basename
963 pos = mem.lastIndexOfAny(u8, line[0..marks[0]], "\\/") orelse {963 pos = mem.lastIndexOfScalar(u8, line[0..marks[0]], fs.path.sep) orelse {
964 // unexpected pattern: emit raw line and cont964 // unexpected pattern: emit raw line and cont
965 try buf.appendSlice(line);965 try buf.appendSlice(line);
966 try buf.appendSlice("\n");966 try buf.appendSlice("\n");