go-delve / delve

Delve is a debugger for the Go programming language.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

panic incorrectly attributed to wrong line

stapelberg opened this issue · comments

  1. What version of Delve are you using (dlv version)?
% dlv version
Delve Debugger
Version: 1.22.0
Build: $Id: 61ecdbbe1b574f0dd7d7bad8b6a5d564cce981e9 $
  1. What version of Go are you using? (go version)?

go version go1.21.5 linux/amd64

  1. What operating system and processor architecture are you using?

linux/amd64

  1. What did you do?
% go mod init debugme
% cat > debugme.go <<'EOT'
package main

import "os"

func main() {
	fi, _ := os.Lstat("/this/path/does/not/exist")
	fi.Size()
}
EOT
% go build -gcflags="all=-N -l" debugme.go
% dlv exec ./debugme
(dlv) c
> [unrecovered-panic] runtime.fatalpanic() /usr/lib/go-1.21/src/runtime/panic.go:1188 (hits goroutine(1):1 total:1) (PC: 0x4353e4)
Warning: debugging optimized function
	runtime.curg._panic.arg: interface {}(string) "runtime error: invalid memory address or nil pointer dereference"
  1183:	// fatalpanic implements an unrecoverable panic. It is like fatalthrow, except
  1184:	// that if msgs != nil, fatalpanic also prints panic messages and decrements
  1185:	// runningPanicDefers once main is blocked from exiting.
  1186:	//
  1187:	//go:nosplit
=>1188:	func fatalpanic(msgs *_panic) {
  1189:		pc := getcallerpc()
  1190:		sp := getcallersp()
  1191:		gp := getg()
  1192:		var docrash bool
  1193:		// Switch to the system stack to avoid any stack growth, which
(dlv) bt
0  0x00000000004353e4 in runtime.fatalpanic
   at /usr/lib/go-1.21/src/runtime/panic.go:1188
1  0x0000000000434bb9 in runtime.gopanic
   at /usr/lib/go-1.21/src/runtime/panic.go:1017
2  0x000000000043373e in runtime.panicmem
   at /usr/lib/go-1.21/src/runtime/panic.go:261
3  0x000000000044a0a5 in runtime.sigpanic
   at /usr/lib/go-1.21/src/runtime/signal_unix.go:861
4  0x00000000004800bf in main.main
   at ./debugme.go:6
5  0x0000000000437787 in runtime.main
   at /usr/lib/go-1.21/src/runtime/proc.go:267
6  0x0000000000461de1 in runtime.goexit
   at /usr/lib/go-1.21/src/runtime/asm_amd64.s:1650
(dlv) frame 4
> [unrecovered-panic] runtime.fatalpanic() /usr/lib/go-1.21/src/runtime/panic.go:1188 (hits goroutine(1):1 total:1) (PC: 0x4353e4)
Warning: debugging optimized function
Frame 4: ./debugme.go:6 (PC: 4800bf)
     1:	package main
     2:	
     3:	import "os"
     4:	
     5:	func main() {
=>   6:		fi, _ := os.Lstat("/this/path/does/not/exist")
     7:		fi.Size()
     8:	}
(dlv) 

  1. What did you expect to see?

frame 4 should have been line 7 (fi.Size() where fi == nil)

  1. What did you see instead?

frame 4 is shown as line 6 (the call to os.Lstat — no invalid memory access yet)

I see “Warning: debugging optimized function” despite having built with go build -gcflags="all=-N -l" debugme.go. The go version -m output confirms that gcflags was set as specified:

% go version -m ./debugme
./debugme: go1.21.5
	path	command-line-arguments
	build	-buildmode=exe
	build	-compiler=gc
	build	-gcflags="all=-N -l"
	build	CGO_ENABLED=1
	build	CGO_CFLAGS=
	build	CGO_CPPFLAGS=
	build	CGO_CXXFLAGS=
	build	CGO_LDFLAGS=
	build	GOARCH=amd64
	build	GOOS=linux
	build	GOAMD64=v1

When stepping through the program, dlv executes line 6 successfully, then encounters a panic when running line 7 (as expected), but in the backtrace of that panic, it says the panic was raised from line 6 (incorrectly): https://gist.github.com/stapelberg/8a752b5363bf5329aff446779e267636