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)
This commit is contained in:
Xavier Bouchoux 2024-02-28 08:15:40 +01:00
parent 7a7421c749
commit 7e966de45e
2 changed files with 41 additions and 21 deletions

View File

@ -239,7 +239,7 @@ pub const Die = struct {
return switch (form_value.*) {
.addr => |value| value,
.addrx => |index| di.readDebugAddr(compile_unit, index),
else => error.InvalidDebugInfo,
else => bad(),
};
}
@ -252,7 +252,7 @@ pub const Die = struct {
const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
return switch (form_value.*) {
.Const => |value| value.asUnsignedLe(),
else => error.InvalidDebugInfo,
else => bad(),
};
}
@ -260,7 +260,7 @@ pub const Die = struct {
const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
return switch (form_value.*) {
.ref => |value| value,
else => error.InvalidDebugInfo,
else => bad(),
};
}
@ -2159,7 +2159,7 @@ pub const ElfModule = struct {
if (mem.eql(u8, name, ".gnu_debuglink")) {
const gnu_debuglink = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size);
const debug_filename = mem.sliceTo(@as([*:0]const u8, @ptrCast(gnu_debuglink.ptr)), 0);
const crc_offset = mem.alignForward(usize, @intFromPtr(&debug_filename[debug_filename.len]) + 1, 4) - @intFromPtr(gnu_debuglink.ptr);
const crc_offset = mem.alignForward(usize, debug_filename.len + 1, 4);
const crc_bytes = gnu_debuglink[crc_offset..][0..4];
separate_debug_crc = mem.readInt(u32, crc_bytes, native_endian);
separate_debug_filename = debug_filename;
@ -2253,25 +2253,30 @@ pub const ElfModule = struct {
if (elf_filename != null and mem.eql(u8, elf_filename.?, separate_filename))
return error.MissingDebugInfo;
// <cwd>/<gnu_debuglink>
if (loadPath(
gpa,
.{
.root_dir = std.Build.Cache.Directory.cwd(),
.sub_path = separate_filename,
},
null,
separate_debug_crc,
&sections,
mapped_mem,
)) |debug_info| {
return debug_info;
} else |_| {}
exe_dir: {
var exe_dir_buf: [std.fs.max_path_bytes]u8 = undefined;
const exe_dir_path = std.fs.selfExeDirPath(&exe_dir_buf) catch break :exe_dir;
var exe_dir = std.fs.openDirAbsolute(exe_dir_path, .{}) catch break :exe_dir;
defer exe_dir.close();
// <cwd>/.debug/<gnu_debuglink>
{
// <exe_dir>/<gnu_debuglink>
if (loadPath(
gpa,
.{
.root_dir = .{ .path = null, .handle = exe_dir },
.sub_path = separate_filename,
},
null,
separate_debug_crc,
&sections,
mapped_mem,
)) |debug_info| {
return debug_info;
} else |_| {}
// <exe_dir>/.debug/<gnu_debuglink>
const path: Path = .{
.root_dir = std.Build.Cache.Directory.cwd(),
.root_dir = .{ .path = null, .handle = exe_dir },
.sub_path = try std.fs.path.join(gpa, &.{ ".debug", separate_filename }),
};
defer gpa.free(path.sub_path);

View File

@ -93,6 +93,21 @@ pub fn build(b: *std.Build) void {
const run_cmd = b.addRunArtifact(exe);
test_step.dependOn(&run_cmd.step);
// Separate debug info ELF file
if (target.result.ofmt == .elf) {
const filename = b.fmt("{s}_stripped", .{exe.out_filename});
const stripped_exe = b.addObjCopy(exe.getEmittedBin(), .{
.basename = filename, // set the name for the debuglink
.compress_debug = true,
.strip = .debug,
.extract_to_separate_file = true,
});
const run_stripped = std.Build.Step.Run.create(b, b.fmt("run {s}", .{filename}));
run_stripped.addFileArg(stripped_exe.getOutput());
test_step.dependOn(&run_stripped.step);
}
}
// Unwinding without libc/posix