From 7e966de45e06c42b40f5fd4b862c3d320a21a486 Mon Sep 17 00:00:00 2001 From: Xavier Bouchoux Date: Wed, 28 Feb 2024 08:15:40 +0100 Subject: [PATCH] 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) --- lib/std/debug/Dwarf.zig | 47 +++++++++++++----------- test/standalone/stack_iterator/build.zig | 15 ++++++++ 2 files changed, 41 insertions(+), 21 deletions(-) diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig index e3d4ab1a8f..eb14b3168d 100644 --- a/lib/std/debug/Dwarf.zig +++ b/lib/std/debug/Dwarf.zig @@ -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; - // / - if (loadPath( - gpa, - .{ - .root_dir = std.Build.Cache.Directory.cwd(), - .sub_path = separate_filename, - }, - null, - separate_debug_crc, - §ions, - 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(); - // /.debug/ - { + // / + if (loadPath( + gpa, + .{ + .root_dir = .{ .path = null, .handle = exe_dir }, + .sub_path = separate_filename, + }, + null, + separate_debug_crc, + §ions, + mapped_mem, + )) |debug_info| { + return debug_info; + } else |_| {} + + // /.debug/ 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); diff --git a/test/standalone/stack_iterator/build.zig b/test/standalone/stack_iterator/build.zig index a989828a8c..d69d590912 100644 --- a/test/standalone/stack_iterator/build.zig +++ b/test/standalone/stack_iterator/build.zig @@ -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