Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

audit line/column number accuracy of windows stack traces #1503

Closed
andrewrk opened this Issue Sep 11, 2018 · 4 comments

Comments

Projects
None yet
4 participants
@andrewrk
Copy link
Member

andrewrk commented Sep 11, 2018

It seems that Windows stack traces are sometimes off by a line. Sometimes above, sometimes below.

One thing to double check: have a program manually print its @returnAddress() for every fn call, and then do a stack trace, and make sure RtlCaptureStackBackTrace is getting the correct addresses.

If those match then it should be a matter of how we are matching addresses with line/column data.

@andrewrk andrewrk added this to the 0.4.0 milestone Sep 11, 2018

@ghost

This comment has been minimized.

Copy link

ghost commented Sep 21, 2018

maybe this https://golang.org/pkg/debug/ specifically implementation of pe | Package pe implements access to PE (Microsoft Windows Portable Executable) files. can help there is https://golang.org/src/debug/pe/section.go?s=1877:2196#L60 PointerToLineNumbers uint32

I have not looked further though.

@suirad

This comment has been minimized.

Copy link
Contributor

suirad commented Nov 30, 2018

Fixed by #1798?

@tgschultz

This comment has been minimized.

Copy link
Contributor

tgschultz commented Nov 30, 2018

Doesn't look like it. I intentionally introduced an error in one of my projects and ran it on both Windows and Linux. The wrong line and carrot position problem persists.

Linux:

error: InvalidEnumTag
/home/tgschultz/zig/lib/zig/std/meta/index.zig:545:5: 0x20886b in ??? (test)
    return error.InvalidEnumTag;
    ^
/home/tgschultz/zig/lib/zig/std/io.zig:1176:29: 0x2086ee in ??? (test)
                    ptr.* = try meta.intToEnum(C, value);
                            ^
/home/tgschultz/zig/lib/zig/std/io.zig:1077:13: 0x207fdd in ??? (test)
            try self.deserializeInto(&value);
            ^
/home/tgschultz/projects/test/test.zig:215:24: 0x206f8a in ??? (test)
        self.version = try deserializer.deserialize(HeaderVersion);
                       ^
/home/tgschultz/zig/lib/zig/std/io.zig:1098:57: 0x206ee9 in ??? (test)
            if (comptime trait.hasFn("deserialize")(C)) return ptr.deserialize(self);
                                                        ^
/home/tgschultz/zig/lib/zig/std/io.zig:1077:13: 0x205785 in ??? (test)
            try self.deserializeInto(&value);
            ^
/home/tgschultz/projects/test/test.zig:22:18: 0x2051aa in ??? (test)
    const bmph = try deserializer.deserialize(BMPHeader);
                 ^
/home/tgschultz/zig/lib/zig/std/special/test_runner.zig:21:21: 0x22cdc3 in ??? (test)
            else => return err,

Windows:

error: InvalidEnumTag
C:\Users\Tanner Schultz\Desktop\Zig\zig\lib\zig\std\meta\index.zig:542:13: 0x7ff75c42483e in intToEnum (test.obj)
            return this_tag_value;
            ^
C:\Users\Tanner Schultz\Desktop\Zig\zig\lib\zig\std\io.zig:1175:33: 0x7ff75c4246ac in Deserializer(Endian.Little,false,error{OperationAborted,BrokenPipe,Unexpected,InputOutput,SystemResources,IsDir,})::Deserializer(Endian.Little,false,error{OperationAborted,BrokenPipe,Unexpected,InputOutput,SystemResources,IsDir,})_deserializeInto (test.obj)
                    var value = try self.deserializeInt(@TagType(C));
                                ^
C:\Users\Tanner Schultz\Desktop\Zig\zig\lib\zig\std\io.zig:1077:21: 0x7ff75c423f62 in Deserializer(Endian.Little,false,error{OperationAborted,BrokenPipe,Unexpected,InputOutput,SystemResources,IsDir,})::Deserializer(Endian.Little,false,error{OperationAborted,BrokenPipe,Unexpected,InputOutput,SystemResources,IsDir,})_deserialize (test.obj)
            try self.deserializeInto(&value);
                    ^
C:\Users\Tanner Schultz\Desktop\Zig\projects\testing\test.zig:215:52: 0x7ff75c422f77 in BMPHeader::BMPHeader_deserialize (test.obj)
        self.version = try deserializer.deserialize(HeaderVersion);
                                                   ^
C:\Users\Tanner Schultz\Desktop\Zig\zig\lib\zig\std\io.zig:1098:67: 0x7ff75c422eda in Deserializer(Endian.Little,false,error{OperationAborted,BrokenPipe,Unexpected,InputOutput,SystemResources,IsDir,})::Deserializer(Endian.Little,false,error{OperationAborted,BrokenPipe,Unexpected,InputOutput,SystemResources,IsDir,})_deserializeInto (test.obj)
            if (comptime trait.hasFn("deserialize")(C)) return ptr.deserialize(self);
                                                                  ^
C:\Users\Tanner Schultz\Desktop\Zig\zig\lib\zig\std\io.zig:1077:21: 0x7ff75c421c29 in Deserializer(Endian.Little,false,error{OperationAborted,BrokenPipe,Unexpected,InputOutput,SystemResources,IsDir,})::Deserializer(Endian.Little,false,error{OperationAborted,BrokenPipe,Unexpected,InputOutput,SystemResources,IsDir,})_deserialize (test.obj)
            try self.deserializeInto(&value);
                    ^
C:\Users\Tanner Schultz\Desktop\Zig\projects\testing\test.zig:22:46: 0x7ff75c42167e in  (test.obj)
    const bmph = try deserializer.deserialize(BMPHeader);
                                             ^
C:\Users\Tanner Schultz\Desktop\Zig\zig\lib\zig\std\special\test_runner.zig:14:22: 0x7ff75c4472f8 in main (test.obj)
            ok_count += 1;
@Sahnvour

This comment has been minimized.

Copy link
Member

Sahnvour commented Jan 13, 2019

#1798 did not fix this issue indeed.

I've been looking at this today and I'm puzzled.

The return addresses we keep in __zig_return_error or get from RtlCaptureStackBackTrace are correct.
I debugged through a small example (exposing the wrong behavior) with WinDBG: it was able to set breakpoints on wanted lines (for example when returning an error) and it showed the good correspondance between the compiler-inserted call __zig_return_error asm block and the line return error.FooError.
So all in all, it seems like the debug info is correct as it can make use of it and we get the expected result in WinDBG.

However I can't see where the problem is. I hacked a bit in the windows source address printing to see if I could list all the source lines from a LineBlock, without any interesting results (and i'm not even sure I did it correctly as some line numbers didn't make sense).
I find it strange that we can read debug data that is just slightly offset from the real source lines.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.