-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
Zig Version
0.15.1
Steps to Reproduce and Observed Behavior
Summary
In Zig 0.15.1, std.debug.dumpStackTrace()
(on any attempt to resolve stack traces) cannot resolve source file locations for error return traces when the current working directory is different from where the source files are located. This worked correctly in Zig 0.14.1, as well as in 0.15.1 Linux builds.
Environment
- Zig Version: 0.15.1
- OS: macOS 14.6.0 (Darwin 24.6.0)
- Architecture: aarch64 (Apple Silicon)
- Previous Working Version: 0.14.1
Reproduction
Directory structure:
testylib/
├── lib.zig
├── build.zig
├── run.zig
└── different-cwd/
└── test_loader.zig
lib.zig:
const std = @import("std");
fn bar() !void {
var x: u8 = 42;
if (x == 42) {
return error.bad;
}
x = 10;
}
export fn foo() void {
bar() catch {
std.debug.dumpStackTrace(@errorReturnTrace().?.*);
};
}
build.zig:
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = std.builtin.OptimizeMode.ReleaseSafe;
const lib_module = b.createModule(.{
.root_source_file = b.path("lib.zig"),
.target = target,
.optimize = optimize,
.error_tracing = true,
.strip = false,
.omit_frame_pointer = false,
});
const lib = b.addLibrary(.{
.name = "lib",
.root_module = lib_module,
.linkage = .dynamic,
});
b.installArtifact(lib);
}
run.zig:
const std = @import("std");
pub fn main() !void {
var lib = try std.DynLib.open("zig-out/lib/liblib.dylib");
const foo = lib.lookup(*const fn () callconv(.c) void, "foo") orelse unreachable;
foo();
}
different-cwd/test_loader.zig:
const std = @import("std");
pub fn main() !void {
var lib = try std.DynLib.open("../zig-out/lib/liblib.dylib");
defer lib.close();
const foo = lib.lookup(*const fn () callconv(.c) void, "foo") orelse unreachable;
foo();
}
Steps to reproduce:
Test from source directory (works):
cd testylib
zig build
zig run run.zig
Expected and actual output:
testylib/lib.zig:6:9: 0x10442c7a7 in foo (lib)
return error.bad;
^
Test from different directory (broken):
cd testylib/different-cwd
zig run test_loader.zig
Expected output:
testylib/lib.zig:6:9: 0x10442c7a7 in foo (lib)
return error.bad;
^
Actual output:
???:?:?: 0x1011947a7 in _foo (???)
Analysis
- The error return trace addresses are captured correctly
- Debug info is present in the dylib (can be verified with
atos
) std.debug.getSelfDebugInfo()
appears to find the debug info- The issue is that source file paths cannot be resolved when CWD differs from source location
Verification that debug info exists:
cd testylib
atos -o zig-out/lib/liblib.dylib -l 0x100000000 0x10442c7a7
# Output shows: _foo (in liblib.dylib) (lib.zig:12)
This proves the debug info is present and atos
can resolve it, but std.debug.dumpStackTrace()
cannot when run from a different directory.
Actual Behavior
Source locations show as ???:?:?:
when the current working directory is different from where the source files are located.
Impact
This breaks error return trace debugging for:
- Dynamically loaded libraries (NIFs, plugins, etc.)
- Applications that change working directory
- Any scenario where the dylib is loaded from a different CWD than the build directory
Additional Notes
- This is a regression from Zig 0.14.1 where it worked correctly on macOS
- The issue affects both Debug and ReleaseSafe optimization modes
- Setting
.error_tracing = true
,.strip = false
,.omit_frame_pointer = false
does not resolve the issue
Expected Behavior
std.debug.dumpStackTrace()
should be able to resolve source locations regardless of the current working directory, as it did in Zig 0.14.1.