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 {...@@ -239,7 +239,7 @@ pub const Die = struct {
239 return switch (form_value.*) {239 return switch (form_value.*) {
240 .addr => |value| value,240 .addr => |value| value,
241 .addrx => |index| di.readDebugAddr(compile_unit, index),241 .addrx => |index| di.readDebugAddr(compile_unit, index),
242 else => error.InvalidDebugInfo,242 else => bad(),
243 };243 };
244 }244 }
245245
...@@ -252,7 +252,7 @@ pub const Die = struct {...@@ -252,7 +252,7 @@ pub const Die = struct {
252 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;252 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
253 return switch (form_value.*) {253 return switch (form_value.*) {
254 .Const => |value| value.asUnsignedLe(),254 .Const => |value| value.asUnsignedLe(),
255 else => error.InvalidDebugInfo,255 else => bad(),
256 };256 };
257 }257 }
258258
...@@ -260,7 +260,7 @@ pub const Die = struct {...@@ -260,7 +260,7 @@ pub const Die = struct {
260 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;260 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
261 return switch (form_value.*) {261 return switch (form_value.*) {
262 .ref => |value| value,262 .ref => |value| value,
263 else => error.InvalidDebugInfo,263 else => bad(),
264 };264 };
265 }265 }
266266
...@@ -2159,7 +2159,7 @@ pub const ElfModule = struct {...@@ -2159,7 +2159,7 @@ pub const ElfModule = struct {
2159 if (mem.eql(u8, name, ".gnu_debuglink")) {2159 if (mem.eql(u8, name, ".gnu_debuglink")) {
2160 const gnu_debuglink = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size);2160 const gnu_debuglink = try chopSlice(mapped_mem, shdr.sh_offset, shdr.sh_size);
2161 const debug_filename = mem.sliceTo(@as([*:0]const u8, @ptrCast(gnu_debuglink.ptr)), 0);2161 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);
2163 const crc_bytes = gnu_debuglink[crc_offset..][0..4];2163 const crc_bytes = gnu_debuglink[crc_offset..][0..4];
2164 separate_debug_crc = mem.readInt(u32, crc_bytes, native_endian);2164 separate_debug_crc = mem.readInt(u32, crc_bytes, native_endian);
2165 separate_debug_filename = debug_filename;2165 separate_debug_filename = debug_filename;
...@@ -2253,25 +2253,30 @@ pub const ElfModule = struct {...@@ -2253,25 +2253,30 @@ pub const ElfModule = struct {
2253 if (elf_filename != null and mem.eql(u8, elf_filename.?, separate_filename))2253 if (elf_filename != null and mem.eql(u8, elf_filename.?, separate_filename))
2254 return error.MissingDebugInfo;2254 return error.MissingDebugInfo;
22552255
2256 // <cwd>/<gnu_debuglink>2256 exe_dir: {
2257 if (loadPath(2257 var exe_dir_buf: [std.fs.max_path_bytes]u8 = undefined;
2258 gpa,2258 const exe_dir_path = std.fs.selfExeDirPath(&exe_dir_buf) catch break :exe_dir;
2259 .{2259 var exe_dir = std.fs.openDirAbsolute(exe_dir_path, .{}) catch break :exe_dir;
2260 .root_dir = std.Build.Cache.Directory.cwd(),2260 defer exe_dir.close();
2261 .sub_path = separate_filename,2261
2262 },2262 // <exe_dir>/<gnu_debuglink>
2263 null,2263 if (loadPath(
2264 separate_debug_crc,2264 gpa,
2265 &sections,2265 .{
2266 mapped_mem,2266 .root_dir = .{ .path = null, .handle = exe_dir },
2267 )) |debug_info| {2267 .sub_path = separate_filename,
2268 return debug_info;2268 },
2269 } else |_| {}2269 null,
22702270 separate_debug_crc,
2271 // <cwd>/.debug/<gnu_debuglink>2271 &sections,
2272 {2272 mapped_mem,
2273 )) |debug_info| {
2274 return debug_info;
2275 } else |_| {}
2276
2277 // <exe_dir>/.debug/<gnu_debuglink>
2273 const path: Path = .{2278 const path: Path = .{
2274 .root_dir = std.Build.Cache.Directory.cwd(),2279 .root_dir = .{ .path = null, .handle = exe_dir },
2275 .sub_path = try std.fs.path.join(gpa, &.{ ".debug", separate_filename }),2280 .sub_path = try std.fs.path.join(gpa, &.{ ".debug", separate_filename }),
2276 };2281 };
2277 defer gpa.free(path.sub_path);2282 defer gpa.free(path.sub_path);
test/standalone/stack_iterator/build.zig+15
...@@ -93,6 +93,21 @@ pub fn build(b: *std.Build) void {...@@ -93,6 +93,21 @@ pub fn build(b: *std.Build) void {
9393
94 const run_cmd = b.addRunArtifact(exe);94 const run_cmd = b.addRunArtifact(exe);
95 test_step.dependOn(&run_cmd.step);95 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 }
96 }111 }
97112
98 // Unwinding without libc/posix113 // Unwinding without libc/posix