Invalid debug info when linking to system library.
Zig Version
0.9.1, on ArtixLinux x64, normal kernel, and hardened.
Steps to Reproduce
build.zig:
const std = @import("std");
pub fn build(b: *std.build.Builder) void {
const target = b.standardTargetOptions(.{});
const mode = b.standardReleaseOptions();
const exe = b.addExecutable("zigample", "src/main.zig");
exe.setTarget(target);
exe.setBuildMode(mode);
exe.linkSystemLibrary("GL");
exe.linkLibC();
exe.install();
const run_cmd = exe.run();
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}
main.zig:
const std = @import("std");
pub fn main() !void {
var testVar = "hello";
var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
const alloc = general_purpose_allocator.allocator();
var gameMap = try alloc.alloc(u8, testVar.len);
std.mem.copy(u8, gameMap, testVar);
const debug_info = std.debug.getSelfDebugInfo() catch unreachable;
const module = debug_info.getModuleForAddress(@returnAddress());
std.log.warn("hello {}", .{module});
//const builtin = @import("builtin");
//std.log.warn("hello {}", .{builtin.position_independent_executable});
std.debug.dumpCurrentStackTrace(@returnAddress());
_ = general_purpose_allocator.deinit();
}
Command to compile:
zig build run
However, this works:
zig build-exe -lX11 -lGL src/main.zig
but this does not:
zig build-exe -lc -GL src/main
Appears to be happening when linking multiple/both libraries?
Expected Behavior
A bunch of gibberish for the first print, then:
/usr/lib/zig/std/start.zig:561:37: 0x22513a in std.start.callMain (main)
const result = root.main() catch |err| {
^
/usr/lib/zig/std/start.zig:495:12: 0x206497 in std.start.callMainWithArgs (main)
return @call(.{ .modifier = .always_inline }, callMain, .{});
^
/usr/lib/zig/std/start.zig:409:17: 0x205594 in std.start.posixCallMainAndExit (main)
std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));
^
/usr/lib/zig/std/start.zig:322:5: 0x2053a1 in std.start._start (main)
@call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
^
error(gpa): memory address 0x7f64405b6000 leaked:
/data/sisyphus/proj/zigample/src/main.zig:9:34: 0x22b8c6 in main (main)
var gameMap = try alloc.alloc(u8, testVar.len);
^
/usr/lib/zig/std/start.zig:561:37: 0x22513a in std.start.callMain (main)
const result = root.main() catch |err| {
^
/usr/lib/zig/std/start.zig:495:12: 0x206497 in std.start.callMainWithArgs (main)
return @call(.{ .modifier = .always_inline }, callMain, .{});
^
/usr/lib/zig/std/start.zig:409:17: 0x205594 in std.start.posixCallMainAndExit (main)
std.os.exit(@call(.{ .modifier = .always_inline }, callMainWithArgs, .{ argc, argv, envp }));
Actual Behavior
warning: hello error.InvalidDebugInfo
???:?:?: 0x22afe7 in ??? (???)
???:?:?: 0x206bf7 in ??? (???)
???:?:?: 0x2069a2 in ??? (???)
error(gpa): memory address 0x7fa8a9429000 leaked:
???:?:?: 0x205e76 in ??? (???)
???:?:?: 0x22afe7 in ??? (???)
???:?:?: 0x206bf7 in ??? (???)
???:?:?: 0x2069a2 in ??? (???)
Thanks for the report - I was able to repro the problem
The problem is that linking certain libraries will cause the debug info to be output in DWARFv5 (instead of DWARFv4), and Zig 0.9.1 cannot correctly parser DWARFv5 debug info
DWARFv5 support was added in #11173, so this works on 0.10 / master
The problem is that linking certain libraries will cause the debug info to be output in DWARFv5 (instead of DWARFv4), and Zig 0.9.1 cannot correctly parser DWARFv5 debug info
Zig does build GL, but only when it is alone. How does that relate to DWARFv5 support?
The problem I see on my system is that the system-provided glibc on Arch was built with DWARFv5 debug info, so linking with that libc will generate an executable with DWARFv5 debug info
Can you test with the 0.10.0 master "nightly", and let me know if it resolves the issue? https://ziglang.org/download/
Can you test with the 0.10.0 master "nightly", and let me know if it resolves the issue?
I installed the other Zig package from AUR, 'zig-dev-bin',. I believe version 0.10.0, does work, and surprisingly is stable for a nightly release.
However, it seems like the first trace sometimes does break. I did not find consistency though.
Hmm, sounds like the parser probably still needs some improvement.
Can you attach a copy of the ELF file that is not parsed correctly?
I do not exactly know how useful this is, but here is a copy of a seg faulting program. 0x0.st upload To get it to segfault and print a stack trace, pass a positive integer as a command line argument.
The faulty stack is not consequential, at least for identifying the problem, though.
Thanks! Can you also share the faulty stack trace? It'll help me check that the symbols can be looked up properly (I just need the list of addresses printed)
[~/./s/sokoban] $ ./zig-out/bin/sokoban-vis 50
warning: hello generator.GeneratedPuzzle{ .map = map.Map{ .alloc = Allocator{ .ptr = anyopaque@55ab07b13660, .vtable = std.mem.Allocator.VTable{ ... } }, .rows = std.array_list.ArrayListAligned(std.array_list.ArrayListAligned(constants.Textile,null),null){ .items = { ... }, .capacity = 8, .allocator = Allocator{ ... } }, .highestId = 26, .displayed = std.array_list.ArrayListAligned(u8,null){ .items = { ... }, .capacity = 38, .allocator = Allocator{ ... } }, .sizeWidth = 5, .sizeHeight = 5, .workerPos = constants.Pos{ .x = 2, .y = 3 } }, .score = 0.0e+00 }
Segmentation fault at address 0x0
???:?:?: 0x7f77def5ce8d in ??? (???)
/usr/lib/zig/lib/std/fmt.zig:560:31: 0x55ab07acf9d0 in std.fmt.formatType (sokoban-vis)
try formatType(@field(value, f.name), ANY, options, writer, max_depth - 1);
^
/usr/lib/zig/lib/std/fmt.zig:178:23: 0x55ab07ac40ee in std.fmt.format (sokoban-vis)
try formatType(
^
/usr/lib/zig/lib/std/fmt.zig:1889:11: 0x55ab07ab8705 in std.fmt.count (sokoban-vis)
format(counting_writer.writer(), fmt, args) catch |err| switch (err) {};
^
/usr/lib/zig/lib/std/fmt.zig:1896:40: 0x55ab07a978d8 in std.fmt.allocPrint (sokoban-vis)
const size = math.cast(usize, count(fmt, args)) orelse return error.OutOfMemory;
^
/usr/lib/zig/lib/std/fmt.zig:1906:34: 0x55ab07a9754b in std.fmt.allocPrintZ (sokoban-vis)
const result = try allocPrint(allocator, fmt ++ "\x00", args);
^
/data/sisyphus/proj/sokoban/src/log.zig:59:38: 0x55ab07a97470 in log.printAlloc (sokoban-vis)
const s = try std.fmt.allocPrintZ(allocator, fmt ++ "\n", args);
^
/data/sisyphus/proj/sokoban/src/log.zig:47:19: 0x55ab07a8bbfc in log.warnAlloc (sokoban-vis)
try printAlloc(allocator, .warn, fmt, args);
^
/data/sisyphus/proj/sokoban/src/log.zig:19:14: 0x55ab07a83d4a in log.warn (sokoban-vis)
warnAlloc(fba.allocator(), fmt, args) catch |err| {
^
/data/sisyphus/proj/sokoban/src/generator.zig:192:17: 0x55ab07a8321f in generator.Node.evaluationFunction (sokoban-vis)
fn evaluationFunction(self: *Node) !f32 {
^
/data/sisyphus/proj/sokoban/src/generator.zig:177:48: 0x55ab07a825ff in generator.Node.evalBackProp (sokoban-vis)
^
/data/sisyphus/proj/sokoban/src/generator.zig:163:42: 0x55ab07a79622 in generator.Node.iterate (sokoban-vis)
}
^
/data/sisyphus/proj/sokoban/src/visualizer.zig:67:35: 0x55ab07a786ec in main (sokoban-vis)
try parentNode.iterate();
^
/usr/lib/zig/lib/std/start.zig:581:37: 0x55ab07a9cdf7 in std.start.callMain (sokoban-vis)
const result = root.main() catch |err| {
^
/usr/lib/zig/lib/std/start.zig:515:12: 0x55ab07a7c207 in std.start.callMainWithArgs (sokoban-vis)
return @call(.{ .modifier = .always_inline }, callMain, .{});
^
/usr/lib/zig/lib/std/start.zig:480:12: 0x55ab07a7bfb2 in std.start.main (sokoban-vis)
return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp });
^
zsh: IOT instruction ./zig-out/bin/sokoban-vis 50
Looks like the first entry is actually memcpy in libc. Lookup fails because Zig builds libc without debug symbols.
There are ways for Zig to get those debug symbols (by building them into libc, or loading them from usr/lib/debug if it's the system libc), but Zig doesn't do those yet.
I think it's worth tracking a fix for that (in this issue or a new one)