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
cmd/compile: incorrect DWARF location for runtime.throw's in-param #46425
Comments
@cherrymui @suzmue reported this problem in go1.16 too (I am not sure if it's the same problem) |
I looked at the DWARF produced by the 1.16 compiler. It is indeed broken, but it looks like in a different way (two different bugs). |
We can get the throw reason by looking at the argument "s" in runtime.throw. This is not currently working in Go 1.16 or Go 1.17 (see golang/go#46425), but does work in Go 1.15 and Go 1.14
Change https://golang.org/cl/332269 mentions this issue: |
With Go 1.17rc1, I am seeing that the location is correct within the systemstack call, but it is optimized out in the body of runtime.throw. Delve sets a breakpoint at runtime.fatalthrow for users to inspect the program state, so this is the point that it would be helpful to have access to the value of s.
If this would be more appropriate as a new issue to open, since it seems that the incorrect location seems to be fixed I can do so. |
Interesting. At the point of fatalthow call Why does it set a breakpoint in fatalthrow instead of throw? |
I think its historical from when fatalpanic and fatalthrow split, but I'm not sure @derekparker @aarzilli would know better. In both Go 1.16 and Go 1.17 the location info appears to only be available in the print function in runtime.throw:
It seems that |
With @thanm 's fix I believe it should work for 1.17. I just tried at tip and it does seem to work
I know it doesn't work with Go 1.16 due to some bug. @thanm would it be possible to fix 1.16 with something simple? |
Thanks it does seem to be working at runtime.throw. Sorry about that those logs must have been using a binary built with 1.16. @derekparker @aarzilli What do you think about moving the fatal throw breakpoint to |
Echoing what Cherry said, the crux of the problem is that "s" is no longer live at the call to fatalthrow; in general it isn't possible to generate a good location unless the lifetime is extended somehow. The location at the start of runtime.throw should be accurate now in 1.17. There are still many other issues with debug locations, but that one at least is working. |
|
I think that should be ok, but I haven't dug into the ramifications of the change. I'll take a closer look tomorrow, but it does seem like a more reliable spot. On initial digging it seems nothing directly calls |
@suzmue ok if I close this issue out? |
@thanm Yes definitely! Thanks for your help with this issue. Delve has also switched to using runtime.throw in PR go-delve/delve#2616, so this information will be surfaced to users. |
Cool, thanks. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes. This is only on tip.
What operating system and processor architecture are you using (
go env
)?linux/amd64
What did you do?
Compile a small program like
https://play.golang.org/p/1wRyGFu3wca
then run it in the debugger. Set a breakpoint in runtime.throw, then run. print "s"
What did you expect to see?
(gdb) p s
$1 = 0x47bfb6 "all goroutines are asleep - deadlock!"
What did you see instead?
(gdb) p s
$2 = 0x0 <error: Cannot access memory at address 0x0>
This is a bug in the Go compiler's debug location analysis phase, being triggered by the register ABI. Things seem to work when the register ABI is disabled, but I think mainly because the incoming locations for "s" are never killed, e.g. the stack location is essentially always available. When "s" is passed in RAX/RAB, it correctly tracks this fact, but then doesn't record the correct entry location when those registers are overwritten. I am not entirely sure what is going wrong, more analysis needed.
The text was updated successfully, but these errors were encountered: