Skip to content

Missing stacktrace on Windows 11 x86_64 for Dynamic Libraries linked at runtime (DynSym) #20255

@katamari64

Description

@katamari64

Zig Version

0.13.0

Steps to Reproduce and Observed Behavior

When linking at runtime with std.DynLib, stacktrace can't find symbols from the .dll.
This used to work fine in 0.11.0, but stopped working on 0.12.0 and 0.13.0.

Here is a repro case (0.13.0) with 3 files [main.zig, my_lib.zig, build.zig]:

// src/main.zig
const std = @import("std");
const do_something = @import("my_lib").do_something;

pub fn main() !void {
    // > Uncomment the following to see the correct expected stacktrace
    // do_something();

    var lib = try std.DynLib.open("./zig-out/bin/my_lib.dll");
    const dynsym__do_something = lib.lookup(*const fn () void, "do_something") orelse return error.SymbolNotFound;
    dynsym__do_something();
}
// src/my_lib.zig
pub fn do_something() callconv(.C) void {
    panic_function();
}

fn panic_function() void {
    @panic("Time to dump the stacktrace");
}

comptime {
    if (@import("root") == @This()) {
        @export(do_something, .{ .name = "do_something", .linkage = .weak });
    }
}
// build.zig
const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});

    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "missing-stacktrace-repro",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    const my_lib: *std.Build.Step.Compile = b.addSharedLibrary(.{
        .name = "my_lib",
        .root_source_file = b.path("src/my_lib.zig"),
        .target = target,
        .optimize = optimize,
    });
    b.installArtifact(my_lib);

    const my_lib_mod = b.addModule("my_lib", .{
        .root_source_file = b.path("src/my_lib.zig"),
        .imports = &.{},
    });
    exe.root_module.addImport("my_lib", my_lib_mod);

    b.installArtifact(exe);

    const run_cmd = b.addRunArtifact(exe);
    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);
}

Expected Behavior

(A) Stacktrace when linked at runtime:

>zig build run
thread 40576 panic: Time to dump the stacktrace
???:?:?: 0x76791066 in ??? (my_lib.dll)
???:?:?: 0x7679102e in ??? (my_lib.dll)
E:\Work\Code\zig\stacktrace-comparison\stacktrace012\src\main.zig:11:25: 0xc4107c in main (stacktrace012.exe.obj)
    dynsym__do_something();
                        ^
C:\Users\karll\Software\Zig\lib\std\start.zig:363:53: 0xc412bc in WinStartup (stacktrace012.exe.obj)
    std.os.windows.ntdll.RtlExitUserProcess(callMain());
                                                    ^
???:?:?: 0x7ffbb106257c in ??? (KERNEL32.DLL)
???:?:?: 0x7ffbb2e2aa47 in ??? (ntdll.dll)
run
└─ run stacktrace012 failure

(B) Stacktrace when linked at startup (expected):

>zig build run
thread 59264 panic: Time to dump the stacktrace
E:\Work\Code\zig\stacktrace-comparison\stacktrace012\src\my_lib.zig:6:5: 0x882d26 in panic_function (stacktrace012.exe.obj)
    @panic("Time to dump the stacktrace");
    ^
E:\Work\Code\zig\stacktrace-comparison\stacktrace012\src\my_lib.zig:2:19: 0x85199e in do_something (stacktrace012.exe.obj)
    panic_function();
                  ^
E:\Work\Code\zig\stacktrace-comparison\stacktrace012\src\main.zig:15:24: 0x8510be in foo (stacktrace012.exe.obj)
    build__do_something();
                       ^
E:\Work\Code\zig\stacktrace-comparison\stacktrace012\src\main.zig:7:8: 0x851012 in main (stacktrace012.exe.obj)
    foo();
       ^
C:\Users\karll\Software\Zig\lib\std\start.zig:363:53: 0x8512dc in WinStartup (stacktrace012.exe.obj)
    std.os.windows.ntdll.RtlExitUserProcess(callMain());
                                                    ^
???:?:?: 0x7ffbb106257c in ??? (KERNEL32.DLL)
???:?:?: 0x7ffbb2e2aa47 in ??? (ntdll.dll)
run
└─ run stacktrace012 failure

Sorry if I'm missing something fundamental here, I'm not familiar with how stacktraces are generated in Zig, but I would expect the stacktrace to be present even when linking at runtime. Also it sounds like a regression to me as it used to work on Zig 0.11.0, but after updating to 0.12.0 it stopped working.

If the build.zig file is adapted, it's possible run the program and do the runtime linking in Zig 0.11.0 to confirm this used to work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behaviorregressionIt worked in a previous version of Zig, but stopped working.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions