authorgravatar for xavierb@gmail.comXavier Bouchoux <xavierb@gmail.com> 2024-02-28 08:15:40+01:00
committergravatar for xavierb@gmail.comXavier Bouchoux <xavierb@gmail.com> 2024-08-08 07:15:00+02:00
log7e966de45e06c42b40f5fd4b862c3d320a21a486
tree4d006015907cfae9a08cd3d0d7dce1a9a79b5117
parent7a7421c74970a0d52286fa33086e80af29fc8d0b

std.debug.Dwarf: fix loading external debuginfo in the ".debuglink" case.

- look up the debuglink file in the directory of the executable file (instead of the cwd) - fix parsing of debuglink section (the 4-byte alignement is within the file, unrelated to the in-memory address)

2 files changed, 42 insertions(+), 22 deletions(-)

lib/std/debug/Dwarf.zig+27-22
......@@ -239,7 +239,7 @@ pub const Die = struct {
239239 return switch (form_value.*) {
240240 .addr => |value| value,
241241 .addrx => |index| di.readDebugAddr(compile_unit, index),
242 else => error.InvalidDebugInfo,
242 else => bad(),
243243 };
244244 }
245245
......@@ -252,7 +252,7 @@ pub const Die = struct {
252252 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
253253 return switch (form_value.*) {
254254 .Const => |value| value.asUnsignedLe(),
255 else => error.InvalidDebugInfo,
255 else => bad(),
256256 };
257257 }
258258
......@@ -260,7 +260,7 @@ pub const Die = struct {
260260 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
261261 return switch (form_value.*) {
262262 .ref => |value| value,
263 else => error.InvalidDebugInfo,
263 else => bad(),
264264 };
265265 }
266266
......@@ -2159,7 +2159,7 @@ pub const ElfModule = struct {
21592159 if (mem.eql(u8, name, ".gnu_debuglink")) {
21602160 const gnu_debuglink = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size);
21612161 const debug_filename = mem.sliceTo(@as([*:0]const u8, @ptrCast(gnu_debuglink.ptr)), 0);
2162 const crc_offset = mem.alignForward(usize, @intFromPtr(&debug_filename[debug_filename.len]) + 1, 4) - @intFromPtr(gnu_debuglink.ptr);
2162 const crc_offset = mem.alignForward(usize, debug_filename.len + 1, 4);
21632163 const crc_bytes = gnu_debuglink[crc_offset..][0..4];
21642164 separate_debug_crc = mem.readInt(u32, crc_bytes, native_endian);
21652165 separate_debug_filename = debug_filename;
......@@ -2253,25 +2253,30 @@ pub const ElfModule = struct {
22532253 if (elf_filename != null and mem.eql(u8, elf_filename.?, separate_filename))
22542254 return error.MissingDebugInfo;
22552255
2256 // <cwd>/<gnu_debuglink>
2257 if (loadPath(
2258 gpa,
2259 .{
2260 .root_dir = std.Build.Cache.Directory.cwd(),
2261 .sub_path = separate_filename,
2262 },
2263 null,
2264 separate_debug_crc,
2265 &sections,
2266 mapped_mem,
2267 )) |debug_info| {
2268 return debug_info;
2269 } else |_| {}
2270
2271 // <cwd>/.debug/<gnu_debuglink>
2272 {
2256 exe_dir: {
2257 var exe_dir_buf: [std.fs.max_path_bytes]u8 = undefined;
2258 const exe_dir_path = std.fs.selfExeDirPath(&exe_dir_buf) catch break :exe_dir;
2259 var exe_dir = std.fs.openDirAbsolute(exe_dir_path, .{}) catch break :exe_dir;
2260 defer exe_dir.close();
2261
2262 // <exe_dir>/<gnu_debuglink>
2263 if (loadPath(
2264 gpa,
2265 .{
2266 .root_dir = .{ .path = null, .handle = exe_dir },
2267 .sub_path = separate_filename,
2268 },
2269 null,
2270 separate_debug_crc,
2271 &sections,
2272 mapped_mem,
2273 )) |debug_info| {
2274 return debug_info;
2275 } else |_| {}
2276
2277 // <exe_dir>/.debug/<gnu_debuglink>
22732278 const path: Path = .{
2274 .root_dir = std.Build.Cache.Directory.cwd(),
2279 .root_dir = .{ .path = null, .handle = exe_dir },
22752280 .sub_path = try std.fs.path.join(gpa, &.{ ".debug", separate_filename }),
22762281 };
22772282 defer gpa.free(path.sub_path);
test/standalone/stack_iterator/build.zig+15
......@@ -93,6 +93,21 @@ pub fn build(b: *std.Build) void {
9393
9494 const run_cmd = b.addRunArtifact(exe);
9595 test_step.dependOn(&run_cmd.step);
96
97 // Separate debug info ELF file
98 if (target.result.ofmt == .elf) {
99 const filename = b.fmt("{s}_stripped", .{exe.out_filename});
100 const stripped_exe = b.addObjCopy(exe.getEmittedBin(), .{
101 .basename = filename, // set the name for the debuglink
102 .compress_debug = true,
103 .strip = .debug,
104 .extract_to_separate_file = true,
105 });
106
107 const run_stripped = std.Build.Step.Run.create(b, b.fmt("run {s}", .{filename}));
108 run_stripped.addFileArg(stripped_exe.getOutput());
109 test_step.dependOn(&run_stripped.step);
110 }
96111 }
97112
98113 // Unwinding without libc/posix