zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 7e966de45e06c42b40f5fd4b862c3d320a21a486 (tree)
parent 7a7421c74970a0d52286fa33086e80af29fc8d0b
Author: Xavier Bouchoux <xavierb@gmail.com>
Date:   Wed, 28 Feb 2024 08:15:40 +0100

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)

Diffstat:
Mlib/std/debug/Dwarf.zig | 49+++++++++++++++++++++++++++----------------------
Mtest/standalone/stack_iterator/build.zig | 15+++++++++++++++
2 files changed, 42 insertions(+), 22 deletions(-)

diff --git 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; - // <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 |_| {} - - // <cwd>/.debug/<gnu_debuglink> - { + 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(); + + // <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); diff --git 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