authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-08-08 11:06:14-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-08-08 11:06:14-07:00
log8031251c33bc66c5648122c0dcd89a8b00c42229
tree12e95b16866f74542587f37abfe9c1d0b36cca01
parentcf87a1a7cf57123aad533a73d8e0fa4d4916a674
parentcbdf9bf5eee3200efbcf7e1ca65dc93e34f94508
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #20997 from xxxbxxx/debuglink

std.debug.Dwarf: improve loading debug symbol from separate files

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

lib/std/debug/Dwarf.zig+67-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;
......@@ -2215,6 +2215,46 @@ pub const ElfModule = struct {
22152215 return error.MissingDebugInfo;
22162216 }
22172217
2218 // $XDG_CACHE_HOME/debuginfod_client/<buildid>/debuginfo
2219 // This only opportunisticly tries to load from the debuginfod cache, but doesn't try to populate it.
2220 // One can manually run `debuginfod-find debuginfo PATH` to download the symbols
2221 if (build_id) |id| blk: {
2222 var debuginfod_dir: std.fs.Dir = switch (builtin.os.tag) {
2223 .wasi, .windows => break :blk,
2224 else => dir: {
2225 if (std.posix.getenv("DEBUGINFOD_CACHE_PATH")) |path| {
2226 break :dir std.fs.openDirAbsolute(path, .{}) catch break :blk;
2227 }
2228 if (std.posix.getenv("XDG_CACHE_HOME")) |cache_path| {
2229 const path = std.fs.path.join(gpa, &[_][]const u8{ cache_path, "debuginfod_client" }) catch break :blk;
2230 defer gpa.free(path);
2231 break :dir std.fs.openDirAbsolute(path, .{}) catch break :blk;
2232 }
2233 if (std.posix.getenv("HOME")) |home_path| {
2234 const path = std.fs.path.join(gpa, &[_][]const u8{ home_path, ".cache", "debuginfod_client" }) catch break :blk;
2235 defer gpa.free(path);
2236 break :dir std.fs.openDirAbsolute(path, .{}) catch break :blk;
2237 }
2238 break :blk;
2239 },
2240 };
2241 defer debuginfod_dir.close();
2242
2243 const filename = std.fmt.allocPrint(
2244 gpa,
2245 "{s}/debuginfo",
2246 .{std.fmt.fmtSliceHexLower(id)},
2247 ) catch break :blk;
2248 defer gpa.free(filename);
2249
2250 const path: Path = .{
2251 .root_dir = .{ .path = null, .handle = debuginfod_dir },
2252 .sub_path = filename,
2253 };
2254
2255 return loadPath(gpa, path, null, separate_debug_crc, &sections, mapped_mem) catch break :blk;
2256 }
2257
22182258 const global_debug_directories = [_][]const u8{
22192259 "/usr/lib/debug",
22202260 };
......@@ -2253,25 +2293,30 @@ pub const ElfModule = struct {
22532293 if (elf_filename != null and mem.eql(u8, elf_filename.?, separate_filename))
22542294 return error.MissingDebugInfo;
22552295
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 {
2296 exe_dir: {
2297 var exe_dir_buf: [std.fs.max_path_bytes]u8 = undefined;
2298 const exe_dir_path = std.fs.selfExeDirPath(&exe_dir_buf) catch break :exe_dir;
2299 var exe_dir = std.fs.openDirAbsolute(exe_dir_path, .{}) catch break :exe_dir;
2300 defer exe_dir.close();
2301
2302 // <exe_dir>/<gnu_debuglink>
2303 if (loadPath(
2304 gpa,
2305 .{
2306 .root_dir = .{ .path = null, .handle = exe_dir },
2307 .sub_path = separate_filename,
2308 },
2309 null,
2310 separate_debug_crc,
2311 &sections,
2312 mapped_mem,
2313 )) |debug_info| {
2314 return debug_info;
2315 } else |_| {}
2316
2317 // <exe_dir>/.debug/<gnu_debuglink>
22732318 const path: Path = .{
2274 .root_dir = std.Build.Cache.Directory.cwd(),
2319 .root_dir = .{ .path = null, .handle = exe_dir },
22752320 .sub_path = try std.fs.path.join(gpa, &.{ ".debug", separate_filename }),
22762321 };
22772322 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