zig icon indicating copy to clipboard operation
zig copied to clipboard

debug info missing from Tracy

Open andrewrk opened this issue 3 years ago • 10 comments
trafficstars

Zig Version: 0.10.0-dev.4583+875e98a57

image

To reproduce:

stage3/bin/zig build -p stage4-tracy -Dskip-install-lib-files  -Drelease -Dtracy=$HOME/Downloads/tracy -Dstatic-llvm --search-prefix ~/dev/zig-bootstrap/out/x86_64-linux-musl-baseline -Dtarget=native-native-musl

Next run tracy, press the connect button. Finally:

stage4-tracy/bin/zig build

andrewrk avatar Oct 26 '22 20:10 andrewrk

Downstream issue filed: https://github.com/wolfpld/tracy/issues/482

andrewrk avatar Oct 27 '22 01:10 andrewrk

Even worse so, this almost immediately crashes on macOS while some debug info is there.

kubkon avatar Oct 27 '22 11:10 kubkon

This appears to be an issue with stage2 compiler. I've hooked up the same very bindings in https://github.com/kubkon/zld/tree/tracy-integration and tracy crashes with the same segfault as reported here when zld is built with stage2 compiler, but is fine when built with stage1 compiler (via -fstage1). I will try to investigate a little more since I have everything in place to debug it.

kubkon avatar Oct 27 '22 13:10 kubkon

I hit possibly the same crash in tigerbeetle with zig 0.9.1. As a workaround, I found that the alloc api seems to work fine:

        ___tracy_emit_zone_begin_alloc(___tracy_alloc_srcloc(
            src.line,
            src.file.ptr,
            src.file.len,
            src.fn_name.ptr,
            src.fn_name.len,
        ), 1);

jamii avatar Nov 29 '22 18:11 jamii

I have been experiencing this issue with all zig projects since switching to stage2.

@Techatrix found that if you don't use .line = src.line but instead hardcode it to .line = 1 it works (at least for the projects i've tested)

leecannon avatar Mar 14 '23 19:03 leecannon

TLDR: tracy assumes the source location is static and it can read it at anytime, but we are passing a pointer to the stack

I have done a bit of investigation and found out that the source location must survive (the tracy manual even spells this out in section 3.4 Marking Zones in the important box at the end of the section), so it cannot be on the stack, this is why ___tracy_alloc_srcloc as mentioned by @jamii works as it allocates the source location on the heap and never frees it.

According to the dissasembly, if you do .line = 1 then the struct is in rodata so will survive and if you do .line = src.line the struct is constructed on the stack and becomes invalid almost immediately.

If you try to force it to be comptime known:

const location = comptime ___tracy_source_location_data{
    .name = null,
    .function = src.fn_name.ptr,
    .file = src.file.ptr,
    .line = src.line,
    .color = 0,
};

An error message stating that src.line is a runtime value is shown:

src/tracy.zig:67:20: error: cannot store runtime value in compile time variable
        .line = src.line,

@andrewrk is it intended that src.line on the parameter comptime src: std.builtin.SourceLocation is not comptime known?

leecannon avatar Mar 14 '23 20:03 leecannon

No it's not intended. This is a regression.

andrewrk avatar Mar 14 '23 23:03 andrewrk

src.line is not comptime-known to avoid breaking incremental compilation https://github.com/ziglang/zig/pull/12016#issuecomment-1178092847

Vexu avatar Mar 15 '23 10:03 Vexu

You can even work around this without calling ___tracy_alloc_srcloc:

pub inline fn trace(comptime src: std.builtin.SourceLocation) Ctx {
    if (!enable) return .{};

    const statics = struct {
        var call: ___tracy_source_location_data = .{
            .name = null,
            .function = undefined,
            .file = undefined,
            .line = undefined,
            .color = 0,
        };
    };

    statics.call.function = src.fn_name.ptr;
    statics.call.file = src.file.ptr;
    statics.call.line = src.line;

    if (enable_callstack)
        return ___tracy_emit_zone_begin_callstack(&statics.call, callstack_depth, 1)
    else
        return ___tracy_emit_zone_begin(&statics.call, 1);
}

Since the function is inline, a static variable is created for each callsite.

Also, if @src() is runtime-known, shouldn't it be a compilation error to pass it to the comptime parameter? Is this a known bug, or did I misunderstand comptimeness again? :P

tau-dev avatar May 05 '23 07:05 tau-dev

Just posting this context from Andrew on Discord:

one note on perf though, I plan to fix #13315 soon so that we have that additional tracing tool at our disposal

idea is that line numbers become comptime-known, but lazy values, and make it a compile error for trying to branch on them at compile-time

This treatment should also be given to the column, since incremental compilation could break in the same way there on code not formatted with zig fmt.

mlugg avatar Jun 14 '23 21:06 mlugg

Regressed in 89cef9f5f731f8f33dc935aac3c21bd57c92900d.

andrewrk avatar Oct 24 '23 00:10 andrewrk