Open klauspost opened 4 years ago
@klauspost This is not problem of dlv.
It is beacause when process panic if invalid operations(ex: access invalid memory), process will received a signal (SIGSEGV) from os. Then process (golang) will enter runtime.sigpanic
to handle this exception. This affect the values of regs.
There is AFAIK no way for LEAQ to fail.
I test it. It is because cpu execute repro.s:7
failed.
And the flow from repro.s:6
enter runtime.sigpanic
.
So not wrong with LEAQ
but MOVQ AX, 2000000(CX)
.
(dlv) n
> _/C_/Users/admin/Desktop/repro.repro() C:/Users/admin/Desktop/repro/repro.s:6 (PC: 0x560593)
1: #include "textflag.h"
2:
3: // func repro(src []byte)
4: TEXT ·repro(SB), NOSPLIT, $0-24
5: XORQ AX, AX
=> 6: LEAQ src_base+0(FP), CX
7: MOVQ AX, 2000000(CX)
8: RET
(dlv) n
> _/C_/Users/admin/Desktop/repro.repro() C:/Users/admin/Desktop/repro/repro.s:7 (PC: 0x560598)
2:
3: // func repro(src []byte)
4: TEXT ·repro(SB), NOSPLIT, $0-24
5: XORQ AX, AX
6: LEAQ src_base+0(FP), CX
=> 7: MOVQ AX, 2000000(CX)
8: RET
(dlv) n
unexpected fault address 0xc000230398
fatal error: fault
> [runtime-fatal-throw] runtime.fatalthrow() c:/go/src/runtime/panic.go:820 (hits goroutine(19):1 total:1) (PC: 0x4356f0)
Warning: debugging optimized function
815: // fatalthrow implements an unrecoverable runtime throw. It freezes the
816: // system, prints stack traces starting from its caller, and terminates the
817: // process.
818: //
819: //go:nosplit
=> 820: func fatalthrow() {
821: pc := getcallerpc()
822: sp := getcallersp()
823: gp := getg()
824: // Switch to the system stack to avoid any stack growth, which
825: // may make things worse if the runtime is in a bad state.
In pratice most frames won't have any registers except the stack and frame pointers. This frame would be an exception because of the context pushed on the stack for the signal handler, but we don't parse that at the moment.
[...] context pushed on the stack for the signal handler, but we don't parse that at the moment.
@aarzilli That is probably what I was expecting. All other debuggers I have worked with will display registers at any given frame. Obviously, this makes assembly debugging quite hard since registers will have been overwritten with random data.
In pratice most frames won't have any registers except the stack and frame pointers.
That sentence doesn't make sense to me. Most Go code uses registers.
I test it. It is because cpu execute repro.s:7 failed. So not wrong with LEAQ but MOVQ AX, 2000000(CX).
@chainhelen Yes, that is my point. If it doesn't fail, just increase 2000000. My point is also that this is still reported wrong above, and you don't address the main issue.
In pratice most frames won't have any registers except the stack and frame pointers.
That sentence doesn't make sense to me. Most Go code uses registers.
Go doesn't track where registers are saved on the stack (besides the stack pointer) so most frames will not have any registers.
@aarzilli Ah, now I get what you mean. I do still think it is quite important to reliably see what registers were when a crash occurs.
Example:
λ dlv test
Type 'help' for list of commands.
(dlv) c
unexpected fault address 0xc0110fe0f0
fatal error: fault
> [runtime-fatal-throw] runtime.fatalthrow() c:/go/src/runtime/panic.go:820 (hits goroutine(544):1 total:1) (PC: 0x436d90)
Warning: debugging optimized function
815: // fatalthrow implements an unrecoverable runtime throw. It freezes the
816: // system, prints stack traces starting from its caller, and terminates the
817: // process.
818: //
819: //go:nosplit
=> 820: func fatalthrow() {
821: pc := getcallerpc()
822: sp := getcallersp()
823: gp := getg()
824: // Switch to the system stack to avoid any stack growth, which
825: // may make things worse if the runtime is in a bad state.
(dlv) frame 3
> [runtime-fatal-throw] runtime.fatalthrow() c:/go/src/runtime/panic.go:820 (hits goroutine(544):1 total:1) (PC: 0x436d90)
Warning: debugging optimized function
Frame 3: c:/gopath/src/github.com/klauspost/compress/s2/encodeblock_amd64.s:638 (PC: 7d8ebb)
633:
634: no_repeat_found_encodeBlockAsm:
635: CMPL (CX)(BX*1), BP
636: SHRQ $0x08, BP
637: JEQ candidate_match_encodeBlockAsm
=> 638: MOVL (SP)(R8*1), BX
639: CMPL (CX)(SI*1), BP
640: JEQ candidate2_match_encodeBlockAsm
641: LEAL 2(AX), SI
642: MOVL SI, (SP)(R8*1)
643: SHRQ $0x08, BP
(dlv) regs
Rip = 0x0000000000436d90
Rsp = 0x000000c00024d880
Rax = 0x000000c000044e00
Rbx = 0x000000c000044e00
Rcx = 0x000000c000044e58
Rdx = 0x0000000000b3e828
Rdi = 0x00000000002f7000
Rsi = 0x000000000317fd01
Rbp = 0x000000c00024d8a8
R8 = 0x000000000317fbf8
R9 = 0x000000000317fd70
R10 = 0x0000000000000000
R11 = 0x0000000000000246
R12 = 0x0000000000000276
R13 = 0x000000c000112280
R14 = 0x0000000000000006
R15 = 0x0000000000000000
Eflags = 0x0000000000000244 [PF ZF IF IOPL=0]
Cs = 0x0000000000000033
Fs = 0x0000000000000053
Gs = 0x000000000000002b
TLS = 0x00000000002f7000
(dlv)
I have a crash, but I am unable to see the values in the registers at the time of the crash. So I basically have no information available.
Also the crash is actually at the line below (CMPL)
I'd think this would be generally useful for panics, especially in optimized binaries with location lists.
I think @aarzilli pointed to this, but to be explicit: It should be possible to recover the registers in at least some circumstances. On Linux it'd be the ctxt argument to sigtrampgo: https://github.com/golang/go/blob/67f0f83216930e053441500e2b28c3fa2b667581/src/runtime/signal_unix.go#L403 On Windows it looks like https://github.com/golang/go/blob/6dbcc8b8651909442ff823231daba096f447a163/src/runtime/signal_windows.go#L104 messes with things badly enough that it would be hard to do.
It seems easy enough to add a sigctxt field somewhere (maybe the m?) and have all the OS handlers fill that in with whatever the platform-specific context structure is. Please feel free to file an issue if that'd help.
Please answer the following before submitting your issue:
Note: Please include any substantial examples (debug session output, stacktraces, etc) as linked gists.
dlv version
)?Latest master.
go version
)?go version go1.13.6 windows/amd64
windows/amd64
Reproduction sample: repro.zip
Run the sample. Crash occurs. We switch to the frame causing the crash (3). Print registers.
RAX to be 0. Note the
XORQ AX, AX
before the crash was invoked.Also the instruction pointed to is wrong. There is AFAIK no way for
LEAQ
to fail.RAX shows the registers at frame 0 as far as I can tell.
Thanks for a great tool!